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