• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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