• 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 "AlbumNapi"
16 
17 #include "album_napi.h"
18 #include "medialibrary_client_errno.h"
19 #include "medialibrary_napi_log.h"
20 #include "medialibrary_tracer.h"
21 #include "media_file_utils.h"
22 #include "userfile_client.h"
23 
24 using OHOS::HiviewDFX::HiLog;
25 using OHOS::HiviewDFX::HiLogLabel;
26 
27 namespace OHOS {
28 namespace Media {
29 using namespace std;
30 using namespace OHOS::DataShare;
31 thread_local napi_ref AlbumNapi::sConstructor_ = nullptr;
32 thread_local AlbumAsset *AlbumNapi::sAlbumData_ = nullptr;
33 using CompleteCallback = napi_async_complete_callback;
34 
35 thread_local napi_ref AlbumNapi::userFileMgrConstructor_ = nullptr;
36 
AlbumNapi()37 AlbumNapi::AlbumNapi()
38     : env_(nullptr) {}
39 
40 AlbumNapi::~AlbumNapi() = default;
41 
AlbumNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)42 void AlbumNapi::AlbumNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
43 {
44     AlbumNapi *album = reinterpret_cast<AlbumNapi*>(nativeObject);
45     if (album != nullptr) {
46         delete album;
47         album = nullptr;
48     }
49 }
50 
Init(napi_env env,napi_value exports)51 napi_value AlbumNapi::Init(napi_env env, napi_value exports)
52 {
53     napi_status status;
54     napi_value ctorObj;
55     int32_t refCount = 1;
56 
57     napi_property_descriptor album_props[] = {
58         DECLARE_NAPI_GETTER("albumId", JSGetAlbumId),
59         DECLARE_NAPI_GETTER_SETTER("albumName", JSGetAlbumName, JSAlbumNameSetter),
60         DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
61         DECLARE_NAPI_GETTER("dateModified", JSGetAlbumDateModified),
62         DECLARE_NAPI_GETTER("count", JSGetCount),
63         DECLARE_NAPI_GETTER("relativePath", JSGetAlbumRelativePath),
64         DECLARE_NAPI_GETTER("coverUri", JSGetCoverUri),
65         DECLARE_NAPI_FUNCTION("commitModify", JSCommitModify),
66         DECLARE_NAPI_GETTER_SETTER("path", JSGetAlbumPath, JSSetAlbumPath),
67         DECLARE_NAPI_GETTER("virtual", JSGetAlbumVirtual),
68         DECLARE_NAPI_FUNCTION("getFileAssets", JSGetAlbumFileAssets)
69     };
70 
71     status = napi_define_class(env, ALBUM_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
72                                AlbumNapiConstructor, nullptr,
73                                sizeof(album_props) / sizeof(album_props[PARAM0]),
74                                album_props, &ctorObj);
75     if (status == napi_ok) {
76         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
77         if (status == napi_ok) {
78             status = napi_set_named_property(env, exports, ALBUM_NAPI_CLASS_NAME.c_str(), ctorObj);
79             if (status == napi_ok) {
80                 return exports;
81             }
82         }
83     }
84 
85     return nullptr;
86 }
87 
UserFileMgrInit(napi_env env,napi_value exports)88 napi_value AlbumNapi::UserFileMgrInit(napi_env env, napi_value exports)
89 {
90     NapiClassInfo info = {
91         .name = USERFILEMGR_ALBUM_NAPI_CLASS_NAME,
92         .ref = &userFileMgrConstructor_,
93         .constructor = AlbumNapiConstructor,
94         .props = {
95             DECLARE_NAPI_FUNCTION("getPhotoAssets", UserFileMgrGetAssets),
96             DECLARE_NAPI_FUNCTION("commitModify", UserFileMgrCommitModify),
97             DECLARE_NAPI_GETTER_SETTER("albumName", JSGetAlbumName, JSAlbumNameSetter),
98             DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
99             DECLARE_NAPI_GETTER("dateModified", JSGetAlbumDateModified),
100             DECLARE_NAPI_GETTER("count", JSGetCount),
101             DECLARE_NAPI_GETTER("relativePath", JSGetAlbumRelativePath),
102             DECLARE_NAPI_GETTER("coverUri", JSGetCoverUri)
103         }
104     };
105 
106     MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
107     return exports;
108 }
109 
SetAlbumNapiProperties()110 void AlbumNapi::SetAlbumNapiProperties()
111 {
112     albumAssetPtr = std::shared_ptr<AlbumAsset>(sAlbumData_);
113 }
114 
115 // Constructor callback
AlbumNapiConstructor(napi_env env,napi_callback_info info)116 napi_value AlbumNapi::AlbumNapiConstructor(napi_env env, napi_callback_info info)
117 {
118     napi_status status;
119     napi_value result = nullptr;
120     napi_value thisVar = nullptr;
121 
122     napi_get_undefined(env, &result);
123     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
124     if (status == napi_ok && thisVar != nullptr) {
125         std::unique_ptr<AlbumNapi> obj = std::make_unique<AlbumNapi>();
126         if (obj != nullptr) {
127             obj->env_ = env;
128             if (sAlbumData_ != nullptr) {
129                 obj->SetAlbumNapiProperties();
130             }
131 
132             status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
133                                AlbumNapi::AlbumNapiDestructor, nullptr, nullptr);
134             if (status == napi_ok) {
135                 obj.release();
136                 return thisVar;
137             } else {
138                 NAPI_ERR_LOG("Failure wrapping js to native napi. status: %{public}d", status);
139             }
140         }
141     }
142 
143     return result;
144 }
145 
CreateAlbumNapi(napi_env env,unique_ptr<AlbumAsset> & albumData)146 napi_value AlbumNapi::CreateAlbumNapi(napi_env env, unique_ptr<AlbumAsset> &albumData)
147 {
148     if (albumData == nullptr) {
149         return nullptr;
150     }
151 
152     napi_value constructor;
153     napi_ref constructorRef = (albumData->GetResultNapiType() == ResultNapiType::TYPE_MEDIALIBRARY) ?
154         (sConstructor_) : (userFileMgrConstructor_);
155     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
156 
157     napi_value result = nullptr;
158     sAlbumData_ = albumData.release();
159     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
160     sAlbumData_ = nullptr;
161     return result;
162 }
163 
GetAlbumName() const164 std::string AlbumNapi::GetAlbumName() const
165 {
166     return albumAssetPtr->GetAlbumName();
167 }
168 
GetAlbumPath() const169 std::string AlbumNapi::GetAlbumPath() const
170 {
171     return albumAssetPtr->GetAlbumPath();
172 }
173 
GetAlbumId() const174 int32_t AlbumNapi::GetAlbumId() const
175 {
176     return albumAssetPtr->GetAlbumId();
177 }
178 
GetAlbumUri() const179 std::string AlbumNapi::GetAlbumUri() const
180 {
181     return albumAssetPtr->GetAlbumUri();
182 }
183 
GetNetworkId() const184 std::string AlbumNapi::GetNetworkId() const
185 {
186     return MediaFileUtils::GetNetworkIdFromUri(GetAlbumUri());
187 }
188 
GetTypeMask() const189 std::string AlbumNapi::GetTypeMask() const
190 {
191     return albumAssetPtr->GetAlbumTypeMask();
192 }
193 
JSGetAlbumId(napi_env env,napi_callback_info info)194 napi_value AlbumNapi::JSGetAlbumId(napi_env env, napi_callback_info info)
195 {
196     napi_status status;
197     napi_value jsResult = nullptr;
198     napi_value undefinedResult = nullptr;
199     AlbumNapi* obj = nullptr;
200     int32_t id;
201     napi_value thisVar = nullptr;
202 
203     napi_get_undefined(env, &undefinedResult);
204     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
205     if (status != napi_ok || thisVar == nullptr) {
206         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
207         return undefinedResult;
208     }
209 
210     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
211     if (status == napi_ok && obj != nullptr) {
212         id = obj->GetAlbumId();
213         status = napi_create_int32(env, id, &jsResult);
214         if (status == napi_ok) {
215             return jsResult;
216         }
217     }
218 
219     return undefinedResult;
220 }
221 
JSGetAlbumName(napi_env env,napi_callback_info info)222 napi_value AlbumNapi::JSGetAlbumName(napi_env env, napi_callback_info info)
223 {
224     napi_status status;
225     napi_value jsResult = nullptr;
226     napi_value undefinedResult = nullptr;
227     AlbumNapi* obj = nullptr;
228     std::string name = "";
229     napi_value thisVar = nullptr;
230     napi_get_undefined(env, &undefinedResult);
231     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
232     if (status != napi_ok || thisVar == nullptr) {
233         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
234         return undefinedResult;
235     }
236 
237     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
238     if (status == napi_ok && obj != nullptr) {
239         name = obj->GetAlbumName();
240         status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &jsResult);
241         if (status == napi_ok) {
242             return jsResult;
243         }
244     }
245 
246     return undefinedResult;
247 }
248 
JSAlbumNameSetter(napi_env env,napi_callback_info info)249 napi_value AlbumNapi::JSAlbumNameSetter(napi_env env, napi_callback_info info)
250 {
251     napi_status status;
252     napi_value jsResult = nullptr;
253     size_t argc = ARGS_ONE;
254     napi_value argv[ARGS_ONE] = {0};
255     size_t res = 0;
256     char buffer[FILENAME_MAX];
257     AlbumNapi* obj = nullptr;
258     napi_value thisVar = nullptr;
259     napi_valuetype valueType = napi_undefined;
260 
261     napi_get_undefined(env, &jsResult);
262     GET_JS_ARGS(env, info, argc, argv, thisVar);
263     NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
264     if (thisVar == nullptr || napi_typeof(env, argv[PARAM0], &valueType) != napi_ok
265         || valueType != napi_string) {
266         NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
267         return jsResult;
268     }
269 
270     napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
271 
272     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
273     if (status == napi_ok && obj != nullptr) {
274         obj->albumAssetPtr->SetAlbumName(std::string(buffer));
275     } else {
276         NAPI_ERR_LOG("status = %{public}d", status);
277     }
278     return jsResult;
279 }
JSGetAlbumUri(napi_env env,napi_callback_info info)280 napi_value AlbumNapi::JSGetAlbumUri(napi_env env, napi_callback_info info)
281 {
282     napi_status status;
283     napi_value jsResult = nullptr;
284     napi_value undefinedResult = nullptr;
285     AlbumNapi* obj = nullptr;
286     std::string uri = "";
287     napi_value thisVar = nullptr;
288 
289     napi_get_undefined(env, &undefinedResult);
290     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
291     if (status != napi_ok || thisVar == nullptr) {
292         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
293         return undefinedResult;
294     }
295 
296     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
297     if (status == napi_ok && obj != nullptr) {
298         uri = obj->GetAlbumUri();
299         status = napi_create_string_utf8(env, uri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
300         if (status == napi_ok) {
301             return jsResult;
302         }
303     }
304 
305     return undefinedResult;
306 }
JSGetAlbumDateModified(napi_env env,napi_callback_info info)307 napi_value AlbumNapi::JSGetAlbumDateModified(napi_env env, napi_callback_info info)
308 {
309     napi_status status;
310     napi_value jsResult = nullptr;
311     napi_value undefinedResult = nullptr;
312     AlbumNapi* obj = nullptr;
313     int64_t dateModified;
314     napi_value thisVar = nullptr;
315 
316     napi_get_undefined(env, &undefinedResult);
317     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
318     if (status != napi_ok || thisVar == nullptr) {
319         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
320         return undefinedResult;
321     }
322 
323     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
324     if (status == napi_ok && obj != nullptr) {
325         dateModified = obj->albumAssetPtr->GetAlbumDateModified();
326         status = napi_create_int64(env, dateModified, &jsResult);
327         if (status == napi_ok) {
328             return jsResult;
329         }
330     }
331 
332     return undefinedResult;
333 }
JSGetCount(napi_env env,napi_callback_info info)334 napi_value AlbumNapi::JSGetCount(napi_env env, napi_callback_info info)
335 {
336     napi_status status;
337     napi_value jsResult = nullptr;
338     napi_value undefinedResult = nullptr;
339     AlbumNapi *obj = nullptr;
340     int32_t count;
341     napi_value thisVar = nullptr;
342 
343     napi_get_undefined(env, &undefinedResult);
344     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
345     if (status != napi_ok || thisVar == nullptr) {
346         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
347         return undefinedResult;
348     }
349     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
350     if (status == napi_ok && obj != nullptr) {
351         count = obj->albumAssetPtr->GetCount();
352         status = napi_create_int32(env, count, &jsResult);
353         if (status == napi_ok) {
354             return jsResult;
355         }
356     }
357     return undefinedResult;
358 }
JSGetAlbumRelativePath(napi_env env,napi_callback_info info)359 napi_value AlbumNapi::JSGetAlbumRelativePath(napi_env env, napi_callback_info info)
360 {
361     napi_status status;
362     napi_value jsResult = nullptr;
363     napi_value undefinedResult = nullptr;
364     AlbumNapi* obj = nullptr;
365     std::string relativePath = "";
366     napi_value thisVar = nullptr;
367 
368     napi_get_undefined(env, &undefinedResult);
369     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
370     if (status != napi_ok || thisVar == nullptr) {
371         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
372         return undefinedResult;
373     }
374 
375     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
376     if (status == napi_ok && obj != nullptr) {
377         relativePath = obj->albumAssetPtr->GetAlbumRelativePath();
378         status = napi_create_string_utf8(env, relativePath.c_str(), NAPI_AUTO_LENGTH, &jsResult);
379         if (status == napi_ok) {
380             return jsResult;
381         }
382     }
383 
384     return undefinedResult;
385 }
JSGetCoverUri(napi_env env,napi_callback_info info)386 napi_value AlbumNapi::JSGetCoverUri(napi_env env, napi_callback_info info)
387 {
388     napi_status status;
389     napi_value jsResult = nullptr;
390     napi_value undefinedResult = nullptr;
391     AlbumNapi* obj = nullptr;
392     std::string coverUri = "";
393     napi_value thisVar = nullptr;
394 
395     napi_get_undefined(env, &undefinedResult);
396     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
397     if (status != napi_ok || thisVar == nullptr) {
398         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
399         return undefinedResult;
400     }
401 
402     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
403     if (status == napi_ok && obj != nullptr) {
404         coverUri = obj->albumAssetPtr->GetCoverUri();
405         status = napi_create_string_utf8(env, coverUri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
406         if (status == napi_ok) {
407             return jsResult;
408         }
409     }
410 
411     return undefinedResult;
412 }
413 
JSSetAlbumPath(napi_env env,napi_callback_info info)414 napi_value AlbumNapi::JSSetAlbumPath(napi_env env, napi_callback_info info)
415 {
416     napi_status status;
417     napi_value jsResult = nullptr;
418     size_t argc = ARGS_ONE;
419     napi_value argv[ARGS_ONE] = {0};
420     size_t res = 0;
421     char buffer[PATH_MAX];
422     AlbumNapi* obj = nullptr;
423     napi_value thisVar = nullptr;
424     napi_valuetype valueType = napi_undefined;
425 
426     napi_get_undefined(env, &jsResult);
427     GET_JS_ARGS(env, info, argc, argv, thisVar);
428     NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
429 
430     if (thisVar == nullptr || napi_typeof(env, argv[PARAM0], &valueType) != napi_ok
431         || valueType != napi_string) {
432         NAPI_ERR_LOG("Invalid arguments type! type: %{public}d", valueType);
433         return jsResult;
434     }
435 
436     napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &res);
437 
438     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
439     if (status == napi_ok && obj != nullptr) {
440         obj->albumAssetPtr->SetAlbumPath(std::string(buffer));
441     }
442 
443     return jsResult;
444 }
445 
JSGetAlbumPath(napi_env env,napi_callback_info info)446 napi_value AlbumNapi::JSGetAlbumPath(napi_env env, napi_callback_info info)
447 {
448     napi_status status;
449     napi_value jsResult = nullptr;
450     napi_value undefinedResult = nullptr;
451     AlbumNapi* obj = nullptr;
452     std::string path = "";
453     napi_value thisVar = nullptr;
454 
455     napi_get_undefined(env, &undefinedResult);
456     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
457     if (status != napi_ok || thisVar == nullptr) {
458         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
459         return undefinedResult;
460     }
461 
462     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
463     if (status == napi_ok && obj != nullptr) {
464         path = obj->GetAlbumPath();
465         status = napi_create_string_utf8(env, path.c_str(), NAPI_AUTO_LENGTH, &jsResult);
466         if (status == napi_ok) {
467             return jsResult;
468         }
469     }
470 
471     return undefinedResult;
472 }
473 
JSGetAlbumVirtual(napi_env env,napi_callback_info info)474 napi_value AlbumNapi::JSGetAlbumVirtual(napi_env env, napi_callback_info info)
475 {
476     napi_status status;
477     napi_value jsResult = nullptr;
478     napi_value undefinedResult = nullptr;
479     AlbumNapi* obj = nullptr;
480     bool virtualAlbum = false;
481     napi_value thisVar = nullptr;
482 
483     napi_get_undefined(env, &undefinedResult);
484     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
485     if (status != napi_ok || thisVar == nullptr) {
486         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
487         return undefinedResult;
488     }
489 
490     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
491     if (status == napi_ok && obj != nullptr) {
492         virtualAlbum = obj->albumAssetPtr->GetAlbumVirtual();
493         status = napi_get_boolean(env, virtualAlbum, &jsResult);
494         if (status == napi_ok) {
495             return jsResult;
496         }
497     }
498 
499     return undefinedResult;
500 }
501 
GetFetchOptionsParam(napi_env env,napi_value arg,const AlbumNapiAsyncContext & context,bool & err)502 static void GetFetchOptionsParam(napi_env env, napi_value arg, const AlbumNapiAsyncContext &context, bool &err)
503 {
504     AlbumNapiAsyncContext *asyncContext = const_cast<AlbumNapiAsyncContext *>(&context);
505     CHECK_NULL_PTR_RETURN_VOID(asyncContext, "Async context is null");
506     char buffer[PATH_MAX];
507     size_t res;
508     uint32_t len = 0;
509     napi_value property = nullptr;
510     napi_value stringItem = nullptr;
511     bool present = false;
512     bool boolResult = false;
513 
514     napi_has_named_property(env, arg, "selections", &present);
515     if (present) {
516         if (napi_get_named_property(env, arg, "selections", &property) != napi_ok
517             || napi_get_value_string_utf8(env, property, buffer, PATH_MAX, &res) != napi_ok) {
518             NAPI_ERR_LOG("Could not get the string argument!");
519             err = true;
520             return;
521         } else {
522             asyncContext->selection = buffer;
523             CHECK_IF_EQUAL(memset_s(buffer, PATH_MAX, 0, sizeof(buffer)) == 0, "Memset for buffer failed");
524         }
525         present = false;
526     }
527 
528     napi_has_named_property(env, arg, "order", &present);
529     if (present) {
530         if (napi_get_named_property(env, arg, "order", &property) != napi_ok
531             || napi_get_value_string_utf8(env, property, buffer, PATH_MAX, &res) != napi_ok) {
532             NAPI_ERR_LOG("Could not get the string argument!");
533             err = true;
534             return;
535         } else {
536             asyncContext->order = buffer;
537             CHECK_IF_EQUAL(memset_s(buffer, PATH_MAX, 0, sizeof(buffer)) == 0, "Memset for buffer failed");
538         }
539         present = false;
540     }
541 
542     napi_has_named_property(env, arg, "selectionArgs", &present);
543     if (present && napi_get_named_property(env, arg, "selectionArgs", &property) == napi_ok &&
544         napi_is_array(env, property, &boolResult) == napi_ok && boolResult) {
545         napi_get_array_length(env, property, &len);
546         for (size_t i = 0; i < len; i++) {
547             napi_get_element(env, property, i, &stringItem);
548             napi_get_value_string_utf8(env, stringItem, buffer, PATH_MAX, &res);
549             asyncContext->selectionArgs.push_back(std::string(buffer));
550             CHECK_IF_EQUAL(memset_s(buffer, PATH_MAX, 0, sizeof(buffer)) == 0, "Memset for buffer failed");
551         }
552     } else {
553         NAPI_ERR_LOG("Could not get the string argument!");
554         err = true;
555     }
556 }
557 
ConvertJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],AlbumNapiAsyncContext & asyncContext)558 static napi_value ConvertJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
559     AlbumNapiAsyncContext &asyncContext)
560 {
561     string str = "";
562     std::vector<string> strArr;
563     string order = "";
564     bool err = false;
565     const int32_t refCount = 1;
566     napi_value result;
567     auto context = &asyncContext;
568     CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
569     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
570 
571     for (size_t i = PARAM0; i < argc; i++) {
572         napi_valuetype valueType = napi_undefined;
573         napi_typeof(env, argv[i], &valueType);
574 
575         if (i == PARAM0 && valueType == napi_object) {
576             GetFetchOptionsParam(env, argv[PARAM0], asyncContext, err);
577             if (err) {
578                 NAPI_ASSERT(env, false, "type mismatch");
579             }
580         } else if (i == PARAM0 && valueType == napi_function) {
581             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
582             break;
583         } else if (i == PARAM1 && valueType == napi_function) {
584             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
585             break;
586         } else {
587             NAPI_ASSERT(env, false, "type mismatch");
588         }
589     }
590 
591     // Return true napi_value if params are successfully obtained
592     napi_get_boolean(env, true, &result);
593     return result;
594 }
ConvertCommitJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],AlbumNapiAsyncContext & asyncContext)595 static napi_value ConvertCommitJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
596     AlbumNapiAsyncContext &asyncContext)
597 {
598     string str = "";
599     vector<string> strArr;
600     string order = "";
601     bool err = false;
602     const int32_t refCount = 1;
603     napi_value result;
604     auto context = &asyncContext;
605     CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
606     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
607 
608     for (size_t i = PARAM0; i < argc; i++) {
609         napi_valuetype valueType = napi_undefined;
610         napi_typeof(env, argv[i], &valueType);
611 
612         if (i == PARAM0 && valueType == napi_object) {
613             GetFetchOptionsParam(env, argv[PARAM0], asyncContext, err);
614             if (err) {
615                 NAPI_ERR_LOG("fetch options retrieval failed. err %{public}d", err);
616                 NAPI_ASSERT(env, false, "type mismatch");
617             }
618         } else if (i == PARAM0 && valueType == napi_function) {
619             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
620             break;
621         } else if (i == PARAM1 && valueType == napi_function) {
622             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
623             break;
624         } else {
625             NAPI_ASSERT(env, false, "type mismatch");
626         }
627     }
628 
629     // Return true napi_value if params are successfully obtained
630     napi_get_boolean(env, true, &result);
631     return result;
632 }
633 
UpdateSelection(AlbumNapiAsyncContext * context)634 static void UpdateSelection(AlbumNapiAsyncContext *context)
635 {
636     if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
637         context->predicates.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, 0);
638         context->predicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_TYPE_ALBUM);
639         context->predicates.EqualTo(MEDIA_DATA_DB_BUCKET_ID, context->objectPtr->GetAlbumId());
640         MediaLibraryNapiUtils::UpdateMediaTypeSelections(context);
641     } else {
642         string trashPrefix = MEDIA_DATA_DB_DATE_TRASHED + " = ? ";
643         MediaLibraryNapiUtils::AppendFetchOptionSelection(context->selection, trashPrefix);
644         context->selectionArgs.emplace_back("0");
645 
646         string prefix = MEDIA_DATA_DB_MEDIA_TYPE + " <> ? ";
647         MediaLibraryNapiUtils::AppendFetchOptionSelection(context->selection, prefix);
648         context->selectionArgs.emplace_back(to_string(MEDIA_TYPE_ALBUM));
649 
650         string idPrefix = MEDIA_DATA_DB_BUCKET_ID + " = ? ";
651         MediaLibraryNapiUtils::AppendFetchOptionSelection(context->selection, idPrefix);
652         context->selectionArgs.emplace_back(std::to_string(context->objectPtr->GetAlbumId()));
653     }
654 }
655 
GetFileAssetsNative(napi_env env,void * data)656 static void GetFileAssetsNative(napi_env env, void *data)
657 {
658     MediaLibraryTracer tracer;
659     tracer.Start("GetFileAssetsNative");
660 
661     AlbumNapiAsyncContext *context = static_cast<AlbumNapiAsyncContext*>(data);
662     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
663 
664     UpdateSelection(context);
665     context->predicates.SetWhereClause(context->selection);
666     context->predicates.SetWhereArgs(context->selectionArgs);
667     context->predicates.SetOrder(context->order);
668     if (context->fetchColumn.size() == 0) {
669         context->fetchColumn.push_back("*");
670     }
671     string queryUri = MEDIALIBRARY_DATA_ABILITY_PREFIX +
672         (MediaFileUtils::GetNetworkIdFromUri(context->objectPtr->GetAlbumUri())) + MEDIALIBRARY_DATA_URI_IDENTIFIER;
673     MediaLibraryNapiUtils::UriAddFragmentTypeMask(queryUri, context->typeMask);
674     NAPI_DEBUG_LOG("queryUri is = %{public}s", queryUri.c_str());
675     Uri uri(queryUri);
676     std::shared_ptr<OHOS::DataShare::DataShareResultSet> resultSet =
677         UserFileClient::Query(uri, context->predicates, context->fetchColumn);
678     context->fetchResult = std::make_unique<FetchResult<FileAsset>>(move(resultSet));
679     context->fetchResult->networkId_ = MediaFileUtils::GetNetworkIdFromUri(context->objectPtr->GetAlbumUri());
680     if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
681         context->fetchResult->resultNapiType_ = context->resultNapiType;
682     }
683 }
684 
JSGetFileAssetsCompleteCallback(napi_env env,napi_status status,void * data)685 static void JSGetFileAssetsCompleteCallback(napi_env env, napi_status status, void*data)
686 {
687     MediaLibraryTracer tracer;
688     tracer.Start("JSGetFileAssetsCompleteCallback");
689 
690     AlbumNapiAsyncContext *context = static_cast<AlbumNapiAsyncContext*>(data);
691     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
692 
693     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
694     jsContext->status = false;
695     if (context->fetchResult != nullptr) {
696         if (context->fetchResult->GetCount() < 0) {
697             napi_get_undefined(env, &jsContext->data);
698             MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
699                                                          "find no data by options");
700         } else {
701             napi_value fetchRes = FetchFileResultNapi::CreateFetchFileResult(env, move(context->fetchResult));
702             if (fetchRes == nullptr) {
703                 NAPI_ERR_LOG("Failed to get file asset napi object");
704                 napi_get_undefined(env, &jsContext->data);
705                 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
706                     "Failed to create js object for FetchFileResult");
707             } else {
708                 jsContext->data = fetchRes;
709                 napi_get_undefined(env, &jsContext->error);
710                 jsContext->status = true;
711             }
712         }
713     } else {
714         NAPI_ERR_LOG("No fetch file result found!");
715         napi_get_undefined(env, &jsContext->data);
716         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
717                                                      "Failed to obtain fetchFileResult from DB");
718     }
719 
720     tracer.Finish();
721     if (context->work != nullptr) {
722         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
723                                                    context->work, *jsContext);
724     }
725     delete context;
726 }
727 
CommitModifyNative(napi_env env,void * data)728 static void CommitModifyNative(napi_env env, void *data)
729 {
730     MediaLibraryTracer tracer;
731     tracer.Start("CommitModifyNative");
732 
733     auto *context = static_cast<AlbumNapiAsyncContext*>(data);
734     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
735     auto objectPtr = context->objectPtr;
736     if (!MediaFileUtils::CheckTitle(objectPtr->GetAlbumName())) {
737         context->error = JS_E_DISPLAYNAME;
738         NAPI_ERR_LOG("album name invalid = %{public}s", objectPtr->GetAlbumName().c_str());
739         return;
740     }
741 
742     DataSharePredicates predicates;
743     DataShareValuesBucket valuesBucket;
744     valuesBucket.Put(MEDIA_DATA_DB_TITLE, objectPtr->GetAlbumName());
745     predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
746     predicates.SetWhereArgs({ std::to_string(objectPtr->GetAlbumId()) });
747 
748     string updateUri = MEDIALIBRARY_DATA_URI;
749     MediaLibraryNapiUtils::UriAddFragmentTypeMask(updateUri, context->typeMask);
750     Uri uri(updateUri);
751     int changedRows = UserFileClient::Update(uri, predicates, valuesBucket);
752     if (changedRows > 0) {
753         DataSharePredicates filePredicates;
754         DataShareValuesBucket fileValuesBucket;
755         fileValuesBucket.Put(MEDIA_DATA_DB_BUCKET_NAME, objectPtr->GetAlbumName());
756         filePredicates.SetWhereClause(MEDIA_DATA_DB_BUCKET_ID + " = ? ");
757         filePredicates.SetWhereArgs({ std::to_string(objectPtr->GetAlbumId()) });
758 
759         string fileUriStr = MEDIALIBRARY_DATA_URI;
760         MediaLibraryNapiUtils::UriAddFragmentTypeMask(fileUriStr, context->typeMask);
761         Uri fileUri(fileUriStr);
762         changedRows = UserFileClient::Update(fileUri, filePredicates, fileValuesBucket);
763     }
764     context->SaveError(changedRows);
765     context->changedRows = changedRows;
766 }
767 
JSCommitModifyCompleteCallback(napi_env env,napi_status status,void * data)768 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, void *data)
769 {
770     MediaLibraryTracer tracer;
771     tracer.Start("JSCommitModifyCompleteCallback");
772 
773     AlbumNapiAsyncContext *context = static_cast<AlbumNapiAsyncContext*>(data);
774     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
775     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
776     jsContext->status = false;
777     if (context->error == ERR_DEFAULT) {
778         napi_create_int32(env, context->changedRows, &jsContext->data);
779         napi_get_undefined(env, &jsContext->error);
780         jsContext->status = true;
781         auto contextUri = make_unique<Uri>(MEDIALIBRARY_ALBUM_URI);
782         UserFileClient::NotifyChange(*contextUri);
783     } else {
784         napi_get_undefined(env, &jsContext->data);
785         context->HandleError(env, jsContext->error);
786     }
787 
788     tracer.Finish();
789     if (context->work != nullptr) {
790         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
791                                                    context->work, *jsContext);
792     }
793 
794     delete context;
795 }
JSGetAlbumFileAssets(napi_env env,napi_callback_info info)796 napi_value AlbumNapi::JSGetAlbumFileAssets(napi_env env, napi_callback_info info)
797 {
798     napi_status status;
799     napi_value result = nullptr;
800     size_t argc = ARGS_TWO;
801     napi_value argv[ARGS_TWO] = {0};
802     napi_value thisVar = nullptr;
803 
804     MediaLibraryTracer tracer;
805     tracer.Start("JSGetAlbumFileAssets");
806 
807     GET_JS_ARGS(env, info, argc, argv, thisVar);
808     NAPI_ASSERT(env, ((argc == ARGS_ZERO) || (argc == ARGS_ONE) || (argc == ARGS_TWO)),
809                 "requires 2 parameter maximum");
810     napi_get_undefined(env, &result);
811 
812     std::unique_ptr<AlbumNapiAsyncContext> asyncContext = std::make_unique<AlbumNapiAsyncContext>();
813     asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
814     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
815     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
816         result = ConvertJSArgsToNative(env, argc, argv, *asyncContext);
817         CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "Failed to obtain arguments");
818         asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
819         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "AlbumAsset is nullptr");
820 
821         result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetAlbumFileAssets",
822             GetFileAssetsNative, JSGetFileAssetsCompleteCallback);
823     }
824 
825     return result;
826 }
JSCommitModify(napi_env env,napi_callback_info info)827 napi_value AlbumNapi::JSCommitModify(napi_env env, napi_callback_info info)
828 {
829     napi_status status;
830     napi_value result = nullptr;
831     size_t argc = ARGS_ONE;
832     napi_value argv[ARGS_ONE] = {0};
833     napi_value thisVar = nullptr;
834 
835     MediaLibraryTracer tracer;
836     tracer.Start("JSCommitModify");
837 
838     GET_JS_ARGS(env, info, argc, argv, thisVar);
839     NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameter maximum");
840     napi_get_undefined(env, &result);
841 
842     std::unique_ptr<AlbumNapiAsyncContext> asyncContext = std::make_unique<AlbumNapiAsyncContext>();
843     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
844     asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
845     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
846     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
847         result = ConvertCommitJSArgsToNative(env, argc, argv, *asyncContext);
848         CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "JSCommitModify fail ");
849         asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
850         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "AlbumAsset is nullptr");
851 
852         result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", CommitModifyNative,
853             JSCommitModifyCompleteCallback);
854     }
855 
856     return result;
857 }
858 
UserFileMgrGetAssets(napi_env env,napi_callback_info info)859 napi_value AlbumNapi::UserFileMgrGetAssets(napi_env env, napi_callback_info info)
860 {
861     napi_value ret = nullptr;
862     unique_ptr<AlbumNapiAsyncContext> asyncContext = make_unique<AlbumNapiAsyncContext>();
863     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
864 
865     asyncContext->mediaTypes.push_back(MEDIA_TYPE_IMAGE);
866     asyncContext->mediaTypes.push_back(MEDIA_TYPE_VIDEO);
867     CHECK_ARGS(env, MediaLibraryNapiUtils::ParseAssetFetchOptCallback(env, info, asyncContext), asyncContext,
868         JS_ERR_PARAMETER_INVALID);
869     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
870     asyncContext->typeMask = asyncContext->objectInfo->GetTypeMask();
871     asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
872     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "AlbumAsset is nullptr");
873 
874     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrGetAssets", GetFileAssetsNative,
875         JSGetFileAssetsCompleteCallback);
876 }
877 
UserFileMgrCommitModify(napi_env env,napi_callback_info info)878 napi_value AlbumNapi::UserFileMgrCommitModify(napi_env env, napi_callback_info info)
879 {
880     MediaLibraryTracer tracer;
881     tracer.Start("UserFileMgrCommitModify");
882 
883     napi_value ret = nullptr;
884     unique_ptr<AlbumNapiAsyncContext> asyncContext = make_unique<AlbumNapiAsyncContext>();
885     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
886     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
887     CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext), asyncContext,
888         JS_ERR_PARAMETER_INVALID);
889     asyncContext->typeMask = asyncContext->objectInfo->GetTypeMask();
890     asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
891     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "AlbumAsset is nullptr");
892 
893     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrCommitModify", CommitModifyNative,
894         JSCommitModifyCompleteCallback);
895 }
896 } // namespace Media
897 } // namespace OHOS
898