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