• 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 "SmartAlbumNapi"
16 
17 #include "smart_album_napi.h"
18 
19 #include "media_file_asset_columns.h"
20 #include "media_library_napi.h"
21 #include "media_smart_album_column.h"
22 #include "media_smart_map_column.h"
23 #include "medialibrary_client_errno.h"
24 #include "medialibrary_napi_log.h"
25 #include "medialibrary_tracer.h"
26 #include "media_file_utils.h"
27 #include "userfile_client.h"
28 #include "media_file_uri.h"
29 
30 using OHOS::HiviewDFX::HiLog;
31 using OHOS::HiviewDFX::HiLogLabel;
32 
33 namespace OHOS {
34 namespace Media {
35 using namespace std;
36 thread_local napi_ref SmartAlbumNapi::sConstructor_ = nullptr;
37 thread_local SmartAlbumAsset *SmartAlbumNapi::sAlbumData_ = nullptr;
38 using CompleteCallback = napi_async_complete_callback;
39 thread_local napi_ref SmartAlbumNapi::userFileMgrConstructor_ = nullptr;
40 constexpr int32_t INVALID_EXPIREDTIME = -1;
SmartAlbumNapi()41 SmartAlbumNapi::SmartAlbumNapi()
42     : env_(nullptr) {}
43 
44 SmartAlbumNapi::~SmartAlbumNapi() = default;
45 
SmartAlbumNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)46 void SmartAlbumNapi::SmartAlbumNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
47 {
48     SmartAlbumNapi *album = reinterpret_cast<SmartAlbumNapi*>(nativeObject);
49     if (album != nullptr) {
50         delete album;
51         album = nullptr;
52     }
53 }
54 
Init(napi_env env,napi_value exports)55 napi_value SmartAlbumNapi::Init(napi_env env, napi_value exports)
56 {
57     napi_status status;
58     napi_value ctorObj;
59     int32_t refCount = 1;
60 
61     napi_property_descriptor album_props[] = {
62         DECLARE_NAPI_GETTER("albumId", JSGetSmartAlbumId),
63         DECLARE_NAPI_GETTER("albumUri", JSGetSmartAlbumUri),
64         DECLARE_NAPI_GETTER("albumType", JSGetSmartAlbumType),
65         DECLARE_NAPI_GETTER_SETTER("albumName", JSGetSmartAlbumName, JSSmartAlbumNameSetter),
66         DECLARE_NAPI_GETTER_SETTER("description", JSGetSmartAlbumDescription, JSSmartAlbumDescriptionSetter),
67         DECLARE_NAPI_GETTER("albumTag", JSGetSmartAlbumTag),
68         DECLARE_NAPI_GETTER("size", JSGetSmartAlbumCapacity),
69         DECLARE_NAPI_GETTER("categoryId", JSGetSmartAlbumCategoryId),
70         DECLARE_NAPI_GETTER("categoryName", JSGetSmartAlbumCategoryName),
71         DECLARE_NAPI_GETTER_SETTER("coverURI", JSGetSmartAlbumCoverUri, JSSmartAlbumCoverUriSetter),
72         DECLARE_NAPI_GETTER_SETTER("expiredTime", JSGetSmartAlbumExpiredTime, JSSmartAlbumExpiredTimeSetter),
73         DECLARE_NAPI_FUNCTION("commitModify", JSCommitModify),
74         DECLARE_NAPI_FUNCTION("addFileAssets", JSAddFileAssets),
75         DECLARE_NAPI_FUNCTION("removeFileAssets", JSRemoveFileAssets),
76         DECLARE_NAPI_FUNCTION("getFileAssets", JSGetSmartAlbumFileAssets)
77     };
78 
79     status = napi_define_class(env, SMART_ALBUM_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
80                                SmartAlbumNapiConstructor, nullptr,
81                                sizeof(album_props) / sizeof(album_props[PARAM0]),
82                                album_props, &ctorObj);
83     if (status == napi_ok) {
84         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
85         if (status == napi_ok) {
86             status = napi_set_named_property(env, exports, SMART_ALBUM_NAPI_CLASS_NAME.c_str(), ctorObj);
87             if (status == napi_ok) {
88                 return exports;
89             }
90         }
91     }
92     NAPI_DEBUG_LOG("SmartAlbumNapi::Init nullptr, status: %{public}d", status);
93     return nullptr;
94 }
95 
UserFileMgrInit(napi_env env,napi_value exports)96 napi_value SmartAlbumNapi::UserFileMgrInit(napi_env env, napi_value exports)
97 {
98     NapiClassInfo info = {
99         .name = USERFILEMGR_SMART_ALBUM_NAPI_CLASS_NAME,
100         .ref = &userFileMgrConstructor_,
101         .constructor = SmartAlbumNapiConstructor,
102         .props = {
103             DECLARE_NAPI_GETTER_SETTER("albumName", JSGetSmartAlbumName, JSSmartAlbumNameSetter),
104             DECLARE_NAPI_GETTER("albumUri", JSGetSmartAlbumUri),
105             DECLARE_NAPI_GETTER("dateModified", JSGetSmartAlbumDateModified),
106             DECLARE_NAPI_GETTER("count", JSGetSmartAlbumCapacity),
107             DECLARE_NAPI_GETTER("coverUri", JSGetSmartAlbumCoverUri),
108             DECLARE_NAPI_FUNCTION("getPhotoAssets", UserFileMgrGetAssets),
109             DECLARE_NAPI_FUNCTION("delete", UserFileMgrDeleteAsset),
110             DECLARE_NAPI_FUNCTION("recover", UserFileMgrRecoverAsset),
111         }
112     };
113 
114     MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
115     return exports;
116 }
117 
SetSmartAlbumNapiProperties()118 void SmartAlbumNapi::SetSmartAlbumNapiProperties()
119 {
120     smartAlbumAssetPtr = std::shared_ptr<SmartAlbumAsset>(sAlbumData_);
121     NAPI_INFO_LOG("SetSmartAlbumNapiProperties name = %{public}s",
122         smartAlbumAssetPtr->GetAlbumName().c_str());
123 }
124 
125 // Constructor callback
SmartAlbumNapiConstructor(napi_env env,napi_callback_info info)126 napi_value SmartAlbumNapi::SmartAlbumNapiConstructor(napi_env env, napi_callback_info info)
127 {
128     napi_status status;
129     napi_value result = nullptr;
130     napi_value thisVar = nullptr;
131     napi_get_undefined(env, &result);
132     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
133     if (status == napi_ok && thisVar != nullptr) {
134         std::unique_ptr<SmartAlbumNapi> obj = std::make_unique<SmartAlbumNapi>();
135         if (obj != nullptr) {
136             obj->env_ = env;
137             if (sAlbumData_ != nullptr) {
138                 obj->SetSmartAlbumNapiProperties();
139             }
140             status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
141                                SmartAlbumNapi::SmartAlbumNapiDestructor, 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         }
149     }
150 
151     return result;
152 }
153 
CreateSmartAlbumNapi(napi_env env,unique_ptr<SmartAlbumAsset> & albumData)154 napi_value SmartAlbumNapi::CreateSmartAlbumNapi(napi_env env, unique_ptr<SmartAlbumAsset> &albumData)
155 {
156     if (albumData == nullptr) {
157         return nullptr;
158     }
159 
160     napi_value constructor;
161     napi_ref constructorRef = (albumData->GetResultNapiType() == ResultNapiType::TYPE_MEDIALIBRARY) ?
162         (sConstructor_) : (userFileMgrConstructor_);
163     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
164 
165     napi_value result = nullptr;
166     sAlbumData_ = albumData.release();
167     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
168     sAlbumData_ = nullptr;
169     return result;
170 }
171 
GetSmartAlbumName() const172 std::string SmartAlbumNapi::GetSmartAlbumName() const
173 {
174     return smartAlbumAssetPtr->GetAlbumName();
175 }
176 
GetAlbumPrivateType() const177 int32_t SmartAlbumNapi::GetAlbumPrivateType() const
178 {
179     return smartAlbumAssetPtr->GetAlbumPrivateType();
180 }
181 
GetSmartAlbumUri() const182 std::string SmartAlbumNapi::GetSmartAlbumUri() const
183 {
184     return smartAlbumAssetPtr->GetAlbumUri();
185 }
186 
GetSmartAlbumId() const187 int32_t SmartAlbumNapi::GetSmartAlbumId() const
188 {
189     return smartAlbumAssetPtr->GetAlbumId();
190 }
GetDescription() const191 std::string SmartAlbumNapi::GetDescription() const
192 {
193     return smartAlbumAssetPtr->GetDescription();
194 }
195 
GetCoverUri() const196 std::string SmartAlbumNapi::GetCoverUri() const
197 {
198     return smartAlbumAssetPtr->GetCoverUri();
199 }
200 
GetExpiredTime() const201 int32_t SmartAlbumNapi::GetExpiredTime() const
202 {
203     return smartAlbumAssetPtr->GetExpiredTime();
204 }
205 
SetAlbumCapacity(int32_t albumCapacity)206 void SmartAlbumNapi::SetAlbumCapacity(int32_t albumCapacity)
207 {
208     smartAlbumAssetPtr->SetAlbumCapacity(albumCapacity);
209 }
210 
GetNetworkId() const211 std::string SmartAlbumNapi::GetNetworkId() const
212 {
213     return MediaFileUtils::GetNetworkIdFromUri(GetSmartAlbumUri());
214 }
215 
SetCoverUri(string & coverUri)216 void SmartAlbumNapi::SetCoverUri(string &coverUri)
217 {
218     smartAlbumAssetPtr->SetCoverUri(coverUri);
219 }
220 
SetDescription(string & description)221 void SmartAlbumNapi::SetDescription(string &description)
222 {
223     smartAlbumAssetPtr->SetDescription(description);
224 }
225 
SetExpiredTime(int32_t expiredTime)226 void SmartAlbumNapi::SetExpiredTime(int32_t expiredTime)
227 {
228     smartAlbumAssetPtr->SetExpiredTime(expiredTime);
229 }
230 
JSGetSmartAlbumId(napi_env env,napi_callback_info info)231 napi_value SmartAlbumNapi::JSGetSmartAlbumId(napi_env env, napi_callback_info info)
232 {
233     napi_status status;
234     napi_value jsResult = nullptr;
235     napi_value undefinedResult = nullptr;
236     SmartAlbumNapi* obj = nullptr;
237     int32_t id;
238     napi_value thisVar = nullptr;
239 
240     napi_get_undefined(env, &undefinedResult);
241     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
242     if ((status != napi_ok) || (thisVar == nullptr)) {
243         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
244         return undefinedResult;
245     }
246 
247     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
248     if ((status == napi_ok) && (obj != nullptr)) {
249         id = obj->GetSmartAlbumId();
250         status = napi_create_int32(env, id, &jsResult);
251         if (status == napi_ok) {
252             return jsResult;
253         }
254     }
255 
256     return undefinedResult;
257 }
258 
JSGetSmartAlbumName(napi_env env,napi_callback_info info)259 napi_value SmartAlbumNapi::JSGetSmartAlbumName(napi_env env, napi_callback_info info)
260 {
261     napi_status status;
262     napi_value jsResult = nullptr;
263     napi_value undefinedResult = nullptr;
264     SmartAlbumNapi* obj = nullptr;
265     std::string name = "";
266     napi_value thisVar = nullptr;
267     napi_get_undefined(env, &undefinedResult);
268     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
269     if ((status != napi_ok) || (thisVar == nullptr)) {
270         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
271         return undefinedResult;
272     }
273     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
274     if ((status == napi_ok) && (obj != nullptr)) {
275         name = obj->GetSmartAlbumName();
276         NAPI_DEBUG_LOG("JSGetSmartAlbumName name = %{private}s", name.c_str());
277         status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &jsResult);
278         if (status == napi_ok) {
279             return jsResult;
280         }
281     }
282 
283     return undefinedResult;
284 }
285 
JSSmartAlbumNameSetter(napi_env env,napi_callback_info info)286 napi_value SmartAlbumNapi::JSSmartAlbumNameSetter(napi_env env, napi_callback_info info)
287 {
288     napi_status status;
289     napi_value jsResult = nullptr;
290     size_t argc = ARGS_ONE;
291     napi_value argv[ARGS_ONE] = {0};
292     size_t res = 0;
293     char buffer[FILENAME_MAX];
294     SmartAlbumNapi* obj = nullptr;
295     napi_value thisVar = nullptr;
296     napi_valuetype valueType = napi_undefined;
297 
298     napi_get_undefined(env, &jsResult);
299     GET_JS_ARGS(env, info, argc, argv, thisVar);
300     NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
301 
302     if (thisVar == nullptr || napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
303         NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
304         return jsResult;
305     }
306 
307     napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
308 
309     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
310     if (status == napi_ok && obj != nullptr) {
311         obj->smartAlbumAssetPtr->SetAlbumName(std::string(buffer));
312     }
313 
314     return jsResult;
315 }
316 
JSGetSmartAlbumTag(napi_env env,napi_callback_info info)317 napi_value SmartAlbumNapi::JSGetSmartAlbumTag(napi_env env, napi_callback_info info)
318 {
319     napi_status status;
320     napi_value jsResult = nullptr;
321     napi_value undefinedResult = nullptr;
322     SmartAlbumNapi* obj = nullptr;
323     std::string albumTag = "";
324     napi_value thisVar = nullptr;
325 
326     napi_get_undefined(env, &undefinedResult);
327     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
328     if ((status != napi_ok) || (thisVar == nullptr)) {
329         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
330         return undefinedResult;
331     }
332 
333     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
334     if (status == napi_ok && obj != nullptr) {
335         albumTag = obj->smartAlbumAssetPtr->GetAlbumTag();
336         status = napi_create_string_utf8(env, albumTag.c_str(), NAPI_AUTO_LENGTH, &jsResult);
337         if (status == napi_ok) {
338             return jsResult;
339         }
340     }
341 
342     return undefinedResult;
343 }
344 
JSGetSmartAlbumCapacity(napi_env env,napi_callback_info info)345 napi_value SmartAlbumNapi::JSGetSmartAlbumCapacity(napi_env env, napi_callback_info info)
346 {
347     napi_status status;
348     napi_value jsResult = nullptr;
349     napi_value undefinedResult = nullptr;
350     SmartAlbumNapi* obj = nullptr;
351     int32_t albumCapacity;
352     napi_value thisVar = nullptr;
353 
354     napi_get_undefined(env, &undefinedResult);
355     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
356     if ((status != napi_ok) || (thisVar == nullptr)) {
357         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
358         return undefinedResult;
359     }
360 
361     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
362     if (status == napi_ok && obj != nullptr) {
363         albumCapacity = obj->smartAlbumAssetPtr->GetAlbumCapacity();
364         status = napi_create_int32(env, albumCapacity, &jsResult);
365         if (status == napi_ok) {
366             return jsResult;
367         }
368     }
369 
370     return undefinedResult;
371 }
372 
JSGetSmartAlbumCategoryId(napi_env env,napi_callback_info info)373 napi_value SmartAlbumNapi::JSGetSmartAlbumCategoryId(napi_env env, napi_callback_info info)
374 {
375     napi_status status;
376     napi_value jsResult = nullptr;
377     napi_value undefinedResult = nullptr;
378     SmartAlbumNapi* obj = nullptr;
379     int32_t categoryId;
380     napi_value thisVar = nullptr;
381 
382     napi_get_undefined(env, &undefinedResult);
383     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
384     if ((status != napi_ok) || (thisVar == nullptr)) {
385         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
386         return undefinedResult;
387     }
388 
389     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
390     if (status == napi_ok && obj != nullptr) {
391         categoryId = obj->smartAlbumAssetPtr->GetCategoryId();
392         status = napi_create_int32(env, categoryId, &jsResult);
393         if (status == napi_ok) {
394             return jsResult;
395         }
396     }
397 
398     return undefinedResult;
399 }
400 
JSGetSmartAlbumCategoryName(napi_env env,napi_callback_info info)401 napi_value SmartAlbumNapi::JSGetSmartAlbumCategoryName(napi_env env, napi_callback_info info)
402 {
403     napi_status status;
404     napi_value jsResult = nullptr;
405     napi_value undefinedResult = nullptr;
406     SmartAlbumNapi* obj = nullptr;
407     std::string categoryName = "";
408     napi_value thisVar = nullptr;
409 
410     napi_get_undefined(env, &undefinedResult);
411     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
412     if ((status != napi_ok) || (thisVar == nullptr)) {
413         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
414         return undefinedResult;
415     }
416 
417     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
418     if (status == napi_ok && obj != nullptr) {
419         categoryName = obj->smartAlbumAssetPtr->GetCategoryName();
420         status = napi_create_string_utf8(env, categoryName.c_str(), NAPI_AUTO_LENGTH, &jsResult);
421         if (status == napi_ok) {
422             return jsResult;
423         }
424     }
425 
426     return undefinedResult;
427 }
428 
JSGetSmartAlbumCoverUri(napi_env env,napi_callback_info info)429 napi_value SmartAlbumNapi::JSGetSmartAlbumCoverUri(napi_env env, napi_callback_info info)
430 {
431     napi_status status;
432     napi_value jsResult = nullptr;
433     napi_value undefinedResult = nullptr;
434     SmartAlbumNapi* obj = nullptr;
435     std::string coverUri = "";
436     napi_value thisVar = nullptr;
437 
438     napi_get_undefined(env, &undefinedResult);
439     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
440     if ((status != napi_ok) || (thisVar == nullptr)) {
441         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
442         return undefinedResult;
443     }
444 
445     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
446     if (status == napi_ok && obj != nullptr) {
447         coverUri = obj->smartAlbumAssetPtr->GetCoverUri();
448         status = napi_create_string_utf8(env, coverUri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
449         if (status == napi_ok) {
450             return jsResult;
451         }
452     }
453 
454     return undefinedResult;
455 }
456 
JSSmartAlbumCoverUriSetter(napi_env env,napi_callback_info info)457 napi_value SmartAlbumNapi::JSSmartAlbumCoverUriSetter(napi_env env, napi_callback_info info)
458 {
459     napi_value jsResult = nullptr;
460     napi_get_undefined(env, &jsResult);
461     napi_value argv[ARGS_ONE] = {0};
462     size_t argc = ARGS_ONE;
463     napi_value thisVar = nullptr;
464     GET_JS_ARGS(env, info, argc, argv, thisVar);
465     NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
466     napi_valuetype valueType = napi_undefined;
467     if (thisVar == nullptr || napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
468         NAPI_ERR_LOG("Invalid arguments type! valueType: %{private}d", valueType);
469         return jsResult;
470     }
471     SmartAlbumNapi* obj = nullptr;
472     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
473     if ((status != napi_ok) || (obj == nullptr)) {
474         NAPI_ERR_LOG("Unwrap object failed");
475         return jsResult;
476     }
477     size_t res = 0;
478     char buffer[FILENAME_MAX];
479     status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
480     if (status != napi_ok) {
481         NAPI_ERR_LOG("Get coverUri value string failed");
482         return jsResult;
483     }
484     obj->smartAlbumAssetPtr->SetCoverUri(std::string(buffer));
485     return jsResult;
486 }
487 
JSGetSmartAlbumUri(napi_env env,napi_callback_info info)488 napi_value SmartAlbumNapi::JSGetSmartAlbumUri(napi_env env, napi_callback_info info)
489 {
490     napi_value undefinedResult = nullptr;
491     napi_get_undefined(env, &undefinedResult);
492     napi_status status;
493     napi_value thisVar = nullptr;
494     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
495     if ((status != napi_ok) || (thisVar == nullptr)) {
496         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
497         return undefinedResult;
498     }
499     SmartAlbumNapi* obj = nullptr;
500     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
501     if ((status != napi_ok) || (obj == nullptr)) {
502         NAPI_ERR_LOG("Unwrap object failed");
503         return undefinedResult;
504     }
505     napi_value jsResult = nullptr;
506     status = napi_create_string_utf8(env, obj->smartAlbumAssetPtr->GetAlbumUri().c_str(), NAPI_AUTO_LENGTH, &jsResult);
507     if (status != napi_ok) {
508         NAPI_ERR_LOG("Create albumUri string failed");
509         return undefinedResult;
510     }
511     return jsResult;
512 }
513 
JSGetSmartAlbumDateModified(napi_env env,napi_callback_info info)514 napi_value SmartAlbumNapi::JSGetSmartAlbumDateModified(napi_env env, napi_callback_info info)
515 {
516     napi_status status;
517     napi_value undefinedResult = nullptr;
518     napi_value thisVar = nullptr;
519 
520     napi_get_undefined(env, &undefinedResult);
521     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
522     if ((status != napi_ok) || (thisVar == nullptr)) {
523         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
524         return undefinedResult;
525     }
526     SmartAlbumNapi* obj = nullptr;
527     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
528     if ((status == napi_ok) && (obj != nullptr)) {
529         int64_t dateModified = obj->smartAlbumAssetPtr->GetAlbumDateModified();
530         napi_value jsResult = nullptr;
531         status = napi_create_int64(env, dateModified, &jsResult);
532         if (status == napi_ok) {
533             return jsResult;
534         }
535     }
536     return undefinedResult;
537 }
538 
JSGetSmartAlbumType(napi_env env,napi_callback_info info)539 napi_value SmartAlbumNapi::JSGetSmartAlbumType(napi_env env, napi_callback_info info)
540 {
541     napi_value undefinedResult = nullptr;
542     napi_get_undefined(env, &undefinedResult);
543     napi_status status;
544     napi_value thisVar = nullptr;
545     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
546     if ((status != napi_ok) || (thisVar == nullptr)) {
547         NAPI_ERR_LOG("Invalid arguments! status: %{private}d", status);
548         return undefinedResult;
549     }
550     SmartAlbumNapi* obj = nullptr;
551     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
552     if ((status != napi_ok) || (obj == nullptr)) {
553         NAPI_ERR_LOG("Unwrap object failed");
554         return undefinedResult;
555     }
556     napi_value jsResult = nullptr;
557     status = napi_create_int32(env, obj->smartAlbumAssetPtr->GetAlbumPrivateType(), &jsResult);
558     if (status != napi_ok) {
559         NAPI_ERR_LOG("Create albumPrivateType int32 failed");
560         return undefinedResult;
561     }
562     return jsResult;
563 }
564 
JSGetSmartAlbumDescription(napi_env env,napi_callback_info info)565 napi_value SmartAlbumNapi::JSGetSmartAlbumDescription(napi_env env, napi_callback_info info)
566 {
567     napi_value undefinedResult = nullptr;
568     napi_get_undefined(env, &undefinedResult);
569     napi_status status;
570     napi_value thisVar = nullptr;
571     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
572     if ((status != napi_ok) || (thisVar == nullptr)) {
573         NAPI_ERR_LOG("Invalid arguments! status: %{private}d", status);
574         return undefinedResult;
575     }
576     SmartAlbumNapi* obj = nullptr;
577     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
578     if ((status != napi_ok) || (obj == nullptr)) {
579         NAPI_ERR_LOG("Unwrap object failed");
580         return undefinedResult;
581     }
582     napi_value jsResult = nullptr;
583     status = napi_create_string_utf8(env, obj->smartAlbumAssetPtr->GetDescription().c_str(), NAPI_AUTO_LENGTH,
584         &jsResult);
585     if (status != napi_ok) {
586         NAPI_ERR_LOG("Create description string failed");
587         return undefinedResult;
588     }
589     return jsResult;
590 }
591 
JSSmartAlbumDescriptionSetter(napi_env env,napi_callback_info info)592 napi_value SmartAlbumNapi::JSSmartAlbumDescriptionSetter(napi_env env, napi_callback_info info)
593 {
594     napi_value jsResult = nullptr;
595     napi_get_undefined(env, &jsResult);
596     size_t argc = ARGS_ONE;
597     napi_value argv[ARGS_ONE] = {0};
598     napi_value thisVar = nullptr;
599     GET_JS_ARGS(env, info, argc, argv, thisVar);
600     NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
601     napi_valuetype valueType = napi_undefined;
602     if (thisVar == nullptr || napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
603         NAPI_ERR_LOG("Invalid arguments type! valueType: %{private}d", valueType);
604         return jsResult;
605     }
606     SmartAlbumNapi* obj = nullptr;
607     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
608     if ((status != napi_ok) || (obj == nullptr)) {
609         NAPI_ERR_LOG("Unwrap object failed");
610         return jsResult;
611     }
612     size_t res = 0;
613     char buffer[FILENAME_MAX];
614     status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
615     if (status != napi_ok) {
616         NAPI_ERR_LOG("Get description value string failed");
617         return jsResult;
618     }
619     obj->smartAlbumAssetPtr->SetDescription(std::string(buffer));
620     return jsResult;
621 }
622 
JSGetSmartAlbumExpiredTime(napi_env env,napi_callback_info info)623 napi_value SmartAlbumNapi::JSGetSmartAlbumExpiredTime(napi_env env, napi_callback_info info)
624 {
625     napi_value undefinedResult = nullptr;
626     napi_get_undefined(env, &undefinedResult);
627     napi_status status;
628     napi_value thisVar = nullptr;
629     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
630     if ((status != napi_ok) || (thisVar == nullptr)) {
631         NAPI_ERR_LOG("Invalid arguments! status: %{private}d", status);
632         return undefinedResult;
633     }
634     SmartAlbumNapi* obj = nullptr;
635     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
636     if ((status != napi_ok) || (obj == nullptr)) {
637         NAPI_ERR_LOG("Unwrap object failed");
638         return undefinedResult;
639     }
640     napi_value jsResult = nullptr;
641     status = napi_create_int32(env, obj->smartAlbumAssetPtr->GetExpiredTime(), &jsResult);
642     if (status != napi_ok) {
643         NAPI_ERR_LOG("Create expiredTime int32 failed");
644         return undefinedResult;
645     }
646     return jsResult;
647 }
648 
JSSmartAlbumExpiredTimeSetter(napi_env env,napi_callback_info info)649 napi_value SmartAlbumNapi::JSSmartAlbumExpiredTimeSetter(napi_env env, napi_callback_info info)
650 {
651     napi_value undefinedResult = nullptr;
652     napi_get_undefined(env, &undefinedResult);
653     size_t argc = ARGS_ONE;
654     napi_value argv[ARGS_ONE] = {0};
655     napi_value thisVar = nullptr;
656     GET_JS_ARGS(env, info, argc, argv, thisVar);
657     NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
658     SmartAlbumNapi* obj = nullptr;
659     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
660     if ((status != napi_ok) || (obj == nullptr)) {
661         NAPI_ERR_LOG("Failed to get expiredTime obj");
662         return undefinedResult;
663     }
664     napi_valuetype valueType = napi_undefined;
665     if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_number) {
666         NAPI_ERR_LOG("Invalid arguments type! valueType: %{private}d", valueType);
667         obj->smartAlbumAssetPtr->SetExpiredTime(INVALID_EXPIREDTIME);
668         return undefinedResult;
669     }
670     int32_t expiredTime;
671     status = napi_get_value_int32(env, argv[PARAM0], &expiredTime);
672     if (status != napi_ok) {
673         NAPI_ERR_LOG("Failed to get expiredTime");
674         return undefinedResult;
675     }
676     obj->smartAlbumAssetPtr->SetExpiredTime(expiredTime);
677     return undefinedResult;
678 }
679 
CommitModifyNative(const SmartAlbumNapiAsyncContext & albumContext)680 static void CommitModifyNative(const SmartAlbumNapiAsyncContext &albumContext)
681 {
682     SmartAlbumNapiAsyncContext *context = const_cast<SmartAlbumNapiAsyncContext *>(&albumContext);
683     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
684     NAPI_DEBUG_LOG("CommitModifyNative = %{private}s", context->objectInfo->GetSmartAlbumName().c_str());
685     if (MediaFileUtils::CheckAlbumName(context->objectInfo->GetSmartAlbumName()) < 0) {
686         context->error = JS_E_DISPLAYNAME;
687         NAPI_ERR_LOG("Failed to checkDisplayName");
688         return;
689     }
690     DataShare::DataShareValuesBucket valuesBucket;
691     valuesBucket.Put(SMARTALBUM_DB_DESCRIPTION, context->objectInfo->GetDescription());
692     string coverUri = context->objectInfo->GetCoverUri();
693     if (coverUri.empty() || (coverUri.find(MEDIALIBRARY_MEDIA_PREFIX) == string::npos)) {
694         context->error = E_VIOLATION_PARAMETERS;
695         NAPI_ERR_LOG("CoverUri is invalid");
696         return;
697     }
698     valuesBucket.Put(SMARTALBUM_DB_COVER_URI, coverUri);
699     if (context->objectInfo->GetExpiredTime() < 0) {
700         context->error = E_VIOLATION_PARAMETERS;
701         NAPI_ERR_LOG("ExpiredTime is invalid");
702         return;
703     }
704     valuesBucket.Put(SMARTALBUM_DB_EXPIRED_TIME, context->objectInfo->GetExpiredTime());
705     DataShare::DataSharePredicates predicates;
706     predicates.SetWhereClause(SMARTALBUM_DB_ID + " = " + std::to_string(context->objectInfo->GetSmartAlbumId()));
707     Uri commitModifyUri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMOPRN + "/" + MEDIA_SMARTALBUMOPRN_MODIFYALBUM);
708     context->changedRows = UserFileClient::Update(commitModifyUri, predicates, valuesBucket);
709     context->SaveError(context->changedRows);
710 }
711 
JSAddAssetExecute(SmartAlbumNapiAsyncContext * context)712 static void JSAddAssetExecute(SmartAlbumNapiAsyncContext *context)
713 {
714     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
715     int32_t smartAlbumId = context->objectInfo->GetSmartAlbumId();
716     if ((smartAlbumId == TRASH_ALBUM_ID_VALUES) || (smartAlbumId == FAVOURITE_ALBUM_ID_VALUES)) {
717         context->error = E_INVALID_VALUES;
718         NAPI_ERR_LOG("SmartAlbumId is invalid, smartAlbumId = %{private}d", smartAlbumId);
719         return;
720     }
721     vector<DataShare::DataShareValuesBucket> values;
722     for (int32_t id : context->assetIds) {
723         DataShare::DataShareValuesBucket valuesBucket;
724         valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, smartAlbumId);
725         valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, id);
726         values.push_back(valuesBucket);
727     }
728     Uri addAssetUri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/" +
729         MEDIA_SMARTALBUMMAPOPRN_ADDSMARTALBUM);
730     context->changedRows = UserFileClient::BatchInsert(addAssetUri, values);
731     if (context->changedRows != static_cast<int32_t>(context->assetIds.size())) {
732         context->error = E_INVALID_VALUES;
733     }
734 }
735 
JSRemoveAssetExecute(SmartAlbumNapiAsyncContext * context)736 static void JSRemoveAssetExecute(SmartAlbumNapiAsyncContext *context)
737 {
738     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
739     int32_t smartAlbumId = context->objectInfo->GetSmartAlbumId();
740     if ((smartAlbumId == TRASH_ALBUM_ID_VALUES) || (smartAlbumId == FAVOURITE_ALBUM_ID_VALUES)) {
741         NAPI_ERR_LOG("SmartAlbumId is invalid, smartAlbumId = %{private}d", smartAlbumId);
742         context->error = E_INVALID_VALUES;
743         return;
744     }
745     vector<DataShare::DataShareValuesBucket> values;
746     for (int32_t id : context->assetIds) {
747         DataShare::DataShareValuesBucket valuesBucket;
748         valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, smartAlbumId);
749         valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, id);
750         values.push_back(valuesBucket);
751     }
752     Uri removeAssetUri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/" +
753         MEDIA_SMARTALBUMMAPOPRN_REMOVESMARTALBUM);
754     context->changedRows = UserFileClient::BatchInsert(removeAssetUri, values);
755     if (context->changedRows != static_cast<int32_t>(context->assetIds.size())) {
756         context->error = E_INVALID_VALUES;
757     }
758 }
759 
JSCommitModifyCompleteCallback(napi_env env,napi_status status,SmartAlbumNapiAsyncContext * context)760 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, SmartAlbumNapiAsyncContext *context)
761 {
762     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
763     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
764     jsContext->status = false;
765     if (context->error == ERR_DEFAULT) {
766         napi_create_int32(env, context->changedRows, &jsContext->data);
767         napi_get_undefined(env, &jsContext->error);
768         jsContext->status = true;
769     } else {
770         context->HandleError(env, jsContext->error);
771         napi_get_undefined(env, &jsContext->data);
772         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->error,
773                                                      "Failed to commit smart album");
774     }
775 
776     if (context->work != nullptr) {
777         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
778                                                    context->work, *jsContext);
779     }
780     delete context;
781 }
782 
JSAddAssetCompleteCallback(napi_env env,napi_status status,SmartAlbumNapiAsyncContext * context)783 static void JSAddAssetCompleteCallback(napi_env env, napi_status status, SmartAlbumNapiAsyncContext *context)
784 {
785     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
786     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
787     jsContext->status = false;
788     if (context->error == ERR_DEFAULT) {
789         napi_create_int32(env, context->changedRows, &jsContext->data);
790         napi_get_undefined(env, &jsContext->error);
791         jsContext->status = true;
792     } else {
793         context->HandleError(env, jsContext->error);
794         napi_get_undefined(env, &jsContext->data);
795         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error,  context->error,
796                                                      "Failed to add smartalbum asset");
797     }
798 
799     if (context->work != nullptr) {
800         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
801                                                    context->work, *jsContext);
802     }
803     delete context;
804 }
805 
JSRemoveAssetCompleteCallback(napi_env env,napi_status status,SmartAlbumNapiAsyncContext * context)806 static void JSRemoveAssetCompleteCallback(napi_env env, napi_status status, SmartAlbumNapiAsyncContext *context)
807 {
808     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
809     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
810     jsContext->status = false;
811 
812     if (context->error == ERR_DEFAULT) {
813         napi_create_int32(env, context->changedRows, &jsContext->data);
814         napi_get_undefined(env, &jsContext->error);
815         jsContext->status = true;
816     } else {
817         context->HandleError(env, jsContext->error);
818         napi_get_undefined(env, &jsContext->data);
819         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error,  context->error,
820                                                      "Failed to remove smartalbum asset");
821     }
822 
823     if (context->work != nullptr) {
824         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
825                                                    context->work, *jsContext);
826     }
827     delete context;
828 }
829 
ConvertCommitJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],SmartAlbumNapiAsyncContext & asyncContext)830 static napi_value ConvertCommitJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
831     SmartAlbumNapiAsyncContext &asyncContext)
832 {
833     const int32_t refCount = 1;
834     napi_value result;
835     auto context = &asyncContext;
836 
837     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
838 
839     for (size_t i = PARAM0; i < argc; i++) {
840         napi_valuetype valueType = napi_undefined;
841         napi_typeof(env, argv[i], &valueType);
842         if (i == PARAM0 && valueType == napi_function) {
843             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
844         } else {
845             NAPI_ASSERT(env, false, "type mismatch");
846         }
847     }
848 
849     // Return true napi_value if params are successfully obtained
850     napi_get_boolean(env, true, &result);
851     return result;
852 }
853 
GetAssetIds(napi_env env,napi_value param,SmartAlbumNapiAsyncContext & context)854 static napi_value GetAssetIds(napi_env env, napi_value param, SmartAlbumNapiAsyncContext &context)
855 {
856     uint32_t arraySize = 0;
857     if (!MediaLibraryNapiUtils::IsArrayForNapiValue(env, param, arraySize)) {
858         NAPI_ERR_LOG("GetAssetIds get args fail, not array");
859         return nullptr;
860     }
861     string uri = "";
862     for (uint32_t i = 0; i < arraySize; i++) {
863         napi_value jsValue = nullptr;
864         int32_t result;
865         if ((napi_get_element(env, param, i, &jsValue)) != napi_ok) {
866             NAPI_ERR_LOG("GetAssetIds get args fail");
867             return nullptr;
868         }
869         if (napi_get_value_int32(env, jsValue, &result) != napi_ok) {
870             NAPI_ERR_LOG("Get ids value fail");
871             return nullptr;
872         } else {
873             if (result < 0) {
874                 NAPI_ERR_LOG("GetAssetIds < 0 is invalid , id = %{public}d", result);
875                 return nullptr;
876             }
877             context.assetIds.push_back(result);
878         }
879     }
880     napi_value res;
881     napi_get_undefined(env, &res);
882     return res;
883 }
884 
GetJSArgsForAsset(napi_env env,size_t argc,const napi_value argv[],SmartAlbumNapiAsyncContext & asyncContext)885 napi_value GetJSArgsForAsset(napi_env env, size_t argc,
886                              const napi_value argv[],
887                              SmartAlbumNapiAsyncContext &asyncContext)
888 {
889     const int32_t refCount = 1;
890     napi_value result = nullptr;
891     auto context = &asyncContext;
892 
893     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
894 
895     for (size_t i = PARAM0; i < argc; i++) {
896         napi_valuetype valueType = napi_undefined;
897         napi_typeof(env, argv[i], &valueType);
898         if (i == PARAM0) {
899             napi_value res = GetAssetIds(env, argv[PARAM0], asyncContext);
900             if (res == nullptr) {
901                 napi_throw_error(env, std::to_string(ERR_INVALID_OUTPUT).c_str(), "Failed to obtain arguments ids");
902                 return nullptr;
903             }
904         } else if (i == PARAM1 && valueType == napi_function) {
905             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
906             break;
907         } else {
908             NAPI_ASSERT(env, false, "type mismatch");
909         }
910     }
911     // Return true napi_value if params are successfully obtained
912     napi_get_boolean(env, true, &result);
913     return result;
914 }
915 
JSAddFileAssets(napi_env env,napi_callback_info info)916 napi_value SmartAlbumNapi::JSAddFileAssets(napi_env env, napi_callback_info info)
917 {
918     napi_status status;
919     napi_value result = nullptr;
920     size_t argc = ARGS_TWO;
921     napi_value argv[ARGS_TWO] = {0};
922     napi_value thisVar = nullptr;
923     napi_value resource = nullptr;
924     GET_JS_ARGS(env, info, argc, argv, thisVar);
925     NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameter maximum");
926     napi_get_undefined(env, &result);
927     std::unique_ptr<SmartAlbumNapiAsyncContext> asyncContext = std::make_unique<SmartAlbumNapiAsyncContext>();
928 
929     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
930     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
931         result = GetJSArgsForAsset(env, argc, argv, *asyncContext);
932         CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "JSAddFileAssets fail");
933         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
934         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSAddFileAssets", asyncContext);
935 
936         asyncContext->objectPtr = asyncContext->objectInfo->smartAlbumAssetPtr;
937         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "SmartAlbumAsset is nullptr");
938 
939         status = napi_create_async_work(
940             env, nullptr, resource, [](napi_env env, void *data) {
941                 auto context = static_cast<SmartAlbumNapiAsyncContext*>(data);
942                 JSAddAssetExecute(context);
943             },
944             reinterpret_cast<CompleteCallback>(JSAddAssetCompleteCallback),
945             static_cast<void *>(asyncContext.get()), &asyncContext->work);
946         if (status != napi_ok) {
947             napi_get_undefined(env, &result);
948         } else {
949             napi_queue_async_work(env, asyncContext->work);
950             asyncContext.release();
951         }
952     }
953 
954     return result;
955 }
956 
JSRemoveFileAssets(napi_env env,napi_callback_info info)957 napi_value SmartAlbumNapi::JSRemoveFileAssets(napi_env env, napi_callback_info info)
958 {
959     napi_status status;
960     napi_value result = nullptr;
961     size_t argc = ARGS_TWO;
962     napi_value argv[ARGS_TWO] = {0};
963     napi_value thisVar = nullptr;
964     napi_value resource = nullptr;
965     GET_JS_ARGS(env, info, argc, argv, thisVar);
966     NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameter maximum");
967     napi_get_undefined(env, &result);
968     std::unique_ptr<SmartAlbumNapiAsyncContext> asyncContext = std::make_unique<SmartAlbumNapiAsyncContext>();
969 
970     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
971     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
972         result = GetJSArgsForAsset(env, argc, argv, *asyncContext);
973         CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "JSRemoveFileAssets fail ");
974 
975         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
976         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSRemoveFileAssets", asyncContext);
977 
978         asyncContext->objectPtr = asyncContext->objectInfo->smartAlbumAssetPtr;
979         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "SmartAlbumAsset is nullptr");
980 
981         status = napi_create_async_work(
982             env, nullptr, resource, [](napi_env env, void *data) {
983                 auto context = static_cast<SmartAlbumNapiAsyncContext*>(data);
984                 JSRemoveAssetExecute(context);
985             },
986             reinterpret_cast<CompleteCallback>(JSRemoveAssetCompleteCallback),
987             static_cast<void *>(asyncContext.get()), &asyncContext->work);
988         if (status != napi_ok) {
989             napi_get_undefined(env, &result);
990         } else {
991             napi_queue_async_work(env, asyncContext->work);
992             asyncContext.release();
993         }
994     }
995 
996     return result;
997 }
998 
JSCommitModify(napi_env env,napi_callback_info info)999 napi_value SmartAlbumNapi::JSCommitModify(napi_env env, napi_callback_info info)
1000 {
1001     napi_status status;
1002     napi_value result = nullptr;
1003     size_t argc = ARGS_ONE;
1004     napi_value argv[ARGS_ONE] = {0};
1005     napi_value thisVar = nullptr;
1006     napi_value resource = nullptr;
1007     GET_JS_ARGS(env, info, argc, argv, thisVar);
1008     NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameter maximum");
1009     napi_get_undefined(env, &result);
1010     std::unique_ptr<SmartAlbumNapiAsyncContext> asyncContext = std::make_unique<SmartAlbumNapiAsyncContext>();
1011 
1012     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1013     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1014         result = ConvertCommitJSArgsToNative(env, argc, argv, *asyncContext);
1015         CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "JSCommitModify fail ");
1016 
1017         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1018         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSCommitModify", asyncContext);
1019 
1020         asyncContext->objectPtr = asyncContext->objectInfo->smartAlbumAssetPtr;
1021         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "SmartAlbumAsset is nullptr");
1022 
1023         status = napi_create_async_work(
1024             env, nullptr, resource, [](napi_env env, void *data) {
1025                 auto context = static_cast<SmartAlbumNapiAsyncContext*>(data);
1026                 CommitModifyNative(*context);
1027             },
1028             reinterpret_cast<CompleteCallback>(JSCommitModifyCompleteCallback),
1029             static_cast<void *>(asyncContext.get()), &asyncContext->work);
1030         if (status != napi_ok) {
1031             napi_get_undefined(env, &result);
1032         } else {
1033             napi_queue_async_work(env, asyncContext->work);
1034             asyncContext.release();
1035         }
1036     }
1037 
1038     return result;
1039 }
1040 
GetFetchOptionsParam(napi_env env,napi_value arg,const SmartAlbumNapiAsyncContext & context,bool & err)1041 static void GetFetchOptionsParam(napi_env env, napi_value arg, const SmartAlbumNapiAsyncContext &context, bool &err)
1042 {
1043     SmartAlbumNapiAsyncContext *asyncContext = const_cast<SmartAlbumNapiAsyncContext *>(&context);
1044     CHECK_NULL_PTR_RETURN_VOID(asyncContext, "Async context is null");
1045     char buffer[PATH_MAX];
1046     size_t res;
1047     uint32_t len = 0;
1048     napi_value property = nullptr;
1049     napi_value stringItem = nullptr;
1050     bool present = false;
1051     bool boolResult = false;
1052 
1053     string propertyName = "selections";
1054     string tmp = MediaLibraryNapiUtils::GetStringFetchProperty(env, arg, err, present, propertyName);
1055     if (!tmp.empty()) {
1056         asyncContext->selection = tmp;
1057     }
1058 
1059     propertyName = "order";
1060     tmp = MediaLibraryNapiUtils::GetStringFetchProperty(env, arg, err, present, propertyName);
1061     if (!tmp.empty()) {
1062         asyncContext->order = tmp;
1063     }
1064 
1065     napi_has_named_property(env, arg, "selectionArgs", &present);
1066     if (present && napi_get_named_property(env, arg, "selectionArgs", &property) == napi_ok &&
1067         napi_is_array(env, property, &boolResult) == napi_ok && boolResult) {
1068         napi_get_array_length(env, property, &len);
1069         for (size_t i = 0; i < len; i++) {
1070             napi_get_element(env, property, i, &stringItem);
1071             napi_get_value_string_utf8(env, stringItem, buffer, PATH_MAX, &res);
1072             asyncContext->selectionArgs.push_back(std::string(buffer));
1073             CHECK_IF_EQUAL(memset_s(buffer, PATH_MAX, 0, sizeof(buffer)) == 0, "Memset for buffer failed");
1074         }
1075     } else {
1076         NAPI_ERR_LOG("Could not get the string argument!");
1077         err = true;
1078     }
1079 }
1080 
ConvertJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],SmartAlbumNapiAsyncContext & asyncContext)1081 static napi_value ConvertJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
1082     SmartAlbumNapiAsyncContext &asyncContext)
1083 {
1084     string str = "";
1085     std::vector<string> strArr;
1086     string order = "";
1087     bool err = false;
1088     const int32_t refCount = 1;
1089     napi_value result;
1090     auto context = &asyncContext;
1091 
1092     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1093 
1094     for (size_t i = PARAM0; i < argc; i++) {
1095         napi_valuetype valueType = napi_undefined;
1096         napi_typeof(env, argv[i], &valueType);
1097 
1098         if (i == PARAM0 && valueType == napi_object) {
1099             GetFetchOptionsParam(env, argv[PARAM0], asyncContext, err);
1100             if (err) {
1101                 NAPI_ASSERT(env, false, "type mismatch");
1102             }
1103         } else if (i == PARAM0 && valueType == napi_function) {
1104             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1105             break;
1106         } else if (i == PARAM1 && valueType == napi_function) {
1107             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1108             break;
1109         } else {
1110             NAPI_ASSERT(env, false, "type mismatch");
1111         }
1112     }
1113 
1114     // Return true napi_value if params are successfully obtained
1115     napi_get_boolean(env, true, &result);
1116     return result;
1117 }
1118 
UpdateSelection(SmartAlbumNapiAsyncContext * context)1119 static void UpdateSelection(SmartAlbumNapiAsyncContext *context)
1120 {
1121     if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
1122         context->predicates.EqualTo(SMARTALBUMMAP_DB_ALBUM_ID, context->objectPtr->GetAlbumId());
1123         context->predicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, to_string(0));
1124         if (context->objectPtr->GetAlbumId() == TRASH_ALBUM_ID_VALUES) {
1125             context->predicates.NotEqualTo(MEDIA_DATA_DB_DATE_TRASHED, "0");
1126         } else {
1127             context->predicates.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, "0");
1128         }
1129         MediaLibraryNapiUtils::UpdateMediaTypeSelections(context);
1130     } else {
1131         string trashPrefix;
1132         if (context->objectPtr->GetAlbumId() == TRASH_ALBUM_ID_VALUES) {
1133             trashPrefix = MEDIA_DATA_DB_DATE_TRASHED + " <> ? AND " + SMARTALBUMMAP_DB_ALBUM_ID + " = ? ";
1134         } else {
1135             trashPrefix = MEDIA_DATA_DB_DATE_TRASHED + " = ? AND " + SMARTALBUMMAP_DB_ALBUM_ID + " = ? ";
1136         }
1137         MediaLibraryNapiUtils::AppendFetchOptionSelection(context->selection, trashPrefix);
1138         context->selectionArgs.emplace_back("0");
1139         context->selectionArgs.emplace_back(std::to_string(context->objectPtr->GetAlbumId()));
1140         MediaLibraryNapi::ReplaceSelection(context->selection, context->selectionArgs,
1141             MEDIA_DATA_DB_RELATIVE_PATH, MEDIA_DATA_DB_RELATIVE_PATH, ReplaceSelectionMode::ADD_DOCS_TO_RELATIVE_PATH);
1142     }
1143 }
1144 
GetFileAssetsNative(napi_env env,void * data)1145 static void GetFileAssetsNative(napi_env env, void *data)
1146 {
1147     MediaLibraryTracer tracer;
1148     tracer.Start("GetFileAssetsNative");
1149 
1150     auto context = static_cast<SmartAlbumNapiAsyncContext *>(data);
1151     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1152 
1153     UpdateSelection(context);
1154     MediaLibraryNapiUtils::FixSpecialDateType(context->selection);
1155     context->predicates.SetWhereClause(context->selection);
1156     context->predicates.SetWhereArgs(context->selectionArgs);
1157     context->predicates.SetOrder(context->order);
1158 
1159     if (context->resultNapiType == ResultNapiType::TYPE_MEDIALIBRARY) {
1160         context->fetchColumn = FILE_ASSET_COLUMNS;
1161     } else {
1162         context->fetchColumn.push_back(MEDIA_DATA_DB_ID);
1163         context->fetchColumn.push_back(MEDIA_DATA_DB_NAME);
1164         context->fetchColumn.push_back(MEDIA_DATA_DB_MEDIA_TYPE);
1165     }
1166 
1167     string queryUri = MEDIALIBRARY_DATA_ABILITY_PREFIX +
1168         (MediaFileUtils::GetNetworkIdFromUri(context->objectPtr->GetAlbumUri())) +
1169         MEDIALIBRARY_DATA_URI_IDENTIFIER + "/" + MEDIA_ALBUMOPRN_QUERYALBUM + "/" + ASSETMAP_VIEW_NAME;
1170     Uri uri(queryUri);
1171     int errCode = 0;
1172     auto resultSet = UserFileClient::Query(uri, context->predicates, context->fetchColumn, errCode);
1173     if (resultSet == nullptr) {
1174         NAPI_ERR_LOG("resultSet == nullptr, errCode is %{public}d", errCode);
1175         return;
1176     }
1177     context->fetchResult = std::make_unique<FetchResult<FileAsset>>(move(resultSet));
1178     context->fetchResult->SetNetworkId(
1179         MediaFileUtils::GetNetworkIdFromUri(context->objectPtr->GetAlbumUri()));
1180     if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
1181         context->fetchResult->SetResultNapiType(context->resultNapiType);
1182     }
1183 }
1184 
JSGetFileAssetsCompleteCallback(napi_env env,napi_status status,void * data)1185 static void JSGetFileAssetsCompleteCallback(napi_env env, napi_status status, void *data)
1186 {
1187     MediaLibraryTracer tracer;
1188     tracer.Start("JSGetFileAssetsCompleteCallback");
1189 
1190     auto context = static_cast<SmartAlbumNapiAsyncContext *>(data);
1191     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1192 
1193     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
1194     jsContext->status = false;
1195 
1196     if (context->fetchResult != nullptr) {
1197         if (context->fetchResult->GetCount() < 0) {
1198             napi_get_undefined(env, &jsContext->data);
1199             MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
1200                 "Find no data by options");
1201         } else {
1202             napi_value fetchRes = FetchFileResultNapi::CreateFetchFileResult(env, move(context->fetchResult));
1203             if (fetchRes == nullptr) {
1204                 NAPI_ERR_LOG("Failed to get file asset napi object");
1205                 napi_get_undefined(env, &jsContext->data);
1206                 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
1207                     "Failed to create js object for FetchFileResult");
1208             } else {
1209                 jsContext->data = fetchRes;
1210                 napi_get_undefined(env, &jsContext->error);
1211                 jsContext->status = true;
1212             }
1213         }
1214     } else {
1215         NAPI_ERR_LOG("No fetch file result found!");
1216         napi_get_undefined(env, &jsContext->data);
1217         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1218                                                      "Failed to get fetchFileResult from DB");
1219     }
1220 
1221     tracer.Finish();
1222     if (context->work != nullptr) {
1223         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1224                                                    context->work, *jsContext);
1225     }
1226     delete context;
1227 }
1228 
JSGetSmartAlbumFileAssets(napi_env env,napi_callback_info info)1229 napi_value SmartAlbumNapi::JSGetSmartAlbumFileAssets(napi_env env, napi_callback_info info)
1230 {
1231     napi_status status;
1232     napi_value result = nullptr;
1233     constexpr int maxArgs = 2;
1234     size_t argc = maxArgs;
1235     napi_value argv[maxArgs] = {0};
1236     napi_value thisVar = nullptr;
1237 
1238     GET_JS_ARGS(env, info, argc, argv, thisVar);
1239     NAPI_ASSERT(env, ((argc == ARGS_ZERO) || (argc == ARGS_ONE) || (argc == ARGS_TWO)),
1240                 "requires 2 parameter maximum");
1241 
1242     napi_get_undefined(env, &result);
1243     std::unique_ptr<SmartAlbumNapiAsyncContext> asyncContext = std::make_unique<SmartAlbumNapiAsyncContext>();
1244     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1245     asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
1246     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1247         result = ConvertJSArgsToNative(env, argc, argv, *asyncContext);
1248         CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "Failed to obtain arguments");
1249 
1250         asyncContext->objectPtr = asyncContext->objectInfo->smartAlbumAssetPtr;
1251         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "SmartAlbumAsset is nullptr");
1252 
1253         result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetSmartAlbumFileAssets",
1254             GetFileAssetsNative, JSGetFileAssetsCompleteCallback);
1255     }
1256 
1257     return result;
1258 }
1259 
UserFileMgrGetAssets(napi_env env,napi_callback_info info)1260 napi_value SmartAlbumNapi::UserFileMgrGetAssets(napi_env env, napi_callback_info info)
1261 {
1262     napi_value ret = nullptr;
1263     unique_ptr<SmartAlbumNapiAsyncContext> asyncContext = make_unique<SmartAlbumNapiAsyncContext>();
1264     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "AsyncContext context is null");
1265 
1266     asyncContext->mediaTypes.push_back(MEDIA_TYPE_IMAGE);
1267     asyncContext->mediaTypes.push_back(MEDIA_TYPE_VIDEO);
1268     CHECK_ARGS(env, MediaLibraryNapiUtils::ParseAssetFetchOptCallback(env, info, asyncContext),
1269         JS_ERR_PARAMETER_INVALID);
1270     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1271 
1272     asyncContext->objectPtr = asyncContext->objectInfo->smartAlbumAssetPtr;
1273     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "SmartAlbumAsset is nullptr");
1274 
1275     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrGetAssets", GetFileAssetsNative,
1276         JSGetFileAssetsCompleteCallback);
1277 }
1278 
JSRecoverAssetExecute(napi_env env,void * data)1279 static void JSRecoverAssetExecute(napi_env env, void *data)
1280 {
1281     MediaLibraryTracer tracer;
1282     tracer.Start("JSRecoverAssetExecute");
1283 
1284     auto context = static_cast<SmartAlbumNapiAsyncContext *>(data);
1285     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1286 
1287     string recoverUri = MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/" +
1288         MEDIA_SMARTALBUMMAPOPRN_REMOVESMARTALBUM;
1289     Uri recoverAssetUri(recoverUri);
1290     DataShare::DataShareValuesBucket valuesBucket;
1291     valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, context->objectPtr->GetAlbumId());
1292     valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, stoi(MediaLibraryNapiUtils::GetFileIdFromUri(context->uri)));
1293     int retVal = UserFileClient::Insert(recoverAssetUri, valuesBucket);
1294     context->SaveError(retVal);
1295 }
1296 
JSRecoverAssetCompleteCallback(napi_env env,napi_status status,void * data)1297 static void JSRecoverAssetCompleteCallback(napi_env env, napi_status status, void *data)
1298 {
1299     MediaLibraryTracer tracer;
1300     tracer.Start("JSRecoverAssetCompleteCallback");
1301 
1302     SmartAlbumNapiAsyncContext *context = static_cast<SmartAlbumNapiAsyncContext*>(data);
1303     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1304     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1305     CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1306     jsContext->status = false;
1307     napi_get_undefined(env, &jsContext->data);
1308     if (context->error == ERR_DEFAULT) {
1309         jsContext->status = true;
1310         Media::MediaType mediaType = MediaLibraryNapiUtils::GetMediaTypeFromUri(context->uri);
1311         string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
1312         Uri modifyNotify(notifyUri);
1313         UserFileClient::NotifyChange(modifyNotify);
1314     } else {
1315         context->HandleError(env, jsContext->error);
1316     }
1317     if (context->work != nullptr) {
1318         tracer.Finish();
1319         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1320             context->work, *jsContext);
1321     }
1322 
1323     delete context;
1324 }
1325 
UserFileMgrRecoverAsset(napi_env env,napi_callback_info info)1326 napi_value SmartAlbumNapi::UserFileMgrRecoverAsset(napi_env env, napi_callback_info info)
1327 {
1328     napi_value ret = nullptr;
1329     unique_ptr<SmartAlbumNapiAsyncContext> asyncContext = make_unique<SmartAlbumNapiAsyncContext>();
1330     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "AsyncContext context is null");
1331 
1332     CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, asyncContext->uri),
1333         JS_ERR_PARAMETER_INVALID);
1334     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1335     asyncContext->objectPtr = asyncContext->objectInfo->smartAlbumAssetPtr;
1336     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "SmartAlbumAsset is nullptr");
1337 
1338     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrRecoverAsset",
1339         JSRecoverAssetExecute, JSRecoverAssetCompleteCallback);
1340 }
1341 
JSDeleteAssetExecute(napi_env env,void * data)1342 static void JSDeleteAssetExecute(napi_env env, void *data)
1343 {
1344     MediaLibraryTracer tracer;
1345     tracer.Start("JSDeleteAssetExecute");
1346 
1347     auto context = static_cast<SmartAlbumNapiAsyncContext *>(data);
1348     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1349 
1350     string deleteUri = MEDIALIBRARY_DATA_URI + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_DELETEASSET;
1351     Uri deleteAssetUri(deleteUri);
1352     DataShare::DataSharePredicates predicates;
1353     predicates.EqualTo(MEDIA_DATA_DB_ID, MediaLibraryNapiUtils::GetFileIdFromUri(context->uri));
1354     int retVal = UserFileClient::Delete(deleteAssetUri, {});
1355     context->SaveError(retVal);
1356 }
1357 
JSDeleteAssetCompleteCallback(napi_env env,napi_status status,void * data)1358 static void JSDeleteAssetCompleteCallback(napi_env env, napi_status status, void *data)
1359 {
1360     MediaLibraryTracer tracer;
1361     tracer.Start("JSDeleteAssetCompleteCallback");
1362 
1363     SmartAlbumNapiAsyncContext *context = static_cast<SmartAlbumNapiAsyncContext*>(data);
1364     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1365     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1366     CHECK_NULL_PTR_RETURN_VOID(jsContext, "JsContext context is null");
1367     jsContext->status = false;
1368     napi_get_undefined(env, &jsContext->data);
1369     if (context->error == ERR_DEFAULT) {
1370         jsContext->status = true;
1371         Media::MediaType mediaType = MediaLibraryNapiUtils::GetMediaTypeFromUri(context->uri);
1372         string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
1373         Uri modifyNotify(notifyUri);
1374         UserFileClient::NotifyChange(modifyNotify);
1375     } else {
1376         context->HandleError(env, jsContext->error);
1377     }
1378     if (context->work != nullptr) {
1379         tracer.Finish();
1380         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1381             context->work, *jsContext);
1382     }
1383 
1384     delete context;
1385 }
1386 
UserFileMgrDeleteAsset(napi_env env,napi_callback_info info)1387 napi_value SmartAlbumNapi::UserFileMgrDeleteAsset(napi_env env, napi_callback_info info)
1388 {
1389     napi_value ret = nullptr;
1390     unique_ptr<SmartAlbumNapiAsyncContext> asyncContext = make_unique<SmartAlbumNapiAsyncContext>();
1391     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "AsyncContext context is null");
1392 
1393     CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, asyncContext->uri),
1394         JS_ERR_PARAMETER_INVALID);
1395     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1396 
1397     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrDeleteAsset", JSDeleteAssetExecute,
1398         JSDeleteAssetCompleteCallback);
1399 }
1400 } // namespace Media
1401 } // namespace OHOS
1402