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 "AlbumNapi"
16
17 #include "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 using namespace OHOS::DataShare;
31 thread_local napi_ref AlbumNapi::sConstructor_ = nullptr;
32 thread_local AlbumAsset *AlbumNapi::sAlbumData_ = nullptr;
33 using CompleteCallback = napi_async_complete_callback;
34
35 thread_local napi_ref AlbumNapi::userFileMgrConstructor_ = nullptr;
36
AlbumNapi()37 AlbumNapi::AlbumNapi()
38 : env_(nullptr) {}
39
40 AlbumNapi::~AlbumNapi() = default;
41
AlbumNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)42 void AlbumNapi::AlbumNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
43 {
44 AlbumNapi *album = reinterpret_cast<AlbumNapi*>(nativeObject);
45 if (album != nullptr) {
46 delete album;
47 album = nullptr;
48 }
49 }
50
Init(napi_env env,napi_value exports)51 napi_value AlbumNapi::Init(napi_env env, napi_value exports)
52 {
53 napi_status status;
54 napi_value ctorObj;
55 int32_t refCount = 1;
56
57 napi_property_descriptor album_props[] = {
58 DECLARE_NAPI_GETTER("albumId", JSGetAlbumId),
59 DECLARE_NAPI_GETTER_SETTER("albumName", JSGetAlbumName, JSAlbumNameSetter),
60 DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
61 DECLARE_NAPI_GETTER("dateModified", JSGetAlbumDateModified),
62 DECLARE_NAPI_GETTER("count", JSGetCount),
63 DECLARE_NAPI_GETTER("relativePath", JSGetAlbumRelativePath),
64 DECLARE_NAPI_GETTER("coverUri", JSGetCoverUri),
65 DECLARE_NAPI_FUNCTION("commitModify", JSCommitModify),
66 DECLARE_NAPI_GETTER_SETTER("path", JSGetAlbumPath, JSSetAlbumPath),
67 DECLARE_NAPI_GETTER("virtual", JSGetAlbumVirtual),
68 DECLARE_NAPI_FUNCTION("getFileAssets", JSGetAlbumFileAssets)
69 };
70
71 status = napi_define_class(env, ALBUM_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
72 AlbumNapiConstructor, nullptr,
73 sizeof(album_props) / sizeof(album_props[PARAM0]),
74 album_props, &ctorObj);
75 if (status == napi_ok) {
76 status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
77 if (status == napi_ok) {
78 status = napi_set_named_property(env, exports, ALBUM_NAPI_CLASS_NAME.c_str(), ctorObj);
79 if (status == napi_ok) {
80 return exports;
81 }
82 }
83 }
84
85 return nullptr;
86 }
87
UserFileMgrInit(napi_env env,napi_value exports)88 napi_value AlbumNapi::UserFileMgrInit(napi_env env, napi_value exports)
89 {
90 NapiClassInfo info = {
91 .name = USERFILEMGR_ALBUM_NAPI_CLASS_NAME,
92 .ref = &userFileMgrConstructor_,
93 .constructor = AlbumNapiConstructor,
94 .props = {
95 DECLARE_NAPI_FUNCTION("getPhotoAssets", UserFileMgrGetAssets),
96 DECLARE_NAPI_FUNCTION("commitModify", UserFileMgrCommitModify),
97 DECLARE_NAPI_GETTER_SETTER("albumName", JSGetAlbumName, JSAlbumNameSetter),
98 DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
99 DECLARE_NAPI_GETTER("dateModified", JSGetAlbumDateModified),
100 DECLARE_NAPI_GETTER("count", JSGetCount),
101 DECLARE_NAPI_GETTER("relativePath", JSGetAlbumRelativePath),
102 DECLARE_NAPI_GETTER("coverUri", JSGetCoverUri)
103 }
104 };
105
106 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
107 return exports;
108 }
109
SetAlbumNapiProperties()110 void AlbumNapi::SetAlbumNapiProperties()
111 {
112 albumAssetPtr = std::shared_ptr<AlbumAsset>(sAlbumData_);
113 }
114
115 // Constructor callback
AlbumNapiConstructor(napi_env env,napi_callback_info info)116 napi_value AlbumNapi::AlbumNapiConstructor(napi_env env, napi_callback_info info)
117 {
118 napi_status status;
119 napi_value result = nullptr;
120 napi_value thisVar = nullptr;
121
122 napi_get_undefined(env, &result);
123 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
124 if (status == napi_ok && thisVar != nullptr) {
125 std::unique_ptr<AlbumNapi> obj = std::make_unique<AlbumNapi>();
126 if (obj != nullptr) {
127 obj->env_ = env;
128 if (sAlbumData_ != nullptr) {
129 obj->SetAlbumNapiProperties();
130 }
131
132 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
133 AlbumNapi::AlbumNapiDestructor, nullptr, nullptr);
134 if (status == napi_ok) {
135 obj.release();
136 return thisVar;
137 } else {
138 NAPI_ERR_LOG("Failure wrapping js to native napi. status: %{public}d", status);
139 }
140 }
141 }
142
143 return result;
144 }
145
CreateAlbumNapi(napi_env env,unique_ptr<AlbumAsset> & albumData)146 napi_value AlbumNapi::CreateAlbumNapi(napi_env env, unique_ptr<AlbumAsset> &albumData)
147 {
148 if (albumData == nullptr) {
149 return nullptr;
150 }
151
152 napi_value constructor;
153 napi_ref constructorRef = (albumData->GetResultNapiType() == ResultNapiType::TYPE_MEDIALIBRARY) ?
154 (sConstructor_) : (userFileMgrConstructor_);
155 NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
156
157 napi_value result = nullptr;
158 sAlbumData_ = albumData.release();
159 NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
160 sAlbumData_ = nullptr;
161 return result;
162 }
163
GetAlbumName() const164 std::string AlbumNapi::GetAlbumName() const
165 {
166 return albumAssetPtr->GetAlbumName();
167 }
168
GetAlbumPath() const169 std::string AlbumNapi::GetAlbumPath() const
170 {
171 return albumAssetPtr->GetAlbumPath();
172 }
173
GetAlbumId() const174 int32_t AlbumNapi::GetAlbumId() const
175 {
176 return albumAssetPtr->GetAlbumId();
177 }
178
GetAlbumUri() const179 std::string AlbumNapi::GetAlbumUri() const
180 {
181 return albumAssetPtr->GetAlbumUri();
182 }
183
GetNetworkId() const184 std::string AlbumNapi::GetNetworkId() const
185 {
186 return MediaFileUtils::GetNetworkIdFromUri(GetAlbumUri());
187 }
188
GetTypeMask() const189 std::string AlbumNapi::GetTypeMask() const
190 {
191 return albumAssetPtr->GetAlbumTypeMask();
192 }
193
JSGetAlbumId(napi_env env,napi_callback_info info)194 napi_value AlbumNapi::JSGetAlbumId(napi_env env, napi_callback_info info)
195 {
196 napi_status status;
197 napi_value jsResult = nullptr;
198 napi_value undefinedResult = nullptr;
199 AlbumNapi* obj = nullptr;
200 int32_t id;
201 napi_value thisVar = nullptr;
202
203 napi_get_undefined(env, &undefinedResult);
204 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
205 if (status != napi_ok || thisVar == nullptr) {
206 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
207 return undefinedResult;
208 }
209
210 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
211 if (status == napi_ok && obj != nullptr) {
212 id = obj->GetAlbumId();
213 status = napi_create_int32(env, id, &jsResult);
214 if (status == napi_ok) {
215 return jsResult;
216 }
217 }
218
219 return undefinedResult;
220 }
221
JSGetAlbumName(napi_env env,napi_callback_info info)222 napi_value AlbumNapi::JSGetAlbumName(napi_env env, napi_callback_info info)
223 {
224 napi_status status;
225 napi_value jsResult = nullptr;
226 napi_value undefinedResult = nullptr;
227 AlbumNapi* obj = nullptr;
228 std::string name = "";
229 napi_value thisVar = nullptr;
230 napi_get_undefined(env, &undefinedResult);
231 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
232 if (status != napi_ok || thisVar == nullptr) {
233 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
234 return undefinedResult;
235 }
236
237 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
238 if (status == napi_ok && obj != nullptr) {
239 name = obj->GetAlbumName();
240 status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &jsResult);
241 if (status == napi_ok) {
242 return jsResult;
243 }
244 }
245
246 return undefinedResult;
247 }
248
JSAlbumNameSetter(napi_env env,napi_callback_info info)249 napi_value AlbumNapi::JSAlbumNameSetter(napi_env env, napi_callback_info info)
250 {
251 napi_status status;
252 napi_value jsResult = nullptr;
253 size_t argc = ARGS_ONE;
254 napi_value argv[ARGS_ONE] = {0};
255 size_t res = 0;
256 char buffer[FILENAME_MAX];
257 AlbumNapi* obj = nullptr;
258 napi_value thisVar = nullptr;
259 napi_valuetype valueType = napi_undefined;
260
261 napi_get_undefined(env, &jsResult);
262 GET_JS_ARGS(env, info, argc, argv, thisVar);
263 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
264 if (thisVar == nullptr || napi_typeof(env, argv[PARAM0], &valueType) != napi_ok
265 || valueType != napi_string) {
266 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
267 return jsResult;
268 }
269
270 napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
271
272 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
273 if (status == napi_ok && obj != nullptr) {
274 obj->albumAssetPtr->SetAlbumName(std::string(buffer));
275 } else {
276 NAPI_ERR_LOG("status = %{public}d", status);
277 }
278 return jsResult;
279 }
JSGetAlbumUri(napi_env env,napi_callback_info info)280 napi_value AlbumNapi::JSGetAlbumUri(napi_env env, napi_callback_info info)
281 {
282 napi_status status;
283 napi_value jsResult = nullptr;
284 napi_value undefinedResult = nullptr;
285 AlbumNapi* obj = nullptr;
286 std::string uri = "";
287 napi_value thisVar = nullptr;
288
289 napi_get_undefined(env, &undefinedResult);
290 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
291 if (status != napi_ok || thisVar == nullptr) {
292 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
293 return undefinedResult;
294 }
295
296 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
297 if (status == napi_ok && obj != nullptr) {
298 uri = obj->GetAlbumUri();
299 status = napi_create_string_utf8(env, uri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
300 if (status == napi_ok) {
301 return jsResult;
302 }
303 }
304
305 return undefinedResult;
306 }
JSGetAlbumDateModified(napi_env env,napi_callback_info info)307 napi_value AlbumNapi::JSGetAlbumDateModified(napi_env env, napi_callback_info info)
308 {
309 napi_status status;
310 napi_value jsResult = nullptr;
311 napi_value undefinedResult = nullptr;
312 AlbumNapi* obj = nullptr;
313 int64_t dateModified;
314 napi_value thisVar = nullptr;
315
316 napi_get_undefined(env, &undefinedResult);
317 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
318 if (status != napi_ok || thisVar == nullptr) {
319 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
320 return undefinedResult;
321 }
322
323 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
324 if (status == napi_ok && obj != nullptr) {
325 dateModified = obj->albumAssetPtr->GetAlbumDateModified();
326 status = napi_create_int64(env, dateModified, &jsResult);
327 if (status == napi_ok) {
328 return jsResult;
329 }
330 }
331
332 return undefinedResult;
333 }
JSGetCount(napi_env env,napi_callback_info info)334 napi_value AlbumNapi::JSGetCount(napi_env env, napi_callback_info info)
335 {
336 napi_status status;
337 napi_value jsResult = nullptr;
338 napi_value undefinedResult = nullptr;
339 AlbumNapi *obj = nullptr;
340 int32_t count;
341 napi_value thisVar = nullptr;
342
343 napi_get_undefined(env, &undefinedResult);
344 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
345 if (status != napi_ok || thisVar == nullptr) {
346 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
347 return undefinedResult;
348 }
349 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
350 if (status == napi_ok && obj != nullptr) {
351 count = obj->albumAssetPtr->GetCount();
352 status = napi_create_int32(env, count, &jsResult);
353 if (status == napi_ok) {
354 return jsResult;
355 }
356 }
357 return undefinedResult;
358 }
JSGetAlbumRelativePath(napi_env env,napi_callback_info info)359 napi_value AlbumNapi::JSGetAlbumRelativePath(napi_env env, napi_callback_info info)
360 {
361 napi_status status;
362 napi_value jsResult = nullptr;
363 napi_value undefinedResult = nullptr;
364 AlbumNapi* obj = nullptr;
365 std::string relativePath = "";
366 napi_value thisVar = nullptr;
367
368 napi_get_undefined(env, &undefinedResult);
369 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
370 if (status != napi_ok || thisVar == nullptr) {
371 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
372 return undefinedResult;
373 }
374
375 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
376 if (status == napi_ok && obj != nullptr) {
377 relativePath = obj->albumAssetPtr->GetAlbumRelativePath();
378 status = napi_create_string_utf8(env, relativePath.c_str(), NAPI_AUTO_LENGTH, &jsResult);
379 if (status == napi_ok) {
380 return jsResult;
381 }
382 }
383
384 return undefinedResult;
385 }
JSGetCoverUri(napi_env env,napi_callback_info info)386 napi_value AlbumNapi::JSGetCoverUri(napi_env env, napi_callback_info info)
387 {
388 napi_status status;
389 napi_value jsResult = nullptr;
390 napi_value undefinedResult = nullptr;
391 AlbumNapi* obj = nullptr;
392 std::string coverUri = "";
393 napi_value thisVar = nullptr;
394
395 napi_get_undefined(env, &undefinedResult);
396 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
397 if (status != napi_ok || thisVar == nullptr) {
398 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
399 return undefinedResult;
400 }
401
402 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
403 if (status == napi_ok && obj != nullptr) {
404 coverUri = obj->albumAssetPtr->GetCoverUri();
405 status = napi_create_string_utf8(env, coverUri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
406 if (status == napi_ok) {
407 return jsResult;
408 }
409 }
410
411 return undefinedResult;
412 }
413
JSSetAlbumPath(napi_env env,napi_callback_info info)414 napi_value AlbumNapi::JSSetAlbumPath(napi_env env, napi_callback_info info)
415 {
416 napi_status status;
417 napi_value jsResult = nullptr;
418 size_t argc = ARGS_ONE;
419 napi_value argv[ARGS_ONE] = {0};
420 size_t res = 0;
421 char buffer[PATH_MAX];
422 AlbumNapi* obj = nullptr;
423 napi_value thisVar = nullptr;
424 napi_valuetype valueType = napi_undefined;
425
426 napi_get_undefined(env, &jsResult);
427 GET_JS_ARGS(env, info, argc, argv, thisVar);
428 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
429
430 if (thisVar == nullptr || napi_typeof(env, argv[PARAM0], &valueType) != napi_ok
431 || valueType != napi_string) {
432 NAPI_ERR_LOG("Invalid arguments type! type: %{public}d", valueType);
433 return jsResult;
434 }
435
436 napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &res);
437
438 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
439 if (status == napi_ok && obj != nullptr) {
440 obj->albumAssetPtr->SetAlbumPath(std::string(buffer));
441 }
442
443 return jsResult;
444 }
445
JSGetAlbumPath(napi_env env,napi_callback_info info)446 napi_value AlbumNapi::JSGetAlbumPath(napi_env env, napi_callback_info info)
447 {
448 napi_status status;
449 napi_value jsResult = nullptr;
450 napi_value undefinedResult = nullptr;
451 AlbumNapi* obj = nullptr;
452 std::string path = "";
453 napi_value thisVar = nullptr;
454
455 napi_get_undefined(env, &undefinedResult);
456 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
457 if (status != napi_ok || thisVar == nullptr) {
458 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
459 return undefinedResult;
460 }
461
462 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
463 if (status == napi_ok && obj != nullptr) {
464 path = obj->GetAlbumPath();
465 status = napi_create_string_utf8(env, path.c_str(), NAPI_AUTO_LENGTH, &jsResult);
466 if (status == napi_ok) {
467 return jsResult;
468 }
469 }
470
471 return undefinedResult;
472 }
473
JSGetAlbumVirtual(napi_env env,napi_callback_info info)474 napi_value AlbumNapi::JSGetAlbumVirtual(napi_env env, napi_callback_info info)
475 {
476 napi_status status;
477 napi_value jsResult = nullptr;
478 napi_value undefinedResult = nullptr;
479 AlbumNapi* obj = nullptr;
480 bool virtualAlbum = false;
481 napi_value thisVar = nullptr;
482
483 napi_get_undefined(env, &undefinedResult);
484 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
485 if (status != napi_ok || thisVar == nullptr) {
486 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
487 return undefinedResult;
488 }
489
490 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
491 if (status == napi_ok && obj != nullptr) {
492 virtualAlbum = obj->albumAssetPtr->GetAlbumVirtual();
493 status = napi_get_boolean(env, virtualAlbum, &jsResult);
494 if (status == napi_ok) {
495 return jsResult;
496 }
497 }
498
499 return undefinedResult;
500 }
501
GetFetchOptionsParam(napi_env env,napi_value arg,const AlbumNapiAsyncContext & context,bool & err)502 static void GetFetchOptionsParam(napi_env env, napi_value arg, const AlbumNapiAsyncContext &context, bool &err)
503 {
504 AlbumNapiAsyncContext *asyncContext = const_cast<AlbumNapiAsyncContext *>(&context);
505 CHECK_NULL_PTR_RETURN_VOID(asyncContext, "Async context is null");
506 char buffer[PATH_MAX];
507 size_t res;
508 uint32_t len = 0;
509 napi_value property = nullptr;
510 napi_value stringItem = nullptr;
511 bool present = false;
512 bool boolResult = false;
513
514 napi_has_named_property(env, arg, "selections", &present);
515 if (present) {
516 if (napi_get_named_property(env, arg, "selections", &property) != napi_ok
517 || napi_get_value_string_utf8(env, property, buffer, PATH_MAX, &res) != napi_ok) {
518 NAPI_ERR_LOG("Could not get the string argument!");
519 err = true;
520 return;
521 } else {
522 asyncContext->selection = buffer;
523 CHECK_IF_EQUAL(memset_s(buffer, PATH_MAX, 0, sizeof(buffer)) == 0, "Memset for buffer failed");
524 }
525 present = false;
526 }
527
528 napi_has_named_property(env, arg, "order", &present);
529 if (present) {
530 if (napi_get_named_property(env, arg, "order", &property) != napi_ok
531 || napi_get_value_string_utf8(env, property, buffer, PATH_MAX, &res) != napi_ok) {
532 NAPI_ERR_LOG("Could not get the string argument!");
533 err = true;
534 return;
535 } else {
536 asyncContext->order = buffer;
537 CHECK_IF_EQUAL(memset_s(buffer, PATH_MAX, 0, sizeof(buffer)) == 0, "Memset for buffer failed");
538 }
539 present = false;
540 }
541
542 napi_has_named_property(env, arg, "selectionArgs", &present);
543 if (present && napi_get_named_property(env, arg, "selectionArgs", &property) == napi_ok &&
544 napi_is_array(env, property, &boolResult) == napi_ok && boolResult) {
545 napi_get_array_length(env, property, &len);
546 for (size_t i = 0; i < len; i++) {
547 napi_get_element(env, property, i, &stringItem);
548 napi_get_value_string_utf8(env, stringItem, buffer, PATH_MAX, &res);
549 asyncContext->selectionArgs.push_back(std::string(buffer));
550 CHECK_IF_EQUAL(memset_s(buffer, PATH_MAX, 0, sizeof(buffer)) == 0, "Memset for buffer failed");
551 }
552 } else {
553 NAPI_ERR_LOG("Could not get the string argument!");
554 err = true;
555 }
556 }
557
ConvertJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],AlbumNapiAsyncContext & asyncContext)558 static napi_value ConvertJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
559 AlbumNapiAsyncContext &asyncContext)
560 {
561 string str = "";
562 std::vector<string> strArr;
563 string order = "";
564 bool err = false;
565 const int32_t refCount = 1;
566 napi_value result;
567 auto context = &asyncContext;
568 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
569 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
570
571 for (size_t i = PARAM0; i < argc; i++) {
572 napi_valuetype valueType = napi_undefined;
573 napi_typeof(env, argv[i], &valueType);
574
575 if (i == PARAM0 && valueType == napi_object) {
576 GetFetchOptionsParam(env, argv[PARAM0], asyncContext, err);
577 if (err) {
578 NAPI_ASSERT(env, false, "type mismatch");
579 }
580 } else if (i == PARAM0 && valueType == napi_function) {
581 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
582 break;
583 } else if (i == PARAM1 && valueType == napi_function) {
584 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
585 break;
586 } else {
587 NAPI_ASSERT(env, false, "type mismatch");
588 }
589 }
590
591 // Return true napi_value if params are successfully obtained
592 napi_get_boolean(env, true, &result);
593 return result;
594 }
ConvertCommitJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],AlbumNapiAsyncContext & asyncContext)595 static napi_value ConvertCommitJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
596 AlbumNapiAsyncContext &asyncContext)
597 {
598 string str = "";
599 vector<string> strArr;
600 string order = "";
601 bool err = false;
602 const int32_t refCount = 1;
603 napi_value result;
604 auto context = &asyncContext;
605 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
606 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
607
608 for (size_t i = PARAM0; i < argc; i++) {
609 napi_valuetype valueType = napi_undefined;
610 napi_typeof(env, argv[i], &valueType);
611
612 if (i == PARAM0 && valueType == napi_object) {
613 GetFetchOptionsParam(env, argv[PARAM0], asyncContext, err);
614 if (err) {
615 NAPI_ERR_LOG("fetch options retrieval failed. err %{public}d", err);
616 NAPI_ASSERT(env, false, "type mismatch");
617 }
618 } else if (i == PARAM0 && valueType == napi_function) {
619 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
620 break;
621 } else if (i == PARAM1 && valueType == napi_function) {
622 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
623 break;
624 } else {
625 NAPI_ASSERT(env, false, "type mismatch");
626 }
627 }
628
629 // Return true napi_value if params are successfully obtained
630 napi_get_boolean(env, true, &result);
631 return result;
632 }
633
UpdateSelection(AlbumNapiAsyncContext * context)634 static void UpdateSelection(AlbumNapiAsyncContext *context)
635 {
636 if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
637 context->predicates.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, 0);
638 context->predicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_TYPE_ALBUM);
639 context->predicates.EqualTo(MEDIA_DATA_DB_BUCKET_ID, context->objectPtr->GetAlbumId());
640 MediaLibraryNapiUtils::UpdateMediaTypeSelections(context);
641 } else {
642 string trashPrefix = MEDIA_DATA_DB_DATE_TRASHED + " = ? ";
643 MediaLibraryNapiUtils::AppendFetchOptionSelection(context->selection, trashPrefix);
644 context->selectionArgs.emplace_back("0");
645
646 string prefix = MEDIA_DATA_DB_MEDIA_TYPE + " <> ? ";
647 MediaLibraryNapiUtils::AppendFetchOptionSelection(context->selection, prefix);
648 context->selectionArgs.emplace_back(to_string(MEDIA_TYPE_ALBUM));
649
650 string idPrefix = MEDIA_DATA_DB_BUCKET_ID + " = ? ";
651 MediaLibraryNapiUtils::AppendFetchOptionSelection(context->selection, idPrefix);
652 context->selectionArgs.emplace_back(std::to_string(context->objectPtr->GetAlbumId()));
653 }
654 }
655
GetFileAssetsNative(napi_env env,void * data)656 static void GetFileAssetsNative(napi_env env, void *data)
657 {
658 MediaLibraryTracer tracer;
659 tracer.Start("GetFileAssetsNative");
660
661 AlbumNapiAsyncContext *context = static_cast<AlbumNapiAsyncContext*>(data);
662 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
663
664 UpdateSelection(context);
665 context->predicates.SetWhereClause(context->selection);
666 context->predicates.SetWhereArgs(context->selectionArgs);
667 context->predicates.SetOrder(context->order);
668 if (context->fetchColumn.size() == 0) {
669 context->fetchColumn.push_back("*");
670 }
671 string queryUri = MEDIALIBRARY_DATA_ABILITY_PREFIX +
672 (MediaFileUtils::GetNetworkIdFromUri(context->objectPtr->GetAlbumUri())) + MEDIALIBRARY_DATA_URI_IDENTIFIER;
673 MediaLibraryNapiUtils::UriAddFragmentTypeMask(queryUri, context->typeMask);
674 NAPI_DEBUG_LOG("queryUri is = %{public}s", queryUri.c_str());
675 Uri uri(queryUri);
676 std::shared_ptr<OHOS::DataShare::DataShareResultSet> resultSet =
677 UserFileClient::Query(uri, context->predicates, context->fetchColumn);
678 context->fetchResult = std::make_unique<FetchResult<FileAsset>>(move(resultSet));
679 context->fetchResult->networkId_ = MediaFileUtils::GetNetworkIdFromUri(context->objectPtr->GetAlbumUri());
680 if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
681 context->fetchResult->resultNapiType_ = context->resultNapiType;
682 }
683 }
684
JSGetFileAssetsCompleteCallback(napi_env env,napi_status status,void * data)685 static void JSGetFileAssetsCompleteCallback(napi_env env, napi_status status, void*data)
686 {
687 MediaLibraryTracer tracer;
688 tracer.Start("JSGetFileAssetsCompleteCallback");
689
690 AlbumNapiAsyncContext *context = static_cast<AlbumNapiAsyncContext*>(data);
691 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
692
693 std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
694 jsContext->status = false;
695 if (context->fetchResult != nullptr) {
696 if (context->fetchResult->GetCount() < 0) {
697 napi_get_undefined(env, &jsContext->data);
698 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
699 "find no data by options");
700 } else {
701 napi_value fetchRes = FetchFileResultNapi::CreateFetchFileResult(env, move(context->fetchResult));
702 if (fetchRes == nullptr) {
703 NAPI_ERR_LOG("Failed to get file asset napi object");
704 napi_get_undefined(env, &jsContext->data);
705 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
706 "Failed to create js object for FetchFileResult");
707 } else {
708 jsContext->data = fetchRes;
709 napi_get_undefined(env, &jsContext->error);
710 jsContext->status = true;
711 }
712 }
713 } else {
714 NAPI_ERR_LOG("No fetch file result found!");
715 napi_get_undefined(env, &jsContext->data);
716 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
717 "Failed to obtain fetchFileResult from DB");
718 }
719
720 tracer.Finish();
721 if (context->work != nullptr) {
722 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
723 context->work, *jsContext);
724 }
725 delete context;
726 }
727
CommitModifyNative(napi_env env,void * data)728 static void CommitModifyNative(napi_env env, void *data)
729 {
730 MediaLibraryTracer tracer;
731 tracer.Start("CommitModifyNative");
732
733 auto *context = static_cast<AlbumNapiAsyncContext*>(data);
734 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
735 auto objectPtr = context->objectPtr;
736 if (!MediaFileUtils::CheckTitle(objectPtr->GetAlbumName())) {
737 context->error = JS_E_DISPLAYNAME;
738 NAPI_ERR_LOG("album name invalid = %{public}s", objectPtr->GetAlbumName().c_str());
739 return;
740 }
741
742 DataSharePredicates predicates;
743 DataShareValuesBucket valuesBucket;
744 valuesBucket.Put(MEDIA_DATA_DB_TITLE, objectPtr->GetAlbumName());
745 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
746 predicates.SetWhereArgs({ std::to_string(objectPtr->GetAlbumId()) });
747
748 string updateUri = MEDIALIBRARY_DATA_URI;
749 MediaLibraryNapiUtils::UriAddFragmentTypeMask(updateUri, context->typeMask);
750 Uri uri(updateUri);
751 int changedRows = UserFileClient::Update(uri, predicates, valuesBucket);
752 if (changedRows > 0) {
753 DataSharePredicates filePredicates;
754 DataShareValuesBucket fileValuesBucket;
755 fileValuesBucket.Put(MEDIA_DATA_DB_BUCKET_NAME, objectPtr->GetAlbumName());
756 filePredicates.SetWhereClause(MEDIA_DATA_DB_BUCKET_ID + " = ? ");
757 filePredicates.SetWhereArgs({ std::to_string(objectPtr->GetAlbumId()) });
758
759 string fileUriStr = MEDIALIBRARY_DATA_URI;
760 MediaLibraryNapiUtils::UriAddFragmentTypeMask(fileUriStr, context->typeMask);
761 Uri fileUri(fileUriStr);
762 changedRows = UserFileClient::Update(fileUri, filePredicates, fileValuesBucket);
763 }
764 context->SaveError(changedRows);
765 context->changedRows = changedRows;
766 }
767
JSCommitModifyCompleteCallback(napi_env env,napi_status status,void * data)768 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, void *data)
769 {
770 MediaLibraryTracer tracer;
771 tracer.Start("JSCommitModifyCompleteCallback");
772
773 AlbumNapiAsyncContext *context = static_cast<AlbumNapiAsyncContext*>(data);
774 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
775 std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
776 jsContext->status = false;
777 if (context->error == ERR_DEFAULT) {
778 napi_create_int32(env, context->changedRows, &jsContext->data);
779 napi_get_undefined(env, &jsContext->error);
780 jsContext->status = true;
781 auto contextUri = make_unique<Uri>(MEDIALIBRARY_ALBUM_URI);
782 UserFileClient::NotifyChange(*contextUri);
783 } else {
784 napi_get_undefined(env, &jsContext->data);
785 context->HandleError(env, jsContext->error);
786 }
787
788 tracer.Finish();
789 if (context->work != nullptr) {
790 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
791 context->work, *jsContext);
792 }
793
794 delete context;
795 }
JSGetAlbumFileAssets(napi_env env,napi_callback_info info)796 napi_value AlbumNapi::JSGetAlbumFileAssets(napi_env env, napi_callback_info info)
797 {
798 napi_status status;
799 napi_value result = nullptr;
800 size_t argc = ARGS_TWO;
801 napi_value argv[ARGS_TWO] = {0};
802 napi_value thisVar = nullptr;
803
804 MediaLibraryTracer tracer;
805 tracer.Start("JSGetAlbumFileAssets");
806
807 GET_JS_ARGS(env, info, argc, argv, thisVar);
808 NAPI_ASSERT(env, ((argc == ARGS_ZERO) || (argc == ARGS_ONE) || (argc == ARGS_TWO)),
809 "requires 2 parameter maximum");
810 napi_get_undefined(env, &result);
811
812 std::unique_ptr<AlbumNapiAsyncContext> asyncContext = std::make_unique<AlbumNapiAsyncContext>();
813 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
814 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
815 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
816 result = ConvertJSArgsToNative(env, argc, argv, *asyncContext);
817 CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "Failed to obtain arguments");
818 asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
819 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "AlbumAsset is nullptr");
820
821 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetAlbumFileAssets",
822 GetFileAssetsNative, JSGetFileAssetsCompleteCallback);
823 }
824
825 return result;
826 }
JSCommitModify(napi_env env,napi_callback_info info)827 napi_value AlbumNapi::JSCommitModify(napi_env env, napi_callback_info info)
828 {
829 napi_status status;
830 napi_value result = nullptr;
831 size_t argc = ARGS_ONE;
832 napi_value argv[ARGS_ONE] = {0};
833 napi_value thisVar = nullptr;
834
835 MediaLibraryTracer tracer;
836 tracer.Start("JSCommitModify");
837
838 GET_JS_ARGS(env, info, argc, argv, thisVar);
839 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameter maximum");
840 napi_get_undefined(env, &result);
841
842 std::unique_ptr<AlbumNapiAsyncContext> asyncContext = std::make_unique<AlbumNapiAsyncContext>();
843 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
844 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
845 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
846 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
847 result = ConvertCommitJSArgsToNative(env, argc, argv, *asyncContext);
848 CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "JSCommitModify fail ");
849 asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
850 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "AlbumAsset is nullptr");
851
852 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", CommitModifyNative,
853 JSCommitModifyCompleteCallback);
854 }
855
856 return result;
857 }
858
UserFileMgrGetAssets(napi_env env,napi_callback_info info)859 napi_value AlbumNapi::UserFileMgrGetAssets(napi_env env, napi_callback_info info)
860 {
861 napi_value ret = nullptr;
862 unique_ptr<AlbumNapiAsyncContext> asyncContext = make_unique<AlbumNapiAsyncContext>();
863 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
864
865 asyncContext->mediaTypes.push_back(MEDIA_TYPE_IMAGE);
866 asyncContext->mediaTypes.push_back(MEDIA_TYPE_VIDEO);
867 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseAssetFetchOptCallback(env, info, asyncContext), asyncContext,
868 JS_ERR_PARAMETER_INVALID);
869 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
870 asyncContext->typeMask = asyncContext->objectInfo->GetTypeMask();
871 asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
872 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "AlbumAsset is nullptr");
873
874 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrGetAssets", GetFileAssetsNative,
875 JSGetFileAssetsCompleteCallback);
876 }
877
UserFileMgrCommitModify(napi_env env,napi_callback_info info)878 napi_value AlbumNapi::UserFileMgrCommitModify(napi_env env, napi_callback_info info)
879 {
880 MediaLibraryTracer tracer;
881 tracer.Start("UserFileMgrCommitModify");
882
883 napi_value ret = nullptr;
884 unique_ptr<AlbumNapiAsyncContext> asyncContext = make_unique<AlbumNapiAsyncContext>();
885 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
886 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
887 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext), asyncContext,
888 JS_ERR_PARAMETER_INVALID);
889 asyncContext->typeMask = asyncContext->objectInfo->GetTypeMask();
890 asyncContext->objectPtr = asyncContext->objectInfo->albumAssetPtr;
891 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "AlbumAsset is nullptr");
892
893 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrCommitModify", CommitModifyNative,
894 JSCommitModifyCompleteCallback);
895 }
896 } // namespace Media
897 } // namespace OHOS
898