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