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