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