• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2023 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 #include "userfile_manager_types.h"
16 #define MLOG_TAG "SendableFileAssetNapi"
17 
18 #include "sendable_file_asset_napi.h"
19 
20 #include <algorithm>
21 #include <cstring>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 
26 #include "abs_shared_result_set.h"
27 #include "access_token.h"
28 #include "accesstoken_kit.h"
29 #include "datashare_errno.h"
30 #include "datashare_predicates.h"
31 #include "datashare_result_set.h"
32 #include "datashare_values_bucket.h"
33 #include "hitrace_meter.h"
34 #include "fetch_result.h"
35 #include "file_uri.h"
36 #include "hilog/log.h"
37 #include "ipc_skeleton.h"
38 #include "iservice_registry.h"
39 #include "js_native_api.h"
40 #include "js_native_api_types.h"
41 #include "location_column.h"
42 #include "locale_config.h"
43 #include "media_asset_edit_data_napi.h"
44 #include "media_exif.h"
45 #include "media_column.h"
46 #include "media_file_utils.h"
47 #include "media_file_uri.h"
48 #include "media_smart_map_column.h"
49 #include "medialibrary_client_errno.h"
50 #include "medialibrary_db_const.h"
51 #include "medialibrary_errno.h"
52 #include "medialibrary_napi_log.h"
53 #include "medialibrary_napi_utils.h"
54 #include "medialibrary_tracer.h"
55 #include "nlohmann/json.hpp"
56 #include "post_proc.h"
57 #include "rdb_errno.h"
58 #include "sandbox_helper.h"
59 #include "string_ex.h"
60 #include "thumbnail_const.h"
61 #include "thumbnail_utils.h"
62 #include "unique_fd.h"
63 #include "userfile_client.h"
64 #include "userfilemgr_uri.h"
65 #include "vision_aesthetics_score_column.h"
66 #include "vision_album_column.h"
67 #include "vision_column_comm.h"
68 #include "vision_column.h"
69 #include "vision_composition_column.h"
70 #include "vision_face_tag_column.h"
71 #include "vision_head_column.h"
72 #include "vision_image_face_column.h"
73 #include "vision_label_column.h"
74 #include "vision_object_column.h"
75 #include "vision_ocr_column.h"
76 #include "vision_photo_map_column.h"
77 #include "vision_pose_column.h"
78 #include "vision_recommendation_column.h"
79 #include "vision_saliency_detect_column.h"
80 #include "vision_segmentation_column.h"
81 #include "vision_total_column.h"
82 #include "vision_video_label_column.h"
83 #include "sendable_medialibrary_napi_utils.h"
84 #include "file_asset_napi.h"
85 
86 using OHOS::HiviewDFX::HiLog;
87 using OHOS::HiviewDFX::HiLogLabel;
88 using namespace std;
89 using namespace OHOS::AppExecFwk;
90 using namespace OHOS::NativeRdb;
91 using namespace OHOS::DataShare;
92 using namespace OHOS::Security::AccessToken;
93 using std::string;
94 
95 namespace OHOS {
96 namespace Media {
97 static const std::string MEDIA_FILEDESCRIPTOR = "fd";
98 static const std::string MEDIA_FILEMODE = "mode";
99 static const std::string ANALYSIS_NO_RESULTS = "[]";
100 static const std::string ANALYSIS_INIT_VALUE = "0";
101 static const std::string ANALYSIS_STATUS_ANALYZED = "Analyzed, no results";
102 
103 thread_local FileAsset *SendableFileAssetNapi::sFileAsset_ = nullptr;
104 shared_ptr<ThumbnailManager> SendableFileAssetNapi::thumbnailManager_ = nullptr;
105 
106 constexpr int32_t IS_TRASH = 1;
107 constexpr int32_t NOT_TRASH = 0;
108 constexpr int64_t SECONDS_LEVEL_LIMIT = 1e10;
109 
110 using CompleteCallback = napi_async_complete_callback;
111 
112 thread_local napi_ref SendableFileAssetNapi::photoAccessHelperConstructor_ = nullptr;
113 
SendableFileAssetNapi()114 SendableFileAssetNapi::SendableFileAssetNapi()
115     : env_(nullptr) {}
116 
117 SendableFileAssetNapi::~SendableFileAssetNapi() = default;
118 
FileAssetNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)119 void SendableFileAssetNapi::FileAssetNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
120 {
121     SendableFileAssetNapi *fileAssetObj = reinterpret_cast<SendableFileAssetNapi*>(nativeObject);
122     if (fileAssetObj != nullptr) {
123         delete fileAssetObj;
124         fileAssetObj = nullptr;
125     }
126 }
127 
PhotoAccessHelperInit(napi_env env,napi_value exports)128 napi_value SendableFileAssetNapi::PhotoAccessHelperInit(napi_env env, napi_value exports)
129 {
130     napi_value ctorObj;
131     napi_property_descriptor sendable_file_props[] = {
132         DECLARE_NAPI_FUNCTION("get", PhotoAccessHelperGet),
133         DECLARE_NAPI_FUNCTION("set", PhotoAccessHelperSet),
134         DECLARE_NAPI_FUNCTION("commitModify", PhotoAccessHelperCommitModify),
135         DECLARE_NAPI_GETTER("uri", JSGetFileUri),
136         DECLARE_NAPI_GETTER("photoType", JSGetMediaType),
137         DECLARE_NAPI_GETTER_SETTER("displayName", JSGetFileDisplayName, JSSetFileDisplayName),
138         DECLARE_NAPI_FUNCTION("getThumbnail", PhotoAccessHelperGetThumbnail),
139         DECLARE_NAPI_FUNCTION("requestSource", PhotoAccessHelperRequestSource),
140         DECLARE_NAPI_FUNCTION("getAnalysisData", PhotoAccessHelperGetAnalysisData),
141         DECLARE_NAPI_FUNCTION("convertFromPhotoAsset", ConvertFromPhotoAsset),
142         DECLARE_NAPI_FUNCTION("convertToPhotoAsset", ConvertToPhotoAsset),
143     };
144     napi_define_sendable_class(env, SENDABLE_PHOTOACCESSHELPER_FILEASSET_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
145                                FileAssetNapiConstructor, nullptr,
146                                sizeof(sendable_file_props) / sizeof(sendable_file_props[0]),
147                                sendable_file_props, nullptr, &ctorObj);
148     NAPI_CALL(env, napi_create_reference(env, ctorObj, NAPI_INIT_REF_COUNT, &photoAccessHelperConstructor_));
149     NAPI_CALL(env, napi_set_named_property(env, exports,
150               SENDABLE_PHOTOACCESSHELPER_FILEASSET_NAPI_CLASS_NAME.c_str(), ctorObj));
151     return exports;
152 }
153 
154 // Constructor callback
FileAssetNapiConstructor(napi_env env,napi_callback_info info)155 napi_value SendableFileAssetNapi::FileAssetNapiConstructor(napi_env env, napi_callback_info info)
156 {
157     napi_status status;
158     napi_value result = nullptr;
159     napi_value thisVar = nullptr;
160 
161     napi_get_undefined(env, &result);
162     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
163     if (napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr) != napi_ok) {
164         NAPI_ERR_LOG("FileAssetNapiConstructor Failed to get cb info");
165         return nullptr;
166     }
167 
168     if (status == napi_ok && thisVar != nullptr) {
169         std::unique_ptr<SendableFileAssetNapi> obj = std::make_unique<SendableFileAssetNapi>();
170         if (obj != nullptr) {
171             obj->env_ = env;
172             if (sFileAsset_ != nullptr) {
173                 obj->UpdateFileAssetInfo();
174             }
175             status = napi_wrap_sendable(env, thisVar, reinterpret_cast<void *>(obj.get()),
176                                         SendableFileAssetNapi::FileAssetNapiDestructor, nullptr);
177             if (status == napi_ok) {
178                 obj.release();
179                 return thisVar;
180             } else {
181                 NAPI_ERR_LOG("Failure wrapping js to native napi, status: %{public}d", status);
182             }
183         }
184     }
185 
186     return result;
187 }
188 
CreateFileAsset(napi_env env,unique_ptr<FileAsset> & iAsset)189 napi_value SendableFileAssetNapi::CreateFileAsset(napi_env env, unique_ptr<FileAsset> &iAsset)
190 {
191     if (iAsset == nullptr) {
192         return nullptr;
193     }
194 
195     if (photoAccessHelperConstructor_ == nullptr) {
196         napi_value exports = nullptr;
197         napi_create_object(env, &exports);
198         SendableFileAssetNapi::PhotoAccessHelperInit(env, exports);
199     }
200 
201     napi_value constructor = nullptr;
202     napi_ref constructorRef;
203     if (iAsset->GetResultNapiType() == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
204         constructorRef = photoAccessHelperConstructor_;
205     } else {
206         NAPI_ERR_LOG("Invalid result napi type: %{public}d", static_cast<int>(iAsset->GetResultNapiType()));
207         return nullptr;
208     }
209 
210     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
211 
212     sFileAsset_ = iAsset.release();
213 
214     napi_value result = nullptr;
215     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
216 
217     sFileAsset_ = nullptr;
218     return result;
219 }
220 
CreatePhotoAsset(napi_env env,shared_ptr<FileAsset> & fileAsset)221 napi_value SendableFileAssetNapi::CreatePhotoAsset(napi_env env, shared_ptr<FileAsset> &fileAsset)
222 {
223     if (fileAsset == nullptr || fileAsset->GetResultNapiType() != ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
224         NAPI_ERR_LOG("Unsupported fileAsset");
225         return nullptr;
226     }
227 
228     if (photoAccessHelperConstructor_ == nullptr) {
229         napi_value exports = nullptr;
230         napi_create_object(env, &exports);
231         SendableFileAssetNapi::PhotoAccessHelperInit(env, exports);
232     }
233 
234     napi_value constructor = nullptr;
235     napi_value result = nullptr;
236     NAPI_CALL(env, napi_get_reference_value(env, photoAccessHelperConstructor_, &constructor));
237     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
238     CHECK_COND(env, result != nullptr, JS_INNER_FAIL);
239 
240     SendableFileAssetNapi* SendableFileAssetNapi = nullptr;
241     CHECK_ARGS(env, napi_unwrap_sendable(env, result, reinterpret_cast<void**>(&SendableFileAssetNapi)), JS_INNER_FAIL);
242     CHECK_COND(env, SendableFileAssetNapi != nullptr, JS_INNER_FAIL);
243     SendableFileAssetNapi->fileAssetPtr = fileAsset;
244     return result;
245 }
246 
GetFileDisplayName() const247 std::string SendableFileAssetNapi::GetFileDisplayName() const
248 {
249     return fileAssetPtr->GetDisplayName();
250 }
251 
GetRelativePath() const252 std::string SendableFileAssetNapi::GetRelativePath() const
253 {
254     return fileAssetPtr->GetRelativePath();
255 }
256 
GetFilePath() const257 std::string SendableFileAssetNapi::GetFilePath() const
258 {
259     return fileAssetPtr->GetPath();
260 }
261 
GetTitle() const262 std::string SendableFileAssetNapi::GetTitle() const
263 {
264     return fileAssetPtr->GetTitle();
265 }
266 
GetFileUri() const267 std::string SendableFileAssetNapi::GetFileUri() const
268 {
269     return fileAssetPtr->GetUri();
270 }
271 
GetFileId() const272 int32_t SendableFileAssetNapi::GetFileId() const
273 {
274     return fileAssetPtr->GetId();
275 }
276 
GetMediaType() const277 Media::MediaType SendableFileAssetNapi::GetMediaType() const
278 {
279     return fileAssetPtr->GetMediaType();
280 }
281 
GetOrientation() const282 int32_t SendableFileAssetNapi::GetOrientation() const
283 {
284     return fileAssetPtr->GetOrientation();
285 }
286 
GetNetworkId() const287 std::string SendableFileAssetNapi::GetNetworkId() const
288 {
289     return MediaFileUtils::GetNetworkIdFromUri(GetFileUri());
290 }
291 
IsFavorite() const292 bool SendableFileAssetNapi::IsFavorite() const
293 {
294     return fileAssetPtr->IsFavorite();
295 }
296 
SetFavorite(bool isFavorite)297 void SendableFileAssetNapi::SetFavorite(bool isFavorite)
298 {
299     fileAssetPtr->SetFavorite(isFavorite);
300 }
301 
IsTrash() const302 bool SendableFileAssetNapi::IsTrash() const
303 {
304     return (fileAssetPtr->GetIsTrash() != NOT_TRASH);
305 }
306 
SetTrash(bool isTrash)307 void SendableFileAssetNapi::SetTrash(bool isTrash)
308 {
309     int32_t trashFlag = (isTrash ? IS_TRASH : NOT_TRASH);
310     fileAssetPtr->SetIsTrash(trashFlag);
311 }
312 
IsHidden() const313 bool SendableFileAssetNapi::IsHidden() const
314 {
315     return fileAssetPtr->IsHidden();
316 }
317 
SetHidden(bool isHidden)318 void SendableFileAssetNapi::SetHidden(bool isHidden)
319 {
320     fileAssetPtr->SetHidden(isHidden);
321 }
322 
GetAllExif() const323 std::string SendableFileAssetNapi::GetAllExif() const
324 {
325     return fileAssetPtr->GetAllExif();
326 }
327 
GetUserComment() const328 std::string SendableFileAssetNapi::GetUserComment() const
329 {
330     return fileAssetPtr->GetUserComment();
331 }
332 
GetNapiObject(napi_env env,napi_callback_info info,SendableFileAssetNapi ** obj)333 napi_status GetNapiObject(napi_env env, napi_callback_info info, SendableFileAssetNapi **obj)
334 {
335     napi_value thisVar = nullptr;
336     CHECK_STATUS_RET(napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr), "Failed to get cb info");
337     CHECK_STATUS_RET(napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(obj)), "Failed to unwrap thisVar");
338     CHECK_COND_RET(*obj != nullptr, napi_invalid_arg, "Failed to get napi object!");
339     return napi_ok;
340 }
341 
JSGetFileUri(napi_env env,napi_callback_info info)342 napi_value SendableFileAssetNapi::JSGetFileUri(napi_env env, napi_callback_info info)
343 {
344     SendableFileAssetNapi *obj = nullptr;
345     CHECK_ARGS(env, GetNapiObject(env, info, &obj), JS_INNER_FAIL);
346 
347     napi_value jsResult = nullptr;
348     CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetFileUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
349         JS_INNER_FAIL);
350     return jsResult;
351 }
352 
JSGetFilePath(napi_env env,napi_callback_info info)353 napi_value SendableFileAssetNapi::JSGetFilePath(napi_env env, napi_callback_info info)
354 {
355     napi_status status;
356     napi_value jsResult = nullptr;
357     SendableFileAssetNapi *obj = nullptr;
358     string path = "";
359     napi_value thisVar = nullptr;
360 
361     napi_get_undefined(env, &jsResult);
362     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
363     if (status != napi_ok || thisVar == nullptr) {
364         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
365         return jsResult;
366     }
367 
368     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
369     if (status == napi_ok && obj != nullptr) {
370         path = obj->GetFilePath();
371         napi_create_string_utf8(env, path.c_str(), NAPI_AUTO_LENGTH, &jsResult);
372     }
373 
374     return jsResult;
375 }
376 
JSGetFileDisplayName(napi_env env,napi_callback_info info)377 napi_value SendableFileAssetNapi::JSGetFileDisplayName(napi_env env, napi_callback_info info)
378 {
379     napi_status status;
380     napi_value jsResult = nullptr;
381     SendableFileAssetNapi *obj = nullptr;
382     string displayName = "";
383     napi_value thisVar = nullptr;
384 
385     napi_get_undefined(env, &jsResult);
386     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
387     if (status != napi_ok || thisVar == nullptr) {
388         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
389         return jsResult;
390     }
391 
392     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
393     if (status == napi_ok && obj != nullptr) {
394         displayName = obj->GetFileDisplayName();
395         napi_create_string_utf8(env, displayName.c_str(), NAPI_AUTO_LENGTH, &jsResult);
396     }
397 
398     return jsResult;
399 }
400 
JSSetFileDisplayName(napi_env env,napi_callback_info info)401 napi_value SendableFileAssetNapi::JSSetFileDisplayName(napi_env env, napi_callback_info info)
402 {
403     napi_status status;
404     napi_value undefinedResult = nullptr;
405     SendableFileAssetNapi *obj = nullptr;
406     napi_valuetype valueType = napi_undefined;
407     size_t res = 0;
408     char buffer[FILENAME_MAX];
409     size_t argc = ARGS_ONE;
410     napi_value argv[ARGS_ONE] = {0};
411     napi_value thisVar = nullptr;
412 
413     napi_get_undefined(env, &undefinedResult);
414 
415     GET_JS_ARGS(env, info, argc, argv, thisVar);
416     NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
417 
418     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
419     if (status == napi_ok && obj != nullptr) {
420         if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
421             NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
422             return undefinedResult;
423         }
424         status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
425         if (status == napi_ok) {
426             string displayName = string(buffer);
427             obj->fileAssetPtr->SetDisplayName(displayName);
428 #ifdef MEDIALIBRARY_COMPATIBILITY
429             obj->fileAssetPtr->SetTitle(MediaFileUtils::GetTitleFromDisplayName(displayName));
430 #endif
431         }
432     }
433 
434     return undefinedResult;
435 }
436 
JSGetMediaType(napi_env env,napi_callback_info info)437 napi_value SendableFileAssetNapi::JSGetMediaType(napi_env env, napi_callback_info info)
438 {
439     napi_status status;
440     napi_value jsResult = nullptr;
441     SendableFileAssetNapi *obj = nullptr;
442     int32_t mediaType;
443     napi_value thisVar = nullptr;
444 
445     napi_get_undefined(env, &jsResult);
446     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
447     if (status != napi_ok || thisVar == nullptr) {
448         NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
449         return jsResult;
450     }
451 
452     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
453     if (status == napi_ok && obj != nullptr) {
454         mediaType = static_cast<int32_t>(obj->GetMediaType());
455         napi_create_int32(env, mediaType, &jsResult);
456     }
457 
458     return jsResult;
459 }
460 
BuildCommitModifyValuesBucket(SendableFileAssetAsyncContext * context,DataShareValuesBucket & valuesBucket)461 void BuildCommitModifyValuesBucket(SendableFileAssetAsyncContext* context, DataShareValuesBucket &valuesBucket)
462 {
463     const auto fileAsset = context->objectPtr;
464     if (context->resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
465         valuesBucket.Put(MediaColumn::MEDIA_TITLE, fileAsset->GetTitle());
466     } else if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
467         valuesBucket.Put(MediaColumn::MEDIA_NAME, fileAsset->GetDisplayName());
468     } else {
469 #ifdef MEDIALIBRARY_COMPATIBILITY
470         valuesBucket.Put(MEDIA_DATA_DB_TITLE, fileAsset->GetTitle());
471         valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH,
472             MediaFileUtils::AddDocsToRelativePath(fileAsset->GetRelativePath()));
473         if (fileAsset->GetMediaType() != MediaType::MEDIA_TYPE_AUDIO) {
474             // IMAGE, VIDEO AND FILES
475             if (fileAsset->GetOrientation() >= 0) {
476                 valuesBucket.Put(MEDIA_DATA_DB_ORIENTATION, fileAsset->GetOrientation());
477             }
478             if ((fileAsset->GetMediaType() != MediaType::MEDIA_TYPE_IMAGE) &&
479                 (fileAsset->GetMediaType() != MediaType::MEDIA_TYPE_VIDEO)) {
480                 // ONLY FILES
481                 valuesBucket.Put(MEDIA_DATA_DB_URI, fileAsset->GetUri());
482                 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, fileAsset->GetMediaType());
483             }
484         }
485 #else
486         valuesBucket.Put(MEDIA_DATA_DB_URI, fileAsset->GetUri());
487         valuesBucket.Put(MEDIA_DATA_DB_TITLE, fileAsset->GetTitle());
488 
489         if (fileAsset->GetOrientation() >= 0) {
490             valuesBucket.Put(MEDIA_DATA_DB_ORIENTATION, fileAsset->GetOrientation());
491         }
492         valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, fileAsset->GetRelativePath());
493         valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, fileAsset->GetMediaType());
494 #endif
495         valuesBucket.Put(MEDIA_DATA_DB_NAME, fileAsset->GetDisplayName());
496     }
497 }
498 
499 #ifdef MEDIALIBRARY_COMPATIBILITY
BuildCommitModifyUriApi9(SendableFileAssetAsyncContext * context,string & uri)500 static void BuildCommitModifyUriApi9(SendableFileAssetAsyncContext *context, string &uri)
501 {
502     if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
503         context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
504         uri = URI_UPDATE_PHOTO;
505     } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
506         uri = URI_UPDATE_AUDIO;
507     } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_FILE) {
508         uri = URI_UPDATE_FILE;
509     }
510 }
511 #endif
512 
BuildCommitModifyUriApi10(SendableFileAssetAsyncContext * context,string & uri)513 static void BuildCommitModifyUriApi10(SendableFileAssetAsyncContext *context, string &uri)
514 {
515     if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
516         context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
517         uri = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ? UFM_UPDATE_PHOTO : PAH_UPDATE_PHOTO;
518     } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
519         uri = UFM_UPDATE_AUDIO;
520     }
521 }
522 
CheckDisplayNameInCommitModify(SendableFileAssetAsyncContext * context)523 static bool CheckDisplayNameInCommitModify(SendableFileAssetAsyncContext *context)
524 {
525     if (context->resultNapiType != ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
526         if (context->objectPtr->GetMediaType() != MediaType::MEDIA_TYPE_FILE) {
527             if (MediaFileUtils::CheckDisplayName(context->objectPtr->GetDisplayName()) != E_OK) {
528                 context->error = JS_E_DISPLAYNAME;
529                 return false;
530             }
531         } else {
532             if (MediaFileUtils::CheckFileDisplayName(context->objectPtr->GetDisplayName()) != E_OK) {
533                 context->error = JS_E_DISPLAYNAME;
534                 return false;
535             }
536         }
537     }
538     return true;
539 }
540 
JSCommitModifyExecute(napi_env env,void * data)541 static void JSCommitModifyExecute(napi_env env, void *data)
542 {
543     auto *context = static_cast<SendableFileAssetAsyncContext*>(data);
544     MediaLibraryTracer tracer;
545     tracer.Start("JSCommitModifyExecute");
546     if (!CheckDisplayNameInCommitModify(context)) {
547         return;
548     }
549     string uri;
550     if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR ||
551         context->resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
552         BuildCommitModifyUriApi10(context, uri);
553         SendableMediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
554     } else {
555 #ifdef MEDIALIBRARY_COMPATIBILITY
556         BuildCommitModifyUriApi9(context, uri);
557 #else
558         uri = URI_UPDATE_FILE;
559 #endif
560     }
561 
562     Uri updateAssetUri(uri);
563     MediaType mediaType = context->objectPtr->GetMediaType();
564     string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
565     DataSharePredicates predicates;
566     DataShareValuesBucket valuesBucket;
567     BuildCommitModifyValuesBucket(context, valuesBucket);
568     predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
569     predicates.SetWhereArgs({std::to_string(context->objectPtr->GetId())});
570 
571     int32_t changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
572     if (changedRows < 0) {
573         context->SaveError(changedRows);
574         NAPI_ERR_LOG("File asset modification failed, err: %{public}d", changedRows);
575     } else {
576         context->changedRows = changedRows;
577         Uri modifyNotify(notifyUri);
578         UserFileClient::NotifyChange(modifyNotify);
579     }
580 }
581 
JSCommitModifyCompleteCallback(napi_env env,napi_status status,void * data)582 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, void *data)
583 {
584     SendableFileAssetAsyncContext *context = static_cast<SendableFileAssetAsyncContext*>(data);
585     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
586     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
587     jsContext->status = false;
588 
589     MediaLibraryTracer tracer;
590     tracer.Start("JSCommitModifyCompleteCallback");
591 
592     if (context->error == ERR_DEFAULT) {
593         if (context->changedRows < 0) {
594             SendableMediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
595                                                                  "File asset modification failed");
596             napi_get_undefined(env, &jsContext->data);
597         } else {
598             napi_create_int32(env, context->changedRows, &jsContext->data);
599             jsContext->status = true;
600             napi_get_undefined(env, &jsContext->error);
601         }
602     } else {
603         NAPI_ERR_LOG("JSCommitModify fail %{public}d", context->error);
604         context->HandleError(env, jsContext->error);
605         napi_get_undefined(env, &jsContext->data);
606     }
607     tracer.Finish();
608     if (context->work != nullptr) {
609         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
610                                                            context->work, *jsContext);
611     }
612     delete context;
613 }
614 
JSGetThumbnailExecute(SendableFileAssetAsyncContext * context)615 static void JSGetThumbnailExecute(SendableFileAssetAsyncContext* context)
616 {
617     MediaLibraryTracer tracer;
618     tracer.Start("JSGetThumbnailExecute");
619 
620     string path = context->objectPtr->GetPath();
621 #ifndef MEDIALIBRARY_COMPATIBILITY
622     if (path.empty()
623             && !context->objectPtr->GetRelativePath().empty() && !context->objectPtr->GetDisplayName().empty()) {
624         path = ROOT_MEDIA_DIR + context->objectPtr->GetRelativePath() + context->objectPtr->GetDisplayName();
625     }
626 #endif
627     context->pixelmap = ThumbnailManager::QueryThumbnail(context->objectPtr->GetUri(), context->size, path);
628 }
629 
JSGetThumbnailCompleteCallback(napi_env env,napi_status status,SendableFileAssetAsyncContext * context)630 static void JSGetThumbnailCompleteCallback(napi_env env, napi_status status,
631                                            SendableFileAssetAsyncContext* context)
632 {
633     MediaLibraryTracer tracer;
634     tracer.Start("JSGetThumbnailCompleteCallback");
635 
636     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
637 
638     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
639     jsContext->status = false;
640 
641     if (context->error == ERR_DEFAULT) {
642         if (context->pixelmap != nullptr) {
643             jsContext->data = Media::PixelMapNapi::CreatePixelMap(env, context->pixelmap);
644             napi_get_undefined(env, &jsContext->error);
645             jsContext->status = true;
646         } else {
647             SendableMediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
648                 "Get thumbnail failed");
649             napi_get_undefined(env, &jsContext->data);
650         }
651     } else {
652         SendableMediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
653             "Ability helper or thumbnail helper is null");
654         napi_get_undefined(env, &jsContext->data);
655     }
656 
657     tracer.Finish();
658     if (context->work != nullptr) {
659         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
660                                                            context->work, *jsContext);
661     }
662 
663     delete context;
664 }
665 
GetInt32InfoFromNapiObject(napi_env env,napi_value configObj,std::string type,int32_t & result)666 static bool GetInt32InfoFromNapiObject(napi_env env, napi_value configObj, std::string type, int32_t &result)
667 {
668     napi_value item = nullptr;
669     bool exist = false;
670     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
671     if (status != napi_ok || !exist) {
672         NAPI_ERR_LOG("can not find named property, status: %{public}d", status);
673         return false;
674     }
675 
676     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
677         NAPI_ERR_LOG("get named property fail");
678         return false;
679     }
680 
681     if (napi_get_value_int32(env, item, &result) != napi_ok) {
682         NAPI_ERR_LOG("get property value fail");
683         return false;
684     }
685 
686     return true;
687 }
688 
GetNapiObjectFromNapiObject(napi_env env,napi_value configObj,std::string type,napi_value * object)689 static bool GetNapiObjectFromNapiObject(napi_env env, napi_value configObj, std::string type, napi_value *object)
690 {
691     bool exist = false;
692     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
693     if (status != napi_ok || !exist) {
694         NAPI_ERR_LOG("can not find named property, status: %{public}d", status);
695         return false;
696     }
697 
698     if (napi_get_named_property(env, configObj, type.c_str(), object) != napi_ok) {
699         NAPI_ERR_LOG("get named property fail");
700         return false;
701     }
702 
703     return true;
704 }
705 
GetJSArgsForGetThumbnail(napi_env env,size_t argc,const napi_value argv[],unique_ptr<SendableFileAssetAsyncContext> & asyncContext)706 napi_value GetJSArgsForGetThumbnail(napi_env env, size_t argc, const napi_value argv[],
707                                     unique_ptr<SendableFileAssetAsyncContext> &asyncContext)
708 {
709     asyncContext->size.width = DEFAULT_THUMB_SIZE;
710     asyncContext->size.height = DEFAULT_THUMB_SIZE;
711 
712     if (argc == ARGS_ONE) {
713         napi_valuetype valueType = napi_undefined;
714         if (napi_typeof(env, argv[PARAM0], &valueType) == napi_ok &&
715             (valueType == napi_undefined || valueType == napi_null)) {
716             argc -= 1;
717         }
718     }
719 
720     for (size_t i = PARAM0; i < argc; i++) {
721         napi_valuetype valueType = napi_undefined;
722         napi_typeof(env, argv[i], &valueType);
723 
724         if (i == PARAM0 && valueType == napi_object) {
725             GetInt32InfoFromNapiObject(env, argv[PARAM0], "width", asyncContext->size.width);
726             GetInt32InfoFromNapiObject(env, argv[PARAM0], "height", asyncContext->size.height);
727         } else if (i == PARAM0 && valueType == napi_function) {
728             napi_create_reference(env, argv[i], NAPI_INIT_REF_COUNT, &asyncContext->callbackRef);
729             break;
730         } else if (i == PARAM1 && valueType == napi_function) {
731             napi_create_reference(env, argv[i], NAPI_INIT_REF_COUNT, &asyncContext->callbackRef);
732             break;
733         } else {
734             NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Invalid parameter type");
735             return nullptr;
736         }
737     }
738 
739     napi_value result = nullptr;
740     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
741     return result;
742 }
743 
GetPhotoRequestOption(napi_env env,napi_value object,unique_ptr<SendableFileAssetAsyncContext> & asyncContext,RequestPhotoType & type)744 static napi_value GetPhotoRequestOption(napi_env env, napi_value object,
745     unique_ptr<SendableFileAssetAsyncContext> &asyncContext, RequestPhotoType &type)
746 {
747     napi_value sizeObj;
748     if (GetNapiObjectFromNapiObject(env, object, "size", &sizeObj)) {
749         GetInt32InfoFromNapiObject(env, sizeObj, "width", asyncContext->size.width);
750         GetInt32InfoFromNapiObject(env, sizeObj, "height", asyncContext->size.height);
751     }
752     int32_t requestType = 0;
753     if (GetInt32InfoFromNapiObject(env, object, REQUEST_PHOTO_TYPE, requestType)) {
754         if (requestType >= static_cast<int>(RequestPhotoType::REQUEST_TYPE_END)) {
755             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Invalid parameter type");
756             return nullptr;
757         }
758         type = static_cast<RequestPhotoType>(requestType);
759     } else {
760         type = RequestPhotoType::REQUEST_ALL_THUMBNAILS;
761     }
762 
763     napi_value result = nullptr;
764     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
765     return result;
766 }
767 
GetPhotoRequestArgs(napi_env env,size_t argc,const napi_value argv[],unique_ptr<SendableFileAssetAsyncContext> & asyncContext,RequestPhotoType & type)768 napi_value GetPhotoRequestArgs(napi_env env, size_t argc, const napi_value argv[],
769     unique_ptr<SendableFileAssetAsyncContext> &asyncContext, RequestPhotoType &type)
770 {
771     if (argc != ARGS_ONE && argc != ARGS_TWO) {
772         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Invalid parameter number " + to_string(argc));
773         return nullptr;
774     }
775     asyncContext->size.width = DEFAULT_THUMB_SIZE;
776     asyncContext->size.height = DEFAULT_THUMB_SIZE;
777 
778     for (size_t i = PARAM0; i < argc; i++) {
779         napi_valuetype valueType = napi_undefined;
780         napi_typeof(env, argv[i], &valueType);
781 
782         if (argc == PARAM1) {
783             if (valueType == napi_function) {
784                 napi_create_reference(env, argv[i], NAPI_INIT_REF_COUNT, &asyncContext->callbackRef);
785                 break;
786             } else {
787                 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Invalid parameter type");
788                 return nullptr;
789             }
790         }
791         if (i == PARAM0 && valueType == napi_object) {
792             napi_value result = GetPhotoRequestOption(env, argv[i], asyncContext, type);
793             ASSERT_NULLPTR_CHECK(env, result);
794         } else if (i == PARAM1 && valueType == napi_function) {
795             napi_create_reference(env, argv[i], NAPI_INIT_REF_COUNT, &asyncContext->callbackRef);
796             break;
797         } else {
798             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Invalid parameter type");
799             return nullptr;
800         }
801     }
802 
803     napi_value result = nullptr;
804     CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
805     return result;
806 }
807 
808 static const map<int32_t, struct SendableAnalysisSourceInfo> ANALYSIS_SOURCE_INFO_MAP = {
809     { ANALYSIS_AESTHETICS_SCORE, { AESTHETICS_SCORE, PAH_QUERY_ANA_ATTS, { AESTHETICS_SCORE, PROB } } },
810     { ANALYSIS_LABEL, { LABEL, PAH_QUERY_ANA_LABEL, { CATEGORY_ID, SUB_LABEL, PROB, FEATURE, SIM_RESULT,
811         SALIENCY_SUB_PROB } } },
812     { ANALYSIS_VIDEO_LABEL, { VIDEO_LABEL, PAH_QUERY_ANA_VIDEO_LABEL, { CATEGORY_ID, CONFIDENCE_PROBABILITY,
813         SUB_CATEGORY, SUB_CONFIDENCE_PROB, SUB_LABEL, SUB_LABEL_PROB, SUB_LABEL_TYPE, TRACKS, VIDEO_PART_FEATURE,
814         FILTER_TAG} } },
815     { ANALYSIS_OCR, { OCR, PAH_QUERY_ANA_OCR, { OCR_TEXT, OCR_TEXT_MSG, OCR_WIDTH, OCR_HEIGHT } } },
816     { ANALYSIS_FACE, { FACE, PAH_QUERY_ANA_FACE, { FACE_ID, TAG_ID, SCALE_X, SCALE_Y, SCALE_WIDTH, SCALE_HEIGHT,
817         LANDMARKS, PITCH, YAW, ROLL, PROB, TOTAL_FACES, FEATURES, FACE_OCCLUSION } } },
818     { ANALYSIS_OBJECT, { OBJECT, PAH_QUERY_ANA_OBJECT, { OBJECT_ID, OBJECT_LABEL, OBJECT_SCALE_X, OBJECT_SCALE_Y,
819         OBJECT_SCALE_WIDTH, OBJECT_SCALE_HEIGHT, PROB, SCALE_X, SCALE_Y, SCALE_WIDTH, SCALE_HEIGHT } } },
820     { ANALYSIS_RECOMMENDATION, { RECOMMENDATION, PAH_QUERY_ANA_RECOMMENDATION, { RECOMMENDATION_ID,
821         RECOMMENDATION_RESOLUTION, RECOMMENDATION_SCALE_X, RECOMMENDATION_SCALE_Y, RECOMMENDATION_SCALE_WIDTH,
822         RECOMMENDATION_SCALE_HEIGHT, SCALE_X, SCALE_Y, SCALE_WIDTH, SCALE_HEIGHT } } },
823     { ANALYSIS_SEGMENTATION, { SEGMENTATION, PAH_QUERY_ANA_SEGMENTATION, { SEGMENTATION_AREA, SEGMENTATION_NAME,
824         PROB } } },
825     { ANALYSIS_COMPOSITION, { COMPOSITION, PAH_QUERY_ANA_COMPOSITION, { COMPOSITION_ID, COMPOSITION_RESOLUTION,
826         CLOCK_STYLE, CLOCK_LOCATION_X, CLOCK_LOCATION_Y, CLOCK_COLOUR, COMPOSITION_SCALE_X, COMPOSITION_SCALE_Y,
827         COMPOSITION_SCALE_WIDTH, COMPOSITION_SCALE_HEIGHT, SCALE_X, SCALE_Y, SCALE_WIDTH, SCALE_HEIGHT } } },
828     { ANALYSIS_SALIENCY, { SALIENCY, PAH_QUERY_ANA_SAL, { SALIENCY_X, SALIENCY_Y } } },
829     { ANALYSIS_DETAIL_ADDRESS, { DETAIL_ADDRESS, PAH_QUERY_ANA_ADDRESS, { PhotoColumn::PHOTOS_TABLE + "." + LATITUDE,
830         PhotoColumn::PHOTOS_TABLE + "." + LONGITUDE, LANGUAGE, COUNTRY, ADMIN_AREA, SUB_ADMIN_AREA, LOCALITY,
831         SUB_LOCALITY, THOROUGHFARE, SUB_THOROUGHFARE, FEATURE_NAME, CITY_NAME, ADDRESS_DESCRIPTION, LOCATION_TYPE,
832         AOI, POI, FIRST_AOI, FIRST_POI, LOCATION_VERSION, FIRST_AOI_CATEGORY, FIRST_POI_CATEGORY} } },
833     { ANALYSIS_HUMAN_FACE_TAG, { FACE_TAG, PAH_QUERY_ANA_FACE_TAG, { VISION_FACE_TAG_TABLE + "." + TAG_ID, TAG_NAME,
834         USER_OPERATION, GROUP_TAG, RENAME_OPERATION, CENTER_FEATURES, USER_DISPLAY_LEVEL, TAG_ORDER, IS_ME, COVER_URI,
835         COUNT, PORTRAIT_DATE_MODIFY, ALBUM_TYPE, IS_REMOVED } } },
836     { ANALYSIS_HEAD_POSITION, { HEAD, PAH_QUERY_ANA_HEAD, { HEAD_ID, HEAD_LABEL, HEAD_SCALE_X, HEAD_SCALE_Y,
837         HEAD_SCALE_WIDTH, HEAD_SCALE_HEIGHT, PROB, SCALE_X, SCALE_Y, SCALE_WIDTH, SCALE_HEIGHT } } },
838     { ANALYSIS_BONE_POSE, { POSE, PAH_QUERY_ANA_POSE, { POSE_ID, POSE_LANDMARKS, POSE_SCALE_X, POSE_SCALE_Y,
839         POSE_SCALE_WIDTH, POSE_SCALE_HEIGHT, PROB, POSE_TYPE, SCALE_X, SCALE_Y, SCALE_WIDTH, SCALE_HEIGHT } } },
840 };
841 
JSGetAnalysisDataExecute(SendableFileAssetAsyncContext * context)842 static void JSGetAnalysisDataExecute(SendableFileAssetAsyncContext *context)
843 {
844     MediaLibraryTracer tracer;
845     tracer.Start("JSGetThumbnailExecute");
846     if (ANALYSIS_SOURCE_INFO_MAP.find(context->analysisType) == ANALYSIS_SOURCE_INFO_MAP.end()) {
847         NAPI_ERR_LOG("Invalid analysisType");
848         return;
849     }
850     auto &analysisInfo = ANALYSIS_SOURCE_INFO_MAP.at(context->analysisType);
851     DataShare::DataSharePredicates predicates;
852     if (context->analysisType == ANALYSIS_HUMAN_FACE_TAG) {
853         string onClause = VISION_IMAGE_FACE_TABLE + "." + TAG_ID + " = " + VISION_FACE_TAG_TABLE + "." + TAG_ID;
854         predicates.InnerJoin(VISION_IMAGE_FACE_TABLE)->On({ onClause });
855     }
856     string fileId = to_string(context->objectInfo->GetFileId());
857     if (context->analysisType == ANALYSIS_DETAIL_ADDRESS) {
858         string language = Global::I18n::LocaleConfig::GetSystemLanguage();
859         vector<string> onClause = { PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_ID + " = " +
860             GEO_KNOWLEDGE_TABLE + "." + FILE_ID + " AND " +
861             GEO_KNOWLEDGE_TABLE + "." + LANGUAGE + " = \'" + language + "\'" };
862         predicates.LeftOuterJoin(GEO_KNOWLEDGE_TABLE)->On(onClause);
863         predicates.EqualTo(PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID, fileId);
864     } else {
865         predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
866     }
867     Uri uri(analysisInfo.uriStr);
868     std::vector<std::string> fetchColumn = analysisInfo.fetchColumn;
869     int errCode = 0;
870     auto resultSet = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
871     context->analysisData = MediaLibraryNapiUtils::ParseResultSet2JsonStr(resultSet, fetchColumn);
872     if (context->analysisData == ANALYSIS_NO_RESULTS) {
873         Uri uri(PAH_QUERY_ANA_TOTAL);
874         DataShare::DataSharePredicates predicates;
875         std::vector<std::string> fetchColumn = { analysisInfo.fieldStr };
876         predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
877         auto fieldValue = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
878         string value = MediaLibraryNapiUtils::ParseResultSet2JsonStr(fieldValue, fetchColumn);
879         if (strstr(value.c_str(), ANALYSIS_INIT_VALUE.c_str()) == NULL) {
880             context->analysisData = ANALYSIS_STATUS_ANALYZED;
881         }
882     }
883 }
884 
UpdateFileAssetInfo()885 void SendableFileAssetNapi::UpdateFileAssetInfo()
886 {
887     fileAssetPtr = std::shared_ptr<FileAsset>(sFileAsset_);
888 }
889 
GetFileAssetInstance() const890 shared_ptr<FileAsset> SendableFileAssetNapi::GetFileAssetInstance() const
891 {
892     return fileAssetPtr;
893 }
894 
CheckSystemApiKeys(napi_env env,const string & key)895 static int32_t CheckSystemApiKeys(napi_env env, const string &key)
896 {
897     static const set<string> SYSTEM_API_KEYS = {
898         PhotoColumn::PHOTO_POSITION,
899         MediaColumn::MEDIA_DATE_TRASHED,
900         MediaColumn::MEDIA_HIDDEN,
901         PhotoColumn::PHOTO_USER_COMMENT,
902         PhotoColumn::CAMERA_SHOT_KEY,
903         PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
904         PENDING_STATUS,
905         MEDIA_DATA_DB_DATE_TRASHED_MS,
906     };
907 
908     if (SYSTEM_API_KEYS.find(key) != SYSTEM_API_KEYS.end() && !SendableMediaLibraryNapiUtils::IsSystemApp()) {
909         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This key can only be used by system apps");
910         return E_CHECK_SYSTEMAPP_FAIL;
911     }
912     return E_SUCCESS;
913 }
914 
IsSpecialKey(const string & key)915 static bool IsSpecialKey(const string &key)
916 {
917     static const set<string> SPECIAL_KEY = {
918         PENDING_STATUS
919     };
920 
921     if (SPECIAL_KEY.find(key) != SPECIAL_KEY.end()) {
922         return true;
923     }
924     return false;
925 }
926 
HandleGettingSpecialKey(napi_env env,const string & key,const shared_ptr<FileAsset> & fileAssetPtr)927 static napi_value HandleGettingSpecialKey(napi_env env, const string &key, const shared_ptr<FileAsset> &fileAssetPtr)
928 {
929     napi_value jsResult = nullptr;
930     if (key == PENDING_STATUS) {
931         if (fileAssetPtr->GetTimePending() == 0) {
932             napi_get_boolean(env, false, &jsResult);
933         } else {
934             napi_get_boolean(env, true, &jsResult);
935         }
936     }
937 
938     return jsResult;
939 }
940 
GetDateTakenFromResultSet(const shared_ptr<DataShare::DataShareResultSet> & resultSet,int64_t & dateTaken)941 static bool GetDateTakenFromResultSet(const shared_ptr<DataShare::DataShareResultSet> &resultSet,
942     int64_t &dateTaken)
943 {
944     if (resultSet == nullptr) {
945         NAPI_ERR_LOG("ResultSet is null");
946         return false;
947     }
948     int32_t count = 0;
949     int32_t errCode = resultSet->GetRowCount(count);
950     if (errCode != DataShare::E_OK) {
951         NAPI_ERR_LOG("Can not get row count from resultSet, errCode=%{public}d", errCode);
952         return false;
953     }
954     if (count == 0) {
955         NAPI_ERR_LOG("Can not find photo edit time from database");
956         return false;
957     }
958     errCode = resultSet->GoToFirstRow();
959     if (errCode != DataShare::E_OK) {
960         NAPI_ERR_LOG("ResultSet GotoFirstRow failed, errCode=%{public}d", errCode);
961         return false;
962     }
963     int32_t index = 0;
964     errCode = resultSet->GetColumnIndex(PhotoColumn::MEDIA_DATE_TAKEN, index);
965     if (errCode != DataShare::E_OK) {
966         NAPI_ERR_LOG("ResultSet GetColumnIndex failed, errCode=%{public}d", errCode);
967         return false;
968     }
969     errCode = resultSet->GetLong(index, dateTaken);
970     if (errCode != DataShare::E_OK) {
971         NAPI_ERR_LOG("ResultSet GetLong failed, errCode=%{public}d", errCode);
972         return false;
973     }
974     return true;
975 }
976 
UpdateDetailTimeByDateTaken(napi_env env,const shared_ptr<FileAsset> & fileAssetPtr,const string & detailTime)977 static void UpdateDetailTimeByDateTaken(napi_env env, const shared_ptr<FileAsset> &fileAssetPtr,
978     const string &detailTime)
979 {
980     string uri = PAH_UPDATE_PHOTO;
981     SendableMediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
982     Uri updateAssetUri(uri);
983     DataSharePredicates predicates;
984     DataShareValuesBucket valuesBucket;
985     valuesBucket.Put(PhotoColumn::PHOTO_DETAIL_TIME, detailTime);
986     predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
987     predicates.SetWhereArgs({ MediaFileUtils::GetIdFromUri(fileAssetPtr->GetUri()) });
988     int32_t changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
989     if (changedRows < 0) {
990         NAPI_ERR_LOG("Failed to modify detail time, err: %{public}d", changedRows);
991         NapiError::ThrowError(env, JS_INNER_FAIL);
992     }
993 }
994 
HandleGettingDetailTimeKey(napi_env env,const shared_ptr<FileAsset> & fileAssetPtr)995 static napi_value HandleGettingDetailTimeKey(napi_env env, const shared_ptr<FileAsset> &fileAssetPtr)
996 {
997     napi_value jsResult = nullptr;
998     auto detailTimeValue = fileAssetPtr->GetMemberMap().at(PhotoColumn::PHOTO_DETAIL_TIME);
999     if (detailTimeValue.index() == MEMBER_TYPE_STRING && !get<string>(detailTimeValue).empty()) {
1000         napi_create_string_utf8(env, get<string>(detailTimeValue).c_str(), NAPI_AUTO_LENGTH, &jsResult);
1001     } else {
1002         string fileId = MediaFileUtils::GetIdFromUri(fileAssetPtr->GetUri());
1003         string queryUriStr = PAH_QUERY_PHOTO;
1004         SendableMediaLibraryNapiUtils::UriAppendKeyValue(queryUriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
1005         Uri uri(queryUriStr);
1006         DataShare::DataSharePredicates predicates;
1007         predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1008         DataShare::DataShareValuesBucket values;
1009         vector<string> columns = { MediaColumn::MEDIA_DATE_TAKEN };
1010         int32_t errCode = 0;
1011         int64_t dateTaken = 0;
1012         shared_ptr<DataShare::DataShareResultSet> resultSet = UserFileClient::Query(uri, predicates, columns, errCode);
1013         if (GetDateTakenFromResultSet(resultSet, dateTaken)) {
1014             if (dateTaken > SECONDS_LEVEL_LIMIT) {
1015                 dateTaken = dateTaken / MSEC_TO_SEC;
1016             }
1017             string detailTime = MediaFileUtils::StrCreateTime(PhotoColumn::PHOTO_DETAIL_TIME_FORMAT, dateTaken);
1018             napi_create_string_utf8(env, detailTime.c_str(), NAPI_AUTO_LENGTH, &jsResult);
1019             UpdateDetailTimeByDateTaken(env, fileAssetPtr, detailTime);
1020         } else {
1021             NapiError::ThrowError(env, JS_INNER_FAIL);
1022         }
1023     }
1024     return jsResult;
1025 }
1026 
HandleDateTransitionKey(napi_env env,const string & key,const shared_ptr<FileAsset> & fileAssetPtr)1027 static napi_value HandleDateTransitionKey(napi_env env, const string &key, const shared_ptr<FileAsset> &fileAssetPtr)
1028 {
1029     napi_value jsResult = nullptr;
1030     if (fileAssetPtr->GetMemberMap().count(key) == 0) {
1031         NapiError::ThrowError(env, JS_E_FILE_KEY);
1032         return jsResult;
1033     }
1034 
1035     auto m = fileAssetPtr->GetMemberMap().at(key);
1036     if (m.index() == MEMBER_TYPE_INT64) {
1037         napi_create_int64(env, get<int64_t>(m), &jsResult);
1038     } else {
1039         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
1040         return jsResult;
1041     }
1042     return jsResult;
1043 }
1044 
GetCompatDate(const string inputKey,const int64_t date)1045 static inline int64_t GetCompatDate(const string inputKey, const int64_t date)
1046 {
1047     if (inputKey == MEDIA_DATA_DB_DATE_ADDED || inputKey == MEDIA_DATA_DB_DATE_MODIFIED ||
1048         inputKey == MEDIA_DATA_DB_DATE_TRASHED || inputKey == MEDIA_DATA_DB_DATE_TAKEN) {
1049             return date / MSEC_TO_SEC;
1050         }
1051     return date;
1052 }
1053 
PhotoAccessHelperGet(napi_env env,napi_callback_info info)1054 napi_value SendableFileAssetNapi::PhotoAccessHelperGet(napi_env env, napi_callback_info info)
1055 {
1056     napi_value ret = nullptr;
1057     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1058     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
1059 
1060     string inputKey;
1061     CHECK_ARGS(env, SendableMediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey),
1062         JS_ERR_PARAMETER_INVALID);
1063 
1064     if (CheckSystemApiKeys(env, inputKey) < 0) {
1065         return nullptr;
1066     }
1067 
1068     napi_value jsResult = nullptr;
1069     auto obj = asyncContext->objectInfo;
1070     napi_get_undefined(env, &jsResult);
1071     if (DATE_TRANSITION_MAP.count(inputKey) != 0) {
1072         return HandleDateTransitionKey(env, DATE_TRANSITION_MAP.at(inputKey), obj->fileAssetPtr);
1073     }
1074 
1075     if (obj->fileAssetPtr->GetMemberMap().count(inputKey) == 0) {
1076         // no exist throw error
1077         NapiError::ThrowError(env, JS_E_FILE_KEY);
1078         return jsResult;
1079     }
1080 
1081     if (IsSpecialKey(inputKey)) {
1082         return HandleGettingSpecialKey(env, inputKey, obj->fileAssetPtr);
1083     }
1084     if (inputKey == PhotoColumn::PHOTO_DETAIL_TIME) {
1085         return HandleGettingDetailTimeKey(env, obj->fileAssetPtr);
1086     }
1087     auto m = obj->fileAssetPtr->GetMemberMap().at(inputKey);
1088     if (m.index() == MEMBER_TYPE_STRING) {
1089         napi_create_string_utf8(env, get<string>(m).c_str(), NAPI_AUTO_LENGTH, &jsResult);
1090     } else if (m.index() == MEMBER_TYPE_INT32) {
1091         napi_create_int32(env, get<int32_t>(m), &jsResult);
1092     } else if (m.index() == MEMBER_TYPE_INT64) {
1093         napi_create_int64(env, GetCompatDate(inputKey, get<int64_t>(m)), &jsResult);
1094     } else {
1095         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
1096         return jsResult;
1097     }
1098     return jsResult;
1099 }
1100 
HandleParamSet(const string & inputKey,const string & value,ResultNapiType resultNapiType)1101 bool SendableFileAssetNapi::HandleParamSet(const string &inputKey, const string &value, ResultNapiType resultNapiType)
1102 {
1103     if (resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
1104         if (inputKey == MediaColumn::MEDIA_TITLE) {
1105             fileAssetPtr->SetTitle(value);
1106         } else {
1107             NAPI_ERR_LOG("invalid key %{private}s, no support key", inputKey.c_str());
1108             return false;
1109         }
1110     } else if (resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
1111         if (inputKey == MediaColumn::MEDIA_NAME) {
1112             fileAssetPtr->SetDisplayName(value);
1113             fileAssetPtr->SetTitle(MediaFileUtils::GetTitleFromDisplayName(value));
1114         } else if (inputKey == MediaColumn::MEDIA_TITLE) {
1115             fileAssetPtr->SetTitle(value);
1116             string displayName = fileAssetPtr->GetDisplayName();
1117             if (!displayName.empty()) {
1118                 string extention = MediaFileUtils::SplitByChar(displayName, '.');
1119                 fileAssetPtr->SetDisplayName(value + "." + extention);
1120             }
1121         } else {
1122             NAPI_ERR_LOG("invalid key %{private}s, no support key", inputKey.c_str());
1123             return false;
1124         }
1125     } else {
1126         NAPI_ERR_LOG("invalid resultNapiType");
1127         return false;
1128     }
1129     return true;
1130 }
1131 
PhotoAccessHelperSet(napi_env env,napi_callback_info info)1132 napi_value SendableFileAssetNapi::PhotoAccessHelperSet(napi_env env, napi_callback_info info)
1133 {
1134     MediaLibraryTracer tracer;
1135     tracer.Start("PhotoAccessHelperSet");
1136 
1137     napi_value ret = nullptr;
1138     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1139     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
1140     string inputKey;
1141     CHECK_ARGS(env, SendableMediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey),
1142         JS_ERR_PARAMETER_INVALID);
1143     string value;
1144     CHECK_ARGS(env, SendableMediaLibraryNapiUtils::GetParamStringPathMax(env, asyncContext->argv[ARGS_ONE], value),
1145         JS_ERR_PARAMETER_INVALID);
1146     napi_value jsResult = nullptr;
1147     napi_get_undefined(env, &jsResult);
1148     auto obj = asyncContext->objectInfo;
1149     if (!obj->HandleParamSet(inputKey, value, obj->fileAssetPtr->GetResultNapiType())) {
1150         NapiError::ThrowError(env, JS_E_FILE_KEY);
1151         return jsResult;
1152     }
1153     return jsResult;
1154 }
1155 
JSGetAnalysisDataCompleteCallback(napi_env env,napi_status status,void * data)1156 static void JSGetAnalysisDataCompleteCallback(napi_env env, napi_status status, void *data)
1157 {
1158     MediaLibraryTracer tracer;
1159     tracer.Start("JSGetAnalysisDataCompleteCallback");
1160 
1161     auto *context = static_cast<SendableFileAssetAsyncContext *>(data);
1162     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1163 
1164     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
1165     jsContext->status = false;
1166 
1167     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1168     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1169     if (context->error == ERR_DEFAULT) {
1170         CHECK_ARGS_RET_VOID(env, napi_create_string_utf8(env, context->analysisData.c_str(),
1171             NAPI_AUTO_LENGTH, &jsContext->data), JS_INNER_FAIL);
1172         jsContext->status = true;
1173     } else {
1174         context->HandleError(env, jsContext->error);
1175     }
1176 
1177     tracer.Finish();
1178     if (context->work != nullptr) {
1179         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1180                                                            context->work, *jsContext);
1181     }
1182     delete context;
1183 }
1184 
PhotoAccessHelperCommitModify(napi_env env,napi_callback_info info)1185 napi_value SendableFileAssetNapi::PhotoAccessHelperCommitModify(napi_env env, napi_callback_info info)
1186 {
1187     MediaLibraryTracer tracer;
1188     tracer.Start("PhotoAccessHelperCommitModify");
1189 
1190     napi_value ret = nullptr;
1191     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1192     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
1193     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1194     NAPI_ASSERT(env, SendableMediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
1195         "Failed to parse js args");
1196     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1197     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
1198 
1199     return SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperCommitModify",
1200         JSCommitModifyExecute, JSCommitModifyCompleteCallback);
1201 }
1202 
PhotoAccessHelperGetThumbnail(napi_env env,napi_callback_info info)1203 napi_value SendableFileAssetNapi::PhotoAccessHelperGetThumbnail(napi_env env, napi_callback_info info)
1204 {
1205     MediaLibraryTracer tracer;
1206     tracer.Start("PhotoAccessHelperGetThumbnail");
1207 
1208     napi_value result = nullptr;
1209     NAPI_CALL(env, napi_get_undefined(env, &result));
1210     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1211     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1212 
1213     CHECK_COND_RET(SendableMediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info,
1214         asyncContext, ARGS_ZERO, ARGS_TWO) == napi_ok, result, "Failed to get object info");
1215     result = GetJSArgsForGetThumbnail(env, asyncContext->argc, asyncContext->argv, asyncContext);
1216     ASSERT_NULLPTR_CHECK(env, result);
1217     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1218     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1219     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1220     result = SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperGetThumbnail",
1221         [](napi_env env, void *data) {
1222             auto context = static_cast<SendableFileAssetAsyncContext*>(data);
1223             JSGetThumbnailExecute(context);
1224         },
1225         reinterpret_cast<CompleteCallback>(JSGetThumbnailCompleteCallback));
1226 
1227     return result;
1228 }
1229 
PhotoAccessHelperGetAnalysisData(napi_env env,napi_callback_info info)1230 napi_value SendableFileAssetNapi::PhotoAccessHelperGetAnalysisData(napi_env env, napi_callback_info info)
1231 {
1232     MediaLibraryTracer tracer;
1233     tracer.Start("PhotoAccessHelperGetAnalysisData");
1234 
1235     napi_value result = nullptr;
1236     NAPI_CALL(env, napi_get_undefined(env, &result));
1237     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1238     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1239     CHECK_ARGS(env,
1240         SendableMediaLibraryNapiUtils::ParseArgsNumberCallback(env, info, asyncContext, asyncContext->analysisType),
1241         JS_ERR_PARAMETER_INVALID);
1242     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1243     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1244     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1245     return SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperGetAnalysisData",
1246         [](napi_env env, void *data) {
1247             auto context = static_cast<SendableFileAssetAsyncContext*>(data);
1248             JSGetAnalysisDataExecute(context);
1249         },
1250         reinterpret_cast<CompleteCallback>(JSGetAnalysisDataCompleteCallback));
1251 }
1252 
PhotoAccessHelperRequestSourceExecute(napi_env env,void * data)1253 static void PhotoAccessHelperRequestSourceExecute(napi_env env, void *data)
1254 {
1255     MediaLibraryTracer tracer;
1256     tracer.Start("PhotoAccessHelperRequestSourceExecute");
1257     auto *context = static_cast<SendableFileAssetAsyncContext *>(data);
1258     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1259     bool isValid = false;
1260     string fileUri = context->valuesBucket.Get(MEDIA_DATA_DB_URI, isValid);
1261     if (!isValid) {
1262         context->error = OHOS_INVALID_PARAM_CODE;
1263         return;
1264     }
1265     MediaFileUtils::UriAppendKeyValue(fileUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
1266     Uri uri(fileUri);
1267     int32_t retVal = UserFileClient::OpenFile(uri, "r");
1268     if (retVal <= 0) {
1269         if (retVal == E_PERMISSION_DENIED) {
1270             context->error = OHOS_PERMISSION_DENIED_CODE;
1271         } else {
1272             context->SaveError(retVal);
1273         }
1274         NAPI_ERR_LOG("Photo request edit data failed, ret: %{public}d", retVal);
1275     } else {
1276         context->fd = retVal;
1277         context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_READONLY);
1278     }
1279 }
1280 
PhotoAccessHelperRequestSourceComplete(napi_env env,napi_status status,void * data)1281 static void PhotoAccessHelperRequestSourceComplete(napi_env env, napi_status status, void *data)
1282 {
1283     auto *context = static_cast<SendableFileAssetAsyncContext *>(data);
1284     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1285 
1286     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
1287     jsContext->status = false;
1288 
1289     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1290     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1291     if (context->error == ERR_DEFAULT) {
1292         CHECK_ARGS_RET_VOID(env, napi_create_int32(env, context->fd, &jsContext->data), JS_INNER_FAIL);
1293         jsContext->status = true;
1294     } else {
1295         context->HandleError(env, jsContext->error);
1296     }
1297 
1298     if (context->work != nullptr) {
1299         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1300                                                            context->work, *jsContext);
1301     }
1302     delete context;
1303 }
1304 
PhotoAccessHelperRequestSource(napi_env env,napi_callback_info info)1305 napi_value SendableFileAssetNapi::PhotoAccessHelperRequestSource(napi_env env, napi_callback_info info)
1306 {
1307     MediaLibraryTracer tracer;
1308     tracer.Start("PhotoAccessHelperRequestSource");
1309 
1310     // edit function in API11 is system api, maybe public soon
1311     if (!SendableMediaLibraryNapiUtils::IsSystemApp()) {
1312         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
1313         return nullptr;
1314     }
1315 
1316     auto asyncContext = make_unique<SendableFileAssetAsyncContext>();
1317     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1318     CHECK_COND_WITH_MESSAGE(env,
1319                             SendableMediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
1320                             "Failed to parse js args");
1321     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1322     napi_value ret = nullptr;
1323     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "PhotoAsset is nullptr");
1324     auto fileUri = asyncContext->objectInfo->GetFileUri();
1325     SendableMediaLibraryNapiUtils::UriAppendKeyValue(fileUri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
1326     asyncContext->valuesBucket.Put(MEDIA_DATA_DB_URI, fileUri);
1327     return SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperRequestSource",
1328         PhotoAccessHelperRequestSourceExecute, PhotoAccessHelperRequestSourceComplete);
1329 }
1330 
ConvertFromPhotoAsset(napi_env env,napi_callback_info info)1331 napi_value SendableFileAssetNapi::ConvertFromPhotoAsset(napi_env env, napi_callback_info info)
1332 {
1333     if (photoAccessHelperConstructor_ == nullptr) {
1334         napi_value exports = nullptr;
1335         napi_create_object(env, &exports);
1336         SendableFileAssetNapi::PhotoAccessHelperInit(env, exports);
1337     }
1338 
1339     napi_value result = nullptr;
1340     napi_status status;
1341     napi_value thisVar = nullptr;
1342 
1343     napi_get_undefined(env, &result);
1344     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
1345     if (status != napi_ok || thisVar == nullptr) {
1346         NAPI_ERR_LOG("ConvertFromPhotoAsset Invalid arguments! status: %{public}d", status);
1347         return result;
1348     }
1349 
1350     FileAssetNapi *obj = nullptr;
1351     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1352     if ((status != napi_ok) && (obj == nullptr)) {
1353         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "ConvertFromPhotoAsset napi unwrap failed");
1354         return nullptr;
1355     }
1356 
1357     auto fileAsset = obj->GetFileAssetInstance();
1358     CHECK_COND(env, fileAsset != nullptr, JS_INNER_FAIL);
1359     if (fileAsset->GetId() > 0) {
1360         return SendableFileAssetNapi::CreatePhotoAsset(env, fileAsset);
1361     }
1362 
1363     // FileAsset object has not been actually created, return null.
1364     napi_value nullValue;
1365     napi_get_null(env, &nullValue);
1366     return nullValue;
1367 }
1368 
ConvertToPhotoAsset(napi_env env,napi_callback_info info)1369 napi_value SendableFileAssetNapi::ConvertToPhotoAsset(napi_env env, napi_callback_info info)
1370 {
1371     if (photoAccessHelperConstructor_ == nullptr) {
1372         napi_value exports = nullptr;
1373         napi_create_object(env, &exports);
1374         SendableFileAssetNapi::PhotoAccessHelperInit(env, exports);
1375     }
1376 
1377     napi_value result = nullptr;
1378     napi_status status;
1379     napi_value thisVar = nullptr;
1380 
1381     napi_get_undefined(env, &result);
1382     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
1383     if (status != napi_ok || thisVar == nullptr) {
1384         NAPI_ERR_LOG("ConvertToPhotoAsset Invalid arguments! status: %{public}d", status);
1385         return result;
1386     }
1387 
1388     SendableFileAssetNapi *obj = nullptr;
1389     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
1390     if ((status != napi_ok) && (obj == nullptr)) {
1391         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "ConvertToPhotoAsset napi unwrap sendable failed");
1392         return nullptr;
1393     }
1394 
1395     auto fileAsset = obj->GetFileAssetInstance();
1396     CHECK_COND(env, fileAsset != nullptr, JS_INNER_FAIL);
1397     if (fileAsset->GetId() > 0) {
1398         return FileAssetNapi::CreatePhotoAsset(env, fileAsset);
1399     }
1400 
1401     // FileAsset object has not been actually created, return null.
1402     napi_value nullValue;
1403     napi_get_null(env, &nullValue);
1404     return nullValue;
1405 }
1406 
1407 } // namespace Media
1408 } // namespace OHOS
1409