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_napi_utils_ext.h"
26 #include "medialibrary_tracer.h"
27 #include "photo_map_column.h"
28 #include "result_set_utils.h"
29 #include "userfile_client.h"
30 #include "album_operation_uri.h"
31 #include "user_define_ipc_client.h"
32 #include "medialibrary_business_code.h"
33 #include "delete_photos_vo.h"
34 #include "album_commit_modify_vo.h"
35 #include "album_add_assets_vo.h"
36 #include "album_remove_assets_vo.h"
37 #include "album_recover_assets_vo.h"
38 #include "album_photo_query_vo.h"
39 #include "album_get_assets_vo.h"
40 #include "get_face_id_vo.h"
41 #include "shooting_mode_column.h"
42
43 using namespace std;
44 using namespace OHOS::DataShare;
45
46 namespace OHOS::Media {
47 thread_local PhotoAlbum *PhotoAlbumNapi::pAlbumData_ = nullptr;
48 thread_local napi_ref PhotoAlbumNapi::constructor_ = nullptr;
49 thread_local napi_ref PhotoAlbumNapi::photoAccessConstructor_ = nullptr;
50 static const string PHOTO_ALBUM_CLASS = "UserFileMgrPhotoAlbum";
51 static const string PHOTOACCESS_PHOTO_ALBUM_CLASS = "PhotoAccessPhotoAlbum";
52 static const string COUNT_GROUP_BY = "count(*) AS count";
53 std::mutex PhotoAlbumNapi::mutex_;
54
55 struct TrashAlbumExecuteOpt {
56 napi_env env;
57 void *data;
58 string tracerLabel;
59 string uri;
60 };
61
62 using CompleteCallback = napi_async_complete_callback;
63
PhotoAlbumNapi()64 PhotoAlbumNapi::PhotoAlbumNapi() : env_(nullptr) {}
65
66 PhotoAlbumNapi::~PhotoAlbumNapi() = default;
67
Init(napi_env env,napi_value exports)68 napi_value PhotoAlbumNapi::Init(napi_env env, napi_value exports)
69 {
70 NapiClassInfo info = {
71 .name = PHOTO_ALBUM_CLASS,
72 .ref = &constructor_,
73 .constructor = PhotoAlbumNapiConstructor,
74 .props = {
75 DECLARE_NAPI_GETTER_SETTER("albumName", JSGetAlbumName, JSSetAlbumName),
76 DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
77 DECLARE_NAPI_GETTER("count", JSGetAlbumCount),
78 DECLARE_NAPI_GETTER("albumType", JSGetPhotoAlbumType),
79 DECLARE_NAPI_GETTER("albumSubType", JSGetPhotoAlbumSubType),
80 DECLARE_NAPI_GETTER_SETTER("coverUri", JSGetCoverUri, JSSetCoverUri),
81 DECLARE_NAPI_GETTER("dateModified", JSGetDateModified),
82 DECLARE_NAPI_FUNCTION("commitModify", JSCommitModify),
83 DECLARE_NAPI_FUNCTION("addPhotoAssets", JSPhotoAlbumAddAssets),
84 DECLARE_NAPI_FUNCTION("removePhotoAssets", JSPhotoAlbumRemoveAssets),
85 DECLARE_NAPI_FUNCTION("getPhotoAssets", JSGetPhotoAssets),
86 DECLARE_NAPI_FUNCTION("recoverPhotoAssets", JSRecoverPhotos),
87 DECLARE_NAPI_FUNCTION("deletePhotoAssets", JSDeletePhotos),
88 // PrivateAlbum.recover
89 DECLARE_NAPI_FUNCTION("recover", PrivateAlbumRecoverPhotos),
90 // PrivateAlbum.delete
91 DECLARE_NAPI_FUNCTION("delete", PrivateAlbumDeletePhotos),
92 }
93 };
94
95 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
96 return exports;
97 }
98
PhotoAccessInit(napi_env env,napi_value exports)99 napi_value PhotoAlbumNapi::PhotoAccessInit(napi_env env, napi_value exports)
100 {
101 NapiClassInfo info = {
102 .name = PHOTOACCESS_PHOTO_ALBUM_CLASS,
103 .ref = &photoAccessConstructor_,
104 .constructor = PhotoAlbumNapiConstructor,
105 .props = {
106 DECLARE_NAPI_GETTER_SETTER("albumName", JSPhotoAccessGetAlbumName, JSPhotoAccessSetAlbumName),
107 DECLARE_NAPI_GETTER("albumUri", JSPhotoAccessGetAlbumUri),
108 DECLARE_NAPI_GETTER("count", JSPhotoAccessGetAlbumCount),
109 DECLARE_NAPI_GETTER("imageCount", JSPhotoAccessGetAlbumImageCount),
110 DECLARE_NAPI_GETTER("videoCount", JSPhotoAccessGetAlbumVideoCount),
111 DECLARE_NAPI_GETTER("albumType", JSGetPhotoAlbumType),
112 DECLARE_NAPI_GETTER("albumSubtype", JSGetPhotoAlbumSubType),
113 DECLARE_NAPI_GETTER("coverUri", JSGetCoverUri),
114 DECLARE_NAPI_GETTER("latitude", JSGetLatitude),
115 DECLARE_NAPI_GETTER("longitude", JSGetLongitude),
116 DECLARE_NAPI_GETTER("lpath", JSGetAlbumLPath),
117 DECLARE_NAPI_GETTER("dateModified", JSGetDateModifiedSystem),
118 DECLARE_NAPI_GETTER("dateAdded", JSGetDateAdded),
119 DECLARE_NAPI_GETTER("coverUriSource", JSGetCoverUriSource),
120 DECLARE_NAPI_FUNCTION("commitModify", PhotoAccessHelperCommitModify),
121 DECLARE_NAPI_FUNCTION("addAssets", PhotoAccessHelperAddAssets),
122 DECLARE_NAPI_FUNCTION("removeAssets", PhotoAccessHelperRemoveAssets),
123 DECLARE_NAPI_FUNCTION("getAssets", JSPhotoAccessGetPhotoAssets),
124 DECLARE_NAPI_FUNCTION("recoverAssets", PhotoAccessHelperRecoverPhotos),
125 DECLARE_NAPI_FUNCTION("deleteAssets", PhotoAccessHelperDeletePhotos),
126 DECLARE_NAPI_FUNCTION("setCoverUri", PhotoAccessHelperSetCoverUri),
127 DECLARE_NAPI_FUNCTION("getAssetsSync", JSPhotoAccessGetPhotoAssetsSync),
128 DECLARE_NAPI_FUNCTION("getSharedPhotoAssets", JSPhotoAccessGetSharedPhotoAssets),
129 DECLARE_NAPI_FUNCTION("getFaceId", PhotoAccessHelperGetFaceId),
130 }
131 };
132
133 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
134 return exports;
135 }
136
CreatePhotoAlbumNapi(napi_env env,unique_ptr<PhotoAlbum> & albumData)137 napi_value PhotoAlbumNapi::CreatePhotoAlbumNapi(napi_env env, unique_ptr<PhotoAlbum> &albumData)
138 {
139 if (albumData == nullptr) {
140 return nullptr;
141 }
142
143 napi_value constructor;
144 napi_ref constructorRef;
145 if (albumData->GetResultNapiType() == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
146 constructorRef = photoAccessConstructor_;
147 } else {
148 constructorRef = constructor_;
149 }
150 CHECK_ARGS(env, napi_get_reference_value(env, constructorRef, &constructor), JS_INNER_FAIL);
151
152 napi_value result = nullptr;
153 pAlbumData_ = albumData.release();
154 CHECK_ARGS(env, napi_new_instance(env, constructor, 0, nullptr, &result), JS_INNER_FAIL);
155 pAlbumData_ = nullptr;
156 return result;
157 }
158
CreatePhotoAlbumNapi(napi_env env,shared_ptr<PhotoAlbum> & albumData)159 napi_value PhotoAlbumNapi::CreatePhotoAlbumNapi(napi_env env, shared_ptr<PhotoAlbum>& albumData)
160 {
161 if (albumData == nullptr || albumData->GetResultNapiType() != ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
162 NAPI_ERR_LOG("Unsupported photo album data");
163 return nullptr;
164 }
165
166 napi_value constructor = nullptr;
167 napi_value result = nullptr;
168 CHECK_ARGS(env, napi_get_reference_value(env, photoAccessConstructor_, &constructor), JS_INNER_FAIL);
169 CHECK_ARGS(env, napi_new_instance(env, constructor, 0, nullptr, &result), JS_INNER_FAIL);
170 CHECK_COND(env, result != nullptr, JS_INNER_FAIL);
171
172 PhotoAlbumNapi* photoAlbumNapi = nullptr;
173 CHECK_ARGS(env, napi_unwrap(env, result, reinterpret_cast<void**>(&photoAlbumNapi)), JS_INNER_FAIL);
174 CHECK_COND(env, photoAlbumNapi != nullptr, JS_INNER_FAIL);
175 photoAlbumNapi->photoAlbumPtr = albumData;
176 return result;
177 }
178
GetAlbumId() const179 int32_t PhotoAlbumNapi::GetAlbumId() const
180 {
181 return photoAlbumPtr->GetAlbumId();
182 }
183
GetCount() const184 int32_t PhotoAlbumNapi::GetCount() const
185 {
186 return photoAlbumPtr->GetCount();
187 }
188
SetCount(int32_t count)189 void PhotoAlbumNapi::SetCount(int32_t count)
190 {
191 return photoAlbumPtr->SetCount(count);
192 }
193
GetImageCount() const194 int32_t PhotoAlbumNapi::GetImageCount() const
195 {
196 return photoAlbumPtr->GetImageCount();
197 }
198
SetImageCount(int32_t count)199 void PhotoAlbumNapi::SetImageCount(int32_t count)
200 {
201 return photoAlbumPtr->SetImageCount(count);
202 }
203
GetVideoCount() const204 int32_t PhotoAlbumNapi::GetVideoCount() const
205 {
206 return photoAlbumPtr->GetVideoCount();
207 }
208
SetVideoCount(int32_t count)209 void PhotoAlbumNapi::SetVideoCount(int32_t count)
210 {
211 return photoAlbumPtr->SetVideoCount(count);
212 }
213
GetAlbumUri() const214 const string& PhotoAlbumNapi::GetAlbumUri() const
215 {
216 return photoAlbumPtr->GetAlbumUri();
217 }
218
GetCoverUri() const219 const string& PhotoAlbumNapi::GetCoverUri() const
220 {
221 return photoAlbumPtr->GetCoverUri();
222 }
223
GetDateModified() const224 int64_t PhotoAlbumNapi::GetDateModified() const
225 {
226 return photoAlbumPtr->GetDateModified();
227 }
228
GetDateAdded() const229 int64_t PhotoAlbumNapi::GetDateAdded() const
230 {
231 return photoAlbumPtr->GetDateAdded();
232 }
233
GetCoverUriSource() const234 int32_t PhotoAlbumNapi::GetCoverUriSource() const
235 {
236 return photoAlbumPtr->GetCoverUriSource();
237 }
238
GetAlbumName() const239 const string& PhotoAlbumNapi::GetAlbumName() const
240 {
241 return photoAlbumPtr->GetAlbumName();
242 }
243
GetPhotoAlbumType() const244 PhotoAlbumType PhotoAlbumNapi::GetPhotoAlbumType() const
245 {
246 return photoAlbumPtr->GetPhotoAlbumType();
247 }
248
GetPhotoAlbumSubType() const249 PhotoAlbumSubType PhotoAlbumNapi::GetPhotoAlbumSubType() const
250 {
251 return photoAlbumPtr->GetPhotoAlbumSubType();
252 }
253
GetLatitude() const254 double PhotoAlbumNapi::GetLatitude() const
255 {
256 return photoAlbumPtr->GetLatitude();
257 }
258
GetLongitude() const259 double PhotoAlbumNapi::GetLongitude() const
260 {
261 return photoAlbumPtr->GetLongitude();
262 }
263
GetLPath() const264 const string& PhotoAlbumNapi::GetLPath() const
265 {
266 return photoAlbumPtr->GetLPath();
267 }
268
GetPhotoAlbumInstance() const269 shared_ptr<PhotoAlbum> PhotoAlbumNapi::GetPhotoAlbumInstance() const
270 {
271 return photoAlbumPtr;
272 }
273
GetHiddenOnly() const274 bool PhotoAlbumNapi::GetHiddenOnly() const
275 {
276 return photoAlbumPtr->GetHiddenOnly();
277 }
278
SetHiddenOnly(const bool hiddenOnly_)279 void PhotoAlbumNapi::SetHiddenOnly(const bool hiddenOnly_)
280 {
281 return photoAlbumPtr->SetHiddenOnly(hiddenOnly_);
282 }
283
SetPhotoAlbumNapiProperties()284 void PhotoAlbumNapi::SetPhotoAlbumNapiProperties()
285 {
286 photoAlbumPtr = shared_ptr<PhotoAlbum>(pAlbumData_);
287 }
288
289 // Constructor callback
PhotoAlbumNapiConstructor(napi_env env,napi_callback_info info)290 napi_value PhotoAlbumNapi::PhotoAlbumNapiConstructor(napi_env env, napi_callback_info info)
291 {
292 napi_value result = nullptr;
293 CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
294
295 napi_value thisVar = nullptr;
296 CHECK_ARGS(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr), JS_INNER_FAIL);
297 if (thisVar == nullptr) {
298 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
299 return result;
300 }
301
302 unique_ptr<PhotoAlbumNapi> obj = make_unique<PhotoAlbumNapi>();
303 obj->env_ = env;
304 if (pAlbumData_ != nullptr) {
305 obj->SetPhotoAlbumNapiProperties();
306 }
307 CHECK_ARGS(env, napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
308 PhotoAlbumNapi::PhotoAlbumNapiDestructor, nullptr, nullptr), JS_INNER_FAIL);
309 obj.release();
310 return thisVar;
311 }
312
PhotoAlbumNapiDestructor(napi_env env,void * nativeObject,void * finalizeHint)313 void PhotoAlbumNapi::PhotoAlbumNapiDestructor(napi_env env, void *nativeObject, void *finalizeHint)
314 {
315 auto *album = reinterpret_cast<PhotoAlbumNapi*>(nativeObject);
316 lock_guard<mutex> lockGuard(mutex_);
317 if (album != nullptr) {
318 delete album;
319 album = nullptr;
320 }
321 }
322
UnwrapPhotoAlbumObject(napi_env env,napi_callback_info info,PhotoAlbumNapi ** obj)323 napi_value UnwrapPhotoAlbumObject(napi_env env, napi_callback_info info, PhotoAlbumNapi** obj)
324 {
325 napi_value result = nullptr;
326 CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
327
328 napi_value thisVar = nullptr;
329 CHECK_ARGS(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr), JS_INNER_FAIL);
330 if (thisVar == nullptr) {
331 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
332 return result;
333 }
334
335 CHECK_ARGS(env, napi_unwrap(env, thisVar, reinterpret_cast<void **>(obj)), JS_INNER_FAIL);
336 if (obj == nullptr) {
337 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
338 return result;
339 }
340
341 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
342 return result;
343 }
344
JSGetAlbumName(napi_env env,napi_callback_info info)345 napi_value PhotoAlbumNapi::JSGetAlbumName(napi_env env, napi_callback_info info)
346 {
347 PhotoAlbumNapi *obj = nullptr;
348 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
349
350 napi_value jsResult = nullptr;
351 CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumName().c_str(), NAPI_AUTO_LENGTH, &jsResult),
352 JS_INNER_FAIL);
353 return jsResult;
354 }
355
JSPhotoAccessGetAlbumName(napi_env env,napi_callback_info info)356 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumName(napi_env env, napi_callback_info info)
357 {
358 PhotoAlbumNapi *obj = nullptr;
359 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
360
361 napi_value jsResult = nullptr;
362 CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumName().c_str(), NAPI_AUTO_LENGTH, &jsResult),
363 JS_INNER_FAIL);
364 return jsResult;
365 }
366
JSGetAlbumUri(napi_env env,napi_callback_info info)367 napi_value PhotoAlbumNapi::JSGetAlbumUri(napi_env env, napi_callback_info info)
368 {
369 PhotoAlbumNapi *obj = nullptr;
370 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
371
372 napi_value jsResult = nullptr;
373 CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
374 JS_INNER_FAIL);
375 return jsResult;
376 }
377
JSPhotoAccessGetAlbumUri(napi_env env,napi_callback_info info)378 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumUri(napi_env env, napi_callback_info info)
379 {
380 PhotoAlbumNapi *obj = nullptr;
381 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
382
383 napi_value jsResult = nullptr;
384 CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetAlbumUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
385 JS_INNER_FAIL);
386 return jsResult;
387 }
388
JSGetAlbumCount(napi_env env,napi_callback_info info)389 napi_value PhotoAlbumNapi::JSGetAlbumCount(napi_env env, napi_callback_info info)
390 {
391 PhotoAlbumNapi *obj = nullptr;
392 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
393
394 napi_value jsResult = nullptr;
395 CHECK_ARGS(env, napi_create_int32(env, obj->GetCount(), &jsResult), JS_INNER_FAIL);
396 return jsResult;
397 }
398
JSPhotoAccessGetAlbumCount(napi_env env,napi_callback_info info)399 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumCount(napi_env env, napi_callback_info info)
400 {
401 PhotoAlbumNapi *obj = nullptr;
402 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
403
404 napi_value jsResult = nullptr;
405 CHECK_ARGS(env, napi_create_int32(env, obj->GetCount(), &jsResult), JS_INNER_FAIL);
406 return jsResult;
407 }
408
JSPhotoAccessGetAlbumImageCount(napi_env env,napi_callback_info info)409 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumImageCount(napi_env env, napi_callback_info info)
410 {
411 PhotoAlbumNapi *obj = nullptr;
412 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
413
414 napi_value jsResult = nullptr;
415 CHECK_ARGS(env, napi_create_int32(env, obj->GetImageCount(), &jsResult), JS_INNER_FAIL);
416 return jsResult;
417 }
418
JSPhotoAccessGetAlbumVideoCount(napi_env env,napi_callback_info info)419 napi_value PhotoAlbumNapi::JSPhotoAccessGetAlbumVideoCount(napi_env env, napi_callback_info info)
420 {
421 PhotoAlbumNapi *obj = nullptr;
422 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
423
424 napi_value jsResult = nullptr;
425 CHECK_ARGS(env, napi_create_int32(env, obj->GetVideoCount(), &jsResult), JS_INNER_FAIL);
426 return jsResult;
427 }
428
JSGetPhotoAlbumType(napi_env env,napi_callback_info info)429 napi_value PhotoAlbumNapi::JSGetPhotoAlbumType(napi_env env, napi_callback_info info)
430 {
431 PhotoAlbumNapi *obj = nullptr;
432 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
433
434 napi_value jsResult = nullptr;
435 CHECK_ARGS(env, napi_create_int32(env, obj->GetPhotoAlbumType(), &jsResult), JS_INNER_FAIL);
436 return jsResult;
437 }
438
JSGetPhotoAlbumSubType(napi_env env,napi_callback_info info)439 napi_value PhotoAlbumNapi::JSGetPhotoAlbumSubType(napi_env env, napi_callback_info info)
440 {
441 PhotoAlbumNapi *obj = nullptr;
442 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
443
444 napi_value jsResult = nullptr;
445 CHECK_ARGS(env, napi_create_int32(env, obj->GetPhotoAlbumSubType(), &jsResult), JS_INNER_FAIL);
446 return jsResult;
447 }
448
JSGetCoverUri(napi_env env,napi_callback_info info)449 napi_value PhotoAlbumNapi::JSGetCoverUri(napi_env env, napi_callback_info info)
450 {
451 PhotoAlbumNapi *obj = nullptr;
452 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
453
454 napi_value jsResult = nullptr;
455 CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetCoverUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
456 JS_INNER_FAIL);
457 return jsResult;
458 }
459
JSGetLatitude(napi_env env,napi_callback_info info)460 napi_value PhotoAlbumNapi::JSGetLatitude(napi_env env, napi_callback_info info)
461 {
462 PhotoAlbumNapi *obj = nullptr;
463 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
464
465 napi_value jsResult = nullptr;
466 CHECK_ARGS(env, napi_create_double(env, obj->GetLatitude(), &jsResult), JS_INNER_FAIL);
467 return jsResult;
468 }
469
JSGetLongitude(napi_env env,napi_callback_info info)470 napi_value PhotoAlbumNapi::JSGetLongitude(napi_env env, napi_callback_info info)
471 {
472 PhotoAlbumNapi *obj = nullptr;
473 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
474
475 napi_value jsResult = nullptr;
476 CHECK_ARGS(env, napi_create_double(env, obj->GetLongitude(), &jsResult), JS_INNER_FAIL);
477 return jsResult;
478 }
479
JSGetAlbumLPath(napi_env env,napi_callback_info info)480 napi_value PhotoAlbumNapi::JSGetAlbumLPath(napi_env env, napi_callback_info info)
481 {
482 CHECK_COND_LOG_THROW_RETURN_RET(env, MediaLibraryNapiUtils::IsSystemApp(), JS_ERR_PERMISSION_DENIED,
483 "Get lpath permission denied: not a system app", nullptr, "Get album lpath failed: not a system app");
484 CHECK_COND(env, MediaLibraryNapiUtils::IsSystemApp(), JS_ERR_PERMISSION_DENIED);
485 PhotoAlbumNapi *obj = nullptr;
486 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
487
488 napi_value jsResult = nullptr;
489 CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetLPath().c_str(), NAPI_AUTO_LENGTH, &jsResult), JS_INNER_FAIL);
490 return jsResult;
491 }
492
GetStringArg(napi_env env,napi_callback_info info,PhotoAlbumNapi ** obj,string & output)493 napi_value GetStringArg(napi_env env, napi_callback_info info, PhotoAlbumNapi **obj, string &output)
494 {
495 size_t argc = ARGS_ONE;
496 napi_value argv[ARGS_ONE];
497 napi_value thisVar = nullptr;
498 CHECK_ARGS(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr), JS_INNER_FAIL);
499 CHECK_COND(env, argc == ARGS_ONE, JS_ERR_PARAMETER_INVALID);
500
501 napi_value result = nullptr;
502 CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
503 napi_valuetype valueType = napi_undefined;
504 if ((thisVar == nullptr) || (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok) || (valueType != napi_string)) {
505 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
506 return result;
507 }
508
509 size_t res = 0;
510 char buffer[FILENAME_MAX];
511 CHECK_ARGS(env, napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res), JS_INNER_FAIL);
512 output = string(buffer);
513
514 CHECK_ARGS(env, napi_unwrap(env, thisVar, reinterpret_cast<void **>(obj)), JS_INNER_FAIL);
515 if (obj == nullptr) {
516 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
517 return result;
518 }
519
520 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
521 return result;
522 }
523
JSSetAlbumName(napi_env env,napi_callback_info info)524 napi_value PhotoAlbumNapi::JSSetAlbumName(napi_env env, napi_callback_info info)
525 {
526 PhotoAlbumNapi *obj = nullptr;
527 string albumName;
528 CHECK_NULLPTR_RET(GetStringArg(env, info, &obj, albumName));
529 obj->photoAlbumPtr->SetAlbumName(albumName);
530
531 napi_value result = nullptr;
532 CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
533 return result;
534 }
535
JSPhotoAccessSetAlbumName(napi_env env,napi_callback_info info)536 napi_value PhotoAlbumNapi::JSPhotoAccessSetAlbumName(napi_env env, napi_callback_info info)
537 {
538 PhotoAlbumNapi *obj = nullptr;
539 string albumName;
540 CHECK_NULLPTR_RET(GetStringArg(env, info, &obj, albumName));
541 obj->photoAlbumPtr->SetAlbumName(albumName);
542
543 napi_value result = nullptr;
544 CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
545 return result;
546 }
547
JSSetCoverUri(napi_env env,napi_callback_info info)548 napi_value PhotoAlbumNapi::JSSetCoverUri(napi_env env, napi_callback_info info)
549 {
550 PhotoAlbumNapi *obj = nullptr;
551 string coverUri;
552 CHECK_NULLPTR_RET(GetStringArg(env, info, &obj, coverUri));
553 obj->photoAlbumPtr->SetCoverUri(coverUri);
554
555 napi_value result = nullptr;
556 CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL);
557 return result;
558 }
559
JSGetDateModified(napi_env env,napi_callback_info info)560 napi_value PhotoAlbumNapi::JSGetDateModified(napi_env env, napi_callback_info info)
561 {
562 PhotoAlbumNapi *obj = nullptr;
563 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
564
565 napi_value jsResult = nullptr;
566 CHECK_ARGS(env, napi_create_int64(env, obj->GetDateModified(), &jsResult),
567 JS_INNER_FAIL);
568 return jsResult;
569 }
570
JSGetDateModifiedSystem(napi_env env,napi_callback_info info)571 napi_value PhotoAlbumNapi::JSGetDateModifiedSystem(napi_env env, napi_callback_info info)
572 {
573 CHECK_COND_LOG_THROW_RETURN_RET(env, MediaLibraryNapiUtils::IsSystemApp(), JS_ERR_PERMISSION_DENIED,
574 "Get dateModified permission denied: not a system app", nullptr,
575 "Get album dateModified failed: not a system app");
576 PhotoAlbumNapi *obj = nullptr;
577 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
578
579 napi_value jsResult = nullptr;
580 CHECK_ARGS(env, napi_create_int64(env, obj->GetDateModified(), &jsResult),
581 JS_INNER_FAIL);
582 return jsResult;
583 }
584
585
JSGetDateAdded(napi_env env,napi_callback_info info)586 napi_value PhotoAlbumNapi::JSGetDateAdded(napi_env env, napi_callback_info info)
587 {
588 CHECK_COND_LOG_THROW_RETURN_RET(env, MediaLibraryNapiUtils::IsSystemApp(), JS_ERR_PERMISSION_DENIED,
589 "Get dateAdded permission denied: not a system app", nullptr, "Get album dateAdded failed: not a system app");
590 PhotoAlbumNapi *obj = nullptr;
591 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
592
593 napi_value jsResult = nullptr;
594 CHECK_ARGS(env, napi_create_int64(env, obj->GetDateAdded(), &jsResult),
595 JS_INNER_FAIL);
596 return jsResult;
597 }
598
JSGetCoverUriSource(napi_env env,napi_callback_info info)599 napi_value PhotoAlbumNapi::JSGetCoverUriSource(napi_env env, napi_callback_info info)
600 {
601 CHECK_COND_LOG_THROW_RETURN_RET(env, MediaLibraryNapiUtils::IsSystemApp(), JS_ERR_PERMISSION_DENIED,
602 "GetCoverUriSource permission denied: not a system app", nullptr, "GetCoverUriSource failed: not a system app");
603 PhotoAlbumNapi *obj = nullptr;
604 CHECK_NULLPTR_RET(UnwrapPhotoAlbumObject(env, info, &obj));
605
606 napi_value jsResult = nullptr;
607 CHECK_ARGS(env, napi_create_int32(env, obj->GetCoverUriSource(), &jsResult),
608 JS_INNER_FAIL);
609 return jsResult;
610 }
611
ParseArgsCommitModify(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)612 static napi_value ParseArgsCommitModify(napi_env env, napi_callback_info info,
613 unique_ptr<PhotoAlbumNapiAsyncContext> &context)
614 {
615 constexpr size_t minArgs = ARGS_ZERO;
616 constexpr size_t maxArgs = ARGS_ONE;
617 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
618 JS_ERR_PARAMETER_INVALID);
619
620 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
621 if (photoAlbum == nullptr) {
622 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
623 return nullptr;
624 }
625 if (!PhotoAlbum::IsUserPhotoAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
626 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
627 return nullptr;
628 }
629
630 if (MediaFileUtils::CheckAlbumName(photoAlbum->GetAlbumName()) < 0) {
631 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
632 return nullptr;
633 }
634 context->predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(photoAlbum->GetAlbumId()));
635 context->valuesBucket.Put(PhotoAlbumColumns::ALBUM_NAME, photoAlbum->GetAlbumName());
636 context->valuesBucket.Put(PhotoAlbumColumns::ALBUM_COVER_URI, photoAlbum->GetCoverUri());
637 context->businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_COMMIT_MODIFY);
638
639 napi_value result = nullptr;
640 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
641 return result;
642 }
643
JSCommitModifyIPCExecute(PhotoAlbumNapiAsyncContext * context)644 static void JSCommitModifyIPCExecute(PhotoAlbumNapiAsyncContext *context)
645 {
646 int32_t changedRows = 0;
647 auto objectInfo = context->objectInfo;
648 if (objectInfo == nullptr) {
649 NAPI_ERR_LOG("objectInfo is nullptr");
650 return;
651 }
652 auto photoAlbum = objectInfo->GetPhotoAlbumInstance();
653 AlbumCommitModifyReqBody reqBody;
654 reqBody.businessCode = context->businessCode;
655 if (reqBody.businessCode == static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_COMMIT_MODIFY)) {
656 reqBody.albumName = photoAlbum->GetAlbumName();
657 reqBody.albumType = photoAlbum->GetPhotoAlbumType();
658 reqBody.albumSubType = photoAlbum->GetPhotoAlbumSubType();
659 }
660
661 bool isValid = false;
662 string coverUri = context->valuesBucket.Get(PhotoAlbumColumns::ALBUM_COVER_URI, isValid);
663 reqBody.coverUri = coverUri;
664 if (!isValid) {
665 NAPI_ERR_LOG("CommitModify get coveruri fail.");
666 context->SaveError(changedRows);
667 return;
668 }
669
670 reqBody.albumId = photoAlbum->GetAlbumId();
671 changedRows = IPC::UserDefineIPCClient().Call(context->businessCode, reqBody);
672 context->SaveError(changedRows);
673 context->changedRows = changedRows;
674 }
675
JSCommitModifyExecute(napi_env env,void * data)676 static void JSCommitModifyExecute(napi_env env, void *data)
677 {
678 MediaLibraryTracer tracer;
679 tracer.Start("JSCommitModifyExecute");
680
681 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
682 if (context->resultNapiType != ResultNapiType::TYPE_USERFILE_MGR) {
683 JSCommitModifyIPCExecute(context);
684 return;
685 }
686
687 Uri uri(UFM_UPDATE_PHOTO_ALBUM);
688 int changedRows = UserFileClient::Update(uri, context->predicates, context->valuesBucket);
689 context->SaveError(changedRows);
690 context->changedRows = changedRows;
691 }
692
JSCommitModifyCompleteCallback(napi_env env,napi_status status,void * data)693 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, void *data)
694 {
695 MediaLibraryTracer tracer;
696 tracer.Start("JSCommitModifyCompleteCallback");
697
698 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
699 auto jsContext = make_unique<JSAsyncContextOutput>();
700 jsContext->status = false;
701 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
702 if (context->error == ERR_DEFAULT) {
703 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
704 jsContext->status = true;
705 } else {
706 context->HandleError(env, jsContext->error);
707 }
708
709 tracer.Finish();
710 if (context->work != nullptr) {
711 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
712 context->work, *jsContext);
713 }
714 delete context;
715 }
716
JSCommitModify(napi_env env,napi_callback_info info)717 napi_value PhotoAlbumNapi::JSCommitModify(napi_env env, napi_callback_info info)
718 {
719 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
720 CHECK_NULLPTR_RET(ParseArgsCommitModify(env, info, asyncContext));
721 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
722
723 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
724 JSCommitModifyCompleteCallback);
725 }
726
PhotoAccessHelperCommitModify(napi_env env,napi_callback_info info)727 napi_value PhotoAlbumNapi::PhotoAccessHelperCommitModify(napi_env env, napi_callback_info info)
728 {
729 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
730 CHECK_NULLPTR_RET(ParseArgsCommitModify(env, info, asyncContext));
731 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
732
733 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
734 JSCommitModifyCompleteCallback);
735 }
736
GetAssetsIdArray(napi_env env,napi_value arg,vector<string> & assetsArray)737 static napi_value GetAssetsIdArray(napi_env env, napi_value arg, vector<string> &assetsArray)
738 {
739 bool isArray = false;
740 CHECK_ARGS(env, napi_is_array(env, arg, &isArray), JS_INNER_FAIL);
741 if (!isArray) {
742 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check array type");
743 return nullptr;
744 }
745
746 uint32_t len = 0;
747 CHECK_ARGS(env, napi_get_array_length(env, arg, &len), JS_INNER_FAIL);
748 if (len < 0) {
749 NAPI_ERR_LOG("Failed to check array length: %{public}u", len);
750 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check array length");
751 return nullptr;
752 }
753 if (len == 0) {
754 napi_value result = nullptr;
755 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
756 return result;
757 }
758
759 for (uint32_t i = 0; i < len; i++) {
760 napi_value asset = nullptr;
761 CHECK_ARGS(env, napi_get_element(env, arg, i, &asset), JS_INNER_FAIL);
762 if (asset == nullptr) {
763 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get asset element");
764 return nullptr;
765 }
766
767 FileAssetNapi *obj = nullptr;
768 CHECK_ARGS(env, napi_unwrap(env, asset, reinterpret_cast<void **>(&obj)), JS_INNER_FAIL);
769 if (obj == nullptr) {
770 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get asset napi object");
771 return nullptr;
772 }
773 if ((obj->GetMediaType() != MEDIA_TYPE_IMAGE && obj->GetMediaType() != MEDIA_TYPE_VIDEO)) {
774 NAPI_INFO_LOG("Skip invalid asset, mediaType: %{public}d", obj->GetMediaType());
775 continue;
776 }
777 assetsArray.push_back(obj->GetFileUri());
778 }
779
780 napi_value result = nullptr;
781 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
782 return result;
783 }
784
ParseArgsAddAssets(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)785 static napi_value ParseArgsAddAssets(napi_env env, napi_callback_info info,
786 unique_ptr<PhotoAlbumNapiAsyncContext> &context)
787 {
788 constexpr size_t minArgs = ARGS_ONE;
789 constexpr size_t maxArgs = ARGS_TWO;
790 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
791 JS_ERR_PARAMETER_INVALID);
792
793 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
794 if (!PhotoAlbum::IsUserPhotoAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
795 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
796 return nullptr;
797 }
798
799 /* Parse the first argument */
800 vector<string> assetsArray;
801 CHECK_NULLPTR_RET(GetAssetsIdArray(env, context->argv[PARAM0], assetsArray));
802 context->assetsArray = assetsArray;
803 if (assetsArray.empty()) {
804 napi_value result = nullptr;
805 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
806 return result;
807 }
808 int32_t albumId = photoAlbum->GetAlbumId();
809 for (const auto &assetId : assetsArray) {
810 DataShareValuesBucket valuesBucket;
811 valuesBucket.Put(PhotoColumn::PHOTO_OWNER_ALBUM_ID, albumId);
812 valuesBucket.Put(PhotoColumn::MEDIA_ID, assetId);
813 context->valuesBuckets.push_back(valuesBucket);
814 }
815
816 napi_value result = nullptr;
817 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
818 return result;
819 }
820
FetchNewCount(PhotoAlbumNapiAsyncContext * context)821 static int32_t FetchNewCount(PhotoAlbumNapiAsyncContext *context)
822 {
823 string queryUri = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
824 UFM_QUERY_PHOTO_ALBUM : PAH_QUERY_PHOTO_ALBUM;
825 Uri qUri(queryUri);
826 int errCode = 0;
827 DataSharePredicates predicates;
828 predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, context->objectInfo->GetAlbumId());
829 vector<string> fetchColumn = {
830 PhotoAlbumColumns::ALBUM_ID,
831 PhotoAlbumColumns::ALBUM_COUNT,
832 };
833 bool isSmartAlbum = (context->objectInfo->GetPhotoAlbumType() == PhotoAlbumType::SMART);
834 if (!isSmartAlbum) {
835 fetchColumn.push_back(PhotoAlbumColumns::ALBUM_IMAGE_COUNT);
836 fetchColumn.push_back(PhotoAlbumColumns::ALBUM_VIDEO_COUNT);
837 }
838 auto resultSet = UserFileClient::Query(qUri, predicates, fetchColumn, errCode);
839 if (resultSet == nullptr) {
840 NAPI_ERR_LOG("resultSet == nullptr, errCode is %{public}d", errCode);
841 return -1;
842 }
843 if (resultSet->GoToFirstRow() != 0) {
844 NAPI_ERR_LOG("go to first row failed");
845 return -1;
846 }
847 bool hiddenOnly = context->objectInfo->GetHiddenOnly();
848 int imageCount = (hiddenOnly || isSmartAlbum) ? -1 :
849 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_IMAGE_COUNT, resultSet, TYPE_INT32));
850 int videoCount = (hiddenOnly || isSmartAlbum) ? -1 :
851 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_VIDEO_COUNT, resultSet, TYPE_INT32));
852 context->newCount =
853 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_COUNT, resultSet, TYPE_INT32));
854 context->newImageCount = imageCount;
855 context->newVideoCount = videoCount;
856 return 0;
857 }
858
JSPhotoAlbumAddAssetsIPCExecute(PhotoAlbumNapiAsyncContext * context)859 static void JSPhotoAlbumAddAssetsIPCExecute(PhotoAlbumNapiAsyncContext *context)
860 {
861 auto objectInfo = context->objectInfo;
862 if (objectInfo == nullptr) {
863 NAPI_ERR_LOG("objectInfo is nullptr");
864 return;
865 }
866 auto photoAlbum = objectInfo->GetPhotoAlbumInstance();
867 if (photoAlbum == nullptr) {
868 NAPI_ERR_LOG("photoAlbum is nullptr");
869 return;
870 }
871 AlbumPhotoQueryRespBody respBody;
872 AlbumAddAssetsReqBody reqBody;
873 reqBody.albumId = photoAlbum->GetAlbumId();
874 reqBody.albumType = photoAlbum->GetPhotoAlbumType();
875 reqBody.albumSubType = photoAlbum->GetPhotoAlbumSubType();
876 reqBody.assetsArray = context->assetsArray;
877 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_ADD_ASSETS);
878
879 int32_t changedRows = IPC::UserDefineIPCClient().Call(businessCode, reqBody, respBody);
880 if (changedRows < 0) {
881 context->SaveError(changedRows);
882 return;
883 }
884
885 bool hiddenOnly = objectInfo->GetHiddenOnly();
886 bool isSmartAlbum = photoAlbum->GetPhotoAlbumType() == PhotoAlbumType::SMART;
887
888 context->changedRows = changedRows;
889 context->newCount = respBody.newCount;
890 context->newImageCount = (hiddenOnly || isSmartAlbum) ? -1 : respBody.newImageCount;
891 context->newVideoCount = (hiddenOnly || isSmartAlbum) ? -1 : respBody.newVideoCount;
892 }
893
JSPhotoAlbumAddAssetsExecute(napi_env env,void * data)894 static void JSPhotoAlbumAddAssetsExecute(napi_env env, void *data)
895 {
896 MediaLibraryTracer tracer;
897 tracer.Start("JSPhotoAlbumAddAssetsExecute");
898 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
899 if (context->valuesBuckets.empty()) {
900 return;
901 }
902
903 if (context->resultNapiType != ResultNapiType::TYPE_USERFILE_MGR) {
904 JSPhotoAlbumAddAssetsIPCExecute(context);
905 return;
906 }
907
908 Uri uri(UFM_PHOTO_ALBUM_ADD_ASSET);
909 auto changedRows = UserFileClient::BatchInsert(uri, context->valuesBuckets);
910 if (changedRows < 0) {
911 context->SaveError(changedRows);
912 return;
913 }
914 context->changedRows = changedRows;
915 int32_t ret = FetchNewCount(context);
916 if (ret < 0) {
917 NAPI_ERR_LOG("Update count failed");
918 context->SaveError(E_HAS_DB_ERROR);
919 }
920 }
921
JSPhotoAlbumAddAssetsCompleteCallback(napi_env env,napi_status status,void * data)922 static void JSPhotoAlbumAddAssetsCompleteCallback(napi_env env, napi_status status, void *data)
923 {
924 MediaLibraryTracer tracer;
925 tracer.Start("JSPhotoAlbumAddAssetsCompleteCallback");
926
927 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
928 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
929 jsContext->status = false;
930 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
931 if (context->error == ERR_DEFAULT) {
932 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
933 jsContext->status = true;
934 context->objectInfo->SetCount(context->newCount);
935 context->objectInfo->SetImageCount(context->newImageCount);
936 context->objectInfo->SetVideoCount(context->newVideoCount);
937 } else {
938 context->HandleError(env, jsContext->error);
939 }
940
941 tracer.Finish();
942 if (context->work != nullptr) {
943 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
944 context->work, *jsContext);
945 }
946 delete context;
947 }
948
JSPhotoAlbumAddAssets(napi_env env,napi_callback_info info)949 napi_value PhotoAlbumNapi::JSPhotoAlbumAddAssets(napi_env env, napi_callback_info info)
950 {
951 unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
952 CHECK_NULLPTR_RET(ParseArgsAddAssets(env, info, asyncContext));
953 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
954
955 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumAddAssets",
956 JSPhotoAlbumAddAssetsExecute, JSPhotoAlbumAddAssetsCompleteCallback);
957 }
958
PhotoAccessHelperAddAssets(napi_env env,napi_callback_info info)959 napi_value PhotoAlbumNapi::PhotoAccessHelperAddAssets(napi_env env, napi_callback_info info)
960 {
961 unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
962 CHECK_NULLPTR_RET(ParseArgsAddAssets(env, info, asyncContext));
963 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
964
965 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumAddAssets",
966 JSPhotoAlbumAddAssetsExecute, JSPhotoAlbumAddAssetsCompleteCallback);
967 }
968
ParseArgsRemoveAssets(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)969 static napi_value ParseArgsRemoveAssets(napi_env env, napi_callback_info info,
970 unique_ptr<PhotoAlbumNapiAsyncContext> &context)
971 {
972 constexpr size_t minArgs = ARGS_ONE;
973 constexpr size_t maxArgs = ARGS_TWO;
974 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
975 JS_ERR_PARAMETER_INVALID);
976
977 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
978 if (!PhotoAlbum::IsUserPhotoAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
979 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
980 return nullptr;
981 }
982
983 /* Parse the first argument */
984 vector<string> assetsArray;
985 CHECK_NULLPTR_RET(GetAssetsIdArray(env, context->argv[PARAM0], assetsArray));
986 if (assetsArray.empty()) {
987 napi_value result = nullptr;
988 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
989 return result;
990 }
991
992 context->assetsArray = assetsArray;
993 context->predicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(photoAlbum->GetAlbumId()));
994 context->predicates.And()->In(PhotoColumn::MEDIA_ID, assetsArray);
995
996 napi_value result = nullptr;
997 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
998 return result;
999 }
1000
JSPhotoAlbumRemoveAssetsIPCExecute(PhotoAlbumNapiAsyncContext * context)1001 static void JSPhotoAlbumRemoveAssetsIPCExecute(PhotoAlbumNapiAsyncContext *context)
1002 {
1003 auto objectInfo = context->objectInfo;
1004 CHECK_IF_EQUAL(objectInfo != nullptr, "objectInfo is nullptr");
1005 auto photoAlbum = objectInfo->GetPhotoAlbumInstance();
1006 CHECK_IF_EQUAL(photoAlbum != nullptr, "photoAlbum is nullptr");
1007 AlbumPhotoQueryRespBody respBody;
1008 AlbumRemoveAssetsReqBody reqBody;
1009 reqBody.albumId = photoAlbum->GetAlbumId();
1010 reqBody.albumType = photoAlbum->GetPhotoAlbumType();
1011 reqBody.albumSubType = photoAlbum->GetPhotoAlbumSubType();
1012 reqBody.assetsArray = context->assetsArray;
1013 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_REMOVE_ASSETS);
1014
1015 int32_t deletedRows = IPC::UserDefineIPCClient().Call(businessCode, reqBody, respBody);
1016 if (deletedRows < 0) {
1017 NAPI_ERR_LOG("Remove assets failed: %{public}d", deletedRows);
1018 context->SaveError(deletedRows);
1019 return;
1020 }
1021
1022 bool hiddenOnly = objectInfo->GetHiddenOnly();
1023 bool isSmartAlbum = photoAlbum->GetPhotoAlbumType() == PhotoAlbumType::SMART;
1024
1025 context->changedRows = deletedRows;
1026 context->newCount = respBody.newCount;
1027 context->newImageCount = (hiddenOnly || isSmartAlbum) ? -1 : respBody.newImageCount;
1028 context->newVideoCount = (hiddenOnly || isSmartAlbum) ? -1 : respBody.newVideoCount;
1029 }
1030
JSPhotoAlbumRemoveAssetsExecute(napi_env env,void * data)1031 static void JSPhotoAlbumRemoveAssetsExecute(napi_env env, void *data)
1032 {
1033 MediaLibraryTracer tracer;
1034 tracer.Start("JSPhotoAlbumRemoveAssetsExecute");
1035
1036 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
1037 if (context->predicates.GetOperationList().empty()) {
1038 NAPI_ERR_LOG("Invalid input: operation list is empty");
1039 return;
1040 }
1041
1042 if (context->resultNapiType != ResultNapiType::TYPE_USERFILE_MGR) {
1043 JSPhotoAlbumRemoveAssetsIPCExecute(context);
1044 return;
1045 }
1046
1047 Uri uri(UFM_PHOTO_ALBUM_REMOVE_ASSET);
1048 auto deletedRows = UserFileClient::Delete(uri, context->predicates);
1049 if (deletedRows < 0) {
1050 NAPI_ERR_LOG("Remove assets failed: %{public}d", deletedRows);
1051 context->SaveError(deletedRows);
1052 return;
1053 }
1054 context->changedRows = deletedRows;
1055 int32_t ret = FetchNewCount(context);
1056 if (ret < 0) {
1057 NAPI_ERR_LOG("Update count failed");
1058 context->SaveError(E_HAS_DB_ERROR);
1059 }
1060 }
1061
JSPhotoAlbumRemoveAssetsCompleteCallback(napi_env env,napi_status status,void * data)1062 static void JSPhotoAlbumRemoveAssetsCompleteCallback(napi_env env, napi_status status, void *data)
1063 {
1064 MediaLibraryTracer tracer;
1065 tracer.Start("JSPhotoAlbumRemoveAssetsCompleteCallback");
1066
1067 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
1068 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1069 jsContext->status = false;
1070 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1071 if (context->error == ERR_DEFAULT) {
1072 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1073 jsContext->status = true;
1074 context->objectInfo->SetCount(context->newCount);
1075 context->objectInfo->SetImageCount(context->newImageCount);
1076 context->objectInfo->SetVideoCount(context->newVideoCount);
1077 } else {
1078 context->HandleError(env, jsContext->error);
1079 }
1080
1081 tracer.Finish();
1082 if (context->work != nullptr) {
1083 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1084 context->work, *jsContext);
1085 }
1086 delete context;
1087 }
1088
JSPhotoAlbumRemoveAssets(napi_env env,napi_callback_info info)1089 napi_value PhotoAlbumNapi::JSPhotoAlbumRemoveAssets(napi_env env, napi_callback_info info)
1090 {
1091 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1092 CHECK_NULLPTR_RET(ParseArgsRemoveAssets(env, info, asyncContext));
1093 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1094
1095 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumRemoveAssets",
1096 JSPhotoAlbumRemoveAssetsExecute, JSPhotoAlbumRemoveAssetsCompleteCallback);
1097 }
1098
PhotoAccessHelperRemoveAssets(napi_env env,napi_callback_info info)1099 napi_value PhotoAlbumNapi::PhotoAccessHelperRemoveAssets(napi_env env, napi_callback_info info)
1100 {
1101 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1102 CHECK_NULLPTR_RET(ParseArgsRemoveAssets(env, info, asyncContext));
1103 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1104
1105 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPhotoAlbumRemoveAssets",
1106 JSPhotoAlbumRemoveAssetsExecute, JSPhotoAlbumRemoveAssetsCompleteCallback);
1107 }
1108
NapiGetAnalysisAlbumPredicates(const shared_ptr<PhotoAlbum> & photoAlbum,DataSharePredicates & predicates)1109 static int32_t NapiGetAnalysisAlbumPredicates(const shared_ptr<PhotoAlbum>& photoAlbum,
1110 DataSharePredicates& predicates)
1111 {
1112 PhotoAlbumSubType subType = photoAlbum->GetPhotoAlbumSubType();
1113 if (subType == PhotoAlbumSubType::PORTRAIT || subType == PhotoAlbumSubType::GROUP_PHOTO) {
1114 MediaLibraryNapiUtils::GetPortraitAlbumPredicates(photoAlbum->GetAlbumId(), predicates);
1115 return E_SUCCESS;
1116 }
1117 if (subType == PhotoAlbumSubType::GEOGRAPHY_LOCATION) {
1118 return MediaLibraryNapiUtils::GetAllLocationPredicates(predicates);
1119 }
1120 if (subType == PhotoAlbumSubType::SHOOTING_MODE) {
1121 ShootingModeAlbumType type {};
1122 if (!ShootingModeAlbum::AlbumNameToShootingModeAlbumType(photoAlbum->GetAlbumName(), type)) {
1123 NAPI_ERR_LOG("Invalid shooting mode album name: %{public}s", photoAlbum->GetAlbumName().c_str());
1124 return E_INVALID_ARGUMENTS;
1125 }
1126 ShootingModeAlbum::GetShootingModeAlbumPredicates(type, predicates, photoAlbum->GetHiddenOnly());
1127 return E_SUCCESS;
1128 }
1129 string albumName = photoAlbum->GetAlbumName();
1130 if (MediaLibraryNapiUtils::IsFeaturedSinglePortraitAlbum(albumName, predicates)) {
1131 return MediaLibraryNapiUtils::GetFeaturedSinglePortraitAlbumPredicates(
1132 photoAlbum->GetAlbumId(), predicates);
1133 }
1134 MediaLibraryNapiUtils::GetAnalysisPhotoMapPredicates(photoAlbum->GetAlbumId(), predicates);
1135 return E_SUCCESS;
1136 }
1137
GetPredicatesByAlbumTypes(const shared_ptr<PhotoAlbum> & photoAlbum,DataSharePredicates & predicates,const bool hiddenOnly)1138 static int32_t GetPredicatesByAlbumTypes(const shared_ptr<PhotoAlbum> &photoAlbum,
1139 DataSharePredicates &predicates, const bool hiddenOnly)
1140 {
1141 int32_t albumId = photoAlbum->GetAlbumId();
1142 PhotoAlbumSubType subType = photoAlbum->GetPhotoAlbumSubType();
1143 bool isLocationAlbum = subType == PhotoAlbumSubType::GEOGRAPHY_LOCATION;
1144 if (albumId <= 0 && !isLocationAlbum) {
1145 NAPI_ERR_LOG("Invalid album ID");
1146 return E_INVALID_ARGUMENTS;
1147 }
1148 PhotoAlbumType type = photoAlbum->GetPhotoAlbumType();
1149 if ((!PhotoAlbum::CheckPhotoAlbumType(type)) || (!PhotoAlbum::CheckPhotoAlbumSubType(subType))) {
1150 NAPI_ERR_LOG("Invalid album type or subtype: type=%{public}d, subType=%{public}d", static_cast<int>(type),
1151 static_cast<int>(subType));
1152 return E_INVALID_ARGUMENTS;
1153 }
1154
1155 if (PhotoAlbum::IsUserPhotoAlbum(type, subType)) {
1156 return MediaLibraryNapiUtils::GetUserAlbumPredicates(photoAlbum->GetAlbumId(), predicates, hiddenOnly);
1157 }
1158
1159 if (PhotoAlbum::IsSourceAlbum(type, subType)) {
1160 return MediaLibraryNapiUtils::GetSourceAlbumPredicates(photoAlbum->GetAlbumId(), predicates, hiddenOnly);
1161 }
1162
1163 if (type == PhotoAlbumType::SMART) {
1164 return NapiGetAnalysisAlbumPredicates(photoAlbum, predicates);
1165 }
1166
1167 if (type == PhotoAlbumType::SYSTEM) {
1168 return MediaLibraryNapiUtils::GetSystemAlbumPredicates(subType, predicates, hiddenOnly);
1169 }
1170
1171 NAPI_ERR_LOG("Invalid album type and subtype: type=%{public}d, subType=%{public}d", static_cast<int>(type),
1172 static_cast<int>(subType));
1173 return E_INVALID_ARGUMENTS;
1174 }
1175
ParseArgsGetPhotoAssets(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1176 static napi_value ParseArgsGetPhotoAssets(napi_env env, napi_callback_info info,
1177 unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1178 {
1179 constexpr size_t minArgs = ARGS_ONE;
1180 constexpr size_t maxArgs = ARGS_TWO;
1181 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
1182 JS_ERR_PARAMETER_INVALID);
1183
1184 /* Parse the first argument */
1185 CHECK_ARGS(env, MediaLibraryNapiUtils::GetFetchOption(env, context->argv[PARAM0], ASSET_FETCH_OPT, context),
1186 JS_INNER_FAIL);
1187
1188 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1189 auto ret = GetPredicatesByAlbumTypes(photoAlbum, context->predicates, photoAlbum->GetHiddenOnly());
1190 if (ret != E_SUCCESS) {
1191 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
1192 return nullptr;
1193 }
1194 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::AddDefaultAssetColumns(env, context->fetchColumn,
1195 PhotoColumn::IsPhotoColumn, NapiAssetType::TYPE_PHOTO));
1196 if (photoAlbum->GetHiddenOnly() || photoAlbum->GetPhotoAlbumSubType() == PhotoAlbumSubType::HIDDEN) {
1197 if (!MediaLibraryNapiUtils::IsSystemApp()) {
1198 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
1199 return nullptr;
1200 }
1201 context->isSystemApi = true;
1202 // sort by hidden time desc if is hidden asset
1203 context->predicates.IndexedBy(PhotoColumn::PHOTO_HIDDEN_TIME_INDEX);
1204 }
1205
1206 napi_value result = nullptr;
1207 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1208 return result;
1209 }
1210
JSGetPhotoAssetsExecute(napi_env env,void * data)1211 static void JSGetPhotoAssetsExecute(napi_env env, void *data)
1212 {
1213 MediaLibraryTracer tracer;
1214 tracer.Start("JSGetPhotoAssetsExecute");
1215
1216 auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1217 string queryUri = UFM_QUERY_PHOTO_MAP;
1218 Uri uri(queryUri);
1219 int32_t errCode = 0;
1220 std::vector<DataShare::OperationItem> operationItems = context->predicates.GetOperationList();
1221 for (DataShare::OperationItem item : operationItems) {
1222 if (item.operation == DataShare::OperationType::GROUP_BY) {
1223 context->fetchColumn.insert(context->fetchColumn.begin(), COUNT_GROUP_BY);
1224 }
1225 }
1226 auto resultSet = UserFileClient::Query(uri, context->predicates, context->fetchColumn, errCode);
1227 if (resultSet == nullptr) {
1228 context->SaveError(E_HAS_DB_ERROR);
1229 return;
1230 }
1231 context->fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
1232 context->fetchResult->SetResultNapiType(ResultNapiType::TYPE_USERFILE_MGR);
1233 }
1234
IsFeaturedSinglePortraitAlbum(const shared_ptr<PhotoAlbum> & photoAlbum)1235 static bool IsFeaturedSinglePortraitAlbum(const shared_ptr<PhotoAlbum>& photoAlbum)
1236 {
1237 constexpr int portraitAlbumId = 0;
1238 return photoAlbum->GetPhotoAlbumSubType() == PhotoAlbumSubType::CLASSIFY &&
1239 photoAlbum->GetAlbumName().compare(to_string(portraitAlbumId)) == 0;
1240 }
1241
ConvertColumnsForPortrait(PhotoAlbumNapiAsyncContext * context)1242 static void ConvertColumnsForPortrait(PhotoAlbumNapiAsyncContext *context)
1243 {
1244 if (context == nullptr || context->objectInfo == nullptr) {
1245 NAPI_ERR_LOG("context is null or PhotoAlbumNapi is null");
1246 return;
1247 }
1248
1249 shared_ptr<PhotoAlbum> photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1250 if (photoAlbum == nullptr || (photoAlbum->GetPhotoAlbumSubType() != PhotoAlbumSubType::PORTRAIT &&
1251 photoAlbum->GetPhotoAlbumSubType() != PhotoAlbumSubType::GROUP_PHOTO &&
1252 !IsFeaturedSinglePortraitAlbum(photoAlbum))) {
1253 return;
1254 }
1255
1256 for (size_t i = 0; i < context->fetchColumn.size(); i++) {
1257 if (context->fetchColumn[i] != "count(*)") {
1258 context->fetchColumn[i] = PhotoColumn::PHOTOS_TABLE + "." + context->fetchColumn[i];
1259 }
1260 }
1261 }
1262
JSPhotoAccessGetPhotoAssetsExecute(napi_env env,void * data)1263 static void JSPhotoAccessGetPhotoAssetsExecute(napi_env env, void *data)
1264 {
1265 MediaLibraryTracer tracer;
1266 tracer.Start("JSPhotoAccessGetPhotoAssetsExecute");
1267
1268 auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1269 CHECK_IF_EQUAL(context != nullptr, "context is nullptr");
1270 Uri uri(PAH_QUERY_PHOTO_MAP);
1271 ConvertColumnsForPortrait(context);
1272 int32_t errCode = 0;
1273 int32_t userId = -1;
1274 if (context->objectInfo != nullptr) {
1275 shared_ptr<PhotoAlbum> photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1276 if (photoAlbum != nullptr) {
1277 userId = photoAlbum->GetUserId();
1278 }
1279 }
1280 auto [accessSandbox, resultSet] =
1281 UserFileClient::QueryAccessibleViaSandBox(uri, context->predicates, context->fetchColumn, errCode, userId);
1282 if (accessSandbox) {
1283 if (resultSet == nullptr) {
1284 NAPI_ERR_LOG("QueryAccessibleViaSandBox failed, resultSet is nullptr");
1285 }
1286 } else {
1287 AlbumGetAssetsReqBody reqBody;
1288 reqBody.predicates = context->predicates;
1289 reqBody.columns = context->fetchColumn;
1290 AlbumGetAssetsRespBody respBody;
1291 uint32_t businessCode = context->isSystemApi
1292 ? static_cast<uint32_t>(MediaLibraryBusinessCode::ALBUM_SYS_GET_ASSETS)
1293 : static_cast<uint32_t>(MediaLibraryBusinessCode::ALBUM_GET_ASSETS);
1294 errCode = IPC::UserDefineIPCClient().SetUserId(userId).Call(businessCode, reqBody, respBody);
1295 if (errCode == E_OK) {
1296 resultSet = respBody.resultSet;
1297 } else {
1298 NAPI_ERR_LOG("UserDefineIPCClient Call failed, errCode is %{public}d", errCode);
1299 }
1300 }
1301
1302 if (resultSet == nullptr) {
1303 context->SaveError(E_HAS_DB_ERROR);
1304 return;
1305 }
1306 context->fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
1307 context->fetchResult->SetResultNapiType(ResultNapiType::TYPE_PHOTOACCESS_HELPER);
1308 context->fetchResult->SetUserId(userId);
1309 }
1310
JSPhotoAccessGetPhotoAssetsExecuteSync(napi_env env,PhotoAlbumNapiAsyncContext & asyncContext)1311 static napi_value JSPhotoAccessGetPhotoAssetsExecuteSync(napi_env env, PhotoAlbumNapiAsyncContext& asyncContext)
1312 {
1313 auto context = &asyncContext;
1314 Uri uri(PAH_QUERY_PHOTO_MAP);
1315 ConvertColumnsForPortrait(context);
1316 int32_t errCode = 0;
1317 auto resultSet = UserFileClient::Query(uri, context->predicates, context->fetchColumn, errCode);
1318 CHECK_NULLPTR_RET(resultSet);
1319 auto fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
1320 fetchResult->SetResultNapiType(ResultNapiType::TYPE_PHOTOACCESS_HELPER);
1321
1322 std::vector<std::unique_ptr<FileAsset>> fileAssetArray;
1323 auto file = fetchResult->GetFirstObject();
1324 while (file != nullptr) {
1325 fileAssetArray.push_back(move(file));
1326 file = fetchResult->GetNextObject();
1327 }
1328 napi_value jsFileArray = nullptr;
1329 size_t len = fileAssetArray.size();
1330 napi_create_array_with_length(env, len, &jsFileArray);
1331 size_t i = 0;
1332 int32_t userId = -1;
1333 if (context->objectInfo != nullptr) {
1334 shared_ptr<PhotoAlbum> photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1335 if (photoAlbum != nullptr) {
1336 userId = photoAlbum->GetUserId();
1337 }
1338 }
1339 for (i = 0; i < len; i++) {
1340 fileAssetArray[i]->SetUserId(userId);
1341 napi_value jsFileAsset = FileAssetNapi::CreateFileAsset(env, fileAssetArray[i]);
1342 if ((jsFileAsset == nullptr) || (napi_set_element(env, jsFileArray, i, jsFileAsset) != napi_ok)) {
1343 NAPI_ERR_LOG("Failed to get file asset napi object");
1344 break;
1345 }
1346 }
1347 return (i == len) ? jsFileArray : nullptr;
1348 }
1349
GetPhotoMapQueryResult(napi_env env,PhotoAlbumNapiAsyncContext * context,unique_ptr<JSAsyncContextOutput> & jsContext)1350 static void GetPhotoMapQueryResult(napi_env env, PhotoAlbumNapiAsyncContext *context,
1351 unique_ptr<JSAsyncContextOutput> &jsContext)
1352 {
1353 napi_value fetchRes = FetchFileResultNapi::CreateFetchFileResult(env, move(context->fetchResult));
1354 if (fetchRes == nullptr) {
1355 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
1356 "Failed to create js object for FetchFileResult");
1357 return;
1358 }
1359 jsContext->data = fetchRes;
1360 jsContext->status = true;
1361 }
1362
JSGetPhotoAssetsCallbackComplete(napi_env env,napi_status status,void * data)1363 static void JSGetPhotoAssetsCallbackComplete(napi_env env, napi_status status, void *data)
1364 {
1365 MediaLibraryTracer tracer;
1366 tracer.Start("JSGetPhotoAssetsCallbackComplete");
1367
1368 auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1369
1370 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1371 jsContext->status = false;
1372
1373 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1374 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1375 if (context->fetchResult != nullptr) {
1376 GetPhotoMapQueryResult(env, context, jsContext);
1377 } else {
1378 NAPI_ERR_LOG("No fetch file result found!");
1379 context->HandleError(env, jsContext->error);
1380 }
1381
1382 tracer.Finish();
1383 if (context->work != nullptr) {
1384 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1385 context->work, *jsContext);
1386 }
1387 delete context;
1388 }
1389
JSGetPhotoAssets(napi_env env,napi_callback_info info)1390 napi_value PhotoAlbumNapi::JSGetPhotoAssets(napi_env env, napi_callback_info info)
1391 {
1392 unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1393 CHECK_NULLPTR_RET(ParseArgsGetPhotoAssets(env, info, asyncContext));
1394
1395 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetPhotoAssets", JSGetPhotoAssetsExecute,
1396 JSGetPhotoAssetsCallbackComplete);
1397 }
1398
JSPhotoAccessGetPhotoAssets(napi_env env,napi_callback_info info)1399 napi_value PhotoAlbumNapi::JSPhotoAccessGetPhotoAssets(napi_env env, napi_callback_info info)
1400 {
1401 unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1402 CHECK_NULLPTR_RET(ParseArgsGetPhotoAssets(env, info, asyncContext));
1403
1404 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetPhotoAssets",
1405 JSPhotoAccessGetPhotoAssetsExecute, JSGetPhotoAssetsCallbackComplete);
1406 }
1407
JSPhotoAccessGetPhotoAssetsSync(napi_env env,napi_callback_info info)1408 napi_value PhotoAlbumNapi::JSPhotoAccessGetPhotoAssetsSync(napi_env env, napi_callback_info info)
1409 {
1410 MediaLibraryTracer tracer;
1411 tracer.Start("JSPhotoAccessGetPhotoAssetsSync");
1412
1413 unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1414 CHECK_NULLPTR_RET(ParseArgsGetPhotoAssets(env, info, asyncContext));
1415 return JSPhotoAccessGetPhotoAssetsExecuteSync(env, *asyncContext);
1416 }
1417
TrashAlbumParseArgs(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1418 static napi_value TrashAlbumParseArgs(napi_env env, napi_callback_info info,
1419 unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1420 {
1421 if (!MediaLibraryNapiUtils::IsSystemApp()) {
1422 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
1423 return nullptr;
1424 }
1425
1426 napi_value result = nullptr;
1427 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1428 constexpr size_t minArgs = ARGS_ONE;
1429 constexpr size_t maxArgs = ARGS_TWO;
1430 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
1431 JS_ERR_PARAMETER_INVALID);
1432 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1433 if (!PhotoAlbum::IsTrashAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
1434 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check trash album type");
1435 return nullptr;
1436 }
1437
1438 /* Parse the first argument */
1439 vector<napi_value> napiValues;
1440 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetNapiValueArray(env, context->argv[PARAM0], napiValues));
1441 if (napiValues.empty()) {
1442 return result;
1443 }
1444 napi_valuetype valueType = napi_undefined;
1445 vector<string> uris;
1446 CHECK_ARGS(env, napi_typeof(env, napiValues.front(), &valueType), JS_ERR_PARAMETER_INVALID);
1447 if (valueType == napi_string) {
1448 // The input should be an array of asset uri.
1449 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetStringArray(env, napiValues, uris));
1450 } else if (valueType == napi_object) {
1451 // The input should be an array of asset object.
1452 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetUriArrayFromAssets(env, napiValues, uris));
1453 }
1454 if (uris.empty()) {
1455 return result;
1456 }
1457
1458 context->uris = uris;
1459 context->predicates.In(MediaColumn::MEDIA_ID, uris);
1460 context->valuesBucket.Put(MediaColumn::MEDIA_DATE_TRASHED, 0);
1461
1462 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1463 return result;
1464 }
1465
TrashAlbumExecute(const TrashAlbumExecuteOpt & opt)1466 static void TrashAlbumExecute(const TrashAlbumExecuteOpt &opt)
1467 {
1468 MediaLibraryTracer tracer;
1469 tracer.Start(opt.tracerLabel);
1470
1471 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(opt.data);
1472 if (context->predicates.GetOperationList().empty()) {
1473 NAPI_ERR_LOG("Operation list is empty.");
1474 return;
1475 }
1476 Uri uri(opt.uri);
1477 int changedRows = UserFileClient::Update(uri, context->predicates, context->valuesBucket);
1478 if (changedRows < 0) {
1479 context->SaveError(changedRows);
1480 NAPI_ERR_LOG("Trash album executed, changeRows: %{public}d.", changedRows);
1481 return;
1482 }
1483 context->changedRows = changedRows;
1484 }
1485
TrashAlbumComplete(napi_env env,napi_status status,void * data)1486 static void TrashAlbumComplete(napi_env env, napi_status status, void *data)
1487 {
1488 auto *context = static_cast<PhotoAlbumNapiAsyncContext*>(data);
1489 auto jsContext = make_unique<JSAsyncContextOutput>();
1490 jsContext->status = false;
1491 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1492 if (context->error == ERR_DEFAULT) {
1493 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1494 jsContext->status = true;
1495 } else {
1496 context->HandleError(env, jsContext->error);
1497 }
1498
1499 if (context->work != nullptr) {
1500 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1501 context->work, *jsContext);
1502 }
1503 delete context;
1504 }
1505
RecoverPhotosExecute(napi_env env,void * data)1506 static void RecoverPhotosExecute(napi_env env, void *data)
1507 {
1508 auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1509 if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
1510 TrashAlbumExecuteOpt opt = {
1511 .env = env,
1512 .data = data,
1513 .tracerLabel = "RecoverPhotosExecute",
1514 .uri = UFM_RECOVER_PHOTOS,
1515 };
1516 TrashAlbumExecute(opt);
1517 return;
1518 }
1519
1520 AlbumRecoverAssetsReqBody reqBody;
1521 CHECK_IF_EQUAL(context->objectInfo != nullptr, "context->objectInfo is nullptr");
1522 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1523 CHECK_IF_EQUAL(photoAlbum != nullptr, "photoAlbum is nullptr");
1524 reqBody.albumType = photoAlbum->GetPhotoAlbumType();
1525 reqBody.albumSubType = photoAlbum->GetPhotoAlbumSubType();
1526 reqBody.uris = context->uris;
1527 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_RECOVER_ASSETS);
1528
1529 int32_t changedRows = IPC::UserDefineIPCClient().Call(businessCode, reqBody);
1530 if (changedRows < 0) {
1531 context->SaveError(changedRows);
1532 NAPI_ERR_LOG("changeRows: %{public}d.", changedRows);
1533 return;
1534 }
1535 context->changedRows = changedRows;
1536 }
1537
RecoverPhotosComplete(napi_env env,napi_status status,void * data)1538 static void RecoverPhotosComplete(napi_env env, napi_status status, void *data)
1539 {
1540 TrashAlbumComplete(env, status, data);
1541 }
1542
JSRecoverPhotos(napi_env env,napi_callback_info info)1543 napi_value PhotoAlbumNapi::JSRecoverPhotos(napi_env env, napi_callback_info info)
1544 {
1545 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1546 CHECK_NULLPTR_RET(TrashAlbumParseArgs(env, info, asyncContext));
1547 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1548
1549 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRecoverPhotos", RecoverPhotosExecute,
1550 RecoverPhotosComplete);
1551 }
1552
PrivateAlbumParseArgs(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1553 static napi_value PrivateAlbumParseArgs(napi_env env, napi_callback_info info,
1554 unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1555 {
1556 string uri;
1557 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, context, uri),
1558 JS_ERR_PARAMETER_INVALID);
1559 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1560 if (photoAlbum == nullptr) {
1561 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get photo album instance");
1562 return nullptr;
1563 }
1564 if (!PhotoAlbum::IsTrashAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
1565 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check trash album type");
1566 return nullptr;
1567 }
1568
1569 context->predicates.EqualTo(MediaColumn::MEDIA_ID, MediaFileUtils::GetIdFromUri(uri));
1570 context->valuesBucket.Put(MediaColumn::MEDIA_DATE_TRASHED, 0);
1571
1572 napi_value result = nullptr;
1573 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1574 return result;
1575 }
1576
PrivateAlbumRecoverPhotos(napi_env env,napi_callback_info info)1577 napi_value PhotoAlbumNapi::PrivateAlbumRecoverPhotos(napi_env env, napi_callback_info info)
1578 {
1579 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1580 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1581 CHECK_NULLPTR_RET(PrivateAlbumParseArgs(env, info, asyncContext));
1582
1583 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PrivateAlbumRecoverPhotos",
1584 RecoverPhotosExecute, RecoverPhotosComplete);
1585 }
1586
PhotoAccessHelperRecoverPhotos(napi_env env,napi_callback_info info)1587 napi_value PhotoAlbumNapi::PhotoAccessHelperRecoverPhotos(napi_env env, napi_callback_info info)
1588 {
1589 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1590 CHECK_NULLPTR_RET(TrashAlbumParseArgs(env, info, asyncContext));
1591 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1592
1593 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRecoverPhotos", RecoverPhotosExecute,
1594 RecoverPhotosComplete);
1595 }
1596
DeletePhotosExecute(napi_env env,void * data)1597 static void DeletePhotosExecute(napi_env env, void *data)
1598 {
1599 TrashAlbumExecuteOpt opt = {
1600 .env = env,
1601 .data = data,
1602 .tracerLabel = "DeletePhotosExecute",
1603 .uri = (static_cast<PhotoAlbumNapiAsyncContext *>(data)->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ?
1604 UFM_DELETE_PHOTOS : PAH_DELETE_PHOTOS,
1605 };
1606 TrashAlbumExecute(opt);
1607 }
1608
DeletePhotosComplete(napi_env env,napi_status status,void * data)1609 static void DeletePhotosComplete(napi_env env, napi_status status, void *data)
1610 {
1611 TrashAlbumComplete(env, status, data);
1612 }
1613
JSDeletePhotos(napi_env env,napi_callback_info info)1614 napi_value PhotoAlbumNapi::JSDeletePhotos(napi_env env, napi_callback_info info)
1615 {
1616 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1617 CHECK_NULLPTR_RET(TrashAlbumParseArgs(env, info, asyncContext));
1618 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1619
1620 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSDeletePhotos", DeletePhotosExecute,
1621 DeletePhotosComplete);
1622 }
1623
PrivateAlbumDeletePhotos(napi_env env,napi_callback_info info)1624 napi_value PhotoAlbumNapi::PrivateAlbumDeletePhotos(napi_env env, napi_callback_info info)
1625 {
1626 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1627 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
1628 CHECK_NULLPTR_RET(PrivateAlbumParseArgs(env, info, asyncContext));
1629
1630 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PrivateAlbumDeletePhotos",
1631 DeletePhotosExecute, DeletePhotosComplete);
1632 }
1633
DeletePhotosParseArgs(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1634 static napi_value DeletePhotosParseArgs(
1635 napi_env env, napi_callback_info info, unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1636 {
1637 if (!MediaLibraryNapiUtils::IsSystemApp()) {
1638 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
1639 return nullptr;
1640 }
1641
1642 napi_value result = nullptr;
1643 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1644 constexpr size_t minArgs = ARGS_ONE;
1645 constexpr size_t maxArgs = ARGS_TWO;
1646 CHECK_ARGS(env,
1647 MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
1648 JS_ERR_PARAMETER_INVALID);
1649 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1650 if (!PhotoAlbum::IsTrashAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType())) {
1651 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to check trash album type");
1652 return nullptr;
1653 }
1654
1655 /* Parse the first argument */
1656 vector<napi_value> napiValues;
1657 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetNapiValueArray(env, context->argv[PARAM0], napiValues));
1658 if (napiValues.empty()) {
1659 return result;
1660 }
1661 napi_valuetype valueType = napi_undefined;
1662 CHECK_ARGS(env, napi_typeof(env, napiValues.front(), &valueType), JS_ERR_PARAMETER_INVALID);
1663 vector<string> uris;
1664 if (valueType == napi_string) {
1665 // The input should be an array of asset uri.
1666 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetStringArray(env, napiValues, uris));
1667 } else if (valueType == napi_object) {
1668 // The input should be an array of asset object.
1669 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetUriArrayFromAssets(env, napiValues, uris));
1670 }
1671 if (uris.empty()) {
1672 return result;
1673 }
1674 context->uris = uris;
1675
1676 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1677 return result;
1678 }
1679
PahDeletePhotosExecute(napi_env env,void * data)1680 static void PahDeletePhotosExecute(napi_env env, void *data)
1681 {
1682 MediaLibraryTracer tracer;
1683 tracer.Start("DeletePhotosExecute");
1684
1685 auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1686 CHECK_NULL_PTR_RETURN_VOID(context, "context is null");
1687 CHECK_IF_EQUAL(!context->uris.empty(), "uris is empty");
1688
1689 DeletePhotosReqBody reqBody;
1690 reqBody.uris = context->uris;
1691 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_DELETE_PHOTOS);
1692 int32_t changedRows = IPC::UserDefineIPCClient().Call(businessCode, reqBody);
1693 if (changedRows < 0) {
1694 context->SaveError(changedRows);
1695 NAPI_ERR_LOG("pah delete photos executed, changeRows: %{public}d.", changedRows);
1696 return;
1697 }
1698 context->changedRows = changedRows;
1699 }
1700
PhotoAccessHelperDeletePhotos(napi_env env,napi_callback_info info)1701 napi_value PhotoAlbumNapi::PhotoAccessHelperDeletePhotos(napi_env env, napi_callback_info info)
1702 {
1703 NAPI_INFO_LOG("enter");
1704 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1705 CHECK_NULLPTR_RET(DeletePhotosParseArgs(env, info, asyncContext));
1706 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1707
1708 return MediaLibraryNapiUtils::NapiCreateAsyncWork(
1709 env, asyncContext, "JSDeletePhotos", PahDeletePhotosExecute, DeletePhotosComplete);
1710 }
1711
ParseArgsSetCoverUri(napi_env env,napi_callback_info info,unique_ptr<PhotoAlbumNapiAsyncContext> & context)1712 static napi_value ParseArgsSetCoverUri(napi_env env, napi_callback_info info,
1713 unique_ptr<PhotoAlbumNapiAsyncContext> &context)
1714 {
1715 string coverUri;
1716 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, context, coverUri),
1717 JS_ERR_PARAMETER_INVALID);
1718 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
1719 if (!MediaLibraryNapiUtils::IsSystemApp()) {
1720 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Only system apps can update album cover");
1721 return nullptr;
1722 }
1723
1724 context->businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_SET_COVER_URI);
1725 context->predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(photoAlbum->GetAlbumId()));
1726 context->valuesBucket.Put(PhotoAlbumColumns::ALBUM_COVER_URI, coverUri);
1727
1728 napi_value result = nullptr;
1729 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1730 return result;
1731 }
1732
PhotoAccessHelperSetCoverUri(napi_env env,napi_callback_info info)1733 napi_value PhotoAlbumNapi::PhotoAccessHelperSetCoverUri(napi_env env, napi_callback_info info)
1734 {
1735 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1736 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1737 CHECK_NULLPTR_RET(ParseArgsSetCoverUri(env, info, asyncContext));
1738
1739 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
1740 JSCommitModifyCompleteCallback);
1741 }
1742
PhotoAccessHelperGetFaceIdExec(napi_env env,void * data)1743 static void PhotoAccessHelperGetFaceIdExec(napi_env env, void *data)
1744 {
1745 auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1746 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1747
1748 auto *objectInfo = context->objectInfo;
1749 CHECK_NULL_PTR_RETURN_VOID(objectInfo, "objectInfo is null");
1750
1751 auto photoAlbumInstance = objectInfo->GetPhotoAlbumInstance();
1752 CHECK_NULL_PTR_RETURN_VOID(photoAlbumInstance, "photoAlbumInstance is null");
1753
1754 PhotoAlbumSubType albumSubType = photoAlbumInstance->GetPhotoAlbumSubType();
1755 if (albumSubType != PhotoAlbumSubType::PORTRAIT && albumSubType != PhotoAlbumSubType::GROUP_PHOTO) {
1756 NAPI_WARN_LOG("albumSubType: %{public}d, not support getFaceId", albumSubType);
1757 return;
1758 }
1759
1760 GetFaceIdReqBody reqBody;
1761 GetFaceIdRespBody respBody;
1762 reqBody.albumId = objectInfo->GetAlbumId();
1763 reqBody.albumSubType = static_cast<int32_t>(albumSubType);
1764 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::GET_FACE_ID);
1765 int32_t ret = IPC::UserDefineIPCClient().Call(businessCode, reqBody, respBody);
1766 if (ret < 0) {
1767 if (ret == E_PERMISSION_DENIED) {
1768 context->error = OHOS_PERMISSION_DENIED_CODE;
1769 } else {
1770 context->SaveError(E_FAIL);
1771 }
1772 NAPI_ERR_LOG("get face id failed, errCode is %{public}d", ret);
1773 return;
1774 }
1775 NAPI_INFO_LOG("respBody.groupTag: %{public}s", respBody.groupTag.c_str());
1776 context->faceTag = respBody.groupTag;
1777 }
1778
GetFaceIdCompleteCallback(napi_env env,napi_status status,void * data)1779 static void GetFaceIdCompleteCallback(napi_env env, napi_status status, void *data)
1780 {
1781 auto *context = static_cast<PhotoAlbumNapiAsyncContext *>(data);
1782 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1783 auto jsContext = make_unique<JSAsyncContextOutput>();
1784 jsContext->status = false;
1785
1786 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1787 if (context->error != ERR_DEFAULT) {
1788 context->HandleError(env, jsContext->error);
1789 } else {
1790 CHECK_ARGS_RET_VOID(env,
1791 napi_create_string_utf8(env, context->faceTag.c_str(), NAPI_AUTO_LENGTH, &jsContext->data), JS_INNER_FAIL);
1792 jsContext->status = true;
1793 }
1794
1795 if (context->work != nullptr) {
1796 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, context->work,
1797 *jsContext);
1798 }
1799 delete context;
1800 }
1801
PhotoAccessHelperGetFaceId(napi_env env,napi_callback_info info)1802 napi_value PhotoAlbumNapi::PhotoAccessHelperGetFaceId(napi_env env, napi_callback_info info)
1803 {
1804 if (!MediaLibraryNapiUtils::IsSystemApp()) {
1805 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "Only system apps can get the Face ID of the album");
1806 return nullptr;
1807 }
1808
1809 auto asyncContext = make_unique<PhotoAlbumNapiAsyncContext>();
1810
1811 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, asyncContext, 0, 0),
1812 JS_ERR_PARAMETER_INVALID);
1813
1814 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSAnalysisAlbumGetFaceId",
1815 PhotoAccessHelperGetFaceIdExec, GetFaceIdCompleteCallback);
1816 }
1817
JSPhotoAccessGetSharedPhotoAssets(napi_env env,napi_callback_info info)1818 napi_value PhotoAlbumNapi::JSPhotoAccessGetSharedPhotoAssets(napi_env env, napi_callback_info info)
1819 {
1820 MediaLibraryTracer tracer;
1821 tracer.Start("JSPhotoAccessGetSharedPhotoAssets");
1822 unique_ptr<PhotoAlbumNapiAsyncContext> asyncContext =
1823 make_unique<PhotoAlbumNapiAsyncContext>();
1824 CHECK_NULLPTR_RET(ParseArgsGetPhotoAssets(env, info, asyncContext));
1825
1826 PhotoAlbumNapiAsyncContext* context =
1827 static_cast<PhotoAlbumNapiAsyncContext*>((asyncContext.get()));
1828
1829 Uri uri(PAH_QUERY_PHOTO_MAP);
1830 ConvertColumnsForPortrait(context);
1831 shared_ptr<NativeRdb::ResultSet> resultSet = UserFileClient::QueryRdb(uri,
1832 context->predicates, context->fetchColumn);
1833 CHECK_NULLPTR_RET(resultSet);
1834
1835 napi_value jsFileArray = 0;
1836 napi_create_array(env, &jsFileArray);
1837
1838 int count = 0;
1839 int err = resultSet->GoToFirstRow();
1840 if (err != napi_ok) {
1841 NAPI_ERR_LOG("Failed GoToFirstRow %{public}d", err);
1842 return jsFileArray;
1843 }
1844 do {
1845 napi_value item = MediaLibraryNapiUtils::GetNextRowObject(env, resultSet, true);
1846 napi_set_element(env, jsFileArray, count++, item);
1847 } while (!resultSet->GoToNextRow());
1848 resultSet->Close();
1849 return jsFileArray;
1850 }
1851 } // namespace OHOS::Media
1852