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 "FileAssetNapi"
16
17 #include "file_asset_napi.h"
18
19 #include <cstring>
20
21 #include "abs_shared_result_set.h"
22 #include "hitrace_meter.h"
23 #include "fetch_result.h"
24 #include "hilog/log.h"
25 #include "media_file_utils.h"
26 #include "medialibrary_client_errno.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_napi_log.h"
29 #include "medialibrary_napi_utils.h"
30 #include "medialibrary_tracer.h"
31 #include "rdb_errno.h"
32 #include "string_ex.h"
33 #include "thumbnail_const.h"
34 #include "userfile_client.h"
35
36 using OHOS::HiviewDFX::HiLog;
37 using OHOS::HiviewDFX::HiLogLabel;
38 using namespace std;
39 using namespace OHOS::AppExecFwk;
40 using namespace OHOS::NativeRdb;
41 using namespace OHOS::DataShare;
42 using std::string;
43
44 namespace OHOS {
45 namespace Media {
46 static const std::string MEDIA_FILEDESCRIPTOR = "fd";
47
48 thread_local napi_ref FileAssetNapi::sConstructor_ = nullptr;
49 thread_local FileAsset *FileAssetNapi::sFileAsset_ = nullptr;
50
51 constexpr int64_t IS_TRASH = 1;
52 constexpr int64_t NOT_TRASH = 0;
53
54 using CompleteCallback = napi_async_complete_callback;
55
56 thread_local napi_ref FileAssetNapi::userFileMgrConstructor_ = nullptr;
57
FileAssetNapi()58 FileAssetNapi::FileAssetNapi()
59 : env_(nullptr) {}
60
61 FileAssetNapi::~FileAssetNapi() = default;
62
FileAssetNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)63 void FileAssetNapi::FileAssetNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
64 {
65 FileAssetNapi *fileAssetObj = reinterpret_cast<FileAssetNapi*>(nativeObject);
66 if (fileAssetObj != nullptr) {
67 delete fileAssetObj;
68 fileAssetObj = nullptr;
69 }
70 }
71
Init(napi_env env,napi_value exports)72 napi_value FileAssetNapi::Init(napi_env env, napi_value exports)
73 {
74 napi_status status;
75 napi_value ctorObj;
76 int32_t refCount = 1;
77 napi_property_descriptor file_asset_props[] = {
78 DECLARE_NAPI_GETTER("id", JSGetFileId),
79 DECLARE_NAPI_GETTER("uri", JSGetFileUri),
80 DECLARE_NAPI_GETTER("mediaType", JSGetMediaType),
81 DECLARE_NAPI_GETTER_SETTER("displayName", JSGetFileDisplayName, JSSetFileDisplayName),
82 DECLARE_NAPI_GETTER_SETTER("relativePath", JSGetRelativePath, JSSetRelativePath),
83 DECLARE_NAPI_GETTER("parent", JSParent),
84 DECLARE_NAPI_GETTER("size", JSGetSize),
85 DECLARE_NAPI_GETTER("dateAdded", JSGetDateAdded),
86 DECLARE_NAPI_GETTER("dateTrashed", JSGetDateTrashed),
87 DECLARE_NAPI_GETTER("dateModified", JSGetDateModified),
88 DECLARE_NAPI_GETTER("dateTaken", JSGetDateTaken),
89 DECLARE_NAPI_GETTER("mimeType", JSGetMimeType),
90 DECLARE_NAPI_GETTER_SETTER("title", JSGetTitle, JSSetTitle),
91 DECLARE_NAPI_GETTER("artist", JSGetArtist),
92 DECLARE_NAPI_GETTER("audioAlbum", JSGetAlbum),
93 DECLARE_NAPI_GETTER("width", JSGetWidth),
94 DECLARE_NAPI_GETTER("height", JSGetHeight),
95 DECLARE_NAPI_GETTER_SETTER("orientation", JSGetOrientation, JSSetOrientation),
96 DECLARE_NAPI_GETTER("duration", JSGetDuration),
97 DECLARE_NAPI_GETTER("albumId", JSGetAlbumId),
98 DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
99 DECLARE_NAPI_GETTER("albumName", JSGetAlbumName),
100 DECLARE_NAPI_GETTER("count", JSGetCount),
101 DECLARE_NAPI_FUNCTION("isDirectory", JSIsDirectory),
102 DECLARE_NAPI_FUNCTION("commitModify", JSCommitModify),
103 DECLARE_NAPI_FUNCTION("open", JSOpen),
104 DECLARE_NAPI_FUNCTION("close", JSClose),
105 DECLARE_NAPI_FUNCTION("getThumbnail", JSGetThumbnail),
106 DECLARE_NAPI_FUNCTION("favorite", JSFavorite),
107 DECLARE_NAPI_FUNCTION("isFavorite", JSIsFavorite),
108 DECLARE_NAPI_FUNCTION("trash", JSTrash),
109 DECLARE_NAPI_FUNCTION("isTrash", JSIsTrash),
110 };
111
112 status = napi_define_class(env, FILE_ASSET_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
113 FileAssetNapiConstructor, nullptr,
114 sizeof(file_asset_props) / sizeof(file_asset_props[PARAM0]),
115 file_asset_props, &ctorObj);
116 if (status == napi_ok) {
117 status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
118 if (status == napi_ok) {
119 status = napi_set_named_property(env, exports, FILE_ASSET_NAPI_CLASS_NAME.c_str(), ctorObj);
120 if (status == napi_ok) {
121 return exports;
122 }
123 }
124 }
125 return nullptr;
126 }
127
UserFileMgrInit(napi_env env,napi_value exports)128 napi_value FileAssetNapi::UserFileMgrInit(napi_env env, napi_value exports)
129 {
130 NapiClassInfo info = {
131 .name = USERFILEMGR_FILEASSET_NAPI_CLASS_NAME,
132 .ref = &userFileMgrConstructor_,
133 .constructor = FileAssetNapiConstructor,
134 .props = {
135 DECLARE_NAPI_FUNCTION("get", UserFileMgrGet),
136 DECLARE_NAPI_FUNCTION("set", UserFileMgrSet),
137 DECLARE_NAPI_FUNCTION("open", UserFileMgrOpen),
138 DECLARE_NAPI_FUNCTION("close", UserFileMgrClose),
139 DECLARE_NAPI_FUNCTION("commitModify", UserFileMgrCommitModify),
140 DECLARE_NAPI_FUNCTION("favorite", UserFileMgrFavorite),
141 DECLARE_NAPI_FUNCTION("trash", UserFileMgrTrash),
142 DECLARE_NAPI_GETTER("uri", JSGetFileUri),
143 DECLARE_NAPI_GETTER("fileType", JSGetMediaType),
144 DECLARE_NAPI_GETTER_SETTER("displayName", JSGetFileDisplayName, JSSetFileDisplayName),
145 DECLARE_NAPI_FUNCTION("isFavorite", JSIsFavorite),
146 DECLARE_NAPI_FUNCTION("isTrash", JSIsTrash),
147 DECLARE_NAPI_FUNCTION("isDirectory", UserFileMgrIsDirectory),
148 DECLARE_NAPI_FUNCTION("getThumbnail", UserFileMgrGetThumbnail),
149 }
150 };
151 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
152
153 return exports;
154 }
155
156 // Constructor callback
FileAssetNapiConstructor(napi_env env,napi_callback_info info)157 napi_value FileAssetNapi::FileAssetNapiConstructor(napi_env env, napi_callback_info info)
158 {
159 napi_status status;
160 napi_value result = nullptr;
161 napi_value thisVar = nullptr;
162
163 napi_get_undefined(env, &result);
164 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
165 if (status == napi_ok && thisVar != nullptr) {
166 std::unique_ptr<FileAssetNapi> obj = std::make_unique<FileAssetNapi>();
167 if (obj != nullptr) {
168 obj->env_ = env;
169 if (sFileAsset_ != nullptr) {
170 obj->UpdateFileAssetInfo();
171 }
172
173 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
174 FileAssetNapi::FileAssetNapiDestructor, nullptr, nullptr);
175 if (status == napi_ok) {
176 obj.release();
177 return thisVar;
178 } else {
179 NAPI_ERR_LOG("Failure wrapping js to native napi, status: %{public}d", status);
180 }
181 }
182 }
183
184 return result;
185 }
186
CreateFileAsset(napi_env env,unique_ptr<FileAsset> & iAsset)187 napi_value FileAssetNapi::CreateFileAsset(napi_env env, unique_ptr<FileAsset> &iAsset)
188 {
189 MediaLibraryTracer tracer;
190 tracer.Start("CreateFileAsset");
191
192 if (iAsset == nullptr) {
193 return nullptr;
194 }
195
196 napi_value constructor = nullptr;
197 napi_ref constructorRef = (iAsset->GetResultNapiType() == ResultNapiType::TYPE_USERFILE_MGR) ?
198 (userFileMgrConstructor_) : (sConstructor_);
199 NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
200
201 sFileAsset_ = iAsset.release();
202
203 napi_value result = nullptr;
204 NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
205
206 sFileAsset_ = nullptr;
207 return result;
208 }
209
GetFileDisplayName() const210 std::string FileAssetNapi::GetFileDisplayName() const
211 {
212 return fileAssetPtr->GetDisplayName();
213 }
214
GetRelativePath() const215 std::string FileAssetNapi::GetRelativePath() const
216 {
217 return fileAssetPtr->GetRelativePath();
218 }
219
GetFilePath() const220 std::string FileAssetNapi::GetFilePath() const
221 {
222 return fileAssetPtr->GetPath();
223 }
224
GetTitle() const225 std::string FileAssetNapi::GetTitle() const
226 {
227 return fileAssetPtr->GetTitle();
228 }
229
GetFileUri() const230 std::string FileAssetNapi::GetFileUri() const
231 {
232 return fileAssetPtr->GetUri();
233 }
234
GetFileId() const235 int32_t FileAssetNapi::GetFileId() const
236 {
237 return fileAssetPtr->GetId();
238 }
239
GetMediaType() const240 Media::MediaType FileAssetNapi::GetMediaType() const
241 {
242 return fileAssetPtr->GetMediaType();
243 }
244
GetOrientation() const245 int32_t FileAssetNapi::GetOrientation() const
246 {
247 return fileAssetPtr->GetOrientation();
248 }
249
GetNetworkId() const250 std::string FileAssetNapi::GetNetworkId() const
251 {
252 return MediaFileUtils::GetNetworkIdFromUri(GetFileUri());
253 }
254
GetTypeMask() const255 std::string FileAssetNapi::GetTypeMask() const
256 {
257 return fileAssetPtr->GetTypeMask();
258 }
259
SetTypeMask(const std::string & typeMask)260 void FileAssetNapi::SetTypeMask(const std::string &typeMask)
261 {
262 fileAssetPtr->SetTypeMask(typeMask);
263 }
264
IsFavorite() const265 bool FileAssetNapi::IsFavorite() const
266 {
267 return fileAssetPtr->IsFavorite();
268 }
269
SetFavorite(bool isFavorite)270 void FileAssetNapi::SetFavorite(bool isFavorite)
271 {
272 fileAssetPtr->SetFavorite(isFavorite);
273 }
274
IsTrash() const275 bool FileAssetNapi::IsTrash() const
276 {
277 return (fileAssetPtr->GetIsTrash() != NOT_TRASH);
278 }
279
SetTrash(bool isTrash)280 void FileAssetNapi::SetTrash(bool isTrash)
281 {
282 int32_t trashFlag = (isTrash ? IS_TRASH : NOT_TRASH);
283 fileAssetPtr->SetIsTrash(trashFlag);
284 }
285
JSGetFileId(napi_env env,napi_callback_info info)286 napi_value FileAssetNapi::JSGetFileId(napi_env env, napi_callback_info info)
287 {
288 napi_status status;
289 napi_value jsResult = nullptr;
290 FileAssetNapi* obj = nullptr;
291 int32_t id;
292 napi_value thisVar = nullptr;
293
294 napi_get_undefined(env, &jsResult);
295 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
296 if (status != napi_ok || thisVar == nullptr) {
297 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
298 return jsResult;
299 }
300
301 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
302 if (status == napi_ok && obj != nullptr) {
303 id = obj->GetFileId();
304 napi_create_int32(env, id, &jsResult);
305 }
306
307 return jsResult;
308 }
309
JSGetFileUri(napi_env env,napi_callback_info info)310 napi_value FileAssetNapi::JSGetFileUri(napi_env env, napi_callback_info info)
311 {
312 napi_status status;
313 napi_value jsResult = nullptr;
314 FileAssetNapi* obj = nullptr;
315 string uri = "";
316 napi_value thisVar = nullptr;
317
318 napi_get_undefined(env, &jsResult);
319 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
320 if (status != napi_ok || thisVar == nullptr) {
321 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
322 return jsResult;
323 }
324
325 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
326 if (status == napi_ok && obj != nullptr) {
327 uri = obj->GetFileUri();
328 napi_create_string_utf8(env, uri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
329 }
330
331 return jsResult;
332 }
333
JSGetFilePath(napi_env env,napi_callback_info info)334 napi_value FileAssetNapi::JSGetFilePath(napi_env env, napi_callback_info info)
335 {
336 napi_status status;
337 napi_value jsResult = nullptr;
338 FileAssetNapi* obj = nullptr;
339 string path = "";
340 napi_value thisVar = nullptr;
341
342 napi_get_undefined(env, &jsResult);
343 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
344 if (status != napi_ok || thisVar == nullptr) {
345 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
346 return jsResult;
347 }
348
349 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
350 if (status == napi_ok && obj != nullptr) {
351 path = obj->GetFilePath();
352 napi_create_string_utf8(env, path.c_str(), NAPI_AUTO_LENGTH, &jsResult);
353 }
354
355 return jsResult;
356 }
357
JSGetFileDisplayName(napi_env env,napi_callback_info info)358 napi_value FileAssetNapi::JSGetFileDisplayName(napi_env env, napi_callback_info info)
359 {
360 napi_status status;
361 napi_value jsResult = nullptr;
362 FileAssetNapi* obj = nullptr;
363 string displayName = "";
364 napi_value thisVar = nullptr;
365
366 napi_get_undefined(env, &jsResult);
367 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
368 if (status != napi_ok || thisVar == nullptr) {
369 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
370 return jsResult;
371 }
372
373 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
374 if (status == napi_ok && obj != nullptr) {
375 displayName = obj->GetFileDisplayName();
376 napi_create_string_utf8(env, displayName.c_str(), NAPI_AUTO_LENGTH, &jsResult);
377 }
378
379 return jsResult;
380 }
381
JSSetFileDisplayName(napi_env env,napi_callback_info info)382 napi_value FileAssetNapi::JSSetFileDisplayName(napi_env env, napi_callback_info info)
383 {
384 napi_status status;
385 napi_value undefinedResult = nullptr;
386 FileAssetNapi* obj = nullptr;
387 napi_valuetype valueType = napi_undefined;
388 size_t res = 0;
389 char buffer[FILENAME_MAX];
390 size_t argc = ARGS_ONE;
391 napi_value argv[ARGS_ONE] = {0};
392 napi_value thisVar = nullptr;
393
394 napi_get_undefined(env, &undefinedResult);
395
396 GET_JS_ARGS(env, info, argc, argv, thisVar);
397 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
398
399 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
400 if (status == napi_ok && obj != nullptr) {
401 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
402 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
403 return undefinedResult;
404 }
405 status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
406 if (status == napi_ok) {
407 obj->fileAssetPtr->SetDisplayName(string(buffer));
408 }
409 }
410
411 return undefinedResult;
412 }
413
JSGetMimeType(napi_env env,napi_callback_info info)414 napi_value FileAssetNapi::JSGetMimeType(napi_env env, napi_callback_info info)
415 {
416 napi_status status;
417 napi_value jsResult = nullptr;
418 FileAssetNapi* obj = nullptr;
419 string mimeType = "";
420 napi_value thisVar = nullptr;
421
422 napi_get_undefined(env, &jsResult);
423 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
424 if (status != napi_ok || thisVar == nullptr) {
425 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
426 return jsResult;
427 }
428
429 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
430 if (status == napi_ok && obj != nullptr) {
431 mimeType = obj->fileAssetPtr->GetMimeType();
432 napi_create_string_utf8(env, mimeType.c_str(), NAPI_AUTO_LENGTH, &jsResult);
433 }
434
435 return jsResult;
436 }
437
JSGetMediaType(napi_env env,napi_callback_info info)438 napi_value FileAssetNapi::JSGetMediaType(napi_env env, napi_callback_info info)
439 {
440 napi_status status;
441 napi_value jsResult = nullptr;
442 FileAssetNapi* obj = nullptr;
443 int32_t mediaType;
444 napi_value thisVar = nullptr;
445
446 napi_get_undefined(env, &jsResult);
447 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
448 if (status != napi_ok || thisVar == nullptr) {
449 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
450 return jsResult;
451 }
452
453 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
454 if (status == napi_ok && obj != nullptr) {
455 mediaType = static_cast<int32_t>(obj->GetMediaType());
456 napi_create_int32(env, mediaType, &jsResult);
457 }
458
459 return jsResult;
460 }
461
JSGetTitle(napi_env env,napi_callback_info info)462 napi_value FileAssetNapi::JSGetTitle(napi_env env, napi_callback_info info)
463 {
464 napi_status status;
465 napi_value jsResult = nullptr;
466 FileAssetNapi* obj = nullptr;
467 string title = "";
468 napi_value thisVar = nullptr;
469
470 napi_get_undefined(env, &jsResult);
471 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
472 if (status != napi_ok || thisVar == nullptr) {
473 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
474 return jsResult;
475 }
476
477 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
478 if (status == napi_ok && obj != nullptr) {
479 title = obj->GetTitle();
480 napi_create_string_utf8(env, title.c_str(), NAPI_AUTO_LENGTH, &jsResult);
481 }
482
483 return jsResult;
484 }
JSSetTitle(napi_env env,napi_callback_info info)485 napi_value FileAssetNapi::JSSetTitle(napi_env env, napi_callback_info info)
486 {
487 napi_status status;
488 napi_value undefinedResult = nullptr;
489 FileAssetNapi* obj = nullptr;
490 napi_valuetype valueType = napi_undefined;
491 size_t res = 0;
492 char buffer[FILENAME_MAX];
493 size_t argc = ARGS_ONE;
494 napi_value argv[ARGS_ONE] = {0};
495 napi_value thisVar = nullptr;
496 napi_get_undefined(env, &undefinedResult);
497 GET_JS_ARGS(env, info, argc, argv, thisVar);
498 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
499 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
500 if (status == napi_ok && obj != nullptr) {
501 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
502 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
503 return undefinedResult;
504 }
505 status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
506 if (status == napi_ok) {
507 obj->fileAssetPtr->SetTitle(string(buffer));
508 }
509 }
510 return undefinedResult;
511 }
512
JSGetSize(napi_env env,napi_callback_info info)513 napi_value FileAssetNapi::JSGetSize(napi_env env, napi_callback_info info)
514 {
515 napi_status status;
516 napi_value jsResult = nullptr;
517 FileAssetNapi* obj = nullptr;
518 int64_t size;
519 napi_value thisVar = nullptr;
520
521 napi_get_undefined(env, &jsResult);
522 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
523 if (status != napi_ok || thisVar == nullptr) {
524 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
525 return jsResult;
526 }
527
528 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
529 if (status == napi_ok && obj != nullptr) {
530 size = obj->fileAssetPtr->GetSize();
531 napi_create_int64(env, size, &jsResult);
532 }
533
534 return jsResult;
535 }
536
JSGetAlbumId(napi_env env,napi_callback_info info)537 napi_value FileAssetNapi::JSGetAlbumId(napi_env env, napi_callback_info info)
538 {
539 napi_status status;
540 napi_value jsResult = nullptr;
541 FileAssetNapi* obj = nullptr;
542 int32_t albumId;
543 napi_value thisVar = nullptr;
544
545 napi_get_undefined(env, &jsResult);
546 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
547 if (status != napi_ok || thisVar == nullptr) {
548 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
549 return jsResult;
550 }
551
552 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
553 if (status == napi_ok && obj != nullptr) {
554 albumId = obj->fileAssetPtr->GetAlbumId();
555 napi_create_int32(env, albumId, &jsResult);
556 }
557
558 return jsResult;
559 }
560
JSGetAlbumName(napi_env env,napi_callback_info info)561 napi_value FileAssetNapi::JSGetAlbumName(napi_env env, napi_callback_info info)
562 {
563 napi_status status;
564 napi_value jsResult = nullptr;
565 FileAssetNapi* obj = nullptr;
566 string albumName = "";
567 napi_value thisVar = nullptr;
568
569 napi_get_undefined(env, &jsResult);
570 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
571 if (status != napi_ok || thisVar == nullptr) {
572 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
573 return jsResult;
574 }
575
576 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
577 if (status == napi_ok && obj != nullptr) {
578 albumName = obj->fileAssetPtr->GetAlbumName();
579 napi_create_string_utf8(env, albumName.c_str(), NAPI_AUTO_LENGTH, &jsResult);
580 }
581
582 return jsResult;
583 }
584
JSGetCount(napi_env env,napi_callback_info info)585 napi_value FileAssetNapi::JSGetCount(napi_env env, napi_callback_info info)
586 {
587 napi_status status;
588 napi_value jsResult = nullptr;
589 napi_value thisVar = nullptr;
590
591 napi_get_undefined(env, &jsResult);
592 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
593 if ((status != napi_ok) || (thisVar == nullptr)) {
594 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
595 return jsResult;
596 }
597
598 FileAssetNapi* obj = nullptr;
599 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
600 if ((status == napi_ok) && (obj != nullptr)) {
601 napi_create_int32(env, obj->fileAssetPtr->GetCount(), &jsResult);
602 }
603
604 return jsResult;
605 }
606
JSGetDateAdded(napi_env env,napi_callback_info info)607 napi_value FileAssetNapi::JSGetDateAdded(napi_env env, napi_callback_info info)
608 {
609 napi_status status;
610 napi_value jsResult = nullptr;
611 FileAssetNapi* obj = nullptr;
612 int64_t dateAdded;
613 napi_value thisVar = nullptr;
614
615 napi_get_undefined(env, &jsResult);
616 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
617 if (status != napi_ok || thisVar == nullptr) {
618 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
619 return jsResult;
620 }
621
622 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
623 if (status == napi_ok && obj != nullptr) {
624 dateAdded = obj->fileAssetPtr->GetDateAdded();
625 napi_create_int64(env, dateAdded, &jsResult);
626 }
627
628 return jsResult;
629 }
630
JSGetDateTrashed(napi_env env,napi_callback_info info)631 napi_value FileAssetNapi::JSGetDateTrashed(napi_env env, napi_callback_info info)
632 {
633 napi_status status;
634 napi_value jsResult = nullptr;
635 FileAssetNapi* obj = nullptr;
636 int64_t dateTrashed;
637 napi_value thisVar = nullptr;
638
639 napi_get_undefined(env, &jsResult);
640 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
641 if (status != napi_ok || thisVar == nullptr) {
642 NAPI_ERR_LOG("Invalid arguments! status: %{private}d", status);
643 return jsResult;
644 }
645
646 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
647 if (status == napi_ok && obj != nullptr) {
648 dateTrashed = obj->fileAssetPtr->GetDateTrashed();
649 napi_create_int64(env, dateTrashed, &jsResult);
650 }
651
652 return jsResult;
653 }
654
JSGetDateModified(napi_env env,napi_callback_info info)655 napi_value FileAssetNapi::JSGetDateModified(napi_env env, napi_callback_info info)
656 {
657 napi_status status;
658 napi_value jsResult = nullptr;
659 FileAssetNapi* obj = nullptr;
660 int64_t dateModified;
661 napi_value thisVar = nullptr;
662
663 napi_get_undefined(env, &jsResult);
664 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
665 if (status != napi_ok || thisVar == nullptr) {
666 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
667 return jsResult;
668 }
669
670 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
671 if (status == napi_ok && obj != nullptr) {
672 dateModified = obj->fileAssetPtr->GetDateModified();
673 napi_create_int64(env, dateModified, &jsResult);
674 }
675
676 return jsResult;
677 }
678
JSGetOrientation(napi_env env,napi_callback_info info)679 napi_value FileAssetNapi::JSGetOrientation(napi_env env, napi_callback_info info)
680 {
681 napi_status status;
682 napi_value jsResult = nullptr;
683 FileAssetNapi* obj = nullptr;
684 int32_t orientation;
685 napi_value thisVar = nullptr;
686
687 napi_get_undefined(env, &jsResult);
688 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
689 if (status != napi_ok || thisVar == nullptr) {
690 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
691 return jsResult;
692 }
693
694 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
695 if (status == napi_ok && obj != nullptr) {
696 orientation = obj->GetOrientation();
697 napi_create_int32(env, orientation, &jsResult);
698 }
699
700 return jsResult;
701 }
JSSetOrientation(napi_env env,napi_callback_info info)702 napi_value FileAssetNapi::JSSetOrientation(napi_env env, napi_callback_info info)
703 {
704 napi_status status;
705 napi_value undefinedResult = nullptr;
706 FileAssetNapi* obj = nullptr;
707 napi_valuetype valueType = napi_undefined;
708 int32_t orientation;
709 size_t argc = ARGS_ONE;
710 napi_value argv[ARGS_ONE] = {0};
711 napi_value thisVar = nullptr;
712 napi_get_undefined(env, &undefinedResult);
713
714 GET_JS_ARGS(env, info, argc, argv, thisVar);
715 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
716
717 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
718 if (status == napi_ok && obj != nullptr) {
719 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_number) {
720 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
721 return undefinedResult;
722 }
723
724 status = napi_get_value_int32(env, argv[PARAM0], &orientation);
725 if (status == napi_ok) {
726 obj->fileAssetPtr->SetOrientation(orientation);
727 }
728 }
729
730 return undefinedResult;
731 }
732
JSGetWidth(napi_env env,napi_callback_info info)733 napi_value FileAssetNapi::JSGetWidth(napi_env env, napi_callback_info info)
734 {
735 napi_status status;
736 napi_value jsResult = nullptr;
737 FileAssetNapi* obj = nullptr;
738 int32_t width;
739 napi_value thisVar = nullptr;
740
741 napi_get_undefined(env, &jsResult);
742 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
743 if (status != napi_ok || thisVar == nullptr) {
744 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
745 return jsResult;
746 }
747
748 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
749 if (status == napi_ok && obj != nullptr) {
750 width = obj->fileAssetPtr->GetWidth();
751 napi_create_int32(env, width, &jsResult);
752 }
753
754 return jsResult;
755 }
756
JSGetHeight(napi_env env,napi_callback_info info)757 napi_value FileAssetNapi::JSGetHeight(napi_env env, napi_callback_info info)
758 {
759 napi_status status;
760 napi_value jsResult = nullptr;
761 FileAssetNapi* obj = nullptr;
762 int32_t height;
763 napi_value thisVar = nullptr;
764
765 napi_get_undefined(env, &jsResult);
766 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
767 if (status != napi_ok || thisVar == nullptr) {
768 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
769 return jsResult;
770 }
771
772 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
773 if (status == napi_ok && obj != nullptr) {
774 height = obj->fileAssetPtr->GetHeight();
775 napi_create_int32(env, height, &jsResult);
776 }
777
778 return jsResult;
779 }
780
JSGetRelativePath(napi_env env,napi_callback_info info)781 napi_value FileAssetNapi::JSGetRelativePath(napi_env env, napi_callback_info info)
782 {
783 napi_status status;
784 napi_value jsResult = nullptr;
785 FileAssetNapi* obj = nullptr;
786 string relativePath = "";
787 napi_value thisVar = nullptr;
788
789 napi_get_undefined(env, &jsResult);
790 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
791 if (status != napi_ok || thisVar == nullptr) {
792 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
793 return jsResult;
794 }
795
796 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
797 if (status == napi_ok && obj != nullptr) {
798 relativePath = obj->GetRelativePath();
799 napi_create_string_utf8(env, relativePath.c_str(), NAPI_AUTO_LENGTH, &jsResult);
800 }
801
802 return jsResult;
803 }
804
JSSetRelativePath(napi_env env,napi_callback_info info)805 napi_value FileAssetNapi::JSSetRelativePath(napi_env env, napi_callback_info info)
806 {
807 napi_status status;
808 napi_value undefinedResult = nullptr;
809 FileAssetNapi* obj = nullptr;
810 napi_valuetype valueType = napi_undefined;
811 size_t res = 0;
812 char buffer[ARG_BUF_SIZE];
813 size_t argc = ARGS_ONE;
814 napi_value argv[ARGS_ONE] = {0};
815 napi_value thisVar = nullptr;
816 napi_get_undefined(env, &undefinedResult);
817 GET_JS_ARGS(env, info, argc, argv, thisVar);
818 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
819 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
820 if (status == napi_ok && obj != nullptr) {
821 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
822 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
823 return undefinedResult;
824 }
825 status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, ARG_BUF_SIZE, &res);
826 if (status == napi_ok) {
827 obj->fileAssetPtr->SetRelativePath(string(buffer));
828 }
829 }
830 return undefinedResult;
831 }
JSGetAlbum(napi_env env,napi_callback_info info)832 napi_value FileAssetNapi::JSGetAlbum(napi_env env, napi_callback_info info)
833 {
834 napi_status status;
835 napi_value jsResult = nullptr;
836 FileAssetNapi* obj = nullptr;
837 string album = "";
838 napi_value thisVar = nullptr;
839
840 napi_get_undefined(env, &jsResult);
841 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
842 if (status != napi_ok || thisVar == nullptr) {
843 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
844 return jsResult;
845 }
846
847 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
848 if (status == napi_ok && obj != nullptr) {
849 album = obj->fileAssetPtr->GetAlbum();
850 napi_create_string_utf8(env, album.c_str(), NAPI_AUTO_LENGTH, &jsResult);
851 }
852
853 return jsResult;
854 }
855
JSGetArtist(napi_env env,napi_callback_info info)856 napi_value FileAssetNapi::JSGetArtist(napi_env env, napi_callback_info info)
857 {
858 napi_status status;
859 napi_value jsResult = nullptr;
860 FileAssetNapi* obj = nullptr;
861 string artist = "";
862 napi_value thisVar = nullptr;
863
864 napi_get_undefined(env, &jsResult);
865 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
866 if (status != napi_ok || thisVar == nullptr) {
867 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
868 return jsResult;
869 }
870
871 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
872 if (status == napi_ok && obj != nullptr) {
873 artist = obj->fileAssetPtr->GetArtist();
874 napi_create_string_utf8(env, artist.c_str(), NAPI_AUTO_LENGTH, &jsResult);
875 }
876
877 return jsResult;
878 }
879
JSGetDuration(napi_env env,napi_callback_info info)880 napi_value FileAssetNapi::JSGetDuration(napi_env env, napi_callback_info info)
881 {
882 napi_status status;
883 napi_value jsResult = nullptr;
884 FileAssetNapi* obj = nullptr;
885 int32_t duration;
886 napi_value thisVar = nullptr;
887
888 napi_get_undefined(env, &jsResult);
889 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
890 if (status != napi_ok || thisVar == nullptr) {
891 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
892 return jsResult;
893 }
894
895 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
896 if (status == napi_ok && obj != nullptr) {
897 duration = obj->fileAssetPtr->GetDuration();
898 napi_create_int32(env, duration, &jsResult);
899 }
900
901 return jsResult;
902 }
903
JSParent(napi_env env,napi_callback_info info)904 napi_value FileAssetNapi::JSParent(napi_env env, napi_callback_info info)
905 {
906 napi_status status;
907 napi_value jsResult = nullptr;
908 FileAssetNapi* obj = nullptr;
909 int32_t parent;
910 napi_value thisVar = nullptr;
911 napi_get_undefined(env, &jsResult);
912 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
913 if (status != napi_ok || thisVar == nullptr) {
914 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
915 return jsResult;
916 }
917 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
918 if (status == napi_ok && obj != nullptr) {
919 parent = obj->fileAssetPtr->GetParent();
920 napi_create_int32(env, parent, &jsResult);
921 }
922 return jsResult;
923 }
JSGetAlbumUri(napi_env env,napi_callback_info info)924 napi_value FileAssetNapi::JSGetAlbumUri(napi_env env, napi_callback_info info)
925 {
926 napi_status status;
927 napi_value jsResult = nullptr;
928 FileAssetNapi* obj = nullptr;
929 string albumUri = "";
930 napi_value thisVar = nullptr;
931 napi_get_undefined(env, &jsResult);
932 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
933 if (status != napi_ok || thisVar == nullptr) {
934 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
935 return jsResult;
936 }
937 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
938 if (status == napi_ok && obj != nullptr) {
939 albumUri = obj->fileAssetPtr->GetAlbumUri();
940 napi_create_string_utf8(env, albumUri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
941 }
942 return jsResult;
943 }
JSGetDateTaken(napi_env env,napi_callback_info info)944 napi_value FileAssetNapi::JSGetDateTaken(napi_env env, napi_callback_info info)
945 {
946 napi_status status;
947 napi_value jsResult = nullptr;
948 FileAssetNapi* obj = nullptr;
949 int64_t dateTaken;
950 napi_value thisVar = nullptr;
951 napi_get_undefined(env, &jsResult);
952 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
953 if (status != napi_ok || thisVar == nullptr) {
954 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
955 return jsResult;
956 }
957 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
958 if (status == napi_ok && obj != nullptr) {
959 dateTaken = obj->fileAssetPtr->GetDateTaken();
960 napi_create_int64(env, dateTaken, &jsResult);
961 }
962 return jsResult;
963 }
964
JSCommitModifyExecute(napi_env env,void * data)965 static void JSCommitModifyExecute(napi_env env, void *data)
966 {
967 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
968 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
969 MediaLibraryTracer tracer;
970 tracer.Start("JSCommitModifyExecute");
971
972 if (!MediaFileUtils::CheckTitle(context->objectPtr->GetTitle()) ||
973 !MediaFileUtils::CheckDisplayName(context->objectPtr->GetDisplayName())) {
974 NAPI_ERR_LOG("JSCommitModify CheckDisplayName fail");
975 context->error = JS_E_DISPLAYNAME;
976 return;
977 }
978
979 string uri = MEDIALIBRARY_DATA_URI + "/" + Media::MEDIA_FILEOPRN + "/" + Media::MEDIA_FILEOPRN_MODIFYASSET;
980 MediaLibraryNapiUtils::UriAddFragmentTypeMask(uri, context->typeMask);
981 Uri updateAssetUri(uri);
982 MediaType mediaType = context->objectPtr->GetMediaType();
983 string notifyUri = MediaLibraryNapiUtils::GetMediaTypeUri(mediaType);
984 DataSharePredicates predicates;
985 DataShareValuesBucket valuesBucket;
986 int32_t changedRows;
987 valuesBucket.Put(MEDIA_DATA_DB_URI, context->objectPtr->GetUri());
988 valuesBucket.Put(MEDIA_DATA_DB_TITLE, context->objectPtr->GetTitle());
989 valuesBucket.Put(MEDIA_DATA_DB_NAME, context->objectPtr->GetDisplayName());
990 if (context->objectPtr->GetOrientation() >= 0) {
991 valuesBucket.Put(MEDIA_DATA_DB_ORIENTATION, context->objectPtr->GetOrientation());
992 }
993 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, context->objectPtr->GetRelativePath());
994 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, context->objectPtr->GetMediaType());
995 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
996 predicates.SetWhereArgs({std::to_string(context->objectPtr->GetId())});
997
998 changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
999 if (changedRows < 0) {
1000 context->SaveError(changedRows);
1001 NAPI_ERR_LOG("File asset modification failed, err: %{public}d", changedRows);
1002 } else {
1003 context->changedRows = changedRows;
1004 Uri modifyNotify(notifyUri);
1005 UserFileClient::NotifyChange(modifyNotify);
1006 }
1007 }
1008
JSCommitModifyCompleteCallback(napi_env env,napi_status status,void * data)1009 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, void *data)
1010 {
1011 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1012 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1013 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1014 jsContext->status = false;
1015
1016 MediaLibraryTracer tracer;
1017 tracer.Start("JSCommitModifyCompleteCallback");
1018
1019 if (context->error == ERR_DEFAULT) {
1020 if (context->changedRows < 0) {
1021 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
1022 "File asset modification failed");
1023 napi_get_undefined(env, &jsContext->data);
1024 } else {
1025 napi_create_int32(env, context->changedRows, &jsContext->data);
1026 jsContext->status = true;
1027 napi_get_undefined(env, &jsContext->error);
1028 }
1029 } else {
1030 NAPI_ERR_LOG("JSCommitModify fail %{public}d", context->error);
1031 context->HandleError(env, jsContext->error);
1032 napi_get_undefined(env, &jsContext->data);
1033 }
1034 tracer.Finish();
1035 if (context->work != nullptr) {
1036 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1037 context->work, *jsContext);
1038 }
1039 delete context;
1040 }
GetJSArgsForCommitModify(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1041 napi_value GetJSArgsForCommitModify(napi_env env, size_t argc, const napi_value argv[],
1042 FileAssetAsyncContext &asyncContext)
1043 {
1044 const int32_t refCount = 1;
1045 napi_value result = nullptr;
1046 auto context = &asyncContext;
1047 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1048 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1049 for (size_t i = PARAM0; i < argc; i++) {
1050 napi_valuetype valueType = napi_undefined;
1051 napi_typeof(env, argv[i], &valueType);
1052 if (i == PARAM0 && valueType == napi_function) {
1053 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1054 break;
1055 } else {
1056 NAPI_ASSERT(env, false, "type mismatch");
1057 }
1058 }
1059 napi_get_boolean(env, true, &result);
1060 return result;
1061 }
1062
JSCommitModify(napi_env env,napi_callback_info info)1063 napi_value FileAssetNapi::JSCommitModify(napi_env env, napi_callback_info info)
1064 {
1065 napi_status status;
1066 napi_value result = nullptr;
1067 size_t argc = ARGS_ONE;
1068 napi_value argv[ARGS_ONE] = {0};
1069 napi_value thisVar = nullptr;
1070 MediaLibraryTracer tracer;
1071 tracer.Start("JSCommitModify");
1072
1073 GET_JS_ARGS(env, info, argc, argv, thisVar);
1074 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameters maximum");
1075 napi_get_undefined(env, &result);
1076
1077 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1078 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1079 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
1080 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1081 result = GetJSArgsForCommitModify(env, argc, argv, *asyncContext);
1082 ASSERT_NULLPTR_CHECK(env, result);
1083 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1084 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1085
1086 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
1087 JSCommitModifyCompleteCallback);
1088 }
1089
1090 return result;
1091 }
1092
JSOpenExecute(napi_env env,void * data)1093 static void JSOpenExecute(napi_env env, void *data)
1094 {
1095 MediaLibraryTracer tracer;
1096 tracer.Start("JSOpenExecute");
1097
1098 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1099 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1100
1101 string fileUri = context->objectPtr->GetUri();
1102
1103 bool isValid = false;
1104 string mode = context->valuesBucket.Get(MEDIA_FILEMODE, isValid);
1105 if (!isValid) {
1106 context->error = ERR_INVALID_OUTPUT;
1107 NAPI_ERR_LOG("getting mode invalid");
1108 return;
1109 }
1110
1111 Uri openFileUri(fileUri);
1112 int32_t retVal = UserFileClient::OpenFile(openFileUri, mode);
1113 if (retVal <= 0) {
1114 context->SaveError(retVal);
1115 NAPI_ERR_LOG("File open asset failed, ret: %{public}d", retVal);
1116 } else {
1117 context->fd = retVal;
1118 }
1119 }
1120
JSOpenCompleteCallback(napi_env env,napi_status status,void * data)1121 static void JSOpenCompleteCallback(napi_env env, napi_status status, void *data)
1122 {
1123 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1124 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1125
1126 MediaLibraryTracer tracer;
1127 tracer.Start("JSOpenCompleteCallback");
1128
1129 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1130 jsContext->status = false;
1131
1132 if (context->error == ERR_DEFAULT) {
1133 NAPI_DEBUG_LOG("return fd = %{public}d", context->fd);
1134 napi_create_int32(env, context->fd, &jsContext->data);
1135 napi_get_undefined(env, &jsContext->error);
1136 jsContext->status = true;
1137 } else {
1138 context->HandleError(env, jsContext->error);
1139 napi_get_undefined(env, &jsContext->data);
1140 }
1141
1142 tracer.Finish();
1143 if (context->work != nullptr) {
1144 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1145 context->work, *jsContext);
1146 }
1147
1148 delete context;
1149 }
1150
GetJSArgsForOpen(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1151 napi_value GetJSArgsForOpen(napi_env env, size_t argc, const napi_value argv[],
1152 FileAssetAsyncContext &asyncContext)
1153 {
1154 const int32_t refCount = 1;
1155 napi_value result = nullptr;
1156 auto context = &asyncContext;
1157 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1158 size_t res = 0;
1159 char buffer[ARG_BUF_SIZE];
1160
1161 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1162
1163 for (size_t i = PARAM0; i < argc; i++) {
1164 napi_valuetype valueType = napi_undefined;
1165 napi_typeof(env, argv[i], &valueType);
1166
1167 if (i == PARAM0 && valueType == napi_string) {
1168 napi_get_value_string_utf8(env, argv[i], buffer, ARG_BUF_SIZE, &res);
1169 } else if (i == PARAM1 && valueType == napi_function) {
1170 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1171 break;
1172 } else {
1173 NAPI_ASSERT(env, false, "type mismatch");
1174 }
1175 }
1176 context->valuesBucket.Put(MEDIA_FILEMODE, string(buffer));
1177 // Return true napi_value if params are successfully obtained
1178 napi_get_boolean(env, true, &result);
1179 return result;
1180 }
1181
JSOpen(napi_env env,napi_callback_info info)1182 napi_value FileAssetNapi::JSOpen(napi_env env, napi_callback_info info)
1183 {
1184 napi_status status;
1185 napi_value result = nullptr;
1186 size_t argc = ARGS_TWO;
1187 napi_value argv[ARGS_TWO] = {0};
1188 napi_value thisVar = nullptr;
1189
1190 MediaLibraryTracer tracer;
1191 tracer.Start("JSOpen");
1192
1193 GET_JS_ARGS(env, info, argc, argv, thisVar);
1194 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
1195 napi_get_undefined(env, &result);
1196
1197 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1198 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1199 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1200 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1201
1202 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1203 result = GetJSArgsForOpen(env, argc, argv, *asyncContext);
1204 ASSERT_NULLPTR_CHECK(env, result);
1205 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSOpen", JSOpenExecute,
1206 JSOpenCompleteCallback);
1207 }
1208
1209 return result;
1210 }
1211
JSCloseExecute(FileAssetAsyncContext * context)1212 static void JSCloseExecute(FileAssetAsyncContext *context)
1213 {
1214 MediaLibraryTracer tracer;
1215 tracer.Start("JSCloseExecute");
1216
1217 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1218
1219 string closeUri = MEDIALIBRARY_DATA_URI + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CLOSEASSET;
1220 MediaLibraryNapiUtils::UriAddFragmentTypeMask(closeUri, context->typeMask);
1221 Uri closeAssetUri(closeUri);
1222
1223 bool isValid = false;
1224 int fd = context->valuesBucket.Get(MEDIA_FILEDESCRIPTOR, isValid);
1225 if (!isValid) {
1226 context->error = ERR_INVALID_OUTPUT;
1227 NAPI_ERR_LOG("getting fd is invalid");
1228 return;
1229 }
1230
1231 int32_t retVal = close(fd);
1232 if (retVal != E_SUCCESS) {
1233 context->SaveError(retVal);
1234 NAPI_ERR_LOG("call close failed %{public}d", retVal);
1235 return;
1236 }
1237
1238 string fileUri = context->valuesBucket.Get(MEDIA_DATA_DB_URI, isValid);
1239 if (!isValid) {
1240 context->error = ERR_INVALID_OUTPUT;
1241 NAPI_ERR_LOG("getting file uri is invalid");
1242 return;
1243 }
1244 if (!MediaFileUtils::GetNetworkIdFromUri(fileUri).empty()) {
1245 return;
1246 }
1247
1248 retVal = UserFileClient::Insert(closeAssetUri, context->valuesBucket);
1249 if (retVal != E_SUCCESS) {
1250 context->SaveError(retVal);
1251 NAPI_ERR_LOG("File close asset failed %{public}d", retVal);
1252 }
1253 }
1254
JSCloseCompleteCallback(napi_env env,napi_status status,FileAssetAsyncContext * context)1255 static void JSCloseCompleteCallback(napi_env env, napi_status status,
1256 FileAssetAsyncContext *context)
1257 {
1258 MediaLibraryTracer tracer;
1259 tracer.Start("JSCloseCompleteCallback");
1260
1261 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1262 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1263 jsContext->status = false;
1264
1265 if (context->error == ERR_DEFAULT) {
1266 napi_create_int32(env, E_SUCCESS, &jsContext->data);
1267 napi_get_undefined(env, &jsContext->error);
1268 jsContext->status = true;
1269 } else {
1270 context->HandleError(env, jsContext->error);
1271 napi_get_undefined(env, &jsContext->data);
1272 }
1273
1274 tracer.Finish();
1275 if (context->work != nullptr) {
1276 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1277 context->work, *jsContext);
1278 }
1279
1280 delete context;
1281 }
1282
GetJSArgsForClose(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1283 napi_value GetJSArgsForClose(napi_env env, size_t argc, const napi_value argv[],
1284 FileAssetAsyncContext &asyncContext)
1285 {
1286 const int32_t refCount = 1;
1287 napi_value result = nullptr;
1288 auto context = &asyncContext;
1289 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1290 int32_t fd = 0;
1291
1292 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1293
1294 for (size_t i = PARAM0; i < argc; i++) {
1295 napi_valuetype valueType = napi_undefined;
1296 napi_typeof(env, argv[i], &valueType);
1297
1298 if (i == PARAM0 && valueType == napi_number) {
1299 napi_get_value_int32(env, argv[i], &fd);
1300 if (fd <= 0) {
1301 NAPI_ASSERT(env, false, "fd <= 0");
1302 }
1303 } else if (i == PARAM1 && valueType == napi_function) {
1304 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1305 break;
1306 } else {
1307 NAPI_ASSERT(env, false, "type mismatch");
1308 }
1309 }
1310 context->valuesBucket.Put(MEDIA_FILEDESCRIPTOR, fd);
1311 context->valuesBucket.Put(MEDIA_DATA_DB_URI, context->objectInfo->GetFileUri());
1312 // Return true napi_value if params are successfully obtained
1313 napi_get_boolean(env, true, &result);
1314 return result;
1315 }
1316
JSClose(napi_env env,napi_callback_info info)1317 napi_value FileAssetNapi::JSClose(napi_env env, napi_callback_info info)
1318 {
1319 napi_status status;
1320 napi_value result = nullptr;
1321 size_t argc = ARGS_TWO;
1322 napi_value argv[ARGS_TWO] = {0};
1323 napi_value thisVar = nullptr;
1324 napi_value resource = nullptr;
1325
1326 MediaLibraryTracer tracer;
1327 tracer.Start("JSClose");
1328
1329 GET_JS_ARGS(env, info, argc, argv, thisVar);
1330 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
1331 napi_get_undefined(env, &result);
1332 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1333 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1334 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1335 result = GetJSArgsForClose(env, argc, argv, *asyncContext);
1336 ASSERT_NULLPTR_CHECK(env, result);
1337 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1338 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSClose", asyncContext);
1339 JSCloseExecute(asyncContext.get());
1340 status = napi_create_async_work(
1341 env, nullptr, resource, [](napi_env env, void* data) {},
1342 reinterpret_cast<CompleteCallback>(JSCloseCompleteCallback),
1343 static_cast<void*>(asyncContext.get()), &asyncContext->work);
1344 if (status != napi_ok) {
1345 napi_get_undefined(env, &result);
1346 } else {
1347 napi_queue_async_work(env, asyncContext->work);
1348 asyncContext.release();
1349 }
1350 }
1351
1352 return result;
1353 }
1354
GetImageFromResult(const shared_ptr<DataShare::DataShareResultSet> & resultSet,Size & size,unique_ptr<PixelMap> & outPixelMap)1355 static int GetImageFromResult(const shared_ptr<DataShare::DataShareResultSet> &resultSet, Size &size,
1356 unique_ptr<PixelMap> &outPixelMap)
1357 {
1358 MediaLibraryTracer tracer;
1359 tracer.Start("MediaThumbnailHelper::GetKv");
1360 int ret = resultSet->GoToFirstRow();
1361 if (ret != DataShare::E_OK) {
1362 NAPI_ERR_LOG("GoToFirstRow error %{public}d", ret);
1363 return ret;
1364 }
1365
1366 vector<uint8_t> key;
1367 ret = resultSet->GetBlob(PARAM0, key);
1368 if (ret != DataShare::E_OK) {
1369 NAPI_ERR_LOG("GetBlob key error %{public}d", ret);
1370 return ret;
1371 }
1372 vector<uint8_t> image;
1373 ret = resultSet->GetBlob(PARAM1, image);
1374 if (ret != DataShare::E_OK) {
1375 NAPI_ERR_LOG("GetBlob image error %{public}d", ret);
1376 return ret;
1377 }
1378 resultSet->Close();
1379 tracer.Finish();
1380
1381 NAPI_DEBUG_LOG("key %{public}s key len %{public}d len %{public}d", string(key.begin(),
1382 key.end()).c_str(), static_cast<int>(key.size()), static_cast<int>(image.size()));
1383
1384 tracer.Start("MediaThumbnailHelper::ResizeImage");
1385 if (!MediaThumbnailHelper::ResizeImage(image, size, outPixelMap)) {
1386 NAPI_ERR_LOG("ResizeImage error");
1387 return E_FAIL;
1388 }
1389 return ret;
1390 }
1391
QueryThumbnail(std::string & uri,Size & size,const std::string & typeMask)1392 static unique_ptr<PixelMap> QueryThumbnail(std::string &uri, Size &size, const std::string &typeMask)
1393 {
1394 MediaLibraryTracer tracer;
1395 tracer.Start("QueryThumbnail");
1396
1397 string queryUriStr = uri + "?" + MEDIA_OPERN_KEYWORD + "=" + MEDIA_DATA_DB_THUMBNAIL + "&" + MEDIA_DATA_DB_WIDTH + "=" +
1398 to_string(size.width) + "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(size.height);
1399 MediaLibraryNapiUtils::UriAddFragmentTypeMask(queryUriStr, typeMask);
1400 Uri queryUri(queryUriStr);
1401 tracer.Start("DataShare::Query");
1402 DataShare::DataSharePredicates predicates;
1403 vector<string> columns;
1404 auto resultSet = UserFileClient::Query(queryUri, predicates, columns);
1405 if (resultSet == nullptr) {
1406 NAPI_ERR_LOG("Query thumbnail error");
1407 return nullptr;
1408 }
1409 int rowCount = 0;
1410 int err = resultSet->GetRowCount(rowCount);
1411 if ((err != DataShare::E_OK) || (rowCount <= 0)) {
1412 NAPI_ERR_LOG("GetRowCount err %{public}d", err);
1413 return nullptr;
1414 }
1415 tracer.Finish();
1416
1417 unique_ptr<PixelMap> pixelMap;
1418 auto ret = GetImageFromResult(resultSet, size, pixelMap);
1419 if (ret != DataShare::E_OK) {
1420 NAPI_ERR_LOG("getImageFromResult error %{public}d", ret);
1421 }
1422
1423 return pixelMap;
1424 }
1425
JSGetThumbnailExecute(FileAssetAsyncContext * context)1426 static void JSGetThumbnailExecute(FileAssetAsyncContext* context)
1427 {
1428 MediaLibraryTracer tracer;
1429 tracer.Start("JSGetThumbnailExecute");
1430
1431 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1432
1433 std::string uri = context->objectPtr->GetUri();
1434 MediaLibraryNapiUtils::UriRemoveAllFragment(uri);
1435 Size size = { .width = context->thumbWidth, .height = context->thumbHeight };
1436 context->pixelmap = QueryThumbnail(uri, size, context->typeMask);
1437 }
1438
JSGetThumbnailCompleteCallback(napi_env env,napi_status status,FileAssetAsyncContext * context)1439 static void JSGetThumbnailCompleteCallback(napi_env env, napi_status status,
1440 FileAssetAsyncContext* context)
1441 {
1442 MediaLibraryTracer tracer;
1443 tracer.Start("JSGetThumbnailCompleteCallback");
1444
1445 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1446
1447 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1448 jsContext->status = false;
1449
1450 if (context->error == ERR_DEFAULT) {
1451 if (context->pixelmap != nullptr) {
1452 jsContext->data = Media::PixelMapNapi::CreatePixelMap(env, context->pixelmap);
1453 napi_get_undefined(env, &jsContext->error);
1454 jsContext->status = true;
1455 } else {
1456 NAPI_ERR_LOG("negative ret");
1457 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1458 "Get thumbnail failed");
1459 napi_get_undefined(env, &jsContext->data);
1460 }
1461 } else {
1462 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1463 "Ability helper or thumbnail helper is null");
1464 napi_get_undefined(env, &jsContext->data);
1465 }
1466
1467 tracer.Finish();
1468 if (context->work != nullptr) {
1469 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1470 context->work, *jsContext);
1471 }
1472
1473 delete context;
1474 }
1475
GetSizeInfo(napi_env env,napi_value configObj,std::string type,int32_t & result)1476 static void GetSizeInfo(napi_env env, napi_value configObj, std::string type, int32_t &result)
1477 {
1478 napi_value item = nullptr;
1479 bool exist = false;
1480 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
1481 if (status != napi_ok || !exist) {
1482 NAPI_ERR_LOG("can not find named property, status: %{public}d", status);
1483 return;
1484 }
1485
1486 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
1487 NAPI_ERR_LOG("get named property fail");
1488 return;
1489 }
1490
1491 if (napi_get_value_int32(env, item, &result) != napi_ok) {
1492 NAPI_ERR_LOG("get property value fail");
1493 }
1494 }
1495
GetJSArgsForGetThumbnail(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1496 napi_value GetJSArgsForGetThumbnail(napi_env env, size_t argc, const napi_value argv[],
1497 FileAssetAsyncContext &asyncContext)
1498 {
1499 const int32_t refCount = 1;
1500 napi_value result = nullptr;
1501 auto context = &asyncContext;
1502 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1503 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1504
1505 context->thumbWidth = DEFAULT_THUMBNAIL_SIZE;
1506 context->thumbHeight = DEFAULT_THUMBNAIL_SIZE;
1507
1508 for (size_t i = PARAM0; i < argc; i++) {
1509 napi_valuetype valueType = napi_undefined;
1510 napi_typeof(env, argv[i], &valueType);
1511
1512 if (i == PARAM0 && valueType == napi_object) {
1513 GetSizeInfo(env, argv[PARAM0], "width", context->thumbWidth);
1514 GetSizeInfo(env, argv[PARAM0], "height", context->thumbHeight);
1515 } else if (i == PARAM0 && valueType == napi_function) {
1516 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1517 break;
1518 } else if (i == PARAM1 && valueType == napi_function) {
1519 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1520 break;
1521 } else {
1522 NAPI_ASSERT(env, false, "type mismatch");
1523 }
1524 }
1525
1526 // Return true napi_value if params are successfully obtained
1527 napi_get_boolean(env, true, &result);
1528 return result;
1529 }
1530
JSGetThumbnail(napi_env env,napi_callback_info info)1531 napi_value FileAssetNapi::JSGetThumbnail(napi_env env, napi_callback_info info)
1532 {
1533 napi_status status;
1534 napi_value result = nullptr;
1535 size_t argc = ARGS_TWO;
1536 napi_value argv[ARGS_TWO] = {0};
1537 napi_value thisVar = nullptr;
1538 napi_value resource = nullptr;
1539
1540 MediaLibraryTracer tracer;
1541 tracer.Start("JSGetThumbnail");
1542
1543 GET_JS_ARGS(env, info, argc, argv, thisVar);
1544 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE || argc == ARGS_TWO),
1545 "requires 2 parameters maximum");
1546 napi_get_undefined(env, &result);
1547 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1548 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1549 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1550 result = GetJSArgsForGetThumbnail(env, argc, argv, *asyncContext);
1551 ASSERT_NULLPTR_CHECK(env, result);
1552 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1553 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetThumbnail", asyncContext);
1554 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1555 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1556
1557 status = napi_create_async_work(
1558 env, nullptr, resource, [](napi_env env, void* data) {
1559 auto context = static_cast<FileAssetAsyncContext*>(data);
1560 JSGetThumbnailExecute(context);
1561 },
1562 reinterpret_cast<CompleteCallback>(JSGetThumbnailCompleteCallback),
1563 static_cast<void*>(asyncContext.get()), &asyncContext->work);
1564 if (status != napi_ok) {
1565 napi_get_undefined(env, &result);
1566 } else {
1567 napi_queue_async_work(env, asyncContext->work);
1568 asyncContext.release();
1569 }
1570 }
1571
1572 return result;
1573 }
1574
OHOS_MEDIA_NativeGetThumbnail(const char * uri,void * context)1575 extern "C" __attribute__((visibility("default"))) void* OHOS_MEDIA_NativeGetThumbnail(const char* uri, void* context)
1576 {
1577 if (uri == nullptr || context == nullptr) {
1578 NAPI_INFO_LOG("uri or context is null while trying call NativeGetThumbnail");
1579 return nullptr;
1580 }
1581 std::string uriStr(uri);
1582 auto runtimeContext = *reinterpret_cast<std::shared_ptr<OHOS::AbilityRuntime::Context>*>(context);
1583 auto ret = FileAssetNapi::NativeGetThumbnail(uriStr, runtimeContext);
1584 if (ret == nullptr) {
1585 NAPI_INFO_LOG("return value from NativeGetThumbnail is nullptr, uri: %{public}s", uri);
1586 return nullptr;
1587 }
1588 return ret.release();
1589 }
1590
NativeGetThumbnail(const string & uri,const std::shared_ptr<AbilityRuntime::Context> & context)1591 std::unique_ptr<PixelMap> FileAssetNapi::NativeGetThumbnail(const string &uri,
1592 const std::shared_ptr<AbilityRuntime::Context> &context)
1593 {
1594 // uri is dataability:///media/image/<id>/thumbnail/<width>/<height>
1595 auto index = uri.find("//");
1596 if (index == string::npos) {
1597 return nullptr;
1598 }
1599 auto tmpIdx = index + 2; // "//" len
1600 if (uri.substr(0, tmpIdx) != MEDIALIBRARY_DATA_ABILITY_PREFIX) {
1601 return nullptr;
1602 }
1603 index = uri.find("thumbnail");
1604 if (index == string::npos) {
1605 return nullptr;
1606 }
1607 auto fileUri = uri.substr(0, index - 1);
1608 tmpIdx = fileUri.rfind("/");
1609 index += strlen("thumbnail");
1610 index = uri.find("/", index);
1611 if (index == string::npos) {
1612 return nullptr;
1613 }
1614 index += 1;
1615 tmpIdx = uri.find("/", index);
1616 if (index == string::npos) {
1617 return nullptr;
1618 }
1619 int32_t width = 0;
1620 StrToInt(uri.substr(index, tmpIdx - index), width);
1621 int32_t height = 0;
1622 StrToInt(uri.substr(tmpIdx + 1), height);
1623
1624 Size size = { .width = width, .height = height };
1625 return QueryThumbnail(fileUri, size, "");
1626 }
1627
JSFavoriteCallbackComplete(napi_env env,napi_status status,void * data)1628 static void JSFavoriteCallbackComplete(napi_env env, napi_status status, void *data)
1629 {
1630 MediaLibraryTracer tracer;
1631 tracer.Start("JSFavoriteCallbackComplete");
1632
1633 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1634 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1635 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1636 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1637 jsContext->status = false;
1638 napi_get_undefined(env, &jsContext->data);
1639 if (context->error == ERR_DEFAULT) {
1640 jsContext->status = true;
1641 Media::MediaType mediaType = context->objectPtr->GetMediaType();
1642 string notifyUri = MediaLibraryNapiUtils::GetMediaTypeUri(mediaType);
1643 Uri modifyNotify(notifyUri);
1644 UserFileClient::NotifyChange(modifyNotify);
1645 } else {
1646 context->HandleError(env, jsContext->error);
1647 napi_get_undefined(env, &jsContext->data);
1648 }
1649
1650 tracer.Finish();
1651 if (context->work != nullptr) {
1652 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1653 context->work, *jsContext);
1654 }
1655
1656 delete context;
1657 }
1658
GetIsDirectoryiteNative(napi_env env,const FileAssetAsyncContext & fileContext)1659 static bool GetIsDirectoryiteNative(napi_env env, const FileAssetAsyncContext &fileContext)
1660 {
1661 MediaLibraryTracer tracer;
1662 tracer.Start("GetIsDirectoryiteNative");
1663
1664 FileAssetAsyncContext *context = const_cast<FileAssetAsyncContext *>(&fileContext);
1665 if (context == nullptr) {
1666 NAPI_ERR_LOG("Async context is null");
1667 return false;
1668 }
1669
1670 bool IsDirectory = false;
1671 string abilityUri = Media::MEDIALIBRARY_DATA_URI;
1672 Uri isDirectoryAssetUri(abilityUri + "/" + Media::MEDIA_FILEOPRN + "/" + Media::MEDIA_FILEOPRN_ISDIRECTORY);
1673 context->valuesBucket.Put(Media::MEDIA_DATA_DB_ID, context->objectPtr->GetId());
1674 int retVal = UserFileClient::Insert(isDirectoryAssetUri, context->valuesBucket);
1675 NAPI_DEBUG_LOG("GetIsDirectoryiteNative retVal = %{public}d", retVal);
1676 if (retVal == SUCCESS) {
1677 IsDirectory = true;
1678 }
1679
1680 return IsDirectory;
1681 }
JSIsDirectoryCallbackComplete(napi_env env,napi_status status,FileAssetAsyncContext * context)1682 static void JSIsDirectoryCallbackComplete(napi_env env, napi_status status,
1683 FileAssetAsyncContext* context)
1684 {
1685 MediaLibraryTracer tracer;
1686 tracer.Start("JSIsDirectoryCallbackComplete");
1687
1688 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1689 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1690 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1691 jsContext->status = false;
1692
1693 if (context->status) {
1694 napi_get_boolean(env, context->isDirectory, &jsContext->data);
1695 napi_get_undefined(env, &jsContext->error);
1696 jsContext->status = true;
1697 } else {
1698 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1699 "UserFileClient is invalid");
1700 napi_get_undefined(env, &jsContext->data);
1701 }
1702
1703 tracer.Finish();
1704 if (context->work != nullptr) {
1705 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1706 context->work, *jsContext);
1707 }
1708
1709 delete context;
1710 }
1711
GetJSArgsForIsDirectory(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1712 static napi_value GetJSArgsForIsDirectory(napi_env env, size_t argc, const napi_value argv[],
1713 FileAssetAsyncContext &asyncContext)
1714 {
1715 string str = "";
1716 vector<string> strArr;
1717 string order = "";
1718 const int32_t refCount = 1;
1719 napi_value result;
1720 auto context = &asyncContext;
1721 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1722 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1723 for (size_t i = PARAM0; i < argc; i++) {
1724 napi_valuetype valueType = napi_undefined;
1725 napi_typeof(env, argv[i], &valueType);
1726 if (i == PARAM0 && valueType == napi_object) {
1727 } else if (i == PARAM0 && valueType == napi_function) {
1728 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1729 break;
1730 } else if (i == PARAM1 && valueType == napi_function) {
1731 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1732 break;
1733 } else {
1734 NAPI_ASSERT(env, false, "type mismatch");
1735 }
1736 }
1737 napi_get_boolean(env, true, &result);
1738 return result;
1739 }
1740
JSIsDirectory(napi_env env,napi_callback_info info)1741 napi_value FileAssetNapi::JSIsDirectory(napi_env env, napi_callback_info info)
1742 {
1743 size_t argc = ARGS_ONE;
1744 napi_value argv[ARGS_ONE] = {0};
1745 napi_value thisVar = nullptr;
1746 napi_value resource = nullptr;
1747
1748 MediaLibraryTracer tracer;
1749 tracer.Start("JSisDirectory");
1750
1751 GET_JS_ARGS(env, info, argc, argv, thisVar);
1752 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 2 parameters maximum");
1753 napi_value result = nullptr;
1754 napi_get_undefined(env, &result);
1755 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1756 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1757 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1758 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1759 result = GetJSArgsForIsDirectory(env, argc, argv, *asyncContext);
1760 ASSERT_NULLPTR_CHECK(env, result);
1761 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1762 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSIsDirectory", asyncContext);
1763 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1764 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1765 status = napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
1766 FileAssetAsyncContext* context = static_cast<FileAssetAsyncContext*>(data);
1767 context->isDirectory = GetIsDirectoryiteNative(env, *context);
1768 context->status = true;
1769 },
1770 reinterpret_cast<CompleteCallback>(JSIsDirectoryCallbackComplete),
1771 static_cast<void*>(asyncContext.get()), &asyncContext->work);
1772 if (status != napi_ok) {
1773 napi_get_undefined(env, &result);
1774 } else {
1775 napi_queue_async_work(env, asyncContext->work);
1776 asyncContext.release();
1777 }
1778 }
1779 return result;
1780 }
1781
JSIsFavoriteExecute(FileAssetAsyncContext * context)1782 static void JSIsFavoriteExecute(FileAssetAsyncContext* context)
1783 {
1784 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1785 context->isFavorite = context->objectPtr->IsFavorite();
1786 return;
1787 }
1788
JSIsFavoriteCallbackComplete(napi_env env,napi_status status,FileAssetAsyncContext * context)1789 static void JSIsFavoriteCallbackComplete(napi_env env, napi_status status,
1790 FileAssetAsyncContext* context)
1791 {
1792 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1793 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1794 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1795 jsContext->status = false;
1796 if (context->error == ERR_DEFAULT) {
1797 napi_get_boolean(env, context->isFavorite, &jsContext->data);
1798 napi_get_undefined(env, &jsContext->error);
1799 jsContext->status = true;
1800 } else {
1801 NAPI_ERR_LOG("Get IsFavorite failed, ret: %{public}d", context->error);
1802 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->error,
1803 "UserFileClient is invalid");
1804 napi_get_undefined(env, &jsContext->data);
1805 }
1806 if (context->work != nullptr) {
1807 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1808 context->work, *jsContext);
1809 }
1810 delete context;
1811 }
1812
GetJSArgsForFavorite(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1813 napi_value GetJSArgsForFavorite(napi_env env, size_t argc, const napi_value argv[],
1814 FileAssetAsyncContext &asyncContext)
1815 {
1816 const int32_t refCount = 1;
1817 napi_value result = nullptr;
1818 auto context = &asyncContext;
1819 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1820 bool isFavorite = false;
1821 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1822 for (size_t i = PARAM0; i < argc; i++) {
1823 napi_valuetype valueType = napi_undefined;
1824 napi_typeof(env, argv[i], &valueType);
1825 if (i == PARAM0 && valueType == napi_boolean) {
1826 napi_get_value_bool(env, argv[i], &isFavorite);
1827 } else if (i == PARAM1 && valueType == napi_function) {
1828 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1829 break;
1830 } else {
1831 NAPI_ASSERT(env, false, "type mismatch");
1832 }
1833 }
1834 context->isFavorite = isFavorite;
1835 napi_get_boolean(env, true, &result);
1836 return result;
1837 }
1838
JSFavouriteExecute(napi_env env,void * data)1839 static void JSFavouriteExecute(napi_env env, void *data)
1840 {
1841 MediaLibraryTracer tracer;
1842 tracer.Start("JSFavouriteExecute");
1843
1844 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1845 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1846
1847 DataShareValuesBucket valuesBucket;
1848 valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, FAVOURITE_ALBUM_ID_VALUES);
1849 valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, context->objectPtr->GetId());
1850 string uriString = MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/";
1851 uriString += context->isFavorite ? MEDIA_SMARTALBUMMAPOPRN_ADDSMARTALBUM : MEDIA_SMARTALBUMMAPOPRN_REMOVESMARTALBUM;
1852 MediaLibraryNapiUtils::UriAddFragmentTypeMask(uriString, context->typeMask);
1853 Uri uri(uriString);
1854 context->changedRows = UserFileClient::Insert(uri, valuesBucket);
1855 if (context->changedRows >= 0) {
1856 context->objectPtr->SetFavorite(context->isFavorite);
1857 }
1858 context->SaveError(context->changedRows);
1859 }
1860
JSFavorite(napi_env env,napi_callback_info info)1861 napi_value FileAssetNapi::JSFavorite(napi_env env, napi_callback_info info)
1862 {
1863 size_t argc = ARGS_TWO;
1864 napi_value argv[ARGS_TWO] = {0};
1865 napi_value thisVar = nullptr;
1866
1867 MediaLibraryTracer tracer;
1868 tracer.Start("JSFavorite");
1869
1870 GET_JS_ARGS(env, info, argc, argv, thisVar);
1871 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
1872 napi_value result = nullptr;
1873 napi_get_undefined(env, &result);
1874
1875 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1876 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1877 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
1878 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1879 if (status == napi_ok && asyncContext->objectInfo == nullptr) {
1880 NAPI_DEBUG_LOG("get this Var fail");
1881 return result;
1882 }
1883
1884 result = GetJSArgsForFavorite(env, argc, argv, *asyncContext);
1885 if (asyncContext->isFavorite == asyncContext->objectInfo->IsFavorite()) {
1886 NAPI_DEBUG_LOG("favorite state is the same");
1887 return result;
1888 }
1889 ASSERT_NULLPTR_CHECK(env, result);
1890 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1891 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1892
1893 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSFavorite", JSFavouriteExecute,
1894 JSFavoriteCallbackComplete);
1895 }
1896
GetJSArgsForIsFavorite(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1897 static napi_value GetJSArgsForIsFavorite(napi_env env, size_t argc, const napi_value argv[],
1898 FileAssetAsyncContext &asyncContext)
1899 {
1900 string str = "";
1901 vector<string> strArr;
1902 string order = "";
1903 const int32_t refCount = 1;
1904 napi_value result;
1905 auto context = &asyncContext;
1906 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1907 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1908 for (size_t i = PARAM0; i < argc; i++) {
1909 napi_valuetype valueType = napi_undefined;
1910 napi_typeof(env, argv[i], &valueType);
1911 if (i == PARAM0 && valueType == napi_object) {
1912 } else if (i == PARAM0 && valueType == napi_function) {
1913 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1914 break;
1915 } else if (i == PARAM1 && valueType == napi_function) {
1916 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1917 break;
1918 } else {
1919 NAPI_ASSERT(env, false, "type mismatch");
1920 }
1921 }
1922 napi_get_boolean(env, true, &result);
1923 return result;
1924 }
1925
JSIsFavorite(napi_env env,napi_callback_info info)1926 napi_value FileAssetNapi::JSIsFavorite(napi_env env, napi_callback_info info)
1927 {
1928 napi_status status;
1929 napi_value result = nullptr;
1930 size_t argc = ARGS_ONE;
1931 napi_value argv[ARGS_ONE] = {0};
1932 napi_value thisVar = nullptr;
1933 napi_value resource = nullptr;
1934 GET_JS_ARGS(env, info, argc, argv, thisVar);
1935 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameters maximum");
1936 napi_get_undefined(env, &result);
1937 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1938 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1939 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1940 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1941 result = GetJSArgsForIsFavorite(env, argc, argv, *asyncContext);
1942 ASSERT_NULLPTR_CHECK(env, result);
1943 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1944 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSIsFavorite", asyncContext);
1945 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1946 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1947
1948 status = napi_create_async_work(
1949 env, nullptr, resource, [](napi_env env, void* data) {
1950 auto context = static_cast<FileAssetAsyncContext*>(data);
1951 JSIsFavoriteExecute(context);
1952 },
1953 reinterpret_cast<CompleteCallback>(JSIsFavoriteCallbackComplete),
1954 static_cast<void*>(asyncContext.get()), &asyncContext->work);
1955 if (status != napi_ok) {
1956 napi_get_undefined(env, &result);
1957 } else {
1958 napi_queue_async_work(env, asyncContext->work);
1959 asyncContext.release();
1960 }
1961 }
1962 return result;
1963 }
1964
JSTrashExecute(napi_env env,void * data)1965 static void JSTrashExecute(napi_env env, void *data)
1966 {
1967 MediaLibraryTracer tracer;
1968 tracer.Start("JSTrashExecute");
1969
1970 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1971 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1972
1973 DataShareValuesBucket valuesBucket;
1974 valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, TRASH_ALBUM_ID_VALUES);
1975 valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, context->objectPtr->GetId());
1976 string uriString = MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/";
1977 uriString += context->isTrash ? MEDIA_SMARTALBUMMAPOPRN_ADDSMARTALBUM : MEDIA_SMARTALBUMMAPOPRN_REMOVESMARTALBUM;
1978 MediaLibraryNapiUtils::UriAddFragmentTypeMask(uriString, context->typeMask);
1979 Uri uri(uriString);
1980 context->changedRows = UserFileClient::Insert(uri, valuesBucket);
1981 if (context->changedRows >= 0) {
1982 int32_t trashFlag = (context->isTrash ? IS_TRASH : NOT_TRASH);
1983 context->objectPtr->SetIsTrash(trashFlag);
1984 }
1985 context->SaveError(context->changedRows);
1986 }
1987
JSTrashCallbackComplete(napi_env env,napi_status status,void * data)1988 static void JSTrashCallbackComplete(napi_env env, napi_status status, void *data)
1989 {
1990 MediaLibraryTracer tracer;
1991 tracer.Start("JSGetThumbnail");
1992
1993 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1994 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1995 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1996 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1997 jsContext->status = false;
1998 napi_get_undefined(env, &jsContext->data);
1999 if (context->error == ERR_DEFAULT) {
2000 jsContext->status = true;
2001 Media::MediaType mediaType = context->objectPtr->GetMediaType();
2002 string notifyUri = MediaLibraryNapiUtils::GetMediaTypeUri(mediaType);
2003 Uri modifyNotify(notifyUri);
2004 UserFileClient::NotifyChange(modifyNotify);
2005 NAPI_DEBUG_LOG("JSTrashCallbackComplete success");
2006 } else {
2007 context->HandleError(env, jsContext->error);
2008 }
2009
2010 tracer.Finish();
2011 if (context->work != nullptr) {
2012 NAPI_ERR_LOG("JSTrashCallbackComplete context->work != nullptr");
2013 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2014 context->work, *jsContext);
2015 }
2016
2017 delete context;
2018 }
2019
GetJSArgsForTrash(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)2020 napi_value GetJSArgsForTrash(napi_env env, size_t argc, const napi_value argv[],
2021 FileAssetAsyncContext &asyncContext)
2022 {
2023 const int32_t refCount = 1;
2024 napi_value result = nullptr;
2025 auto context = &asyncContext;
2026 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
2027 bool isTrash = false;
2028 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
2029 for (size_t i = PARAM0; i < argc; i++) {
2030 napi_valuetype valueType = napi_undefined;
2031 napi_typeof(env, argv[i], &valueType);
2032 if (i == PARAM0 && valueType == napi_boolean) {
2033 napi_get_value_bool(env, argv[i], &isTrash);
2034 } else if (i == PARAM1 && valueType == napi_function) {
2035 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
2036 break;
2037 } else {
2038 NAPI_ASSERT(env, false, "type mismatch");
2039 }
2040 }
2041 context->isTrash = isTrash;
2042 napi_get_boolean(env, true, &result);
2043 return result;
2044 }
2045
JSTrash(napi_env env,napi_callback_info info)2046 napi_value FileAssetNapi::JSTrash(napi_env env, napi_callback_info info)
2047 {
2048 napi_status status;
2049 napi_value result = nullptr;
2050 size_t argc = ARGS_TWO;
2051 napi_value argv[ARGS_TWO] = {0};
2052 napi_value thisVar = nullptr;
2053
2054 MediaLibraryTracer tracer;
2055 tracer.Start("JSTrash");
2056
2057 GET_JS_ARGS(env, info, argc, argv, thisVar);
2058 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
2059
2060 napi_get_undefined(env, &result);
2061 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2062 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
2063 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
2064 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2065 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2066 result = GetJSArgsForTrash(env, argc, argv, *asyncContext);
2067 ASSERT_NULLPTR_CHECK(env, result);
2068 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2069 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
2070 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSTrash", JSTrashExecute,
2071 JSTrashCallbackComplete);
2072 }
2073 return result;
2074 }
2075
JSIsTrashExecute(FileAssetAsyncContext * context)2076 static void JSIsTrashExecute(FileAssetAsyncContext* context)
2077 {
2078 MediaLibraryTracer tracer;
2079 tracer.Start("JSIsTrashExecute");
2080
2081 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2082 context->isTrash = (context->objectPtr->GetIsTrash() != NOT_TRASH);
2083 return;
2084 }
2085
JSIsTrashCallbackComplete(napi_env env,napi_status status,FileAssetAsyncContext * context)2086 static void JSIsTrashCallbackComplete(napi_env env, napi_status status,
2087 FileAssetAsyncContext* context)
2088 {
2089 MediaLibraryTracer tracer;
2090 tracer.Start("JSIsTrashCallbackComplete");
2091
2092 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2093 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2094 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
2095 jsContext->status = false;
2096 if (context->error == ERR_DEFAULT) {
2097 napi_get_boolean(env, context->isTrash, &jsContext->data);
2098 napi_get_undefined(env, &jsContext->error);
2099 jsContext->status = true;
2100 } else {
2101 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->error,
2102 "UserFileClient is invalid");
2103 napi_get_undefined(env, &jsContext->data);
2104 }
2105
2106 tracer.Finish();
2107 if (context->work != nullptr) {
2108 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2109 context->work, *jsContext);
2110 }
2111
2112 delete context;
2113 }
2114
GetJSArgsForIsTrash(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)2115 static napi_value GetJSArgsForIsTrash(napi_env env, size_t argc, const napi_value argv[],
2116 FileAssetAsyncContext &asyncContext)
2117 {
2118 string str = "";
2119 vector<string> strArr;
2120 string order = "";
2121 const int32_t refCount = 1;
2122 napi_value result;
2123 auto context = &asyncContext;
2124 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
2125 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
2126 for (size_t i = PARAM0; i < argc; i++) {
2127 napi_valuetype valueType = napi_undefined;
2128 napi_typeof(env, argv[i], &valueType);
2129 if (i == PARAM0 && valueType == napi_function) {
2130 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
2131 break;
2132 } else {
2133 NAPI_ASSERT(env, false, "type mismatch");
2134 }
2135 }
2136 napi_get_boolean(env, true, &result);
2137 return result;
2138 }
2139
JSIsTrash(napi_env env,napi_callback_info info)2140 napi_value FileAssetNapi::JSIsTrash(napi_env env, napi_callback_info info)
2141 {
2142 napi_status status;
2143 napi_value result = nullptr;
2144 size_t argc = ARGS_ONE;
2145 napi_value argv[ARGS_ONE] = {0};
2146 napi_value thisVar = nullptr;
2147 napi_value resource = nullptr;
2148
2149 MediaLibraryTracer tracer;
2150 tracer.Start("JSIsTrash");
2151
2152 GET_JS_ARGS(env, info, argc, argv, thisVar);
2153 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameters maximum");
2154 napi_get_undefined(env, &result);
2155 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2156 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
2157 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2158 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2159 result = GetJSArgsForIsTrash(env, argc, argv, *asyncContext);
2160 ASSERT_NULLPTR_CHECK(env, result);
2161 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
2162 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSIsTrash", asyncContext);
2163 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2164 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
2165
2166 status = napi_create_async_work(
2167 env, nullptr, resource, [](napi_env env, void* data) {
2168 auto context = static_cast<FileAssetAsyncContext*>(data);
2169 JSIsTrashExecute(context);
2170 },
2171 reinterpret_cast<CompleteCallback>(JSIsTrashCallbackComplete),
2172 static_cast<void*>(asyncContext.get()), &asyncContext->work);
2173 if (status != napi_ok) {
2174 napi_get_undefined(env, &result);
2175 } else {
2176 napi_queue_async_work(env, asyncContext->work);
2177 asyncContext.release();
2178 }
2179 }
2180
2181 return result;
2182 }
2183
UpdateFileAssetInfo()2184 void FileAssetNapi::UpdateFileAssetInfo()
2185 {
2186 fileAssetPtr = std::shared_ptr<FileAsset>(sFileAsset_);
2187 }
2188
UserFileMgrGet(napi_env env,napi_callback_info info)2189 napi_value FileAssetNapi::UserFileMgrGet(napi_env env, napi_callback_info info)
2190 {
2191 MediaLibraryTracer tracer;
2192 tracer.Start("UserFileMgrGet");
2193
2194 napi_value ret = nullptr;
2195 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2196 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2197
2198 string inputKey;
2199 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey), asyncContext,
2200 JS_ERR_PARAMETER_INVALID);
2201 napi_status status;
2202 napi_value thisVar = nullptr;
2203 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
2204 napi_value jsResult = nullptr;
2205 if ((status != napi_ok) || (thisVar == nullptr)) {
2206 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
2207 return jsResult;
2208 }
2209 FileAssetNapi *obj = nullptr;
2210 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2211 napi_get_undefined(env, &jsResult);
2212 if ((status != napi_ok) || (obj == nullptr)) {
2213 NAPI_THROW(env, asyncContext, JS_E_FILE_KEY);
2214 return jsResult;
2215 }
2216 if (obj->fileAssetPtr->GetMemberMap().count(inputKey) == 0) {
2217 // no exist throw error
2218 NAPI_THROW(env, asyncContext, JS_E_FILE_KEY);
2219 return jsResult;
2220 }
2221 auto m = obj->fileAssetPtr->GetMemberMap().at(inputKey);
2222 if (m.index() == MEMBER_TYPE_STRING) {
2223 napi_create_string_utf8(env, get<string>(m).c_str(), NAPI_AUTO_LENGTH, &jsResult);
2224 } else if (m.index() == MEMBER_TYPE_INT32) {
2225 napi_create_int32(env, get<int32_t>(m), &jsResult);
2226 } else if (m.index() == MEMBER_TYPE_INT64) {
2227 napi_create_int64(env, get<int64_t>(m), &jsResult);
2228 } else {
2229 NAPI_THROW(env, asyncContext, JS_ERR_PARAMETER_INVALID);
2230 return jsResult;
2231 }
2232 return jsResult;
2233 }
2234
HandleParamSet(const string & inputKey,const string & value)2235 bool FileAssetNapi::HandleParamSet(const string &inputKey, const string &value)
2236 {
2237 if ((inputKey == MEDIA_DATA_DB_NAME) && (fileAssetPtr->GetMemberMap().count(MEDIA_DATA_DB_NAME))) {
2238 fileAssetPtr->SetDisplayName(value);
2239 fileAssetPtr->GetMemberMap()[MEDIA_DATA_DB_NAME] = value;
2240 } else if ((inputKey == MEDIA_DATA_DB_RELATIVE_PATH) &&
2241 (fileAssetPtr->GetMemberMap().count(MEDIA_DATA_DB_RELATIVE_PATH))) {
2242 fileAssetPtr->SetRelativePath(value);
2243 fileAssetPtr->GetMemberMap()[MEDIA_DATA_DB_RELATIVE_PATH] = value;
2244 } else if ((inputKey == MEDIA_DATA_DB_TITLE) && (fileAssetPtr->GetMemberMap().count(MEDIA_DATA_DB_TITLE))) {
2245 fileAssetPtr->SetTitle(value);
2246 fileAssetPtr->GetMemberMap()[MEDIA_DATA_DB_TITLE] = value;
2247 } else {
2248 NAPI_ERR_LOG("invalid key %{public}s, no support key", inputKey.c_str());
2249 return false;
2250 }
2251 return true;
2252 }
2253
UserFileMgrSet(napi_env env,napi_callback_info info)2254 napi_value FileAssetNapi::UserFileMgrSet(napi_env env, napi_callback_info info)
2255 {
2256 MediaLibraryTracer tracer;
2257 tracer.Start("UserFileMgrGet");
2258
2259 napi_value ret = nullptr;
2260 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2261 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2262 string inputKey;
2263 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey), asyncContext,
2264 JS_ERR_PARAMETER_INVALID);
2265 string value;
2266 CHECK_ARGS(env, MediaLibraryNapiUtils::GetParamStringPathMax(env, asyncContext->argv[ARGS_ONE], value),
2267 asyncContext, JS_ERR_PARAMETER_INVALID);
2268 napi_status status;
2269 napi_value thisVar = nullptr;
2270 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
2271 napi_value jsResult = nullptr;
2272 napi_get_undefined(env, &jsResult);
2273 if ((status != napi_ok) || (thisVar == nullptr)) {
2274 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
2275 return jsResult;
2276 }
2277 FileAssetNapi *obj = nullptr;
2278 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2279 if (status != napi_ok || obj == nullptr) {
2280 NAPI_THROW(env, asyncContext, JS_E_FILE_KEY);
2281 return jsResult;
2282 }
2283 if (!obj->HandleParamSet(inputKey, value)) {
2284 NAPI_THROW(env, asyncContext, JS_E_FILE_KEY);
2285 return jsResult;
2286 }
2287 return jsResult;
2288 }
2289
UserFileMgrOpen(napi_env env,napi_callback_info info)2290 napi_value FileAssetNapi::UserFileMgrOpen(napi_env env, napi_callback_info info)
2291 {
2292 MediaLibraryTracer tracer;
2293 tracer.Start("UserFileMgrOpen");
2294
2295 napi_value ret = nullptr;
2296 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2297 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2298
2299 string mode;
2300 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, mode) == napi_ok,
2301 "Failed to parse js args");
2302 asyncContext->valuesBucket.Put(MEDIA_FILEMODE, mode);
2303 MediaLibraryNapiUtils::GenTypeMaskFromArray({ asyncContext->objectInfo->GetMediaType() }, asyncContext->typeMask);
2304 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2305 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
2306
2307 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrOpen",
2308 JSOpenExecute, JSOpenCompleteCallback);
2309 }
2310
UserFileMgrClose(napi_env env,napi_callback_info info)2311 napi_value FileAssetNapi::UserFileMgrClose(napi_env env, napi_callback_info info)
2312 {
2313 MediaLibraryTracer tracer;
2314 tracer.Start("UserFileMgrClose");
2315
2316 napi_value ret = nullptr;
2317 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2318 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2319
2320 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsNumberCallback(env, info, asyncContext, asyncContext->fd) ==
2321 napi_ok, "Failed to parse js args");
2322
2323 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrClose",
2324 [](napi_env env, void* data) {
2325 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2326 if (close(context->fd) < 0) {
2327 NAPI_ERR_LOG("Failed to close, errno: %{public}d", errno);
2328 context->error = errno;
2329 }
2330 }, reinterpret_cast<CompleteCallback>(JSCloseCompleteCallback));
2331 }
2332
UserFileMgrCommitModify(napi_env env,napi_callback_info info)2333 napi_value FileAssetNapi::UserFileMgrCommitModify(napi_env env, napi_callback_info info)
2334 {
2335 MediaLibraryTracer tracer;
2336 tracer.Start("UserFileMgrCommitModify");
2337
2338 napi_value ret = nullptr;
2339 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2340 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2341 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2342 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
2343 "Failed to parse js args");
2344 MediaLibraryNapiUtils::GenTypeMaskFromArray({ asyncContext->objectInfo->GetMediaType() }, asyncContext->typeMask);
2345 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2346 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
2347
2348 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrCommitModify",
2349 JSCommitModifyExecute, JSCommitModifyCompleteCallback);
2350 }
2351
UserFileMgrFavorite(napi_env env,napi_callback_info info)2352 napi_value FileAssetNapi::UserFileMgrFavorite(napi_env env, napi_callback_info info)
2353 {
2354 MediaLibraryTracer tracer;
2355 tracer.Start("UserFileMgrFavorite");
2356
2357 napi_value ret = nullptr;
2358 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2359 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2360 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2361 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isFavorite) ==
2362 napi_ok, "Failed to parse js args");
2363 MediaLibraryNapiUtils::GenTypeMaskFromArray({ asyncContext->objectInfo->GetMediaType() }, asyncContext->typeMask);
2364 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2365 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
2366
2367 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrFavorite", JSFavouriteExecute,
2368 JSFavoriteCallbackComplete);
2369 }
2370
UserFileMgrTrash(napi_env env,napi_callback_info info)2371 napi_value FileAssetNapi::UserFileMgrTrash(napi_env env, napi_callback_info info)
2372 {
2373 MediaLibraryTracer tracer;
2374 tracer.Start("UserFileMgrTrash");
2375
2376 napi_value ret = nullptr;
2377 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2378 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2379 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2380 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isTrash) ==
2381 napi_ok, "Failed to parse js args");
2382 MediaLibraryNapiUtils::GenTypeMaskFromArray({ asyncContext->objectInfo->GetMediaType() }, asyncContext->typeMask);
2383 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2384 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
2385
2386 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrTrash", JSTrashExecute,
2387 JSTrashCallbackComplete);
2388 }
2389
UserFileMgrIsDirectory(napi_env env,napi_callback_info info)2390 napi_value FileAssetNapi::UserFileMgrIsDirectory(napi_env env, napi_callback_info info)
2391 {
2392 MediaLibraryTracer tracer;
2393 tracer.Start("UserFileMgrIsDirectory");
2394
2395 napi_value ret = nullptr;
2396 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2397 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2398 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
2399 "Failed to parse js args");
2400 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2401 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
2402
2403 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrIsDirectory",
2404 [](napi_env env, void* data) {
2405 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2406 context->isDirectory = MediaFileUtils::IsDirectory(context->objectPtr->GetPath());
2407 context->status = true;
2408 },
2409 reinterpret_cast<CompleteCallback>(JSIsDirectoryCallbackComplete));
2410 }
2411
UserFileMgrGetThumbnail(napi_env env,napi_callback_info info)2412 napi_value FileAssetNapi::UserFileMgrGetThumbnail(napi_env env, napi_callback_info info)
2413 {
2414 MediaLibraryTracer tracer;
2415 tracer.Start("UserFileMgrGetThumbnail");
2416
2417 napi_value result = nullptr;
2418 NAPI_CALL(env, napi_get_undefined(env, &result));
2419 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2420 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
2421
2422 CHECK_COND_RET(MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, asyncContext, ARGS_ZERO, ARGS_TWO) ==
2423 napi_ok, result, "Failed to get object info");
2424 result = GetJSArgsForGetThumbnail(env, asyncContext->argc, asyncContext->argv, *asyncContext);
2425 ASSERT_NULLPTR_CHECK(env, result);
2426 const std::vector<uint32_t> types = { asyncContext->objectInfo->GetMediaType() };
2427 MediaLibraryNapiUtils::GenTypeMaskFromArray(types, asyncContext->typeMask);
2428 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2429 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
2430
2431 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrGetThumbnail",
2432 [](napi_env env, void* data) {
2433 auto context = static_cast<FileAssetAsyncContext*>(data);
2434 JSGetThumbnailExecute(context);
2435 },
2436 reinterpret_cast<CompleteCallback>(JSGetThumbnailCompleteCallback));
2437
2438 return result;
2439 }
2440 } // namespace Media
2441 } // namespace OHOS
2442