• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "PhotoAlbumNapi"
16 
17 #include "photo_album_napi.h"
18 #include <nlohmann/json.hpp>
19 
20 #include "fetch_file_result_napi.h"
21 #include "file_asset_napi.h"
22 #include "media_file_utils.h"
23 #include "medialibrary_client_errno.h"
24 #include "medialibrary_napi_log.h"
25 #include "medialibrary_tracer.h"
26 #include "photo_map_column.h"
27 #include "result_set_utils.h"
28 #include "userfile_client.h"
29 
30 using namespace std;
31 using namespace OHOS::DataShare;
32 
33 namespace OHOS::Media {
34 thread_local PhotoAlbum *PhotoAlbumNapi::pAlbumData_ = nullptr;
35 thread_local napi_ref PhotoAlbumNapi::constructor_ = nullptr;
36 thread_local napi_ref PhotoAlbumNapi::photoAccessConstructor_ = nullptr;
37 static const string PHOTO_ALBUM_CLASS = "UserFileMgrPhotoAlbum";
38 static const string PHOTOACCESS_PHOTO_ALBUM_CLASS = "PhotoAccessPhotoAlbum";
39 static const string COUNT_GROUP_BY = "count(*) AS count";
40 
41 struct TrashAlbumExecuteOpt {
42     napi_env env;
43     void *data;
44     string tracerLabel;
45     string uri;
46 };
47 
48 using CompleteCallback = napi_async_complete_callback;
49 
PhotoAlbumNapi()50 PhotoAlbumNapi::PhotoAlbumNapi() : env_(nullptr) {}
51 
52 PhotoAlbumNapi::~PhotoAlbumNapi() = default;
53 
Init(napi_env env,napi_value exports)54 napi_value PhotoAlbumNapi::Init(napi_env env, napi_value exports)
55 {
56     NapiClassInfo info = {
57         .name = PHOTO_ALBUM_CLASS,
58         .ref = &constructor_,
59         .constructor = PhotoAlbumNapiConstructor,
60         .props = {
61             DECLARE_NAPI_GETTER_SETTER("albumName", JSGetAlbumName, JSSetAlbumName),
62             DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
63             DECLARE_NAPI_GETTER("count", JSGetAlbumCount),
64             DECLARE_NAPI_GETTER("albumType", JSGetPhotoAlbumType),
65             DECLARE_NAPI_GETTER("albumSubType", JSGetPhotoAlbumSubType),
66             DECLARE_NAPI_GETTER_SETTER("coverUri", JSGetCoverUri, JSSetCoverUri),
67             DECLARE_NAPI_GETTER("dateModified", JSGetDateModified),
68             DECLARE_NAPI_FUNCTION("commitModify", JSCommitModify),
69             DECLARE_NAPI_FUNCTION("addPhotoAssets", JSPhotoAlbumAddAssets),
70             DECLARE_NAPI_FUNCTION("removePhotoAssets", JSPhotoAlbumRemoveAssets),
71             DECLARE_NAPI_FUNCTION("getPhotoAssets", JSGetPhotoAssets),
72             DECLARE_NAPI_FUNCTION("recoverPhotoAssets", JSRecoverPhotos),
73             DECLARE_NAPI_FUNCTION("deletePhotoAssets", JSDeletePhotos),
74             // PrivateAlbum.recover
75             DECLARE_NAPI_FUNCTION("recover", PrivateAlbumRecoverPhotos),
76             // PrivateAlbum.delete
77             DECLARE_NAPI_FUNCTION("delete", PrivateAlbumDeletePhotos),
78         }
79     };
80 
81     MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
82     return exports;
83 }
84 
PhotoAccessInit(napi_env env,napi_value exports)85 napi_value PhotoAlbumNapi::PhotoAccessInit(napi_env env, napi_value exports)
86 {
87     NapiClassInfo info = {
88         .name = PHOTOACCESS_PHOTO_ALBUM_CLASS,
89         .ref = &photoAccessConstructor_,
90         .constructor = PhotoAlbumNapiConstructor,
91         .props = {
92             DECLARE_NAPI_GETTER_SETTER("albumName", JSPhotoAccessGetAlbumName, JSPhotoAccessSetAlbumName),
93             DECLARE_NAPI_GETTER("albumUri", JSPhotoAccessGetAlbumUri),
94             DECLARE_NAPI_GETTER("count", JSPhotoAccessGetAlbumCount),
95             DECLARE_NAPI_GETTER("imageCount", JSPhotoAccessGetAlbumImageCount),
96             DECLARE_NAPI_GETTER("videoCount", JSPhotoAccessGetAlbumVideoCount),
97             DECLARE_NAPI_GETTER("albumType", JSGetPhotoAlbumType),
98             DECLARE_NAPI_GETTER("albumSubtype", JSGetPhotoAlbumSubType),
99             DECLARE_NAPI_GETTER("coverUri", JSGetCoverUri),
100             DECLARE_NAPI_GETTER("latitude", JSGetLatitude),
101             DECLARE_NAPI_GETTER("longitude", JSGetLongitude),
102             DECLARE_NAPI_FUNCTION("commitModify", PhotoAccessHelperCommitModify),
103             DECLARE_NAPI_FUNCTION("addAssets", PhotoAccessHelperAddAssets),
104             DECLARE_NAPI_FUNCTION("removeAssets", PhotoAccessHelperRemoveAssets),
105             DECLARE_NAPI_FUNCTION("getAssets", JSPhotoAccessGetPhotoAssets),
106             DECLARE_NAPI_FUNCTION("recoverAssets", PhotoAccessHelperRecoverPhotos),
107             DECLARE_NAPI_FUNCTION("deleteAssets", PhotoAccessHelperDeletePhotos),
108             DECLARE_NAPI_FUNCTION("setCoverUri", PhotoAccessHelperSetCoverUri),
109             DECLARE_NAPI_FUNCTION("getAssetsSync", JSPhotoAccessGetPhotoAssetsSync),
110             DECLARE_NAPI_FUNCTION("getFaceId", PhotoAccessHelperGetFaceId),
111         }
112     };
113 
114     MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
115     return exports;
116 }
117 
CreatePhotoAlbumNapi(napi_env env,unique_ptr<PhotoAlbum> & albumData)118 napi_value PhotoAlbumNapi::CreatePhotoAlbumNapi(napi_env env, unique_ptr<PhotoAlbum> &albumData)
119 {
120     if (albumData == nullptr) {
121         return nullptr;
122     }
123 
124     napi_value constructor;
125     napi_ref constructorRef;
126     if (albumData->GetResultNapiType() == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
127         constructorRef = photoAccessConstructor_;
128     } else {
129         constructorRef = constructor_;
130     }
131     CHECK_ARGS(env, napi_get_reference_value(env, constructorRef, &constructor), JS_INNER_FAIL);
132 
133     napi_value result = nullptr;
134     pAlbumData_ = albumData.release();
135     CHECK_ARGS(env, napi_new_instance(env, constructor, 0, nullptr, &result), JS_INNER_FAIL);
136     pAlbumData_ = nullptr;
137     return result;
138 }
139 
CreatePhotoAlbumNapi(napi_env env,shared_ptr<PhotoAlbum> & albumData)140 napi_value PhotoAlbumNapi::CreatePhotoAlbumNapi(napi_env env, shared_ptr<PhotoAlbum>& albumData)
141 {
142     if (albumData == nullptr || albumData->GetResultNapiType() != ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
143         NAPI_ERR_LOG("Unsupported photo album data");
144         return nullptr;
145     }
146 
147     napi_value constructor = nullptr;
148     napi_value result = nullptr;
149     CHECK_ARGS(env, napi_get_reference_value(env, photoAccessConstructor_, &constructor), JS_INNER_FAIL);
150     CHECK_ARGS(env, napi_new_instance(env, constructor, 0, nullptr, &result), JS_INNER_FAIL);
151     CHECK_COND(env, result != nullptr, JS_INNER_FAIL);
152 
153     PhotoAlbumNapi* photoAlbumNapi = nullptr;
154     CHECK_ARGS(env, napi_unwrap(env, result, reinterpret_cast<void**>(&photoAlbumNapi)), JS_INNER_FAIL);
155     CHECK_COND(env, photoAlbumNapi != nullptr, JS_INNER_FAIL);
156     photoAlbumNapi->photoAlbumPtr = albumData;
157     return result;
158 }
159 
GetAlbumId() const160 int32_t PhotoAlbumNapi::GetAlbumId() const
161 {
162     return photoAlbumPtr->GetAlbumId();
163 }
164 
GetCount() const165 int32_t PhotoAlbumNapi::GetCount() const
166 {
167     return photoAlbumPtr->GetCount();
168 }
169 
SetCount(int32_t count)170 void PhotoAlbumNapi::SetCount(int32_t count)
171 {
172     return photoAlbumPtr->SetCount(count);
173 }
174 
GetImageCount() const175 int32_t PhotoAlbumNapi::GetImageCount() const
176 {
177     return photoAlbumPtr->GetImageCount();
178 }
179 
SetImageCount(int32_t count)180 void PhotoAlbumNapi::SetImageCount(int32_t count)
181 {
182     return photoAlbumPtr->SetImageCount(count);
183 }
184 
GetVideoCount() const185 int32_t PhotoAlbumNapi::GetVideoCount() const
186 {
187     return photoAlbumPtr->GetVideoCount();
188 }
189 
SetVideoCount(int32_t count)190 void PhotoAlbumNapi::SetVideoCount(int32_t count)
191 {
192     return photoAlbumPtr->SetVideoCount(count);
193 }
194 
GetAlbumUri() const195 const string& PhotoAlbumNapi::GetAlbumUri() const
196 {
197     return photoAlbumPtr->GetAlbumUri();
198 }
199 
GetCoverUri() const200 const string& PhotoAlbumNapi::GetCoverUri() const
201 {
202     return photoAlbumPtr->GetCoverUri();
203 }
204 
GetDateModified() const205 int64_t PhotoAlbumNapi::GetDateModified() const
206 {
207     return photoAlbumPtr->GetDateModified();
208 }
209 
GetAlbumName() const210 const string& PhotoAlbumNapi::GetAlbumName() const
211 {
212     return photoAlbumPtr->GetAlbumName();
213 }
214 
GetPhotoAlbumType() const215 PhotoAlbumType PhotoAlbumNapi::GetPhotoAlbumType() const
216 {
217     return photoAlbumPtr->GetPhotoAlbumType();
218 }
219 
GetPhotoAlbumSubType() const220 PhotoAlbumSubType PhotoAlbumNapi::GetPhotoAlbumSubType() const
221 {
222     return photoAlbumPtr->GetPhotoAlbumSubType();
223 }
224 
GetLatitude() const225 double PhotoAlbumNapi::GetLatitude() const
226 {
227     return photoAlbumPtr->GetLatitude();
228 }
229 
GetLongitude() const230 double PhotoAlbumNapi::GetLongitude() const
231 {
232     return photoAlbumPtr->GetLongitude();
233 }
234 
GetPhotoAlbumInstance() const235 shared_ptr<PhotoAlbum> PhotoAlbumNapi::GetPhotoAlbumInstance() const
236 {
237     return photoAlbumPtr;
238 }
239 
GetHiddenOnly() const240 bool PhotoAlbumNapi::GetHiddenOnly() const
241 {
242     return photoAlbumPtr->GetHiddenOnly();
243 }
244 
SetHiddenOnly(const bool hiddenOnly_)245 void PhotoAlbumNapi::SetHiddenOnly(const bool hiddenOnly_)
246 {
247     return photoAlbumPtr->SetHiddenOnly(hiddenOnly_);
248 }
249 
SetPhotoAlbumNapiProperties()250 void PhotoAlbumNapi::SetPhotoAlbumNapiProperties()
251 {
252     photoAlbumPtr = shared_ptr<PhotoAlbum>(pAlbumData_);
253 }
254 
255 // Constructor callback
PhotoAlbumNapiConstructor(napi_env env,napi_callback_info info)256 napi_value PhotoAlbumNapi::PhotoAlbumNapiConstructor(napi_env env, napi_callback_info info)
257 {
258     napi_value result = nullptr;
259     CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
260 
261     napi_value thisVar = nullptr;
262     CHECK_ARGS(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr), JS_INNER_FAIL);
263     if (thisVar == nullptr) {
264         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
265         return result;
266     }
267 
268     unique_ptr<PhotoAlbumNapi> obj = make_unique<PhotoAlbumNapi>();
269     obj->env_ = env;
270     if (pAlbumData_ != nullptr) {
271         obj->SetPhotoAlbumNapiProperties();
272     }
273     CHECK_ARGS(env, napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
274         PhotoAlbumNapi::PhotoAlbumNapiDestructor, nullptr, nullptr), JS_INNER_FAIL);
275     obj.release();
276     return thisVar;
277 }
278 
PhotoAlbumNapiDestructor(napi_env env,void * nativeObject,void * finalizeHint)279 void PhotoAlbumNapi::PhotoAlbumNapiDestructor(napi_env env, void *nativeObject, void *finalizeHint)
280 {
281     auto *album = reinterpret_cast<PhotoAlbumNapi*>(nativeObject);
282     if (album != nullptr) {
283         delete album;
284         album = nullptr;
285     }
286 }
287 
UnwrapPhotoAlbumObject(napi_env env,napi_callback_info info,PhotoAlbumNapi ** obj)288 napi_value UnwrapPhotoAlbumObject(napi_env env, napi_callback_info info, PhotoAlbumNapi** obj)
289 {
290     napi_value result = nullptr;
291     CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
292 
293     napi_value thisVar = nullptr;
294     CHECK_ARGS(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr), JS_INNER_FAIL);
295     if (thisVar == nullptr) {
296         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
297         return result;
298     }
299 
300     CHECK_ARGS(env, napi_unwrap(env, thisVar, reinterpret_cast<void **>(obj)), JS_INNER_FAIL);
301     if (obj == nullptr) {
302         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
303         return result;
304     }
305 
306     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
307     return result;
308 }
309 
JSGetAlbumName(napi_env env,napi_callback_info info)310 napi_value PhotoAlbumNapi::JSGetAlbumName(napi_env env, napi_callback_info info)
311 {
312     PhotoAlbumNapi *obj = nullptr;
313     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
314 
315     napi_value jsResult = nullptr;
316     CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumName().c_str(), NAPI_AUTO_LENGTH, &jsResult),
317         JS_INNER_FAIL);
318     return jsResult;
319 }
320 
JSPhotoAccessGetAlbumName(napi_env env,napi_callback_info info)321 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumName(napi_env env, napi_callback_info info)
322 {
323     PhotoAlbumNapi *obj = nullptr;
324     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
325 
326     napi_value jsResult = nullptr;
327     CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumName().c_str(), NAPI_AUTO_LENGTH, &jsResult),
328         JS_INNER_FAIL);
329     return jsResult;
330 }
331 
JSGetAlbumUri(napi_env env,napi_callback_info info)332 napi_value PhotoAlbumNapi::JSGetAlbumUri(napi_env env, napi_callback_info info)
333 {
334     PhotoAlbumNapi *obj = nullptr;
335     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
336 
337     napi_value jsResult = nullptr;
338     CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
339         JS_INNER_FAIL);
340     return jsResult;
341 }
342 
JSPhotoAccessGetAlbumUri(napi_env env,napi_callback_info info)343 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumUri(napi_env env, napi_callback_info info)
344 {
345     PhotoAlbumNapi *obj = nullptr;
346     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
347 
348     napi_value jsResult = nullptr;
349     CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
350         JS_INNER_FAIL);
351     return jsResult;
352 }
353 
JSGetAlbumCount(napi_env env,napi_callback_info info)354 napi_value PhotoAlbumNapi::JSGetAlbumCount(napi_env env, napi_callback_info info)
355 {
356     PhotoAlbumNapi *obj = nullptr;
357     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
358 
359     napi_value jsResult = nullptr;
360     CHECK_ARGS(env, napi_create_int32(env, obj->GetCount(), &jsResult), JS_INNER_FAIL);
361     return jsResult;
362 }
363 
JSPhotoAccessGetAlbumCount(napi_env env,napi_callback_info info)364 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumCount(napi_env env, napi_callback_info info)
365 {
366     PhotoAlbumNapi *obj = nullptr;
367     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
368 
369     napi_value jsResult = nullptr;
370     CHECK_ARGS(env, napi_create_int32(env, obj->GetCount(), &jsResult), JS_INNER_FAIL);
371     return jsResult;
372 }
373 
JSPhotoAccessGetAlbumImageCount(napi_env env,napi_callback_info info)374 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumImageCount(napi_env env, napi_callback_info info)
375 {
376     PhotoAlbumNapi *obj = nullptr;
377     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
378 
379     napi_value jsResult = nullptr;
380     CHECK_ARGS(env, napi_create_int32(env, obj->GetImageCount(), &jsResult), JS_INNER_FAIL);
381     return jsResult;
382 }
383 
JSPhotoAccessGetAlbumVideoCount(napi_env env,napi_callback_info info)384 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumVideoCount(napi_env env, napi_callback_info info)
385 {
386     PhotoAlbumNapi *obj = nullptr;
387     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
388 
389     napi_value jsResult = nullptr;
390     CHECK_ARGS(env, napi_create_int32(env, obj->GetVideoCount(), &jsResult), JS_INNER_FAIL);
391     return jsResult;
392 }
393 
JSGetPhotoAlbumType(napi_env env,napi_callback_info info)394 napi_value PhotoAlbumNapi::JSGetPhotoAlbumType(napi_env env, napi_callback_info info)
395 {
396     PhotoAlbumNapi *obj = nullptr;
397     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
398 
399     napi_value jsResult = nullptr;
400     CHECK_ARGS(env, napi_create_int32(env, obj->GetPhotoAlbumType(), &jsResult), JS_INNER_FAIL);
401     return jsResult;
402 }
403 
JSGetPhotoAlbumSubType(napi_env env,napi_callback_info info)404 napi_value PhotoAlbumNapi::JSGetPhotoAlbumSubType(napi_env env, napi_callback_info info)
405 {
406     PhotoAlbumNapi *obj = nullptr;
407     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
408 
409     napi_value jsResult = nullptr;
410     CHECK_ARGS(env, napi_create_int32(env, obj->GetPhotoAlbumSubType(), &jsResult), JS_INNER_FAIL);
411     return jsResult;
412 }
413 
JSGetCoverUri(napi_env env,napi_callback_info info)414 napi_value PhotoAlbumNapi::JSGetCoverUri(napi_env env, napi_callback_info info)
415 {
416     PhotoAlbumNapi *obj = nullptr;
417     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
418 
419     napi_value jsResult = nullptr;
420     CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetCoverUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
421         JS_INNER_FAIL);
422     return jsResult;
423 }
424 
JSGetLatitude(napi_env env,napi_callback_info info)425 napi_value PhotoAlbumNapi::JSGetLatitude(napi_env env, napi_callback_info info)
426 {
427     PhotoAlbumNapi *obj = nullptr;
428     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
429 
430     napi_value jsResult = nullptr;
431     CHECK_ARGS(env, napi_create_double(env, obj->GetLatitude(), &jsResult), JS_INNER_FAIL);
432     return jsResult;
433 }
434 
JSGetLongitude(napi_env env,napi_callback_info info)435 napi_value PhotoAlbumNapi::JSGetLongitude(napi_env env, napi_callback_info info)
436 {
437     PhotoAlbumNapi *obj = nullptr;
438     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
439 
440     napi_value jsResult = nullptr;
441     CHECK_ARGS(env, napi_create_double(env, obj->GetLongitude(), &jsResult), JS_INNER_FAIL);
442     return jsResult;
443 }
444 
GetStringArg(napi_env env,napi_callback_info info,PhotoAlbumNapi ** obj,string & output)445 napi_value GetStringArg(napi_env env, napi_callback_info info, PhotoAlbumNapi **obj, string &output)
446 {
447     size_t argc = ARGS_ONE;
448     napi_value argv[ARGS_ONE];
449     napi_value thisVar = nullptr;
450     CHECK_ARGS(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr), JS_INNER_FAIL);
451     CHECK_COND(env, argc == ARGS_ONE, JS_ERR_PARAMETER_INVALID);
452 
453     napi_value result = nullptr;
454     CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
455     napi_valuetype valueType = napi_undefined;
456     if ((thisVar == nullptr) || (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok) || (valueType != napi_string)) {
457         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
458         return result;
459     }
460 
461     size_t res = 0;
462     char buffer[FILENAME_MAX];
463     CHECK_ARGS(env, napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res), JS_INNER_FAIL);
464     output = string(buffer);
465 
466     CHECK_ARGS(env, napi_unwrap(env, thisVar, reinterpret_cast<void **>(obj)), JS_INNER_FAIL);
467     if (obj == nullptr) {
468         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
469         return result;
470     }
471 
472     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
473     return result;
474 }
475 
JSSetAlbumName(napi_env env,napi_callback_info info)476 napi_value PhotoAlbumNapi::JSSetAlbumName(napi_env env, napi_callback_info info)
477 {
478     PhotoAlbumNapi *obj = nullptr;
479     string albumName;
480     CHECK_NULLPTR_RET(GetStringArg(env, info, &obj, albumName));
481     obj->photoAlbumPtr->SetAlbumName(albumName);
482 
483     napi_value result = nullptr;
484     CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
485     return result;
486 }
487 
JSPhotoAccessSetAlbumName(napi_env env,napi_callback_info info)488 napi_value PhotoAlbumNapi::JSPhotoAccessSetAlbumName(napi_env env, napi_callback_info info)
489 {
490     PhotoAlbumNapi *obj = nullptr;
491     string albumName;
492     CHECK_NULLPTR_RET(GetStringArg(env, info, &obj, albumName));
493     obj->photoAlbumPtr->SetAlbumName(albumName);
494 
495     napi_value result = nullptr;
496     CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
497     return result;
498 }
499 
JSSetCoverUri(napi_env env,napi_callback_info info)500 napi_value PhotoAlbumNapi::JSSetCoverUri(napi_env env, napi_callback_info info)
501 {
502     PhotoAlbumNapi *obj = nullptr;
503     string coverUri;
504     CHECK_NULLPTR_RET(GetStringArg(env, info, &obj, coverUri));
505     obj->photoAlbumPtr->SetCoverUri(coverUri);
506 
507     napi_value result = nullptr;
508     CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
509     return result;
510 }
511 
JSGetDateModified(napi_env env,napi_callback_info info)512 napi_value PhotoAlbumNapi::JSGetDateModified(napi_env env, napi_callback_info info)
513 {
514     PhotoAlbumNapi *obj = nullptr;
515     CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
516 
517     napi_value jsResult = nullptr;
518     CHECK_ARGS(env, napi_create_int64(env, obj->GetDateModified(), &jsResult),
519         JS_INNER_FAIL);
520     return jsResult;
521 }
522 
ParseArgsCommitModify(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)523 static napi_value ParseArgsCommitModify(napi_env env, napi_callback_info info,
524     unique_ptr<PhotoAlbumNapiAsyncContext> &context)
525 {
526     constexpr size_t minArgs = ARGS_ZERO;
527     constexpr size_t maxArgs = ARGS_ONE;
528     CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
529         JS_ERR_PARAMETER_INVALID);
530 
531     auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
532     if (photoAlbum == nullptr) {
533         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
534         return nullptr;
535     }
536     if (!PhotoAlbum::IsUserPhotoAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
537         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
538         return nullptr;
539     }
540 
541     if (MediaFileUtils::CheckAlbumName(photoAlbum->GetAlbumName()) < 0) {
542         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
543         return nullptr;
544     }
545     context->predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(photoAlbum->GetAlbumId()));
546     context->valuesBucket.Put(PhotoAlbumColumns::ALBUM_NAME, photoAlbum->GetAlbumName());
547     context->valuesBucket.Put(PhotoAlbumColumns::ALBUM_COVER_URI, photoAlbum->GetCoverUri());
548 
549     napi_value result = nullptr;
550     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
551     return result;
552 }
553 
JSCommitModifyExecute(napi_env env,void * data)554 static void JSCommitModifyExecute(napi_env env, void *data)
555 {
556     MediaLibraryTracer tracer;
557     tracer.Start("JSCommitModifyExecute");
558 
559     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
560     string commitModifyUri = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
561         UFM_UPDATE_PHOTO_ALBUM : PAH_UPDATE_PHOTO_ALBUM;
562     Uri uri(commitModifyUri);
563     int changedRows = UserFileClient::Update(uri, context->predicates, context->valuesBucket);
564     context->SaveError(changedRows);
565     context->changedRows = changedRows;
566 }
567 
JSCommitModifyCompleteCallback(napi_env env,napi_status status,void * data)568 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, void *data)
569 {
570     MediaLibraryTracer tracer;
571     tracer.Start("JSCommitModifyCompleteCallback");
572 
573     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
574     auto jsContext = make_unique<JSAsyncContextOutput>();
575     jsContext->status = false;
576     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
577     if (context->error == ERR_DEFAULT) {
578         CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
579         jsContext->status = true;
580     } else {
581         context->HandleError(env, jsContext->error);
582     }
583 
584     tracer.Finish();
585     if (context->work != nullptr) {
586         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
587                                                    context->work, *jsContext);
588     }
589     delete context;
590 }
591 
JSCommitModify(napi_env env,napi_callback_info info)592 napi_value PhotoAlbumNapi::JSCommitModify(napi_env env, napi_callback_info info)
593 {
594     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
595     CHECK_NULLPTR_RET(ParseArgsCommitModify(env, info, asyncContext));
596     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
597 
598     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
599         JSCommitModifyCompleteCallback);
600 }
601 
PhotoAccessHelperCommitModify(napi_env env,napi_callback_info info)602 napi_value PhotoAlbumNapi::PhotoAccessHelperCommitModify(napi_env env, napi_callback_info info)
603 {
604     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
605     CHECK_NULLPTR_RET(ParseArgsCommitModify(env, info, asyncContext));
606     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
607 
608     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
609         JSCommitModifyCompleteCallback);
610 }
611 
GetAssetsIdArray(napi_env env,napi_value arg,vector<string> & assetsArray)612 static napi_value GetAssetsIdArray(napi_env env, napi_value arg, vector<string> &assetsArray)
613 {
614     bool isArray = false;
615     CHECK_ARGS(env, napi_is_array(env, arg, &isArray), JS_INNER_FAIL);
616     if (!isArray) {
617         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check array type");
618         return nullptr;
619     }
620 
621     uint32_t len = 0;
622     CHECK_ARGS(env, napi_get_array_length(env, arg, &len), JS_INNER_FAIL);
623     if (len < 0) {
624         NAPI_ERR_LOG("Failed to check array length: %{public}u", len);
625         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check array length");
626         return nullptr;
627     }
628     if (len == 0) {
629         napi_value result = nullptr;
630         CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
631         return result;
632     }
633 
634     for (uint32_t i = 0; i < len; i++) {
635         napi_value asset = nullptr;
636         CHECK_ARGS(env, napi_get_element(env, arg, i, &asset), JS_INNER_FAIL);
637         if (asset == nullptr) {
638             NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get asset element");
639             return nullptr;
640         }
641 
642         FileAssetNapi *obj = nullptr;
643         CHECK_ARGS(env, napi_unwrap(env, asset, reinterpret_cast<void **>(&obj)), JS_INNER_FAIL);
644         if (obj == nullptr) {
645             NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get asset napi object");
646             return nullptr;
647         }
648         if ((obj->GetMediaType() != MEDIA_TYPE_IMAGE && obj->GetMediaType() != MEDIA_TYPE_VIDEO)) {
649             NAPI_INFO_LOG("Skip invalid asset, mediaType: %{public}d", obj->GetMediaType());
650             continue;
651         }
652         assetsArray.push_back(obj->GetFileUri());
653     }
654 
655     napi_value result = nullptr;
656     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
657     return result;
658 }
659 
ParseArgsAddAssets(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)660 static napi_value ParseArgsAddAssets(napi_env env, napi_callback_info info,
661     unique_ptr<PhotoAlbumNapiAsyncContext> &context)
662 {
663     constexpr size_t minArgs = ARGS_ONE;
664     constexpr size_t maxArgs = ARGS_TWO;
665     CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
666         JS_ERR_PARAMETER_INVALID);
667 
668     auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
669     if (!PhotoAlbum::IsUserPhotoAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
670         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
671         return nullptr;
672     }
673 
674     /* Parse the first argument */
675     vector<string> assetsArray;
676     CHECK_NULLPTR_RET(GetAssetsIdArray(env, context->argv[PARAM0], assetsArray));
677     if (assetsArray.empty()) {
678         napi_value result = nullptr;
679         CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
680         return result;
681     }
682     int32_t albumId = photoAlbum->GetAlbumId();
683     for (const auto &assetId : assetsArray) {
684         DataShareValuesBucket valuesBucket;
685         valuesBucket.Put(PhotoColumn::PHOTO_OWNER_ALBUM_ID, albumId);
686         valuesBucket.Put(PhotoColumn::MEDIA_ID, assetId);
687         context->valuesBuckets.push_back(valuesBucket);
688     }
689 
690     napi_value result = nullptr;
691     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
692     return result;
693 }
694 
FetchNewCount(PhotoAlbumNapiAsyncContext * context)695 static int32_t FetchNewCount(PhotoAlbumNapiAsyncContext *context)
696 {
697     string queryUri = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
698         UFM_QUERY_PHOTO_ALBUM : PAH_QUERY_PHOTO_ALBUM;
699     Uri qUri(queryUri);
700     int errCode = 0;
701     DataSharePredicates predicates;
702     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, context->objectInfo->GetAlbumId());
703     vector<string> fetchColumn = {
704         PhotoAlbumColumns::ALBUM_ID,
705         PhotoAlbumColumns::ALBUM_COUNT,
706     };
707     bool isSmartAlbum = (context->objectInfo->GetPhotoAlbumType() == PhotoAlbumType::SMART);
708     if (!isSmartAlbum) {
709         fetchColumn.push_back(PhotoAlbumColumns::ALBUM_IMAGE_COUNT);
710         fetchColumn.push_back(PhotoAlbumColumns::ALBUM_VIDEO_COUNT);
711     }
712     auto resultSet = UserFileClient::Query(qUri, predicates, fetchColumn, errCode);
713     if (resultSet == nullptr) {
714         NAPI_ERR_LOG("resultSet == nullptr, errCode is %{public}d", errCode);
715         return -1;
716     }
717     if (resultSet->GoToFirstRow() != 0) {
718         NAPI_ERR_LOG("go to first row failed");
719         return -1;
720     }
721     bool hiddenOnly = context->objectInfo->GetHiddenOnly();
722     int imageCount = (hiddenOnly || isSmartAlbum) ? -1 :
723             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_IMAGE_COUNT, resultSet, TYPE_INT32));
724     int videoCount = (hiddenOnly || isSmartAlbum) ? -1 :
725             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_VIDEO_COUNT, resultSet, TYPE_INT32));
726     context->newCount =
727             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_COUNT, resultSet, TYPE_INT32));
728     context->newImageCount = imageCount;
729     context->newVideoCount = videoCount;
730     return 0;
731 }
732 
JSPhotoAlbumAddAssetsExecute(napi_env env,void * data)733 static void JSPhotoAlbumAddAssetsExecute(napi_env env, void *data)
734 {
735     MediaLibraryTracer tracer;
736     tracer.Start("JSPhotoAlbumAddAssetsExecute");
737     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
738     if (context->valuesBuckets.empty()) {
739         return;
740     }
741     string addAssetsUri = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
742         UFM_PHOTO_ALBUM_ADD_ASSET : PAH_PHOTO_ALBUM_ADD_ASSET;
743     Uri uri(addAssetsUri);
744 
745     auto changedRows = UserFileClient::BatchInsert(uri, context->valuesBuckets);
746     if (changedRows < 0) {
747         context->SaveError(changedRows);
748         return;
749     }
750     context->changedRows = changedRows;
751     int32_t ret = FetchNewCount(context);
752     if (ret < 0) {
753         NAPI_ERR_LOG("Update count failed");
754         context->SaveError(E_HAS_DB_ERROR);
755     }
756 }
757 
JSPhotoAlbumAddAssetsCompleteCallback(napi_env env,napi_status status,void * data)758 static void JSPhotoAlbumAddAssetsCompleteCallback(napi_env env, napi_status status, void *data)
759 {
760     MediaLibraryTracer tracer;
761     tracer.Start("JSPhotoAlbumAddAssetsCompleteCallback");
762 
763     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
764     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
765     jsContext->status = false;
766     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
767     if (context->error == ERR_DEFAULT) {
768         CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
769         jsContext->status = true;
770         context->objectInfo->SetCount(context->newCount);
771         context->objectInfo->SetImageCount(context->newImageCount);
772         context->objectInfo->SetVideoCount(context->newVideoCount);
773     } else {
774         context->HandleError(env, jsContext->error);
775     }
776 
777     tracer.Finish();
778     if (context->work != nullptr) {
779         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
780                                                    context->work, *jsContext);
781     }
782     delete context;
783 }
784 
JSPhotoAlbumAddAssets(napi_env env,napi_callback_info info)785 napi_value PhotoAlbumNapi::JSPhotoAlbumAddAssets(napi_env env, napi_callback_info info)
786 {
787     unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
788     CHECK_NULLPTR_RET(ParseArgsAddAssets(env, info, asyncContext));
789     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
790 
791     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumAddAssets",
792         JSPhotoAlbumAddAssetsExecute, JSPhotoAlbumAddAssetsCompleteCallback);
793 }
794 
PhotoAccessHelperAddAssets(napi_env env,napi_callback_info info)795 napi_value PhotoAlbumNapi::PhotoAccessHelperAddAssets(napi_env env, napi_callback_info info)
796 {
797     unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
798     CHECK_NULLPTR_RET(ParseArgsAddAssets(env, info, asyncContext));
799     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
800 
801     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumAddAssets",
802         JSPhotoAlbumAddAssetsExecute, JSPhotoAlbumAddAssetsCompleteCallback);
803 }
804 
ParseArgsRemoveAssets(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)805 static napi_value ParseArgsRemoveAssets(napi_env env, napi_callback_info info,
806     unique_ptr<PhotoAlbumNapiAsyncContext> &context)
807 {
808     constexpr size_t minArgs = ARGS_ONE;
809     constexpr size_t maxArgs = ARGS_TWO;
810     CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
811         JS_ERR_PARAMETER_INVALID);
812 
813     auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
814     if (!PhotoAlbum::IsUserPhotoAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
815         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
816         return nullptr;
817     }
818 
819     /* Parse the first argument */
820     vector<string> assetsArray;
821     CHECK_NULLPTR_RET(GetAssetsIdArray(env, context->argv[PARAM0], assetsArray));
822     if (assetsArray.empty()) {
823         napi_value result = nullptr;
824         CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
825         return result;
826     }
827     context->predicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(photoAlbum->GetAlbumId()));
828     context->predicates.And()->In(PhotoColumn::MEDIA_ID, assetsArray);
829 
830     napi_value result = nullptr;
831     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
832     return result;
833 }
834 
JSPhotoAlbumRemoveAssetsExecute(napi_env env,void * data)835 static void JSPhotoAlbumRemoveAssetsExecute(napi_env env, void *data)
836 {
837     MediaLibraryTracer tracer;
838     tracer.Start("JSPhotoAlbumRemoveAssetsExecute");
839 
840     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
841     if (context->predicates.GetOperationList().empty()) {
842         return;
843     }
844 
845     string removeAssetsUri = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
846         UFM_PHOTO_ALBUM_REMOVE_ASSET : PAH_PHOTO_ALBUM_REMOVE_ASSET;
847     Uri uri(removeAssetsUri);
848     auto deletedRows = UserFileClient::Delete(uri, context->predicates);
849     if (deletedRows < 0) {
850         context->SaveError(deletedRows);
851         return;
852     }
853     context->changedRows = deletedRows;
854     int32_t ret = FetchNewCount(context);
855     if (ret < 0) {
856         NAPI_ERR_LOG("Update count failed");
857         context->SaveError(E_HAS_DB_ERROR);
858     }
859 }
860 
JSPhotoAlbumRemoveAssetsCompleteCallback(napi_env env,napi_status status,void * data)861 static void JSPhotoAlbumRemoveAssetsCompleteCallback(napi_env env, napi_status status, void *data)
862 {
863     MediaLibraryTracer tracer;
864     tracer.Start("JSPhotoAlbumRemoveAssetsCompleteCallback");
865 
866     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
867     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
868     jsContext->status = false;
869     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
870     if (context->error == ERR_DEFAULT) {
871         CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
872         jsContext->status = true;
873         context->objectInfo->SetCount(context->newCount);
874         context->objectInfo->SetImageCount(context->newImageCount);
875         context->objectInfo->SetVideoCount(context->newVideoCount);
876     } else {
877         context->HandleError(env, jsContext->error);
878     }
879 
880     tracer.Finish();
881     if (context->work != nullptr) {
882         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
883                                                    context->work, *jsContext);
884     }
885     delete context;
886 }
887 
JSPhotoAlbumRemoveAssets(napi_env env,napi_callback_info info)888 napi_value PhotoAlbumNapi::JSPhotoAlbumRemoveAssets(napi_env env, napi_callback_info info)
889 {
890     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
891     CHECK_NULLPTR_RET(ParseArgsRemoveAssets(env, info, asyncContext));
892     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
893 
894     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumRemoveAssets",
895         JSPhotoAlbumRemoveAssetsExecute, JSPhotoAlbumRemoveAssetsCompleteCallback);
896 }
897 
PhotoAccessHelperRemoveAssets(napi_env env,napi_callback_info info)898 napi_value PhotoAlbumNapi::PhotoAccessHelperRemoveAssets(napi_env env, napi_callback_info info)
899 {
900     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
901     CHECK_NULLPTR_RET(ParseArgsRemoveAssets(env, info, asyncContext));
902     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
903 
904     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumRemoveAssets",
905         JSPhotoAlbumRemoveAssetsExecute, JSPhotoAlbumRemoveAssetsCompleteCallback);
906 }
907 
GetPredicatesByAlbumTypes(const shared_ptr<PhotoAlbum> & photoAlbum,DataSharePredicates & predicates,const bool hiddenOnly)908 static int32_t GetPredicatesByAlbumTypes(const shared_ptr<PhotoAlbum> &photoAlbum,
909     DataSharePredicates &predicates, const bool hiddenOnly)
910 {
911     auto albumId = photoAlbum->GetAlbumId();
912     auto subType = photoAlbum->GetPhotoAlbumSubType();
913     bool isLocationAlbum = subType == PhotoAlbumSubType::GEOGRAPHY_LOCATION;
914     if (albumId <= 0 && !isLocationAlbum) {
915         return E_INVALID_ARGUMENTS;
916     }
917     auto type = photoAlbum->GetPhotoAlbumType();
918     if ((!PhotoAlbum::CheckPhotoAlbumType(type)) || (!PhotoAlbum::CheckPhotoAlbumSubType(subType))) {
919         return E_INVALID_ARGUMENTS;
920     }
921 
922     if (type == PhotoAlbumType::SMART && subType == PhotoAlbumSubType::PORTRAIT) {
923         return MediaLibraryNapiUtils::GetPortraitAlbumPredicates(photoAlbum->GetAlbumId(), predicates);
924     }
925 
926     if (PhotoAlbum::IsUserPhotoAlbum(type, subType)) {
927         return MediaLibraryNapiUtils::GetUserAlbumPredicates(photoAlbum->GetAlbumId(), predicates, hiddenOnly);
928     }
929 
930     if (PhotoAlbum::IsSourceAlbum(type, subType)) {
931         return MediaLibraryNapiUtils::GetSourceAlbumPredicates(photoAlbum->GetAlbumId(), predicates, hiddenOnly);
932     }
933 
934     if (type == PhotoAlbumType::SMART) {
935         if (isLocationAlbum) {
936             return MediaLibraryNapiUtils::GetAllLocationPredicates(predicates);
937         }
938         auto albumName = photoAlbum->GetAlbumName();
939         if (MediaLibraryNapiUtils::IsFeaturedSinglePortraitAlbum(albumName, predicates)) {
940             return MediaLibraryNapiUtils::GetFeaturedSinglePortraitAlbumPredicates(
941                 photoAlbum->GetAlbumId(), predicates);
942         }
943         return MediaLibraryNapiUtils::GetAnalysisAlbumPredicates(photoAlbum->GetAlbumId(), predicates);
944     }
945 
946     if ((type != PhotoAlbumType::SYSTEM) || (subType == PhotoAlbumSubType::USER_GENERIC) ||
947         (subType == PhotoAlbumSubType::ANY)) {
948         return E_INVALID_ARGUMENTS;
949     }
950     return MediaLibraryNapiUtils::GetSystemAlbumPredicates(subType, predicates, hiddenOnly);
951 }
952 
ParseArgsGetPhotoAssets(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)953 static napi_value ParseArgsGetPhotoAssets(napi_env env, napi_callback_info info,
954     unique_ptr<PhotoAlbumNapiAsyncContext> &context)
955 {
956     constexpr size_t minArgs = ARGS_ONE;
957     constexpr size_t maxArgs = ARGS_TWO;
958     CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
959         JS_ERR_PARAMETER_INVALID);
960 
961     /* Parse the first argument */
962     CHECK_ARGS(env, MediaLibraryNapiUtils::GetFetchOption(env, context->argv[PARAM0], ASSET_FETCH_OPT, context),
963         JS_INNER_FAIL);
964 
965     auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
966     auto ret = GetPredicatesByAlbumTypes(photoAlbum, context->predicates, photoAlbum->GetHiddenOnly());
967     if (ret != E_SUCCESS) {
968         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
969         return nullptr;
970     }
971     CHECK_NULLPTR_RET(MediaLibraryNapiUtils::AddDefaultAssetColumns(env, context->fetchColumn,
972         PhotoColumn::IsPhotoColumn, NapiAssetType::TYPE_PHOTO));
973     if (photoAlbum->GetHiddenOnly() || photoAlbum->GetPhotoAlbumSubType() == PhotoAlbumSubType::HIDDEN) {
974         if (!MediaLibraryNapiUtils::IsSystemApp()) {
975             NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
976             return nullptr;
977         }
978         // sort by hidden time desc if is hidden asset
979         context->predicates.IndexedBy(PhotoColumn::PHOTO_HIDDEN_TIME_INDEX);
980     }
981 
982     napi_value result = nullptr;
983     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
984     return result;
985 }
986 
JSGetPhotoAssetsExecute(napi_env env,void * data)987 static void JSGetPhotoAssetsExecute(napi_env env, void *data)
988 {
989     MediaLibraryTracer tracer;
990     tracer.Start("JSGetPhotoAssetsExecute");
991 
992     auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
993     string queryUri = UFM_QUERY_PHOTO_MAP;
994     Uri uri(queryUri);
995     int32_t errCode = 0;
996     std::vector<DataShare::OperationItem> operationItems = context->predicates.GetOperationList();
997     for (DataShare::OperationItem item : operationItems) {
998         if (item.operation == DataShare::OperationType::GROUP_BY) {
999             context->fetchColumn.insert(context->fetchColumn.begin(), COUNT_GROUP_BY);
1000         }
1001     }
1002     auto resultSet = UserFileClient::Query(uri, context->predicates, context->fetchColumn, errCode);
1003     if (resultSet == nullptr) {
1004         context->SaveError(E_HAS_DB_ERROR);
1005         return;
1006     }
1007     context->fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
1008     context->fetchResult->SetResultNapiType(ResultNapiType::TYPE_USERFILE_MGR);
1009 }
1010 
IsFeaturedSinglePortraitAlbum(const shared_ptr<PhotoAlbum> & photoAlbum)1011 static bool IsFeaturedSinglePortraitAlbum(const shared_ptr<PhotoAlbum>& photoAlbum)
1012 {
1013     constexpr int portraitAlbumId = 0;
1014     return photoAlbum->GetPhotoAlbumSubType() == PhotoAlbumSubType::CLASSIFY &&
1015         photoAlbum->GetAlbumName().compare(to_string(portraitAlbumId)) == 0;
1016 }
1017 
ConvertColumnsForPortrait(PhotoAlbumNapiAsyncContext * context)1018 static void ConvertColumnsForPortrait(PhotoAlbumNapiAsyncContext *context)
1019 {
1020     if (context == nullptr || context->objectInfo == nullptr) {
1021         NAPI_ERR_LOG("context is null or PhotoAlbumNapi is null");
1022         return;
1023     }
1024 
1025     shared_ptr<PhotoAlbum> photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1026     if (photoAlbum == nullptr || (photoAlbum->GetPhotoAlbumSubType() != PhotoAlbumSubType::PORTRAIT &&
1027         !IsFeaturedSinglePortraitAlbum(photoAlbum))) {
1028         return;
1029     }
1030 
1031     for (size_t i = 0; i < context->fetchColumn.size(); i++) {
1032         if (context->fetchColumn[i] != "count(*)") {
1033             context->fetchColumn[i] = PhotoColumn::PHOTOS_TABLE + "." + context->fetchColumn[i];
1034         }
1035     }
1036 }
1037 
JSPhotoAccessGetPhotoAssetsExecute(napi_env env,void * data)1038 static void JSPhotoAccessGetPhotoAssetsExecute(napi_env env, void *data)
1039 {
1040     MediaLibraryTracer tracer;
1041     tracer.Start("JSPhotoAccessGetPhotoAssetsExecute");
1042 
1043     auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1044     Uri uri(PAH_QUERY_PHOTO_MAP);
1045     ConvertColumnsForPortrait(context);
1046     int32_t errCode = 0;
1047     auto resultSet = UserFileClient::Query(uri, context->predicates, context->fetchColumn, errCode);
1048     if (resultSet == nullptr) {
1049         context->SaveError(E_HAS_DB_ERROR);
1050         return;
1051     }
1052     context->fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
1053     context->fetchResult->SetResultNapiType(ResultNapiType::TYPE_PHOTOACCESS_HELPER);
1054 }
1055 
JSPhotoAccessGetPhotoAssetsExecuteSync(napi_env env,PhotoAlbumNapiAsyncContext & asyncContext)1056 static napi_value JSPhotoAccessGetPhotoAssetsExecuteSync(napi_env env, PhotoAlbumNapiAsyncContext& asyncContext)
1057 {
1058     auto context = &asyncContext;
1059     Uri uri(PAH_QUERY_PHOTO_MAP);
1060     ConvertColumnsForPortrait(context);
1061     int32_t errCode = 0;
1062     auto resultSet = UserFileClient::Query(uri, context->predicates, context->fetchColumn, errCode);
1063     CHECK_NULLPTR_RET(resultSet);
1064     auto fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
1065     fetchResult->SetResultNapiType(ResultNapiType::TYPE_PHOTOACCESS_HELPER);
1066 
1067     std::vector<std::unique_ptr<FileAsset>> fileAssetArray;
1068     auto file = fetchResult->GetFirstObject();
1069     while (file != nullptr) {
1070         fileAssetArray.push_back(move(file));
1071         file = fetchResult->GetNextObject();
1072     }
1073     napi_value jsFileArray = nullptr;
1074     size_t len = fileAssetArray.size();
1075     napi_create_array_with_length(env, len, &jsFileArray);
1076     size_t i = 0;
1077     for (i = 0; i < len; i++) {
1078         napi_value jsFileAsset = FileAssetNapi::CreateFileAsset(env, fileAssetArray[i]);
1079         if ((jsFileAsset == nullptr) || (napi_set_element(env, jsFileArray, i, jsFileAsset) != napi_ok)) {
1080             NAPI_ERR_LOG("Failed to get file asset napi object");
1081             break;
1082         }
1083     }
1084     return (i == len) ? jsFileArray : nullptr;
1085 }
1086 
GetPhotoMapQueryResult(napi_env env,PhotoAlbumNapiAsyncContext * context,unique_ptr<JSAsyncContextOutput> & jsContext)1087 static void GetPhotoMapQueryResult(napi_env env, PhotoAlbumNapiAsyncContext *context,
1088     unique_ptr<JSAsyncContextOutput> &jsContext)
1089 {
1090     napi_value fetchRes = FetchFileResultNapi::CreateFetchFileResult(env, move(context->fetchResult));
1091     if (fetchRes == nullptr) {
1092         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
1093             "Failed to create js object for FetchFileResult");
1094         return;
1095     }
1096     jsContext->data = fetchRes;
1097     jsContext->status = true;
1098 }
1099 
JSGetPhotoAssetsCallbackComplete(napi_env env,napi_status status,void * data)1100 static void JSGetPhotoAssetsCallbackComplete(napi_env env, napi_status status, void *data)
1101 {
1102     MediaLibraryTracer tracer;
1103     tracer.Start("JSGetPhotoAssetsCallbackComplete");
1104 
1105     auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1106 
1107     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1108     jsContext->status = false;
1109 
1110     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1111     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1112     if (context->fetchResult != nullptr) {
1113         GetPhotoMapQueryResult(env, context, jsContext);
1114     } else {
1115         NAPI_ERR_LOG("No fetch file result found!");
1116         MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1117             "Failed to get fetchFileResult from DB");
1118     }
1119 
1120     tracer.Finish();
1121     if (context->work != nullptr) {
1122         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1123                                                    context->work, *jsContext);
1124     }
1125     delete context;
1126 }
1127 
JSGetPhotoAssets(napi_env env,napi_callback_info info)1128 napi_value PhotoAlbumNapi::JSGetPhotoAssets(napi_env env, napi_callback_info info)
1129 {
1130     unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1131     CHECK_NULLPTR_RET(ParseArgsGetPhotoAssets(env, info, asyncContext));
1132 
1133     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetPhotoAssets", JSGetPhotoAssetsExecute,
1134         JSGetPhotoAssetsCallbackComplete);
1135 }
1136 
JSPhotoAccessGetPhotoAssets(napi_env env,napi_callback_info info)1137 napi_value PhotoAlbumNapi::JSPhotoAccessGetPhotoAssets(napi_env env, napi_callback_info info)
1138 {
1139     unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1140     CHECK_NULLPTR_RET(ParseArgsGetPhotoAssets(env, info, asyncContext));
1141 
1142     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetPhotoAssets",
1143         JSPhotoAccessGetPhotoAssetsExecute, JSGetPhotoAssetsCallbackComplete);
1144 }
1145 
JSPhotoAccessGetPhotoAssetsSync(napi_env env,napi_callback_info info)1146 napi_value PhotoAlbumNapi::JSPhotoAccessGetPhotoAssetsSync(napi_env env, napi_callback_info info)
1147 {
1148     MediaLibraryTracer tracer;
1149     tracer.Start("JSPhotoAccessGetPhotoAssetsSync");
1150 
1151     unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1152     CHECK_NULLPTR_RET(ParseArgsGetPhotoAssets(env, info, asyncContext));
1153     return JSPhotoAccessGetPhotoAssetsExecuteSync(env, *asyncContext);
1154 }
1155 
TrashAlbumParseArgs(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1156 static napi_value TrashAlbumParseArgs(napi_env env, napi_callback_info info,
1157     unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1158 {
1159     if (!MediaLibraryNapiUtils::IsSystemApp()) {
1160         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
1161         return nullptr;
1162     }
1163 
1164     napi_value result = nullptr;
1165     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1166     constexpr size_t minArgs = ARGS_ONE;
1167     constexpr size_t maxArgs = ARGS_TWO;
1168     CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
1169         JS_ERR_PARAMETER_INVALID);
1170     auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1171     if (!PhotoAlbum::IsTrashAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
1172         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check trash album type");
1173         return nullptr;
1174     }
1175 
1176     /* Parse the first argument */
1177     vector<napi_value> napiValues;
1178     CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetNapiValueArray(env, context->argv[PARAM0], napiValues));
1179     if (napiValues.empty()) {
1180         return result;
1181     }
1182     napi_valuetype valueType = napi_undefined;
1183     vector<string> uris;
1184     CHECK_ARGS(env, napi_typeof(env, napiValues.front(), &valueType), JS_ERR_PARAMETER_INVALID);
1185     if (valueType == napi_string) {
1186         // The input should be an array of asset uri.
1187         CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetStringArray(env, napiValues, uris));
1188     } else if (valueType == napi_object) {
1189         // The input should be an array of asset object.
1190         CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetUriArrayFromAssets(env, napiValues, uris));
1191     }
1192     if (uris.empty()) {
1193         return result;
1194     }
1195 
1196     context->predicates.In(MediaColumn::MEDIA_ID, uris);
1197     context->valuesBucket.Put(MediaColumn::MEDIA_DATE_TRASHED, 0);
1198 
1199     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1200     return result;
1201 }
1202 
TrashAlbumExecute(const TrashAlbumExecuteOpt & opt)1203 static void TrashAlbumExecute(const TrashAlbumExecuteOpt &opt)
1204 {
1205     MediaLibraryTracer tracer;
1206     tracer.Start(opt.tracerLabel);
1207 
1208     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(opt.data);
1209     if (context->predicates.GetOperationList().empty()) {
1210         return;
1211     }
1212     Uri uri(opt.uri);
1213     int changedRows = UserFileClient::Update(uri, context->predicates, context->valuesBucket);
1214     if (changedRows < 0) {
1215         context->SaveError(changedRows);
1216         return;
1217     }
1218     context->changedRows = changedRows;
1219 }
1220 
TrashAlbumComplete(napi_env env,napi_status status,void * data)1221 static void TrashAlbumComplete(napi_env env, napi_status status, void *data)
1222 {
1223     auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
1224     auto jsContext = make_unique<JSAsyncContextOutput>();
1225     jsContext->status = false;
1226     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1227     if (context->error == ERR_DEFAULT) {
1228         CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1229         jsContext->status = true;
1230     } else {
1231         context->HandleError(env, jsContext->error);
1232     }
1233 
1234     if (context->work != nullptr) {
1235         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1236                                                    context->work, *jsContext);
1237     }
1238     delete context;
1239 }
1240 
RecoverPhotosExecute(napi_env env,void * data)1241 static void RecoverPhotosExecute(napi_env env, void *data)
1242 {
1243     TrashAlbumExecuteOpt opt = {
1244         .env = env,
1245         .data = data,
1246         .tracerLabel = "RecoverPhotosExecute",
1247         .uri = (static_cast<PhotoAlbumNapiAsyncContext *>(data)->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
1248             UFM_RECOVER_PHOTOS : PAH_RECOVER_PHOTOS,
1249     };
1250     TrashAlbumExecute(opt);
1251 }
1252 
RecoverPhotosComplete(napi_env env,napi_status status,void * data)1253 static void RecoverPhotosComplete(napi_env env, napi_status status, void *data)
1254 {
1255     TrashAlbumComplete(env, status, data);
1256 }
1257 
JSRecoverPhotos(napi_env env,napi_callback_info info)1258 napi_value PhotoAlbumNapi::JSRecoverPhotos(napi_env env, napi_callback_info info)
1259 {
1260     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1261     CHECK_NULLPTR_RET(TrashAlbumParseArgs(env, info, asyncContext));
1262     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1263 
1264     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRecoverPhotos", RecoverPhotosExecute,
1265         RecoverPhotosComplete);
1266 }
1267 
PrivateAlbumParseArgs(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1268 static napi_value PrivateAlbumParseArgs(napi_env env, napi_callback_info info,
1269     unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1270 {
1271     string uri;
1272     CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, context, uri),
1273         JS_ERR_PARAMETER_INVALID);
1274     auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1275     if (photoAlbum == nullptr) {
1276         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get photo album instance");
1277         return nullptr;
1278     }
1279     if (!PhotoAlbum::IsTrashAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
1280         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check trash album type");
1281         return nullptr;
1282     }
1283 
1284     context->predicates.EqualTo(MediaColumn::MEDIA_ID, MediaFileUtils::GetIdFromUri(uri));
1285     context->valuesBucket.Put(MediaColumn::MEDIA_DATE_TRASHED, 0);
1286 
1287     napi_value result = nullptr;
1288     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1289     return result;
1290 }
1291 
PrivateAlbumRecoverPhotos(napi_env env,napi_callback_info info)1292 napi_value PhotoAlbumNapi::PrivateAlbumRecoverPhotos(napi_env env, napi_callback_info info)
1293 {
1294     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1295     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1296     CHECK_NULLPTR_RET(PrivateAlbumParseArgs(env, info, asyncContext));
1297 
1298     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PrivateAlbumRecoverPhotos",
1299         RecoverPhotosExecute, RecoverPhotosComplete);
1300 }
1301 
PhotoAccessHelperRecoverPhotos(napi_env env,napi_callback_info info)1302 napi_value PhotoAlbumNapi::PhotoAccessHelperRecoverPhotos(napi_env env, napi_callback_info info)
1303 {
1304     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1305     CHECK_NULLPTR_RET(TrashAlbumParseArgs(env, info, asyncContext));
1306     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1307 
1308     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRecoverPhotos", RecoverPhotosExecute,
1309         RecoverPhotosComplete);
1310 }
1311 
DeletePhotosExecute(napi_env env,void * data)1312 static void DeletePhotosExecute(napi_env env, void *data)
1313 {
1314     TrashAlbumExecuteOpt opt = {
1315         .env = env,
1316         .data = data,
1317         .tracerLabel = "DeletePhotosExecute",
1318         .uri = (static_cast<PhotoAlbumNapiAsyncContext *>(data)->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
1319             UFM_DELETE_PHOTOS : PAH_DELETE_PHOTOS,
1320     };
1321     TrashAlbumExecute(opt);
1322 }
1323 
DeletePhotosComplete(napi_env env,napi_status status,void * data)1324 static void DeletePhotosComplete(napi_env env, napi_status status, void *data)
1325 {
1326     TrashAlbumComplete(env, status, data);
1327 }
1328 
JSDeletePhotos(napi_env env,napi_callback_info info)1329 napi_value PhotoAlbumNapi::JSDeletePhotos(napi_env env, napi_callback_info info)
1330 {
1331     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1332     CHECK_NULLPTR_RET(TrashAlbumParseArgs(env, info, asyncContext));
1333     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1334 
1335     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSDeletePhotos", DeletePhotosExecute,
1336         DeletePhotosComplete);
1337 }
1338 
PrivateAlbumDeletePhotos(napi_env env,napi_callback_info info)1339 napi_value PhotoAlbumNapi::PrivateAlbumDeletePhotos(napi_env env, napi_callback_info info)
1340 {
1341     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1342     asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1343     CHECK_NULLPTR_RET(PrivateAlbumParseArgs(env, info, asyncContext));
1344 
1345     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PrivateAlbumDeletePhotos",
1346         DeletePhotosExecute, DeletePhotosComplete);
1347 }
1348 
PhotoAccessHelperDeletePhotos(napi_env env,napi_callback_info info)1349 napi_value PhotoAlbumNapi::PhotoAccessHelperDeletePhotos(napi_env env, napi_callback_info info)
1350 {
1351     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1352     CHECK_NULLPTR_RET(TrashAlbumParseArgs(env, info, asyncContext));
1353     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1354 
1355     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSDeletePhotos", DeletePhotosExecute,
1356         DeletePhotosComplete);
1357 }
1358 
ParseArgsSetCoverUri(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1359 static napi_value ParseArgsSetCoverUri(napi_env env, napi_callback_info info,
1360     unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1361 {
1362     string coverUri;
1363     CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, context, coverUri),
1364         JS_ERR_PARAMETER_INVALID);
1365     auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1366     if (!MediaLibraryNapiUtils::IsSystemApp()) {
1367         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Only system apps can update album cover");
1368         return nullptr;
1369     }
1370 
1371     context->predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(photoAlbum->GetAlbumId()));
1372     context->valuesBucket.Put(PhotoAlbumColumns::ALBUM_COVER_URI, coverUri);
1373 
1374     napi_value result = nullptr;
1375     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1376     return result;
1377 }
1378 
PhotoAccessHelperSetCoverUri(napi_env env,napi_callback_info info)1379 napi_value PhotoAlbumNapi::PhotoAccessHelperSetCoverUri(napi_env env, napi_callback_info info)
1380 {
1381     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1382     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1383     CHECK_NULLPTR_RET(ParseArgsSetCoverUri(env, info, asyncContext));
1384 
1385     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
1386         JSCommitModifyCompleteCallback);
1387 }
1388 
PhotoAccessHelperGetFaceIdExec(napi_env env,void * data)1389 static void PhotoAccessHelperGetFaceIdExec(napi_env env, void *data)
1390 {
1391     auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1392     auto jsContext = make_unique<JSAsyncContextOutput>();
1393     jsContext->status = false;
1394 
1395     PhotoAlbumSubType albumSubType = context->objectInfo->GetPhotoAlbumInstance()->GetPhotoAlbumSubType();
1396     if (albumSubType != PhotoAlbumSubType::PORTRAIT && albumSubType != PhotoAlbumSubType::GROUP_PHOTO) {
1397         NAPI_WARN_LOG("albumSubType: %{public}d, not support getFaceId", albumSubType);
1398         return;
1399     }
1400 
1401     Uri uri(PAH_QUERY_ANA_PHOTO_ALBUM);
1402     DataShare::DataSharePredicates predicates;
1403     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, context->objectInfo->GetAlbumId());
1404     vector<string> fetchColumn = { GROUP_TAG };
1405     int errCode = 0;
1406 
1407     auto resultSet = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
1408     if (resultSet == nullptr || resultSet->GoToFirstRow() != 0) {
1409         if (errCode == E_PERMISSION_DENIED) {
1410             context->error = OHOS_PERMISSION_DENIED_CODE;
1411         } else {
1412             context->SaveError(E_FAIL);
1413         }
1414         NAPI_ERR_LOG("get face id failed, errCode is %{public}d", errCode);
1415         return;
1416     }
1417 
1418     context->faceTag = GetStringVal(GROUP_TAG, resultSet);
1419 }
1420 
GetFaceIdCompleteCallback(napi_env env,napi_status status,void * data)1421 static void GetFaceIdCompleteCallback(napi_env env, napi_status status, void *data)
1422 {
1423     auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1424     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1425     auto jsContext = make_unique<JSAsyncContextOutput>();
1426     jsContext->status = false;
1427 
1428     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1429     if (context->error != ERR_DEFAULT) {
1430         context->HandleError(env, jsContext->error);
1431     } else {
1432         CHECK_ARGS_RET_VOID(env,
1433             napi_create_string_utf8(env, context->faceTag.c_str(), NAPI_AUTO_LENGTH, &jsContext->data), JS_INNER_FAIL);
1434         jsContext->status = true;
1435     }
1436 
1437     if (context->work != nullptr) {
1438         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, context->work,
1439             *jsContext);
1440     }
1441     delete context;
1442 }
1443 
PhotoAccessHelperGetFaceId(napi_env env,napi_callback_info info)1444 napi_value PhotoAlbumNapi::PhotoAccessHelperGetFaceId(napi_env env, napi_callback_info info)
1445 {
1446     if (!MediaLibraryNapiUtils::IsSystemApp()) {
1447         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "Only system apps can get the Face ID of the album");
1448         return nullptr;
1449     }
1450 
1451     auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1452 
1453     CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, asyncContext, 0, 0),
1454         JS_ERR_PARAMETER_INVALID);
1455 
1456     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSAnalysisAlbumGetFaceId",
1457         PhotoAccessHelperGetFaceIdExec, GetFaceIdCompleteCallback);
1458 }
1459 } // namespace OHOS::Media
1460