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