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