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     string fieldStr;
847     string uriStr;
848     std::vector<std::string> fetchColumn;
849     DataShare::DataSharePredicates predicates;
850     if (ANALYSIS_SOURCE_INFO_MAP.find(context->analysisType) != ANALYSIS_SOURCE_INFO_MAP.end()) {
851         fieldStr = ANALYSIS_SOURCE_INFO_MAP.at(context->analysisType).fieldStr;
852         uriStr = ANALYSIS_SOURCE_INFO_MAP.at(context->analysisType).uriStr;
853         fetchColumn = ANALYSIS_SOURCE_INFO_MAP.at(context->analysisType).fetchColumn;
854         if (context->analysisType == ANALYSIS_DETAIL_ADDRESS) {
855             string language = Global::I18n::LocaleConfig::GetSystemLanguage();
856             vector<string> onClause = {
857                 PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LATITUDE + " = " +
858                 GEO_KNOWLEDGE_TABLE + "." + LATITUDE + " AND " + PhotoColumn::PHOTOS_TABLE + "." +
859                 PhotoColumn::PHOTO_LONGITUDE + " = " + GEO_KNOWLEDGE_TABLE + "." + LONGITUDE +
860                 " AND " + GEO_KNOWLEDGE_TABLE + "." + LANGUAGE + " = \"" + language + "\""
861             };
862             predicates.LeftOuterJoin(GEO_KNOWLEDGE_TABLE)->On(onClause);
863         }
864         if (context->analysisType == ANALYSIS_HUMAN_FACE_TAG) {
865             string onClause = VISION_IMAGE_FACE_TABLE + "." + TAG_ID + " = " + VISION_FACE_TAG_TABLE + "." + TAG_ID;
866             predicates.InnerJoin(VISION_IMAGE_FACE_TABLE)->On({ onClause });
867         }
868     } else {
869         NAPI_ERR_LOG("Invalid analysisType");
870         return;
871     }
872     int fileId = context->objectInfo->GetFileId();
873     Uri uri (uriStr);
874     predicates.EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
875     int errCode = 0;
876     auto resultSet = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
877     context->analysisData = MediaLibraryNapiUtils::ParseResultSet2JsonStr(resultSet, fetchColumn);
878     if (strcmp(context->analysisData.c_str(), ANALYSIS_NO_RESULTS.c_str()) == 0) {
879         Uri uri(PAH_QUERY_ANA_TOTAL);
880         DataShare::DataSharePredicates predicates;
881         std::vector<std::string> fetchColumn = { fieldStr };
882         predicates.EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
883         auto fieldValue = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
884         string value = MediaLibraryNapiUtils::ParseResultSet2JsonStr(fieldValue, fetchColumn);
885         if (strstr(value.c_str(), ANALYSIS_INIT_VALUE.c_str()) == NULL) {
886             context->analysisData = ANALYSIS_STATUS_ANALYZED;
887         }
888     }
889 }
890 
UpdateFileAssetInfo()891 void SendableFileAssetNapi::UpdateFileAssetInfo()
892 {
893     fileAssetPtr = std::shared_ptr<FileAsset>(sFileAsset_);
894 }
895 
GetFileAssetInstance() const896 shared_ptr<FileAsset> SendableFileAssetNapi::GetFileAssetInstance() const
897 {
898     return fileAssetPtr;
899 }
900 
CheckSystemApiKeys(napi_env env,const string & key)901 static int32_t CheckSystemApiKeys(napi_env env, const string &key)
902 {
903     static const set<string> SYSTEM_API_KEYS = {
904         PhotoColumn::PHOTO_POSITION,
905         MediaColumn::MEDIA_DATE_TRASHED,
906         MediaColumn::MEDIA_HIDDEN,
907         PhotoColumn::PHOTO_USER_COMMENT,
908         PhotoColumn::CAMERA_SHOT_KEY,
909         PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
910         PENDING_STATUS,
911         MEDIA_DATA_DB_DATE_TRASHED_MS,
912     };
913 
914     if (SYSTEM_API_KEYS.find(key) != SYSTEM_API_KEYS.end() && !SendableMediaLibraryNapiUtils::IsSystemApp()) {
915         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This key can only be used by system apps");
916         return E_CHECK_SYSTEMAPP_FAIL;
917     }
918     return E_SUCCESS;
919 }
920 
IsSpecialKey(const string & key)921 static bool IsSpecialKey(const string &key)
922 {
923     static const set<string> SPECIAL_KEY = {
924         PENDING_STATUS
925     };
926 
927     if (SPECIAL_KEY.find(key) != SPECIAL_KEY.end()) {
928         return true;
929     }
930     return false;
931 }
932 
HandleGettingSpecialKey(napi_env env,const string & key,const shared_ptr<FileAsset> & fileAssetPtr)933 static napi_value HandleGettingSpecialKey(napi_env env, const string &key, const shared_ptr<FileAsset> &fileAssetPtr)
934 {
935     napi_value jsResult = nullptr;
936     if (key == PENDING_STATUS) {
937         if (fileAssetPtr->GetTimePending() == 0) {
938             napi_get_boolean(env, false, &jsResult);
939         } else {
940             napi_get_boolean(env, true, &jsResult);
941         }
942     }
943 
944     return jsResult;
945 }
946 
GetDateTakenFromResultSet(const shared_ptr<DataShare::DataShareResultSet> & resultSet,int64_t & dateTaken)947 static bool GetDateTakenFromResultSet(const shared_ptr<DataShare::DataShareResultSet> &resultSet,
948     int64_t &dateTaken)
949 {
950     if (resultSet == nullptr) {
951         NAPI_ERR_LOG("ResultSet is null");
952         return false;
953     }
954     int32_t count = 0;
955     int32_t errCode = resultSet->GetRowCount(count);
956     if (errCode != DataShare::E_OK) {
957         NAPI_ERR_LOG("Can not get row count from resultSet, errCode=%{public}d", errCode);
958         return false;
959     }
960     if (count == 0) {
961         NAPI_ERR_LOG("Can not find photo edit time from database");
962         return false;
963     }
964     errCode = resultSet->GoToFirstRow();
965     if (errCode != DataShare::E_OK) {
966         NAPI_ERR_LOG("ResultSet GotoFirstRow failed, errCode=%{public}d", errCode);
967         return false;
968     }
969     int32_t index = 0;
970     errCode = resultSet->GetColumnIndex(PhotoColumn::MEDIA_DATE_TAKEN, index);
971     if (errCode != DataShare::E_OK) {
972         NAPI_ERR_LOG("ResultSet GetColumnIndex failed, errCode=%{public}d", errCode);
973         return false;
974     }
975     errCode = resultSet->GetLong(index, dateTaken);
976     if (errCode != DataShare::E_OK) {
977         NAPI_ERR_LOG("ResultSet GetLong failed, errCode=%{public}d", errCode);
978         return false;
979     }
980     return true;
981 }
982 
UpdateDetailTimeByDateTaken(napi_env env,const shared_ptr<FileAsset> & fileAssetPtr,const string & detailTime)983 static void UpdateDetailTimeByDateTaken(napi_env env, const shared_ptr<FileAsset> &fileAssetPtr,
984     const string &detailTime)
985 {
986     string uri = PAH_UPDATE_PHOTO;
987     SendableMediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
988     Uri updateAssetUri(uri);
989     DataSharePredicates predicates;
990     DataShareValuesBucket valuesBucket;
991     valuesBucket.Put(PhotoColumn::PHOTO_DETAIL_TIME, detailTime);
992     predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
993     predicates.SetWhereArgs({ MediaFileUtils::GetIdFromUri(fileAssetPtr->GetUri()) });
994     int32_t changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
995     if (changedRows < 0) {
996         NAPI_ERR_LOG("Failed to modify detail time, err: %{public}d", changedRows);
997         NapiError::ThrowError(env, JS_INNER_FAIL);
998     }
999 }
1000 
HandleGettingDetailTimeKey(napi_env env,const shared_ptr<FileAsset> & fileAssetPtr)1001 static napi_value HandleGettingDetailTimeKey(napi_env env, const shared_ptr<FileAsset> &fileAssetPtr)
1002 {
1003     napi_value jsResult = nullptr;
1004     auto detailTimeValue = fileAssetPtr->GetMemberMap().at(PhotoColumn::PHOTO_DETAIL_TIME);
1005     if (detailTimeValue.index() == MEMBER_TYPE_STRING && !get<string>(detailTimeValue).empty()) {
1006         napi_create_string_utf8(env, get<string>(detailTimeValue).c_str(), NAPI_AUTO_LENGTH, &jsResult);
1007     } else {
1008         string fileId = MediaFileUtils::GetIdFromUri(fileAssetPtr->GetUri());
1009         string queryUriStr = PAH_QUERY_PHOTO;
1010         SendableMediaLibraryNapiUtils::UriAppendKeyValue(queryUriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
1011         Uri uri(queryUriStr);
1012         DataShare::DataSharePredicates predicates;
1013         predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1014         DataShare::DataShareValuesBucket values;
1015         vector<string> columns = { MediaColumn::MEDIA_DATE_TAKEN };
1016         int32_t errCode = 0;
1017         int64_t dateTaken = 0;
1018         shared_ptr<DataShare::DataShareResultSet> resultSet = UserFileClient::Query(uri, predicates, columns, errCode);
1019         if (GetDateTakenFromResultSet(resultSet, dateTaken)) {
1020             if (dateTaken > SECONDS_LEVEL_LIMIT) {
1021                 dateTaken = dateTaken / MSEC_TO_SEC;
1022             }
1023             string detailTime = MediaFileUtils::StrCreateTime(PhotoColumn::PHOTO_DETAIL_TIME_FORMAT, dateTaken);
1024             napi_create_string_utf8(env, detailTime.c_str(), NAPI_AUTO_LENGTH, &jsResult);
1025             UpdateDetailTimeByDateTaken(env, fileAssetPtr, detailTime);
1026         } else {
1027             NapiError::ThrowError(env, JS_INNER_FAIL);
1028         }
1029     }
1030     return jsResult;
1031 }
1032 
HandleDateTransitionKey(napi_env env,const string & key,const shared_ptr<FileAsset> & fileAssetPtr)1033 static napi_value HandleDateTransitionKey(napi_env env, const string &key, const shared_ptr<FileAsset> &fileAssetPtr)
1034 {
1035     napi_value jsResult = nullptr;
1036     if (fileAssetPtr->GetMemberMap().count(key) == 0) {
1037         NapiError::ThrowError(env, JS_E_FILE_KEY);
1038         return jsResult;
1039     }
1040 
1041     auto m = fileAssetPtr->GetMemberMap().at(key);
1042     if (m.index() == MEMBER_TYPE_INT64) {
1043         napi_create_int64(env, get<int64_t>(m), &jsResult);
1044     } else {
1045         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
1046         return jsResult;
1047     }
1048     return jsResult;
1049 }
1050 
GetCompatDate(const string inputKey,const int64_t date)1051 static inline int64_t GetCompatDate(const string inputKey, const int64_t date)
1052 {
1053     if (inputKey == MEDIA_DATA_DB_DATE_ADDED || inputKey == MEDIA_DATA_DB_DATE_MODIFIED ||
1054         inputKey == MEDIA_DATA_DB_DATE_TRASHED || inputKey == MEDIA_DATA_DB_DATE_TAKEN) {
1055             return date / MSEC_TO_SEC;
1056         }
1057     return date;
1058 }
1059 
PhotoAccessHelperGet(napi_env env,napi_callback_info info)1060 napi_value SendableFileAssetNapi::PhotoAccessHelperGet(napi_env env, napi_callback_info info)
1061 {
1062     napi_value ret = nullptr;
1063     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1064     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
1065 
1066     string inputKey;
1067     CHECK_ARGS(env, SendableMediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey),
1068         JS_ERR_PARAMETER_INVALID);
1069 
1070     if (CheckSystemApiKeys(env, inputKey) < 0) {
1071         return nullptr;
1072     }
1073 
1074     napi_value jsResult = nullptr;
1075     auto obj = asyncContext->objectInfo;
1076     napi_get_undefined(env, &jsResult);
1077     if (DATE_TRANSITION_MAP.count(inputKey) != 0) {
1078         return HandleDateTransitionKey(env, DATE_TRANSITION_MAP.at(inputKey), obj->fileAssetPtr);
1079     }
1080 
1081     if (obj->fileAssetPtr->GetMemberMap().count(inputKey) == 0) {
1082         // no exist throw error
1083         NapiError::ThrowError(env, JS_E_FILE_KEY);
1084         return jsResult;
1085     }
1086 
1087     if (IsSpecialKey(inputKey)) {
1088         return HandleGettingSpecialKey(env, inputKey, obj->fileAssetPtr);
1089     }
1090     if (inputKey == PhotoColumn::PHOTO_DETAIL_TIME) {
1091         return HandleGettingDetailTimeKey(env, obj->fileAssetPtr);
1092     }
1093     auto m = obj->fileAssetPtr->GetMemberMap().at(inputKey);
1094     if (m.index() == MEMBER_TYPE_STRING) {
1095         napi_create_string_utf8(env, get<string>(m).c_str(), NAPI_AUTO_LENGTH, &jsResult);
1096     } else if (m.index() == MEMBER_TYPE_INT32) {
1097         napi_create_int32(env, get<int32_t>(m), &jsResult);
1098     } else if (m.index() == MEMBER_TYPE_INT64) {
1099         napi_create_int64(env, GetCompatDate(inputKey, get<int64_t>(m)), &jsResult);
1100     } else {
1101         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
1102         return jsResult;
1103     }
1104     return jsResult;
1105 }
1106 
HandleParamSet(const string & inputKey,const string & value,ResultNapiType resultNapiType)1107 bool SendableFileAssetNapi::HandleParamSet(const string &inputKey, const string &value, ResultNapiType resultNapiType)
1108 {
1109     if (resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
1110         if (inputKey == MediaColumn::MEDIA_TITLE) {
1111             fileAssetPtr->SetTitle(value);
1112         } else {
1113             NAPI_ERR_LOG("invalid key %{private}s, no support key", inputKey.c_str());
1114             return false;
1115         }
1116     } else if (resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
1117         if (inputKey == MediaColumn::MEDIA_NAME) {
1118             fileAssetPtr->SetDisplayName(value);
1119             fileAssetPtr->SetTitle(MediaFileUtils::GetTitleFromDisplayName(value));
1120         } else if (inputKey == MediaColumn::MEDIA_TITLE) {
1121             fileAssetPtr->SetTitle(value);
1122             string displayName = fileAssetPtr->GetDisplayName();
1123             if (!displayName.empty()) {
1124                 string extention = MediaFileUtils::SplitByChar(displayName, '.');
1125                 fileAssetPtr->SetDisplayName(value + "." + extention);
1126             }
1127         } else {
1128             NAPI_ERR_LOG("invalid key %{private}s, no support key", inputKey.c_str());
1129             return false;
1130         }
1131     } else {
1132         NAPI_ERR_LOG("invalid resultNapiType");
1133         return false;
1134     }
1135     return true;
1136 }
1137 
PhotoAccessHelperSet(napi_env env,napi_callback_info info)1138 napi_value SendableFileAssetNapi::PhotoAccessHelperSet(napi_env env, napi_callback_info info)
1139 {
1140     MediaLibraryTracer tracer;
1141     tracer.Start("PhotoAccessHelperSet");
1142 
1143     napi_value ret = nullptr;
1144     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1145     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
1146     string inputKey;
1147     CHECK_ARGS(env, SendableMediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey),
1148         JS_ERR_PARAMETER_INVALID);
1149     string value;
1150     CHECK_ARGS(env, SendableMediaLibraryNapiUtils::GetParamStringPathMax(env, asyncContext->argv[ARGS_ONE], value),
1151         JS_ERR_PARAMETER_INVALID);
1152     napi_value jsResult = nullptr;
1153     napi_get_undefined(env, &jsResult);
1154     auto obj = asyncContext->objectInfo;
1155     if (!obj->HandleParamSet(inputKey, value, obj->fileAssetPtr->GetResultNapiType())) {
1156         NapiError::ThrowError(env, JS_E_FILE_KEY);
1157         return jsResult;
1158     }
1159     return jsResult;
1160 }
1161 
JSGetAnalysisDataCompleteCallback(napi_env env,napi_status status,void * data)1162 static void JSGetAnalysisDataCompleteCallback(napi_env env, napi_status status, void *data)
1163 {
1164     MediaLibraryTracer tracer;
1165     tracer.Start("JSGetAnalysisDataCompleteCallback");
1166 
1167     auto *context = static_cast<SendableFileAssetAsyncContext *>(data);
1168     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1169 
1170     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
1171     jsContext->status = false;
1172 
1173     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1174     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1175     if (context->error == ERR_DEFAULT) {
1176         CHECK_ARGS_RET_VOID(env, napi_create_string_utf8(env, context->analysisData.c_str(),
1177             NAPI_AUTO_LENGTH, &jsContext->data), JS_INNER_FAIL);
1178         jsContext->status = true;
1179     } else {
1180         context->HandleError(env, jsContext->error);
1181     }
1182 
1183     tracer.Finish();
1184     if (context->work != nullptr) {
1185         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1186                                                            context->work, *jsContext);
1187     }
1188     delete context;
1189 }
1190 
PhotoAccessHelperCommitModify(napi_env env,napi_callback_info info)1191 napi_value SendableFileAssetNapi::PhotoAccessHelperCommitModify(napi_env env, napi_callback_info info)
1192 {
1193     MediaLibraryTracer tracer;
1194     tracer.Start("PhotoAccessHelperCommitModify");
1195 
1196     napi_value ret = nullptr;
1197     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1198     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
1199     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1200     NAPI_ASSERT(env, SendableMediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
1201         "Failed to parse js args");
1202     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1203     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
1204 
1205     return SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperCommitModify",
1206         JSCommitModifyExecute, JSCommitModifyCompleteCallback);
1207 }
1208 
PhotoAccessHelperGetThumbnail(napi_env env,napi_callback_info info)1209 napi_value SendableFileAssetNapi::PhotoAccessHelperGetThumbnail(napi_env env, napi_callback_info info)
1210 {
1211     MediaLibraryTracer tracer;
1212     tracer.Start("PhotoAccessHelperGetThumbnail");
1213 
1214     napi_value result = nullptr;
1215     NAPI_CALL(env, napi_get_undefined(env, &result));
1216     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1217     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1218 
1219     CHECK_COND_RET(SendableMediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info,
1220         asyncContext, ARGS_ZERO, ARGS_TWO) == napi_ok, result, "Failed to get object info");
1221     result = GetJSArgsForGetThumbnail(env, asyncContext->argc, asyncContext->argv, asyncContext);
1222     ASSERT_NULLPTR_CHECK(env, result);
1223     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1224     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1225     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1226     result = SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperGetThumbnail",
1227         [](napi_env env, void *data) {
1228             auto context = static_cast<SendableFileAssetAsyncContext*>(data);
1229             JSGetThumbnailExecute(context);
1230         },
1231         reinterpret_cast<CompleteCallback>(JSGetThumbnailCompleteCallback));
1232 
1233     return result;
1234 }
1235 
PhotoAccessHelperGetAnalysisData(napi_env env,napi_callback_info info)1236 napi_value SendableFileAssetNapi::PhotoAccessHelperGetAnalysisData(napi_env env, napi_callback_info info)
1237 {
1238     MediaLibraryTracer tracer;
1239     tracer.Start("PhotoAccessHelperGetAnalysisData");
1240 
1241     napi_value result = nullptr;
1242     NAPI_CALL(env, napi_get_undefined(env, &result));
1243     unique_ptr<SendableFileAssetAsyncContext> asyncContext = make_unique<SendableFileAssetAsyncContext>();
1244     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1245     CHECK_ARGS(env,
1246         SendableMediaLibraryNapiUtils::ParseArgsNumberCallback(env, info, asyncContext, asyncContext->analysisType),
1247         JS_ERR_PARAMETER_INVALID);
1248     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1249     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1250     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1251     return SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperGetAnalysisData",
1252         [](napi_env env, void *data) {
1253             auto context = static_cast<SendableFileAssetAsyncContext*>(data);
1254             JSGetAnalysisDataExecute(context);
1255         },
1256         reinterpret_cast<CompleteCallback>(JSGetAnalysisDataCompleteCallback));
1257 }
1258 
PhotoAccessHelperRequestSourceExecute(napi_env env,void * data)1259 static void PhotoAccessHelperRequestSourceExecute(napi_env env, void *data)
1260 {
1261     MediaLibraryTracer tracer;
1262     tracer.Start("PhotoAccessHelperRequestSourceExecute");
1263     auto *context = static_cast<SendableFileAssetAsyncContext *>(data);
1264     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1265     bool isValid = false;
1266     string fileUri = context->valuesBucket.Get(MEDIA_DATA_DB_URI, isValid);
1267     if (!isValid) {
1268         context->error = OHOS_INVALID_PARAM_CODE;
1269         return;
1270     }
1271     MediaFileUtils::UriAppendKeyValue(fileUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
1272     Uri uri(fileUri);
1273     int32_t retVal = UserFileClient::OpenFile(uri, "r");
1274     if (retVal <= 0) {
1275         if (retVal == E_PERMISSION_DENIED) {
1276             context->error = OHOS_PERMISSION_DENIED_CODE;
1277         } else {
1278             context->SaveError(retVal);
1279         }
1280         NAPI_ERR_LOG("Photo request edit data failed, ret: %{public}d", retVal);
1281     } else {
1282         context->fd = retVal;
1283         context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_READONLY);
1284     }
1285 }
1286 
PhotoAccessHelperRequestSourceComplete(napi_env env,napi_status status,void * data)1287 static void PhotoAccessHelperRequestSourceComplete(napi_env env, napi_status status, void *data)
1288 {
1289     auto *context = static_cast<SendableFileAssetAsyncContext *>(data);
1290     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1291 
1292     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
1293     jsContext->status = false;
1294 
1295     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
1296     CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
1297     if (context->error == ERR_DEFAULT) {
1298         CHECK_ARGS_RET_VOID(env, napi_create_int32(env, context->fd, &jsContext->data), JS_INNER_FAIL);
1299         jsContext->status = true;
1300     } else {
1301         context->HandleError(env, jsContext->error);
1302     }
1303 
1304     if (context->work != nullptr) {
1305         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1306                                                            context->work, *jsContext);
1307     }
1308     delete context;
1309 }
1310 
PhotoAccessHelperRequestSource(napi_env env,napi_callback_info info)1311 napi_value SendableFileAssetNapi::PhotoAccessHelperRequestSource(napi_env env, napi_callback_info info)
1312 {
1313     MediaLibraryTracer tracer;
1314     tracer.Start("PhotoAccessHelperRequestSource");
1315 
1316     // edit function in API11 is system api, maybe public soon
1317     if (!SendableMediaLibraryNapiUtils::IsSystemApp()) {
1318         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
1319         return nullptr;
1320     }
1321 
1322     auto asyncContext = make_unique<SendableFileAssetAsyncContext>();
1323     asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
1324     CHECK_COND_WITH_MESSAGE(env,
1325                             SendableMediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
1326                             "Failed to parse js args");
1327     asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1328     napi_value ret = nullptr;
1329     CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "PhotoAsset is nullptr");
1330     auto fileUri = asyncContext->objectInfo->GetFileUri();
1331     SendableMediaLibraryNapiUtils::UriAppendKeyValue(fileUri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
1332     asyncContext->valuesBucket.Put(MEDIA_DATA_DB_URI, fileUri);
1333     return SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperRequestSource",
1334         PhotoAccessHelperRequestSourceExecute, PhotoAccessHelperRequestSourceComplete);
1335 }
1336 
ConvertFromPhotoAsset(napi_env env,napi_callback_info info)1337 napi_value SendableFileAssetNapi::ConvertFromPhotoAsset(napi_env env, napi_callback_info info)
1338 {
1339     if (photoAccessHelperConstructor_ == nullptr) {
1340         napi_value exports = nullptr;
1341         napi_create_object(env, &exports);
1342         SendableFileAssetNapi::PhotoAccessHelperInit(env, exports);
1343     }
1344 
1345     napi_value result = nullptr;
1346     napi_status status;
1347     napi_value thisVar = nullptr;
1348 
1349     napi_get_undefined(env, &result);
1350     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
1351     if (status != napi_ok || thisVar == nullptr) {
1352         NAPI_ERR_LOG("ConvertFromPhotoAsset Invalid arguments! status: %{public}d", status);
1353         return result;
1354     }
1355 
1356     FileAssetNapi *obj = nullptr;
1357     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1358     if ((status != napi_ok) && (obj == nullptr)) {
1359         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "ConvertFromPhotoAsset napi unwrap failed");
1360         return nullptr;
1361     }
1362 
1363     auto fileAsset = obj->GetFileAssetInstance();
1364     CHECK_COND(env, fileAsset != nullptr, JS_INNER_FAIL);
1365     if (fileAsset->GetId() > 0) {
1366         return SendableFileAssetNapi::CreatePhotoAsset(env, fileAsset);
1367     }
1368 
1369     // FileAsset object has not been actually created, return null.
1370     napi_value nullValue;
1371     napi_get_null(env, &nullValue);
1372     return nullValue;
1373 }
1374 
ConvertToPhotoAsset(napi_env env,napi_callback_info info)1375 napi_value SendableFileAssetNapi::ConvertToPhotoAsset(napi_env env, napi_callback_info info)
1376 {
1377     if (photoAccessHelperConstructor_ == nullptr) {
1378         napi_value exports = nullptr;
1379         napi_create_object(env, &exports);
1380         SendableFileAssetNapi::PhotoAccessHelperInit(env, exports);
1381     }
1382 
1383     napi_value result = nullptr;
1384     napi_status status;
1385     napi_value thisVar = nullptr;
1386 
1387     napi_get_undefined(env, &result);
1388     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
1389     if (status != napi_ok || thisVar == nullptr) {
1390         NAPI_ERR_LOG("ConvertToPhotoAsset Invalid arguments! status: %{public}d", status);
1391         return result;
1392     }
1393 
1394     SendableFileAssetNapi *obj = nullptr;
1395     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
1396     if ((status != napi_ok) && (obj == nullptr)) {
1397         NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "ConvertToPhotoAsset napi unwrap sendable failed");
1398         return nullptr;
1399     }
1400 
1401     auto fileAsset = obj->GetFileAssetInstance();
1402     CHECK_COND(env, fileAsset != nullptr, JS_INNER_FAIL);
1403     if (fileAsset->GetId() > 0) {
1404         return FileAssetNapi::CreatePhotoAsset(env, fileAsset);
1405     }
1406 
1407     // FileAsset object has not been actually created, return null.
1408     napi_value nullValue;
1409     napi_get_null(env, &nullValue);
1410     return nullValue;
1411 }
1412 
1413 } // namespace Media
1414 } // namespace OHOS
1415