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