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