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