• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #define MLOG_TAG "FetchResultNapi"
16 
17 #include "fetch_file_result_napi.h"
18 
19 #include "album_napi.h"
20 #include "hitrace_meter.h"
21 #include "medialibrary_napi_log.h"
22 #include "medialibrary_tracer.h"
23 #include "smart_album_napi.h"
24 
25 using OHOS::HiviewDFX::HiLog;
26 using OHOS::HiviewDFX::HiLogLabel;
27 using namespace std;
28 
29 namespace OHOS {
30 namespace Media {
31 thread_local napi_ref FetchFileResultNapi::sConstructor_ = nullptr;
32 
33 thread_local napi_ref FetchFileResultNapi::userFileMgrConstructor_ = nullptr;
34 
FetchFileResultNapi()35 FetchFileResultNapi::FetchFileResultNapi()
36     : env_(nullptr) {}
37 
~FetchFileResultNapi()38 FetchFileResultNapi::~FetchFileResultNapi()
39 {
40     propertyPtr = nullptr;
41 }
42 
FetchFileResultNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)43 void FetchFileResultNapi::FetchFileResultNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
44 {
45     FetchFileResultNapi *fetchFileResultObj = reinterpret_cast<FetchFileResultNapi*>(nativeObject);
46     if (fetchFileResultObj != nullptr) {
47         delete fetchFileResultObj;
48         fetchFileResultObj = nullptr;
49     }
50 }
51 
Init(napi_env env,napi_value exports)52 napi_value FetchFileResultNapi::Init(napi_env env, napi_value exports)
53 {
54     napi_status status;
55     napi_value ctorObj;
56     int32_t refCount = 1;
57 
58     napi_property_descriptor fetch_file_result_props[] = {
59         DECLARE_NAPI_FUNCTION("getCount", JSGetCount),
60         DECLARE_NAPI_FUNCTION("isAfterLast", JSIsAfterLast),
61         DECLARE_NAPI_FUNCTION("getFirstObject", JSGetFirstObject),
62         DECLARE_NAPI_FUNCTION("getNextObject", JSGetNextObject),
63         DECLARE_NAPI_FUNCTION("getLastObject", JSGetLastObject),
64         DECLARE_NAPI_FUNCTION("getPositionObject", JSGetPositionObject),
65         DECLARE_NAPI_FUNCTION("getAllObject", JSGetAllObject),
66         DECLARE_NAPI_FUNCTION("close", JSClose)
67     };
68 
69     status = napi_define_class(env, FETCH_FILE_RESULT_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
70                                FetchFileResultNapiConstructor, nullptr,
71                                sizeof(fetch_file_result_props) / sizeof(fetch_file_result_props[PARAM0]),
72                                fetch_file_result_props, &ctorObj);
73     if (status == napi_ok) {
74         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
75         if (status == napi_ok) {
76             status = napi_set_named_property(env, exports, FETCH_FILE_RESULT_CLASS_NAME.c_str(), ctorObj);
77             if (status == napi_ok) {
78                 return exports;
79             }
80         }
81     }
82     NAPI_DEBUG_LOG("Init success");
83     return nullptr;
84 }
85 
GetFetchResult(unique_ptr<FetchFileResultNapi> & obj)86 void FetchFileResultNapi::GetFetchResult(unique_ptr<FetchFileResultNapi> &obj)
87 {
88     switch (sFetchResType_) {
89         case FetchResType::TYPE_FILE:
90             obj->propertyPtr->fetchFileResult_ =
91                 make_shared<FetchResult<FileAsset>>(move(sFetchFileResult_->resultset_));
92             obj->propertyPtr->fetchFileResult_->SetInfo(sFetchFileResult_);
93             obj->propertyPtr->typeMask_ = obj->propertyPtr->fetchFileResult_->typeMask_;
94             break;
95         case FetchResType::TYPE_ALBUM:
96             obj->propertyPtr->fetchAlbumResult_ =
97                 make_shared<FetchResult<AlbumAsset>>(move(sFetchAlbumResult_->resultset_));
98             obj->propertyPtr->fetchAlbumResult_->SetInfo(sFetchAlbumResult_);
99             obj->propertyPtr->typeMask_ = obj->propertyPtr->fetchAlbumResult_->typeMask_;
100             break;
101         case FetchResType::TYPE_SMARTALBUM:
102             obj->propertyPtr->fetchSmartAlbumResult_ =
103                 make_shared<FetchResult<SmartAlbumAsset>>(move(sFetchSmartAlbumResult_->resultset_));
104             obj->propertyPtr->fetchSmartAlbumResult_->SetInfo(sFetchSmartAlbumResult_);
105             obj->propertyPtr->typeMask_ = obj->propertyPtr->fetchSmartAlbumResult_->typeMask_;
106             break;
107         default:
108             NAPI_ERR_LOG("unsupported FetchResType");
109             break;
110     }
111 }
112 
113 // Constructor callback
FetchFileResultNapiConstructor(napi_env env,napi_callback_info info)114 napi_value FetchFileResultNapi::FetchFileResultNapiConstructor(napi_env env, napi_callback_info info)
115 {
116     MediaLibraryTracer tracer;
117     tracer.Start("FetchFileResultNapiConstructor");
118 
119     napi_status status;
120     napi_value result = nullptr;
121     napi_value thisVar = nullptr;
122 
123     napi_get_undefined(env, &result);
124     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
125     if (status != napi_ok || thisVar == nullptr) {
126         NAPI_ERR_LOG("Get Js obj failed, status: %{public}d, (thisVar == nullptr) = %{public}d",
127             status, (thisVar == nullptr));
128         return result;
129     }
130 
131     unique_ptr<FetchFileResultNapi> obj = make_unique<FetchFileResultNapi>();
132     if (obj == nullptr) {
133         NAPI_ERR_LOG("Get FetchFileResultNapi failed");
134         return result;
135     }
136     obj->env_ = env;
137     obj->propertyPtr = make_shared<FetchResultProperty>();
138     GetFetchResult(obj);
139     obj->propertyPtr->fetchResType_ = sFetchResType_;
140     status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
141                        FetchFileResultNapi::FetchFileResultNapiDestructor, nullptr, nullptr);
142     if (status == napi_ok) {
143         obj.release();
144         return thisVar;
145     } else {
146         NAPI_ERR_LOG("Failure wrapping js to native napi, status: %{public}d", status);
147     }
148     return result;
149 }
150 
GetFetchResType()151 FetchResType FetchFileResultNapi::GetFetchResType()
152 {
153     return propertyPtr->fetchResType_;
154 }
155 
CreateFetchFileResult(napi_env env,unique_ptr<FetchResult<FileAsset>> fileResult)156 napi_value FetchFileResultNapi::CreateFetchFileResult(napi_env env, unique_ptr<FetchResult<FileAsset>> fileResult)
157 {
158     MediaLibraryTracer tracer;
159     tracer.Start("CreateFetchFileResult");
160     napi_value constructor;
161     napi_ref constructorRef = (fileResult->resultNapiType_ == ResultNapiType::TYPE_USERFILE_MGR) ?
162         (userFileMgrConstructor_) : (sConstructor_);
163     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
164     sFetchResType_ = fileResult->fetchResType_;
165     sFetchFileResult_ = move(fileResult);
166     napi_value result = nullptr;
167     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
168     sFetchFileResult_ = nullptr;
169     return result;
170 }
171 
CreateFetchFileResult(napi_env env,unique_ptr<FetchResult<AlbumAsset>> fileResult)172 napi_value FetchFileResultNapi::CreateFetchFileResult(napi_env env, unique_ptr<FetchResult<AlbumAsset>> fileResult)
173 {
174     MediaLibraryTracer tracer;
175     tracer.Start("CreateFetchFileResult");
176     napi_value constructor;
177     napi_ref constructorRef = (fileResult->resultNapiType_ == ResultNapiType::TYPE_USERFILE_MGR) ?
178         (userFileMgrConstructor_) : (sConstructor_);
179     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
180     sFetchResType_ = fileResult->fetchResType_;
181     sFetchAlbumResult_ = move(fileResult);
182     napi_value result = nullptr;
183     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
184     sFetchAlbumResult_ = nullptr;
185     return result;
186 }
187 
CreateFetchFileResult(napi_env env,unique_ptr<FetchResult<SmartAlbumAsset>> fileResult)188 napi_value FetchFileResultNapi::CreateFetchFileResult(napi_env env, unique_ptr<FetchResult<SmartAlbumAsset>> fileResult)
189 {
190     MediaLibraryTracer tracer;
191     tracer.Start("CreateFetchFileResult");
192     napi_value constructor;
193     napi_ref constructorRef = (fileResult->resultNapiType_ == ResultNapiType::TYPE_USERFILE_MGR) ?
194         (userFileMgrConstructor_) : (sConstructor_);
195     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
196     sFetchResType_ = fileResult->fetchResType_;
197     sFetchSmartAlbumResult_ = move(fileResult);
198     napi_value result = nullptr;
199     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
200     sFetchSmartAlbumResult_ = nullptr;
201     return result;
202 }
203 
GetFetchFileResult() const204 std::shared_ptr<FetchResult<FileAsset>> FetchFileResultNapi::GetFetchFileResult() const
205 {
206     return propertyPtr->fetchFileResult_;
207 }
208 
UserFileMgrInit(napi_env env,napi_value exports)209 napi_value FetchFileResultNapi::UserFileMgrInit(napi_env env, napi_value exports)
210 {
211     NapiClassInfo info = {
212         .name = UFM_FETCH_FILE_RESULT_CLASS_NAME,
213         .ref = &userFileMgrConstructor_,
214         .constructor = FetchFileResultNapiConstructor,
215         .props = {
216             DECLARE_NAPI_FUNCTION("getCount", JSGetCount),
217             DECLARE_NAPI_FUNCTION("isAfterLast", JSIsAfterLast),
218             DECLARE_NAPI_FUNCTION("getFirstObject", JSGetFirstObject),
219             DECLARE_NAPI_FUNCTION("getNextObject", JSGetNextObject),
220             DECLARE_NAPI_FUNCTION("getLastObject", JSGetLastObject),
221             DECLARE_NAPI_FUNCTION("getPositionObject", JSGetPositionObject),
222             DECLARE_NAPI_FUNCTION("close", JSClose)
223         }
224     };
225     MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
226     return exports;
227 }
228 
CheckIfFFRNapiNotEmpty(FetchFileResultNapi * obj)229 static bool CheckIfFFRNapiNotEmpty(FetchFileResultNapi* obj)
230 {
231     if (obj == nullptr) {
232         NAPI_INFO_LOG("FetchFileResultNapi is nullptr");
233         return false;
234     }
235     if (obj->CheckIfPropertyPtrNull()) {
236         NAPI_INFO_LOG("PropertyPtr in FetchFileResultNapi is nullptr");
237         return false;
238     }
239     return true;
240 }
241 
JSGetCount(napi_env env,napi_callback_info info)242 napi_value FetchFileResultNapi::JSGetCount(napi_env env, napi_callback_info info)
243 {
244     napi_status status;
245     napi_value jsResult = nullptr;
246     FetchFileResultNapi* obj = nullptr;
247     int32_t count = 0;
248     napi_value thisVar = nullptr;
249 
250     MediaLibraryTracer tracer;
251     tracer.Start("JSGetCount");
252 
253     napi_get_undefined(env, &jsResult);
254     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
255     if (status != napi_ok || thisVar == nullptr) {
256         NAPI_ERR_LOG("JSGetCount Invalid arguments!, status: %{public}d", status);
257         NAPI_ASSERT(env, false, "JSGetCount thisVar == nullptr");
258     }
259 
260     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
261     if ((status == napi_ok) && CheckIfFFRNapiNotEmpty(obj)) {
262         switch (obj->GetFetchResType()) {
263             case FetchResType::TYPE_FILE:
264                 count = obj->GetFetchFileResultObject()->GetCount();
265                 break;
266             case FetchResType::TYPE_ALBUM:
267                 count = obj->GetFetchAlbumResultObject()->GetCount();
268                 break;
269             case FetchResType::TYPE_SMARTALBUM:
270                 count = obj->GetFetchSmartAlbumResultObject()->GetCount();
271                 break;
272             default:
273                 NAPI_ERR_LOG("unsupported FetchResType");
274                 break;
275         }
276         napi_create_int32(env, count, &jsResult);
277     } else {
278         NAPI_ERR_LOG("JSGetCount obj == nullptr, status: %{public}d", status);
279         NAPI_ASSERT(env, false, "JSGetCount obj == nullptr");
280     }
281 
282     return jsResult;
283 }
284 
JSIsAfterLast(napi_env env,napi_callback_info info)285 napi_value FetchFileResultNapi::JSIsAfterLast(napi_env env, napi_callback_info info)
286 {
287     napi_status status;
288     napi_value jsResult = nullptr;
289     FetchFileResultNapi* obj = nullptr;
290     bool isAfterLast = false;
291     napi_value thisVar = nullptr;
292 
293     MediaLibraryTracer tracer;
294     tracer.Start("JSIsAfterLast");
295 
296     napi_get_undefined(env, &jsResult);
297     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
298     if (status != napi_ok || thisVar == nullptr) {
299         NAPI_ERR_LOG("JSIsAfterLast Invalid arguments!, status: %{public}d", status);
300         NAPI_ASSERT(env, false, "JSIsAfterLast thisVar == nullptr");
301     }
302 
303     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
304     if ((status == napi_ok) && CheckIfFFRNapiNotEmpty(obj)) {
305         switch (obj->GetFetchResType()) {
306             case FetchResType::TYPE_FILE:
307                 isAfterLast = obj->GetFetchFileResultObject()->IsAtLastRow();
308                 break;
309             case FetchResType::TYPE_ALBUM:
310                 isAfterLast = obj->GetFetchAlbumResultObject()->IsAtLastRow();
311                 break;
312             case FetchResType::TYPE_SMARTALBUM:
313                 isAfterLast = obj->GetFetchSmartAlbumResultObject()->IsAtLastRow();
314                 break;
315             default:
316                 NAPI_ERR_LOG("unsupported FetchResType");
317                 break;
318         }
319         napi_get_boolean(env, isAfterLast, &jsResult);
320     } else {
321         NAPI_ERR_LOG("JSIsAfterLast obj == nullptr, status: %{public}d", status);
322         NAPI_ASSERT(env, false, "JSIsAfterLast obj == nullptr");
323     }
324 
325     return jsResult;
326 }
327 
GetNapiResFromAsset(napi_env env,FetchFileResultAsyncContext * context,unique_ptr<JSAsyncContextOutput> & jsContext)328 static void GetNapiResFromAsset(napi_env env, FetchFileResultAsyncContext *context,
329     unique_ptr<JSAsyncContextOutput> &jsContext)
330 {
331     napi_value jsAsset;
332     switch (context->objectPtr->fetchResType_) {
333         case FetchResType::TYPE_FILE:
334             jsAsset = FileAssetNapi::CreateFileAsset(env, context->fileAsset);
335             break;
336         case FetchResType::TYPE_ALBUM:
337             jsAsset = AlbumNapi::CreateAlbumNapi(env, context->albumAsset);
338             break;
339         case FetchResType::TYPE_SMARTALBUM:
340             jsAsset = SmartAlbumNapi::CreateSmartAlbumNapi(env, context->smartAlbumAsset);
341             break;
342         default:
343             NAPI_ERR_LOG("unsupported FetchResType");
344             break;
345     }
346 
347     if (jsAsset == nullptr) {
348         NAPI_ERR_LOG("Failed to get file asset napi object");
349         napi_get_undefined(env, &jsContext->data);
350         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
351             "Failed to create js object for FileAsset");
352     } else {
353         jsContext->data = jsAsset;
354         napi_get_undefined(env, &jsContext->error);
355         jsContext->status = true;
356     }
357 }
358 
GetPositionObjectCompleteCallback(napi_env env,napi_status status,FetchFileResultAsyncContext * context)359 static void GetPositionObjectCompleteCallback(napi_env env, napi_status status, FetchFileResultAsyncContext* context)
360 {
361     MediaLibraryTracer tracer;
362     tracer.Start("GetPositionObjectCompleteCallback");
363 
364     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
365 
366     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
367     jsContext->status = false;
368 
369     GetNapiResFromAsset(env, context, jsContext);
370 
371     if (context->work != nullptr) {
372         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
373                                                    context->work, *jsContext);
374     }
375 
376     delete context;
377 }
378 
JSGetFirstObject(napi_env env,napi_callback_info info)379 napi_value FetchFileResultNapi::JSGetFirstObject(napi_env env, napi_callback_info info)
380 {
381     napi_status status;
382     napi_value result = nullptr;
383     const int32_t refCount = 1;
384     napi_value resource = nullptr;
385     size_t argc = ARGS_ONE;
386     napi_value argv[ARGS_ONE] = {0};
387     napi_value thisVar = nullptr;
388 
389     MediaLibraryTracer tracer;
390     tracer.Start("JSGetFirstObject");
391 
392     GET_JS_ARGS(env, info, argc, argv, thisVar);
393     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter");
394     napi_get_undefined(env, &result);
395 
396     unique_ptr<FetchFileResultAsyncContext> asyncContext = make_unique<FetchFileResultAsyncContext>();
397     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
398     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
399         if (argc == ARGS_ONE) {
400             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
401         }
402 
403         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
404         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetFirstObject", asyncContext);
405 
406         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
407         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
408 
409         status = napi_create_async_work(
410             env, nullptr, resource, [](napi_env env, void* data) {
411                 auto context = static_cast<FetchFileResultAsyncContext*>(data);
412                 context->GetFirstAsset();
413             },
414             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
415             static_cast<void*>(asyncContext.get()), &asyncContext->work);
416         if (status != napi_ok) {
417             napi_get_undefined(env, &result);
418         } else {
419             napi_queue_async_work(env, asyncContext->work);
420             asyncContext.release();
421         }
422     } else {
423         NAPI_ERR_LOG("JSGetFirstObject obj == nullptr, status: %{public}d", status);
424         NAPI_ASSERT(env, false, "JSGetFirstObject obj == nullptr");
425     }
426 
427     return result;
428 }
429 
JSGetNextObject(napi_env env,napi_callback_info info)430 napi_value FetchFileResultNapi::JSGetNextObject(napi_env env, napi_callback_info info)
431 {
432     napi_status status;
433     napi_value result = nullptr;
434     const int32_t refCount = 1;
435     napi_value resource = nullptr;
436     size_t argc = ARGS_ONE;
437     napi_value argv[ARGS_ONE] = {0};
438     napi_value thisVar = nullptr;
439 
440     MediaLibraryTracer tracer;
441     tracer.Start("JSGetNextObject");
442 
443     GET_JS_ARGS(env, info, argc, argv, thisVar);
444     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter");
445 
446     napi_get_undefined(env, &result);
447     unique_ptr<FetchFileResultAsyncContext> asyncContext = make_unique<FetchFileResultAsyncContext>();
448     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
449     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
450         if (argc == ARGS_ONE) {
451             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
452         }
453 
454         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
455         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetNextObject", asyncContext);
456 
457         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
458         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
459 
460         status = napi_create_async_work(
461             env, nullptr, resource, [](napi_env env, void* data) {
462                 auto context = static_cast<FetchFileResultAsyncContext*>(data);
463                 context->GetNextObject();
464             },
465             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
466             static_cast<void*>(asyncContext.get()), &asyncContext->work);
467         if (status != napi_ok) {
468             napi_get_undefined(env, &result);
469         } else {
470             napi_queue_async_work(env, asyncContext->work);
471             asyncContext.release();
472         }
473     } else {
474         NAPI_ERR_LOG("JSGetNextObject obj == nullptr, status: %{public}d", status);
475         NAPI_ASSERT(env, false, "JSGetNextObject obj == nullptr");
476     }
477 
478     return result;
479 }
480 
JSGetLastObject(napi_env env,napi_callback_info info)481 napi_value FetchFileResultNapi::JSGetLastObject(napi_env env, napi_callback_info info)
482 {
483     napi_status status;
484     napi_value result = nullptr;
485     const int32_t refCount = 1;
486     napi_value resource = nullptr;
487     size_t argc = ARGS_ONE;
488     napi_value argv[ARGS_ONE] = {0};
489     napi_value thisVar = nullptr;
490 
491     MediaLibraryTracer tracer;
492     tracer.Start("JSGetLastObject");
493 
494     GET_JS_ARGS(env, info, argc, argv, thisVar);
495     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter");
496 
497     napi_get_undefined(env, &result);
498     unique_ptr<FetchFileResultAsyncContext> asyncContext = make_unique<FetchFileResultAsyncContext>();
499     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
500     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
501         if (argc == ARGS_ONE) {
502             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
503         }
504 
505         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
506         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetLastObject", asyncContext);
507 
508         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
509         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
510 
511         status = napi_create_async_work(
512             env, nullptr, resource, [](napi_env env, void* data) {
513                 auto context = static_cast<FetchFileResultAsyncContext*>(data);
514                 context->GetLastObject();
515             },
516             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
517             static_cast<void*>(asyncContext.get()), &asyncContext->work);
518         if (status != napi_ok) {
519             napi_get_undefined(env, &result);
520         } else {
521             napi_queue_async_work(env, asyncContext->work);
522             asyncContext.release();
523         }
524     } else {
525         NAPI_ERR_LOG("JSGetLastObject obj == nullptr, status: %{public}d", status);
526         NAPI_ASSERT(env, false, "JSGetLastObject obj == nullptr");
527     }
528 
529     return result;
530 }
531 
JSGetPositionObject(napi_env env,napi_callback_info info)532 napi_value FetchFileResultNapi::JSGetPositionObject(napi_env env, napi_callback_info info)
533 {
534     napi_status status;
535     napi_value result = nullptr;
536     const int32_t refCount = 1;
537     napi_valuetype type = napi_undefined;
538     napi_value resource = nullptr;
539     size_t argc = ARGS_TWO;
540     napi_value argv[ARGS_TWO] = {0};
541     napi_value thisVar = nullptr;
542 
543     MediaLibraryTracer tracer;
544     tracer.Start("JSGetPositionObject");
545 
546     GET_JS_ARGS(env, info, argc, argv, thisVar);
547     NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameter maximum");
548 
549     napi_get_undefined(env, &result);
550     unique_ptr<FetchFileResultAsyncContext> asyncContext = make_unique<FetchFileResultAsyncContext>();
551     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
552     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
553         // Check the arguments and their types
554         napi_typeof(env, argv[PARAM0], &type);
555         if (type == napi_number) {
556             napi_get_value_int32(env, argv[PARAM0], &(asyncContext->position));
557         } else {
558             NAPI_ERR_LOG("Argument mismatch, type: %{public}d", type);
559             return result;
560         }
561 
562         if (argc == ARGS_TWO) {
563             GET_JS_ASYNC_CB_REF(env, argv[PARAM1], refCount, asyncContext->callbackRef);
564         }
565 
566         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
567         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetPositionObject", asyncContext);
568 
569         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
570         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
571 
572         status = napi_create_async_work(
573             env, nullptr, resource, [](napi_env env, void* data) {
574                 auto context = static_cast<FetchFileResultAsyncContext*>(data);
575                 context->GetObjectAtPosition();
576             },
577             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
578             static_cast<void*>(asyncContext.get()), &asyncContext->work);
579         if (status != napi_ok) {
580             napi_get_undefined(env, &result);
581         } else {
582             napi_queue_async_work(env, asyncContext->work);
583             asyncContext.release();
584         }
585     } else {
586         NAPI_ERR_LOG("JSGetPositionObject obj == nullptr, status: %{public}d", status);
587         NAPI_ASSERT(env, false, "JSGetPositionObject obj == nullptr");
588     }
589 
590     return result;
591 }
592 
GetAsset(napi_env env,vector<std::unique_ptr<FileAsset>> & array,int index)593 static napi_value GetAsset(napi_env env, vector<std::unique_ptr<FileAsset>> &array, int index)
594 {
595     return FileAssetNapi::CreateFileAsset(env, array[index]);
596 }
597 
GetAsset(napi_env env,vector<std::unique_ptr<AlbumAsset>> & array,int index)598 static napi_value GetAsset(napi_env env, vector<std::unique_ptr<AlbumAsset>> &array, int index)
599 {
600     return AlbumNapi::CreateAlbumNapi(env, array[index]);
601 }
602 
GetAsset(napi_env env,vector<std::unique_ptr<SmartAlbumAsset>> & array,int index)603 static napi_value GetAsset(napi_env env, vector<std::unique_ptr<SmartAlbumAsset>> &array, int index)
604 {
605     return SmartAlbumNapi::CreateSmartAlbumNapi(env, array[index]);
606 }
607 
608 template<class T>
GetAssetFromArray(napi_env env,FetchFileResultAsyncContext * context,T & array,unique_ptr<JSAsyncContextOutput> & jsContext)609 static void GetAssetFromArray(napi_env env, FetchFileResultAsyncContext* context, T& array,
610     unique_ptr<JSAsyncContextOutput> &jsContext)
611 {
612     napi_value jsFileArray = nullptr;
613     napi_create_array_with_length(env, array.size(), &jsFileArray);
614     napi_value jsFileAsset = nullptr;
615     size_t i = 0;
616     for (i = 0; i < array.size(); i++) {
617         jsFileAsset = GetAsset(env, array, i);
618         if ((jsFileAsset == nullptr) || (napi_set_element(env, jsFileArray, i, jsFileAsset) != napi_ok)) {
619             NAPI_ERR_LOG("Failed to get file asset napi object");
620             napi_get_undefined(env, &jsContext->data);
621             MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
622                 "Failed to create js object");
623             break;
624         }
625     }
626     if (i == array.size()) {
627         jsContext->data = jsFileArray;
628         napi_get_undefined(env, &jsContext->error);
629         jsContext->status = true;
630     }
631 }
632 
GetAllObjectCompleteCallback(napi_env env,napi_status status,FetchFileResultAsyncContext * context)633 static void GetAllObjectCompleteCallback(napi_env env, napi_status status, FetchFileResultAsyncContext* context)
634 {
635     MediaLibraryTracer tracer;
636     tracer.Start("GetAllObjectCompleteCallback");
637     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
638     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
639     jsContext->status = false;
640 
641     switch (context->objectPtr->fetchResType_) {
642         case FetchResType::TYPE_FILE:
643             GetAssetFromArray(env, context, context->fileAssetArray, jsContext);
644             break;
645         case FetchResType::TYPE_ALBUM:
646             GetAssetFromArray(env, context, context->fileAlbumArray, jsContext);
647             break;
648         case FetchResType::TYPE_SMARTALBUM:
649             GetAssetFromArray(env, context, context->fileSmartAlbumArray, jsContext);
650             break;
651         default:
652             NAPI_ERR_LOG("unsupported FetchResType");
653             napi_get_undefined(env, &jsContext->data);
654             MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
655                 "Failed to obtain fileAsset array from DB");
656     }
657 
658     if (context->work != nullptr) {
659         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
660                                                    context->work, *jsContext);
661     }
662 
663     delete context;
664 }
665 
GetFetchFileResultObject()666 std::shared_ptr<FetchResult<FileAsset>> FetchFileResultNapi::GetFetchFileResultObject()
667 {
668     return propertyPtr->fetchFileResult_;
669 }
670 
GetFetchAlbumResultObject()671 std::shared_ptr<FetchResult<AlbumAsset>> FetchFileResultNapi::GetFetchAlbumResultObject()
672 {
673     return propertyPtr->fetchAlbumResult_;
674 }
675 
GetFetchSmartAlbumResultObject()676 std::shared_ptr<FetchResult<SmartAlbumAsset>> FetchFileResultNapi::GetFetchSmartAlbumResultObject()
677 {
678     return propertyPtr->fetchSmartAlbumResult_;
679 }
680 
GetAllObjectFromFetchResult(const FetchFileResultAsyncContext & asyncContext)681 void GetAllObjectFromFetchResult(const FetchFileResultAsyncContext &asyncContext)
682 {
683     MediaLibraryTracer tracer;
684     tracer.Start("GetAllObjectFromFetchResult");
685 
686     FetchFileResultAsyncContext *context = const_cast<FetchFileResultAsyncContext *>(&asyncContext);
687     context->GetAllObjectFromFetchResult();
688 }
689 
JSGetAllObject(napi_env env,napi_callback_info info)690 napi_value FetchFileResultNapi::JSGetAllObject(napi_env env, napi_callback_info info)
691 {
692     napi_status status;
693     napi_value result = nullptr;
694     const int32_t refCount = 1;
695     napi_value resource = nullptr;
696     size_t argc = ARGS_ONE;
697     napi_value argv[ARGS_ONE] = {0};
698     napi_value thisVar = nullptr;
699 
700     MediaLibraryTracer tracer;
701     tracer.Start("JSGetAllObject");
702 
703     GET_JS_ARGS(env, info, argc, argv, thisVar);
704     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
705 
706     napi_get_undefined(env, &result);
707     unique_ptr<FetchFileResultAsyncContext> asyncContext = make_unique<FetchFileResultAsyncContext>();
708     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
709     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
710         if (argc == ARGS_ONE) {
711             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
712         }
713 
714         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
715         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetAllObject", asyncContext);
716 
717         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
718         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
719 
720         status = napi_create_async_work(
721             env, nullptr, resource, [](napi_env env, void* data) {
722                 auto context = static_cast<FetchFileResultAsyncContext*>(data);
723                 GetAllObjectFromFetchResult(*context);
724             },
725             reinterpret_cast<napi_async_complete_callback>(GetAllObjectCompleteCallback),
726             static_cast<void*>(asyncContext.get()), &asyncContext->work);
727         if (status != napi_ok) {
728             napi_get_undefined(env, &result);
729         } else {
730             napi_queue_async_work(env, asyncContext->work);
731             asyncContext.release();
732         }
733     } else {
734         NAPI_ERR_LOG("JSGetAllObject obj == nullptr, status: %{public}d", status);
735         NAPI_ASSERT(env, false, "JSGetAllObject obj == nullptr");
736     }
737 
738     return result;
739 }
740 
JSClose(napi_env env,napi_callback_info info)741 napi_value FetchFileResultNapi::JSClose(napi_env env, napi_callback_info info)
742 {
743     napi_status status;
744     napi_value jsResult = nullptr;
745     FetchFileResultNapi* obj = nullptr;
746     napi_value thisVar = nullptr;
747 
748     MediaLibraryTracer tracer;
749     tracer.Start("JSClose");
750 
751     napi_get_undefined(env, &jsResult);
752     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
753     if (status != napi_ok || thisVar == nullptr) {
754         NAPI_ERR_LOG("Invalid arguments!, status: %{public}d", status);
755         return jsResult;
756     }
757     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
758     if ((status == napi_ok) && (obj != nullptr)) {
759         obj->propertyPtr = nullptr;
760     }
761     status = napi_remove_wrap(env, thisVar, reinterpret_cast<void **>(&obj));
762     if ((status == napi_ok) && (obj != nullptr)) {
763         napi_create_int32(env, SUCCESS, &jsResult);
764     } else {
765         NAPI_INFO_LOG("JSClose obj == nullptr");
766     }
767 
768     NAPI_DEBUG_LOG("JSClose OUT!");
769     return jsResult;
770 }
771 
GetFirstAsset()772 void FetchFileResultAsyncContext::GetFirstAsset()
773 {
774     switch (objectPtr->fetchResType_) {
775         case FetchResType::TYPE_FILE: {
776             fileAsset = objectPtr->fetchFileResult_->GetFirstObject();
777             break;
778         }
779         case FetchResType::TYPE_ALBUM: {
780             albumAsset = objectPtr->fetchAlbumResult_->GetFirstObject();
781             break;
782         }
783         case FetchResType::TYPE_SMARTALBUM: {
784             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetFirstObject();
785             break;
786         }
787         default:
788             NAPI_ERR_LOG("unsupported FetchResType");
789             break;
790     }
791 }
792 
GetObjectAtPosition()793 void FetchFileResultAsyncContext::GetObjectAtPosition()
794 {
795     switch (objectPtr->fetchResType_) {
796         case FetchResType::TYPE_FILE: {
797             fileAsset = objectPtr->fetchFileResult_->GetObjectAtPosition(position);
798             break;
799         }
800         case FetchResType::TYPE_ALBUM: {
801             albumAsset = objectPtr->fetchAlbumResult_->GetObjectAtPosition(position);
802             break;
803         }
804         case FetchResType::TYPE_SMARTALBUM: {
805             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetObjectAtPosition(position);
806             break;
807         }
808         default:
809             NAPI_ERR_LOG("unsupported FetchResType");
810             break;
811     }
812 }
813 
GetLastObject()814 void FetchFileResultAsyncContext::GetLastObject()
815 {
816     switch (objectPtr->fetchResType_) {
817         case FetchResType::TYPE_FILE: {
818             fileAsset = objectPtr->fetchFileResult_->GetLastObject();
819             break;
820         }
821         case FetchResType::TYPE_ALBUM: {
822             albumAsset = objectPtr->fetchAlbumResult_->GetLastObject();
823             break;
824         }
825         case FetchResType::TYPE_SMARTALBUM: {
826             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetLastObject();
827             break;
828         }
829         default:
830             NAPI_ERR_LOG("unsupported FetchResType");
831             break;
832     }
833 }
834 
GetNextObject()835 void FetchFileResultAsyncContext::GetNextObject()
836 {
837     switch (objectPtr->fetchResType_) {
838         case FetchResType::TYPE_FILE: {
839             fileAsset = objectPtr->fetchFileResult_->GetNextObject();
840             break;
841         }
842         case FetchResType::TYPE_ALBUM: {
843             albumAsset = objectPtr->fetchAlbumResult_->GetNextObject();
844             break;
845         }
846         case FetchResType::TYPE_SMARTALBUM: {
847             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetNextObject();
848             break;
849         }
850         default:
851             NAPI_ERR_LOG("unsupported FetchResType");
852             break;
853     }
854 }
855 
GetAllObjectFromFetchResult()856 void FetchFileResultAsyncContext::GetAllObjectFromFetchResult()
857 {
858     switch (objectPtr->fetchResType_) {
859         case FetchResType::TYPE_FILE: {
860             auto fetchResult = objectPtr->fetchFileResult_;
861             auto file = fetchResult->GetFirstObject();
862             while (file != nullptr) {
863                 fileAssetArray.push_back(move(file));
864                     file = fetchResult->GetNextObject();
865             }
866             break;
867         }
868         case FetchResType::TYPE_ALBUM: {
869             auto fetchResult = objectPtr->fetchAlbumResult_;
870             auto album = fetchResult->GetFirstObject();
871             while (album != nullptr) {
872                 fileAlbumArray.push_back(move(album));
873                 album = fetchResult->GetNextObject();
874             }
875             break;
876         }
877         case FetchResType::TYPE_SMARTALBUM: {
878             auto fetchResult = objectPtr->fetchSmartAlbumResult_;
879             auto smartAlbum = fetchResult->GetFirstObject();
880             while (smartAlbum != nullptr) {
881                 fileSmartAlbumArray.push_back(move(smartAlbum));
882                 smartAlbum = fetchResult->GetNextObject();
883             }
884             break;
885         }
886         default:
887             NAPI_ERR_LOG("unsupported FetchResType");
888             break;
889     }
890 }
891 
CheckIfPropertyPtrNull()892 bool FetchFileResultNapi::CheckIfPropertyPtrNull()
893 {
894     return propertyPtr == nullptr;
895 }
896 } // namespace Media
897 } // namespace OHOS