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