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 #define MLOG_TAG "FileAssetNapi"
16
17 #include "file_asset_napi.h"
18
19 #include <algorithm>
20 #include <cstring>
21 #include <fcntl.h>
22 #include <sys/stat.h>
23
24 #include "abs_shared_result_set.h"
25 #include "hitrace_meter.h"
26 #include "fetch_result.h"
27 #include "hilog/log.h"
28 #include "media_exif.h"
29 #include "medialibrary_asset_operations.h"
30 #include "media_column.h"
31 #include "media_file_utils.h"
32 #include "media_file_uri.h"
33 #include "medialibrary_client_errno.h"
34 #include "medialibrary_data_manager_utils.h"
35 #include "medialibrary_errno.h"
36 #include "medialibrary_napi_log.h"
37 #include "medialibrary_napi_utils.h"
38 #include "medialibrary_tracer.h"
39 #include "nlohmann/json.hpp"
40 #include "permission_utils.h"
41 #include "rdb_errno.h"
42 #include "string_ex.h"
43 #include "thumbnail_const.h"
44 #include "thumbnail_utils.h"
45 #include "unique_fd.h"
46 #include "userfile_client.h"
47 #include "userfilemgr_uri.h"
48
49 #ifdef IMAGE_PURGEABLE_PIXELMAP
50 #include "purgeable_pixelmap_builder.h"
51 #endif
52
53 using OHOS::HiviewDFX::HiLog;
54 using OHOS::HiviewDFX::HiLogLabel;
55 using namespace std;
56 using namespace OHOS::AppExecFwk;
57 using namespace OHOS::NativeRdb;
58 using namespace OHOS::DataShare;
59 using std::string;
60
61 namespace OHOS {
62 namespace Media {
63 static const std::string MEDIA_FILEDESCRIPTOR = "fd";
64 static const std::string MEDIA_FILEMODE = "mode";
65
66 thread_local napi_ref FileAssetNapi::sConstructor_ = nullptr;
67 thread_local FileAsset *FileAssetNapi::sFileAsset_ = nullptr;
68
69 constexpr int32_t IS_TRASH = 1;
70 constexpr int32_t NOT_TRASH = 0;
71
72 constexpr int32_t IS_FAV = 1;
73 constexpr int32_t NOT_FAV = 0;
74
75 constexpr int32_t IS_HIDDEN = 1;
76 constexpr int32_t NOT_HIDDEN = 0;
77
78 constexpr int32_t USER_COMMENT_MAX_LEN = 140;
79
80 using CompleteCallback = napi_async_complete_callback;
81
82 thread_local napi_ref FileAssetNapi::userFileMgrConstructor_ = nullptr;
83 thread_local napi_ref FileAssetNapi::photoAccessHelperConstructor_ = nullptr;
84
FileAssetNapi()85 FileAssetNapi::FileAssetNapi()
86 : env_(nullptr) {}
87
88 FileAssetNapi::~FileAssetNapi() = default;
89
FileAssetNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)90 void FileAssetNapi::FileAssetNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
91 {
92 FileAssetNapi *fileAssetObj = reinterpret_cast<FileAssetNapi*>(nativeObject);
93 if (fileAssetObj != nullptr) {
94 delete fileAssetObj;
95 fileAssetObj = nullptr;
96 }
97 }
98
Init(napi_env env,napi_value exports)99 napi_value FileAssetNapi::Init(napi_env env, napi_value exports)
100 {
101 napi_status status;
102 napi_value ctorObj;
103 int32_t refCount = 1;
104 napi_property_descriptor file_asset_props[] = {
105 DECLARE_NAPI_GETTER("id", JSGetFileId),
106 DECLARE_NAPI_GETTER("uri", JSGetFileUri),
107 DECLARE_NAPI_GETTER("mediaType", JSGetMediaType),
108 DECLARE_NAPI_GETTER_SETTER("displayName", JSGetFileDisplayName, JSSetFileDisplayName),
109 DECLARE_NAPI_GETTER_SETTER("relativePath", JSGetRelativePath, JSSetRelativePath),
110 DECLARE_NAPI_GETTER("parent", JSParent),
111 DECLARE_NAPI_GETTER("size", JSGetSize),
112 DECLARE_NAPI_GETTER("dateAdded", JSGetDateAdded),
113 DECLARE_NAPI_GETTER("dateTrashed", JSGetDateTrashed),
114 DECLARE_NAPI_GETTER("dateModified", JSGetDateModified),
115 DECLARE_NAPI_GETTER("dateTaken", JSGetDateTaken),
116 DECLARE_NAPI_GETTER("mimeType", JSGetMimeType),
117 DECLARE_NAPI_GETTER_SETTER("title", JSGetTitle, JSSetTitle),
118 DECLARE_NAPI_GETTER("artist", JSGetArtist),
119 DECLARE_NAPI_GETTER("audioAlbum", JSGetAlbum),
120 DECLARE_NAPI_GETTER("width", JSGetWidth),
121 DECLARE_NAPI_GETTER("height", JSGetHeight),
122 DECLARE_NAPI_GETTER_SETTER("orientation", JSGetOrientation, JSSetOrientation),
123 DECLARE_NAPI_GETTER("duration", JSGetDuration),
124 DECLARE_NAPI_GETTER("albumId", JSGetAlbumId),
125 DECLARE_NAPI_GETTER("albumUri", JSGetAlbumUri),
126 DECLARE_NAPI_GETTER("albumName", JSGetAlbumName),
127 DECLARE_NAPI_GETTER("count", JSGetCount),
128 DECLARE_NAPI_FUNCTION("isDirectory", JSIsDirectory),
129 DECLARE_NAPI_FUNCTION("commitModify", JSCommitModify),
130 DECLARE_NAPI_FUNCTION("open", JSOpen),
131 DECLARE_NAPI_FUNCTION("close", JSClose),
132 DECLARE_NAPI_FUNCTION("getThumbnail", JSGetThumbnail),
133 DECLARE_NAPI_FUNCTION("favorite", JSFavorite),
134 DECLARE_NAPI_FUNCTION("isFavorite", JSIsFavorite),
135 DECLARE_NAPI_FUNCTION("trash", JSTrash),
136 DECLARE_NAPI_FUNCTION("isTrash", JSIsTrash),
137 };
138
139 status = napi_define_class(env, FILE_ASSET_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
140 FileAssetNapiConstructor, nullptr,
141 sizeof(file_asset_props) / sizeof(file_asset_props[PARAM0]),
142 file_asset_props, &ctorObj);
143 if (status == napi_ok) {
144 status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
145 if (status == napi_ok) {
146 status = napi_set_named_property(env, exports, FILE_ASSET_NAPI_CLASS_NAME.c_str(), ctorObj);
147 if (status == napi_ok) {
148 return exports;
149 }
150 }
151 }
152 return nullptr;
153 }
154
UserFileMgrInit(napi_env env,napi_value exports)155 napi_value FileAssetNapi::UserFileMgrInit(napi_env env, napi_value exports)
156 {
157 NapiClassInfo info = {
158 .name = USERFILEMGR_FILEASSET_NAPI_CLASS_NAME,
159 .ref = &userFileMgrConstructor_,
160 .constructor = FileAssetNapiConstructor,
161 .props = {
162 DECLARE_NAPI_FUNCTION("get", UserFileMgrGet),
163 DECLARE_NAPI_FUNCTION("set", UserFileMgrSet),
164 DECLARE_NAPI_FUNCTION("open", UserFileMgrOpen),
165 DECLARE_NAPI_FUNCTION("close", UserFileMgrClose),
166 DECLARE_NAPI_FUNCTION("commitModify", UserFileMgrCommitModify),
167 DECLARE_NAPI_FUNCTION("favorite", UserFileMgrFavorite),
168 DECLARE_NAPI_GETTER("uri", JSGetFileUri),
169 DECLARE_NAPI_GETTER("fileType", JSGetMediaType),
170 DECLARE_NAPI_GETTER_SETTER("displayName", JSGetFileDisplayName, JSSetFileDisplayName),
171 DECLARE_NAPI_FUNCTION("getThumbnail", UserFileMgrGetThumbnail),
172 DECLARE_NAPI_FUNCTION("getReadOnlyFd", JSGetReadOnlyFd),
173 DECLARE_NAPI_FUNCTION("setHidden", UserFileMgrSetHidden),
174 DECLARE_NAPI_FUNCTION("setPending", UserFileMgrSetPending),
175 DECLARE_NAPI_FUNCTION("getExif", JSGetExif),
176 DECLARE_NAPI_FUNCTION("setUserComment", UserFileMgrSetUserComment),
177 }
178 };
179 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
180
181 return exports;
182 }
183
PhotoAccessHelperInit(napi_env env,napi_value exports)184 napi_value FileAssetNapi::PhotoAccessHelperInit(napi_env env, napi_value exports)
185 {
186 NapiClassInfo info = {
187 .name = PHOTOACCESSHELPER_FILEASSET_NAPI_CLASS_NAME,
188 .ref = &photoAccessHelperConstructor_,
189 .constructor = FileAssetNapiConstructor,
190 .props = {
191 DECLARE_NAPI_FUNCTION("get", UserFileMgrGet),
192 DECLARE_NAPI_FUNCTION("set", UserFileMgrSet),
193 DECLARE_NAPI_FUNCTION("open", PhotoAccessHelperOpen),
194 DECLARE_NAPI_FUNCTION("close", PhotoAccessHelperClose),
195 DECLARE_NAPI_FUNCTION("commitModify", PhotoAccessHelperCommitModify),
196 DECLARE_NAPI_FUNCTION("setFavorite", PhotoAccessHelperFavorite),
197 DECLARE_NAPI_GETTER("uri", JSGetFileUri),
198 DECLARE_NAPI_GETTER("photoType", JSGetMediaType),
199 DECLARE_NAPI_GETTER_SETTER("displayName", JSGetFileDisplayName, JSSetFileDisplayName),
200 DECLARE_NAPI_FUNCTION("getThumbnail", PhotoAccessHelperGetThumbnail),
201 DECLARE_NAPI_FUNCTION("getReadOnlyFd", JSGetReadOnlyFd),
202 DECLARE_NAPI_FUNCTION("setHidden", PhotoAccessHelperSetHidden),
203 DECLARE_NAPI_FUNCTION("setPending", PhotoAccessHelperSetPending),
204 DECLARE_NAPI_FUNCTION("getExif", JSGetExif),
205 DECLARE_NAPI_FUNCTION("setUserComment", PhotoAccessHelperSetUserComment),
206 }
207 };
208 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
209 return exports;
210 }
211
212 // Constructor callback
FileAssetNapiConstructor(napi_env env,napi_callback_info info)213 napi_value FileAssetNapi::FileAssetNapiConstructor(napi_env env, napi_callback_info info)
214 {
215 napi_status status;
216 napi_value result = nullptr;
217 napi_value thisVar = nullptr;
218
219 napi_get_undefined(env, &result);
220 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
221 if (status == napi_ok && thisVar != nullptr) {
222 std::unique_ptr<FileAssetNapi> obj = std::make_unique<FileAssetNapi>();
223 if (obj != nullptr) {
224 obj->env_ = env;
225 if (sFileAsset_ != nullptr) {
226 obj->UpdateFileAssetInfo();
227 }
228
229 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
230 FileAssetNapi::FileAssetNapiDestructor, nullptr, nullptr);
231 if (status == napi_ok) {
232 obj.release();
233 return thisVar;
234 } else {
235 NAPI_ERR_LOG("Failure wrapping js to native napi, status: %{public}d", status);
236 }
237 }
238 }
239
240 return result;
241 }
242
CreateFileAsset(napi_env env,unique_ptr<FileAsset> & iAsset)243 napi_value FileAssetNapi::CreateFileAsset(napi_env env, unique_ptr<FileAsset> &iAsset)
244 {
245 if (iAsset == nullptr) {
246 return nullptr;
247 }
248
249 napi_value constructor = nullptr;
250 napi_ref constructorRef;
251 if (iAsset->GetResultNapiType() == ResultNapiType::TYPE_USERFILE_MGR) {
252 constructorRef = userFileMgrConstructor_;
253 } else if (iAsset->GetResultNapiType() == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
254 constructorRef = photoAccessHelperConstructor_;
255 } else {
256 constructorRef = sConstructor_;
257 }
258
259 NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
260
261 sFileAsset_ = iAsset.release();
262
263 napi_value result = nullptr;
264 NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
265
266 sFileAsset_ = nullptr;
267 return result;
268 }
269
GetFileDisplayName() const270 std::string FileAssetNapi::GetFileDisplayName() const
271 {
272 return fileAssetPtr->GetDisplayName();
273 }
274
GetRelativePath() const275 std::string FileAssetNapi::GetRelativePath() const
276 {
277 return fileAssetPtr->GetRelativePath();
278 }
279
GetFilePath() const280 std::string FileAssetNapi::GetFilePath() const
281 {
282 return fileAssetPtr->GetPath();
283 }
284
GetTitle() const285 std::string FileAssetNapi::GetTitle() const
286 {
287 return fileAssetPtr->GetTitle();
288 }
289
GetFileUri() const290 std::string FileAssetNapi::GetFileUri() const
291 {
292 return fileAssetPtr->GetUri();
293 }
294
GetFileId() const295 int32_t FileAssetNapi::GetFileId() const
296 {
297 return fileAssetPtr->GetId();
298 }
299
GetMediaType() const300 Media::MediaType FileAssetNapi::GetMediaType() const
301 {
302 return fileAssetPtr->GetMediaType();
303 }
304
GetOrientation() const305 int32_t FileAssetNapi::GetOrientation() const
306 {
307 return fileAssetPtr->GetOrientation();
308 }
309
GetNetworkId() const310 std::string FileAssetNapi::GetNetworkId() const
311 {
312 return MediaFileUtils::GetNetworkIdFromUri(GetFileUri());
313 }
314
IsFavorite() const315 bool FileAssetNapi::IsFavorite() const
316 {
317 return fileAssetPtr->IsFavorite();
318 }
319
SetFavorite(bool isFavorite)320 void FileAssetNapi::SetFavorite(bool isFavorite)
321 {
322 fileAssetPtr->SetFavorite(isFavorite);
323 }
324
IsTrash() const325 bool FileAssetNapi::IsTrash() const
326 {
327 return (fileAssetPtr->GetIsTrash() != NOT_TRASH);
328 }
329
SetTrash(bool isTrash)330 void FileAssetNapi::SetTrash(bool isTrash)
331 {
332 int32_t trashFlag = (isTrash ? IS_TRASH : NOT_TRASH);
333 fileAssetPtr->SetIsTrash(trashFlag);
334 }
335
IsHidden() const336 bool FileAssetNapi::IsHidden() const
337 {
338 return fileAssetPtr->IsHidden();
339 }
340
SetHidden(bool isHidden)341 void FileAssetNapi::SetHidden(bool isHidden)
342 {
343 fileAssetPtr->SetHidden(isHidden);
344 }
345
GetAllExif() const346 std::string FileAssetNapi::GetAllExif() const
347 {
348 return fileAssetPtr->GetAllExif();
349 }
350
GetUserComment() const351 std::string FileAssetNapi::GetUserComment() const
352 {
353 return fileAssetPtr->GetUserComment();
354 }
355
GetNapiObject(napi_env env,napi_callback_info info,FileAssetNapi ** obj)356 napi_status GetNapiObject(napi_env env, napi_callback_info info, FileAssetNapi **obj)
357 {
358 napi_value thisVar = nullptr;
359 CHECK_STATUS_RET(napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr), "Failed to get cb info");
360 CHECK_STATUS_RET(napi_unwrap(env, thisVar, reinterpret_cast<void **>(obj)), "Failed to unwrap thisVar");
361 CHECK_COND_RET(*obj != nullptr, napi_invalid_arg, "Failed to get napi object!");
362 return napi_ok;
363 }
364
JSGetFileId(napi_env env,napi_callback_info info)365 napi_value FileAssetNapi::JSGetFileId(napi_env env, napi_callback_info info)
366 {
367 napi_status status;
368 napi_value jsResult = nullptr;
369 FileAssetNapi *obj = nullptr;
370 int32_t id;
371 napi_value thisVar = nullptr;
372
373 napi_get_undefined(env, &jsResult);
374 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
375 if (status != napi_ok || thisVar == nullptr) {
376 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
377 return jsResult;
378 }
379
380 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
381 if (status == napi_ok && obj != nullptr) {
382 id = obj->GetFileId();
383 #ifdef MEDIALIBRARY_COMPATIBILITY
384 int64_t virtualId = 0;
385 if (MediaFileUtils::IsFileTablePath(obj->GetFilePath())) {
386 virtualId = MediaFileUtils::GetVirtualIdByType(id, MediaType::MEDIA_TYPE_FILE);
387 } else {
388 virtualId = MediaFileUtils::GetVirtualIdByType(id, obj->GetMediaType());
389 }
390 napi_create_int64(env, virtualId, &jsResult);
391 #else
392 napi_create_int32(env, id, &jsResult);
393 #endif
394 }
395
396 return jsResult;
397 }
398
JSGetFileUri(napi_env env,napi_callback_info info)399 napi_value FileAssetNapi::JSGetFileUri(napi_env env, napi_callback_info info)
400 {
401 FileAssetNapi *obj = nullptr;
402 CHECK_ARGS(env, GetNapiObject(env, info, &obj), JS_INNER_FAIL);
403
404 napi_value jsResult = nullptr;
405 CHECK_ARGS(env, napi_create_string_utf8(env, obj->GetFileUri().c_str(), NAPI_AUTO_LENGTH, &jsResult),
406 JS_INNER_FAIL);
407 return jsResult;
408 }
409
JSGetFilePath(napi_env env,napi_callback_info info)410 napi_value FileAssetNapi::JSGetFilePath(napi_env env, napi_callback_info info)
411 {
412 napi_status status;
413 napi_value jsResult = nullptr;
414 FileAssetNapi *obj = nullptr;
415 string path = "";
416 napi_value thisVar = nullptr;
417
418 napi_get_undefined(env, &jsResult);
419 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
420 if (status != napi_ok || thisVar == nullptr) {
421 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
422 return jsResult;
423 }
424
425 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
426 if (status == napi_ok && obj != nullptr) {
427 path = obj->GetFilePath();
428 napi_create_string_utf8(env, path.c_str(), NAPI_AUTO_LENGTH, &jsResult);
429 }
430
431 return jsResult;
432 }
433
JSGetFileDisplayName(napi_env env,napi_callback_info info)434 napi_value FileAssetNapi::JSGetFileDisplayName(napi_env env, napi_callback_info info)
435 {
436 napi_status status;
437 napi_value jsResult = nullptr;
438 FileAssetNapi *obj = nullptr;
439 string displayName = "";
440 napi_value thisVar = nullptr;
441
442 napi_get_undefined(env, &jsResult);
443 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
444 if (status != napi_ok || thisVar == nullptr) {
445 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
446 return jsResult;
447 }
448
449 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
450 if (status == napi_ok && obj != nullptr) {
451 displayName = obj->GetFileDisplayName();
452 napi_create_string_utf8(env, displayName.c_str(), NAPI_AUTO_LENGTH, &jsResult);
453 }
454
455 return jsResult;
456 }
457
JSSetFileDisplayName(napi_env env,napi_callback_info info)458 napi_value FileAssetNapi::JSSetFileDisplayName(napi_env env, napi_callback_info info)
459 {
460 napi_status status;
461 napi_value undefinedResult = nullptr;
462 FileAssetNapi *obj = nullptr;
463 napi_valuetype valueType = napi_undefined;
464 size_t res = 0;
465 char buffer[FILENAME_MAX];
466 size_t argc = ARGS_ONE;
467 napi_value argv[ARGS_ONE] = {0};
468 napi_value thisVar = nullptr;
469
470 napi_get_undefined(env, &undefinedResult);
471
472 GET_JS_ARGS(env, info, argc, argv, thisVar);
473 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
474
475 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
476 if (status == napi_ok && obj != nullptr) {
477 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
478 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
479 return undefinedResult;
480 }
481 status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
482 if (status == napi_ok) {
483 string displayName = string(buffer);
484 obj->fileAssetPtr->SetDisplayName(displayName);
485 #ifdef MEDIALIBRARY_COMPATIBILITY
486 obj->fileAssetPtr->SetTitle(MediaFileUtils::GetTitleFromDisplayName(displayName));
487 #endif
488 }
489 }
490
491 return undefinedResult;
492 }
493
JSGetMimeType(napi_env env,napi_callback_info info)494 napi_value FileAssetNapi::JSGetMimeType(napi_env env, napi_callback_info info)
495 {
496 napi_status status;
497 napi_value jsResult = nullptr;
498 FileAssetNapi *obj = nullptr;
499 string mimeType = "";
500 napi_value thisVar = nullptr;
501
502 napi_get_undefined(env, &jsResult);
503 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
504 if (status != napi_ok || thisVar == nullptr) {
505 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
506 return jsResult;
507 }
508
509 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
510 if (status == napi_ok && obj != nullptr) {
511 mimeType = obj->fileAssetPtr->GetMimeType();
512 napi_create_string_utf8(env, mimeType.c_str(), NAPI_AUTO_LENGTH, &jsResult);
513 }
514
515 return jsResult;
516 }
517
JSGetMediaType(napi_env env,napi_callback_info info)518 napi_value FileAssetNapi::JSGetMediaType(napi_env env, napi_callback_info info)
519 {
520 napi_status status;
521 napi_value jsResult = nullptr;
522 FileAssetNapi *obj = nullptr;
523 int32_t mediaType;
524 napi_value thisVar = nullptr;
525
526 napi_get_undefined(env, &jsResult);
527 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
528 if (status != napi_ok || thisVar == nullptr) {
529 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
530 return jsResult;
531 }
532
533 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
534 if (status == napi_ok && obj != nullptr) {
535 mediaType = static_cast<int32_t>(obj->GetMediaType());
536 napi_create_int32(env, mediaType, &jsResult);
537 }
538
539 return jsResult;
540 }
541
JSGetTitle(napi_env env,napi_callback_info info)542 napi_value FileAssetNapi::JSGetTitle(napi_env env, napi_callback_info info)
543 {
544 napi_status status;
545 napi_value jsResult = nullptr;
546 FileAssetNapi *obj = nullptr;
547 string title = "";
548 napi_value thisVar = nullptr;
549
550 napi_get_undefined(env, &jsResult);
551 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
552 if (status != napi_ok || thisVar == nullptr) {
553 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
554 return jsResult;
555 }
556
557 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
558 if (status == napi_ok && obj != nullptr) {
559 title = obj->GetTitle();
560 napi_create_string_utf8(env, title.c_str(), NAPI_AUTO_LENGTH, &jsResult);
561 }
562
563 return jsResult;
564 }
JSSetTitle(napi_env env,napi_callback_info info)565 napi_value FileAssetNapi::JSSetTitle(napi_env env, napi_callback_info info)
566 {
567 napi_status status;
568 napi_value undefinedResult = nullptr;
569 FileAssetNapi *obj = nullptr;
570 napi_valuetype valueType = napi_undefined;
571 size_t res = 0;
572 char buffer[FILENAME_MAX];
573 size_t argc = ARGS_ONE;
574 napi_value argv[ARGS_ONE] = {0};
575 napi_value thisVar = nullptr;
576 napi_get_undefined(env, &undefinedResult);
577 GET_JS_ARGS(env, info, argc, argv, thisVar);
578 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
579 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
580 if (status == napi_ok && obj != nullptr) {
581 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
582 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
583 return undefinedResult;
584 }
585 status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, FILENAME_MAX, &res);
586 if (status == napi_ok) {
587 string title = string(buffer);
588 obj->fileAssetPtr->SetTitle(title);
589 #ifdef MEDIALIBRARY_COMPATIBILITY
590 string oldDisplayName = obj->fileAssetPtr->GetDisplayName();
591 string ext = MediaFileUtils::SplitByChar(oldDisplayName, '.');
592 string newDisplayName = title + "." + ext;
593 obj->fileAssetPtr->SetDisplayName(newDisplayName);
594 #endif
595 }
596 }
597 return undefinedResult;
598 }
599
JSGetSize(napi_env env,napi_callback_info info)600 napi_value FileAssetNapi::JSGetSize(napi_env env, napi_callback_info info)
601 {
602 napi_status status;
603 napi_value jsResult = nullptr;
604 FileAssetNapi *obj = nullptr;
605 int64_t size;
606 napi_value thisVar = nullptr;
607
608 napi_get_undefined(env, &jsResult);
609 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
610 if (status != napi_ok || thisVar == nullptr) {
611 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
612 return jsResult;
613 }
614
615 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
616 if (status == napi_ok && obj != nullptr) {
617 size = obj->fileAssetPtr->GetSize();
618 napi_create_int64(env, size, &jsResult);
619 }
620
621 return jsResult;
622 }
623
JSGetAlbumId(napi_env env,napi_callback_info info)624 napi_value FileAssetNapi::JSGetAlbumId(napi_env env, napi_callback_info info)
625 {
626 napi_status status;
627 napi_value jsResult = nullptr;
628 FileAssetNapi *obj = nullptr;
629 int32_t albumId;
630 napi_value thisVar = nullptr;
631
632 napi_get_undefined(env, &jsResult);
633 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
634 if (status != napi_ok || thisVar == nullptr) {
635 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
636 return jsResult;
637 }
638
639 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
640 if (status == napi_ok && obj != nullptr) {
641 albumId = obj->fileAssetPtr->GetAlbumId();
642 napi_create_int32(env, albumId, &jsResult);
643 }
644
645 return jsResult;
646 }
647
JSGetAlbumName(napi_env env,napi_callback_info info)648 napi_value FileAssetNapi::JSGetAlbumName(napi_env env, napi_callback_info info)
649 {
650 napi_status status;
651 napi_value jsResult = nullptr;
652 FileAssetNapi *obj = nullptr;
653 string albumName = "";
654 napi_value thisVar = nullptr;
655
656 napi_get_undefined(env, &jsResult);
657 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
658 if (status != napi_ok || thisVar == nullptr) {
659 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
660 return jsResult;
661 }
662
663 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
664 if (status == napi_ok && obj != nullptr) {
665 albumName = obj->fileAssetPtr->GetAlbumName();
666 napi_create_string_utf8(env, albumName.c_str(), NAPI_AUTO_LENGTH, &jsResult);
667 }
668
669 return jsResult;
670 }
671
JSGetCount(napi_env env,napi_callback_info info)672 napi_value FileAssetNapi::JSGetCount(napi_env env, napi_callback_info info)
673 {
674 napi_status status;
675 napi_value jsResult = nullptr;
676 napi_value thisVar = nullptr;
677
678 napi_get_undefined(env, &jsResult);
679 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
680 if ((status != napi_ok) || (thisVar == nullptr)) {
681 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
682 return jsResult;
683 }
684
685 FileAssetNapi *obj = nullptr;
686 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
687 if ((status == napi_ok) && (obj != nullptr)) {
688 napi_create_int32(env, obj->fileAssetPtr->GetCount(), &jsResult);
689 }
690
691 return jsResult;
692 }
693
JSGetDateAdded(napi_env env,napi_callback_info info)694 napi_value FileAssetNapi::JSGetDateAdded(napi_env env, napi_callback_info info)
695 {
696 napi_status status;
697 napi_value jsResult = nullptr;
698 FileAssetNapi *obj = nullptr;
699 int64_t dateAdded;
700 napi_value thisVar = nullptr;
701
702 napi_get_undefined(env, &jsResult);
703 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
704 if (status != napi_ok || thisVar == nullptr) {
705 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
706 return jsResult;
707 }
708
709 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
710 if (status == napi_ok && obj != nullptr) {
711 dateAdded = obj->fileAssetPtr->GetDateAdded();
712 napi_create_int64(env, dateAdded, &jsResult);
713 }
714
715 return jsResult;
716 }
717
JSGetDateTrashed(napi_env env,napi_callback_info info)718 napi_value FileAssetNapi::JSGetDateTrashed(napi_env env, napi_callback_info info)
719 {
720 napi_status status;
721 napi_value jsResult = nullptr;
722 FileAssetNapi *obj = nullptr;
723 int64_t dateTrashed;
724 napi_value thisVar = nullptr;
725
726 napi_get_undefined(env, &jsResult);
727 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
728 if (status != napi_ok || thisVar == nullptr) {
729 NAPI_ERR_LOG("Invalid arguments! status: %{private}d", status);
730 return jsResult;
731 }
732
733 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
734 if (status == napi_ok && obj != nullptr) {
735 dateTrashed = obj->fileAssetPtr->GetDateTrashed();
736 napi_create_int64(env, dateTrashed, &jsResult);
737 }
738
739 return jsResult;
740 }
741
JSGetDateModified(napi_env env,napi_callback_info info)742 napi_value FileAssetNapi::JSGetDateModified(napi_env env, napi_callback_info info)
743 {
744 napi_status status;
745 napi_value jsResult = nullptr;
746 FileAssetNapi *obj = nullptr;
747 int64_t dateModified;
748 napi_value thisVar = nullptr;
749
750 napi_get_undefined(env, &jsResult);
751 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
752 if (status != napi_ok || thisVar == nullptr) {
753 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
754 return jsResult;
755 }
756
757 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
758 if (status == napi_ok && obj != nullptr) {
759 dateModified = obj->fileAssetPtr->GetDateModified();
760 napi_create_int64(env, dateModified, &jsResult);
761 }
762
763 return jsResult;
764 }
765
JSGetOrientation(napi_env env,napi_callback_info info)766 napi_value FileAssetNapi::JSGetOrientation(napi_env env, napi_callback_info info)
767 {
768 napi_status status;
769 napi_value jsResult = nullptr;
770 FileAssetNapi *obj = nullptr;
771 int32_t orientation;
772 napi_value thisVar = nullptr;
773
774 napi_get_undefined(env, &jsResult);
775 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
776 if (status != napi_ok || thisVar == nullptr) {
777 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
778 return jsResult;
779 }
780
781 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
782 if (status == napi_ok && obj != nullptr) {
783 orientation = obj->GetOrientation();
784 napi_create_int32(env, orientation, &jsResult);
785 }
786
787 return jsResult;
788 }
JSSetOrientation(napi_env env,napi_callback_info info)789 napi_value FileAssetNapi::JSSetOrientation(napi_env env, napi_callback_info info)
790 {
791 napi_status status;
792 napi_value undefinedResult = nullptr;
793 FileAssetNapi *obj = nullptr;
794 napi_valuetype valueType = napi_undefined;
795 int32_t orientation;
796 size_t argc = ARGS_ONE;
797 napi_value argv[ARGS_ONE] = {0};
798 napi_value thisVar = nullptr;
799 napi_get_undefined(env, &undefinedResult);
800
801 GET_JS_ARGS(env, info, argc, argv, thisVar);
802 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
803
804 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
805 if (status == napi_ok && obj != nullptr) {
806 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_number) {
807 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
808 return undefinedResult;
809 }
810
811 status = napi_get_value_int32(env, argv[PARAM0], &orientation);
812 if (status == napi_ok) {
813 obj->fileAssetPtr->SetOrientation(orientation);
814 }
815 }
816
817 return undefinedResult;
818 }
819
JSGetWidth(napi_env env,napi_callback_info info)820 napi_value FileAssetNapi::JSGetWidth(napi_env env, napi_callback_info info)
821 {
822 napi_status status;
823 napi_value jsResult = nullptr;
824 FileAssetNapi *obj = nullptr;
825 int32_t width;
826 napi_value thisVar = nullptr;
827
828 napi_get_undefined(env, &jsResult);
829 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
830 if (status != napi_ok || thisVar == nullptr) {
831 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
832 return jsResult;
833 }
834
835 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
836 if (status == napi_ok && obj != nullptr) {
837 width = obj->fileAssetPtr->GetWidth();
838 napi_create_int32(env, width, &jsResult);
839 }
840
841 return jsResult;
842 }
843
JSGetHeight(napi_env env,napi_callback_info info)844 napi_value FileAssetNapi::JSGetHeight(napi_env env, napi_callback_info info)
845 {
846 napi_status status;
847 napi_value jsResult = nullptr;
848 FileAssetNapi *obj = nullptr;
849 int32_t height;
850 napi_value thisVar = nullptr;
851
852 napi_get_undefined(env, &jsResult);
853 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
854 if (status != napi_ok || thisVar == nullptr) {
855 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
856 return jsResult;
857 }
858
859 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
860 if (status == napi_ok && obj != nullptr) {
861 height = obj->fileAssetPtr->GetHeight();
862 napi_create_int32(env, height, &jsResult);
863 }
864
865 return jsResult;
866 }
867
JSGetRelativePath(napi_env env,napi_callback_info info)868 napi_value FileAssetNapi::JSGetRelativePath(napi_env env, napi_callback_info info)
869 {
870 napi_status status;
871 napi_value jsResult = nullptr;
872 FileAssetNapi *obj = nullptr;
873 string relativePath = "";
874 napi_value thisVar = nullptr;
875
876 napi_get_undefined(env, &jsResult);
877 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
878 if (status != napi_ok || thisVar == nullptr) {
879 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
880 return jsResult;
881 }
882
883 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
884 if (status == napi_ok && obj != nullptr) {
885 relativePath = obj->GetRelativePath();
886 napi_create_string_utf8(env, relativePath.c_str(), NAPI_AUTO_LENGTH, &jsResult);
887 }
888
889 return jsResult;
890 }
891
JSSetRelativePath(napi_env env,napi_callback_info info)892 napi_value FileAssetNapi::JSSetRelativePath(napi_env env, napi_callback_info info)
893 {
894 napi_status status;
895 napi_value undefinedResult = nullptr;
896 FileAssetNapi *obj = nullptr;
897 napi_valuetype valueType = napi_undefined;
898 size_t res = 0;
899 char buffer[ARG_BUF_SIZE];
900 size_t argc = ARGS_ONE;
901 napi_value argv[ARGS_ONE] = {0};
902 napi_value thisVar = nullptr;
903 napi_get_undefined(env, &undefinedResult);
904 GET_JS_ARGS(env, info, argc, argv, thisVar);
905 NAPI_ASSERT(env, argc == ARGS_ONE, "requires 1 parameter");
906 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
907 if (status == napi_ok && obj != nullptr) {
908 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
909 NAPI_ERR_LOG("Invalid arguments type! valueType: %{public}d", valueType);
910 return undefinedResult;
911 }
912 status = napi_get_value_string_utf8(env, argv[PARAM0], buffer, ARG_BUF_SIZE, &res);
913 if (status == napi_ok) {
914 obj->fileAssetPtr->SetRelativePath(string(buffer));
915 }
916 }
917 return undefinedResult;
918 }
JSGetAlbum(napi_env env,napi_callback_info info)919 napi_value FileAssetNapi::JSGetAlbum(napi_env env, napi_callback_info info)
920 {
921 napi_status status;
922 napi_value jsResult = nullptr;
923 FileAssetNapi *obj = nullptr;
924 string album = "";
925 napi_value thisVar = nullptr;
926
927 napi_get_undefined(env, &jsResult);
928 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
929 if (status != napi_ok || thisVar == nullptr) {
930 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
931 return jsResult;
932 }
933
934 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
935 if (status == napi_ok && obj != nullptr) {
936 album = obj->fileAssetPtr->GetAlbum();
937 napi_create_string_utf8(env, album.c_str(), NAPI_AUTO_LENGTH, &jsResult);
938 }
939
940 return jsResult;
941 }
942
JSGetArtist(napi_env env,napi_callback_info info)943 napi_value FileAssetNapi::JSGetArtist(napi_env env, napi_callback_info info)
944 {
945 napi_status status;
946 napi_value jsResult = nullptr;
947 FileAssetNapi *obj = nullptr;
948 string artist = "";
949 napi_value thisVar = nullptr;
950
951 napi_get_undefined(env, &jsResult);
952 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
953 if (status != napi_ok || thisVar == nullptr) {
954 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
955 return jsResult;
956 }
957
958 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
959 if (status == napi_ok && obj != nullptr) {
960 artist = obj->fileAssetPtr->GetArtist();
961 napi_create_string_utf8(env, artist.c_str(), NAPI_AUTO_LENGTH, &jsResult);
962 }
963
964 return jsResult;
965 }
966
JSGetDuration(napi_env env,napi_callback_info info)967 napi_value FileAssetNapi::JSGetDuration(napi_env env, napi_callback_info info)
968 {
969 napi_status status;
970 napi_value jsResult = nullptr;
971 FileAssetNapi *obj = nullptr;
972 int32_t duration;
973 napi_value thisVar = nullptr;
974
975 napi_get_undefined(env, &jsResult);
976 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
977 if (status != napi_ok || thisVar == nullptr) {
978 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
979 return jsResult;
980 }
981
982 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
983 if (status == napi_ok && obj != nullptr) {
984 duration = obj->fileAssetPtr->GetDuration();
985 napi_create_int32(env, duration, &jsResult);
986 }
987
988 return jsResult;
989 }
990
JSParent(napi_env env,napi_callback_info info)991 napi_value FileAssetNapi::JSParent(napi_env env, napi_callback_info info)
992 {
993 napi_status status;
994 napi_value jsResult = nullptr;
995 FileAssetNapi *obj = nullptr;
996 int32_t parent;
997 napi_value thisVar = nullptr;
998 napi_get_undefined(env, &jsResult);
999 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
1000 if (status != napi_ok || thisVar == nullptr) {
1001 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
1002 return jsResult;
1003 }
1004 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1005 if (status == napi_ok && obj != nullptr) {
1006 parent = obj->fileAssetPtr->GetParent();
1007 napi_create_int32(env, parent, &jsResult);
1008 }
1009 return jsResult;
1010 }
JSGetAlbumUri(napi_env env,napi_callback_info info)1011 napi_value FileAssetNapi::JSGetAlbumUri(napi_env env, napi_callback_info info)
1012 {
1013 napi_status status;
1014 napi_value jsResult = nullptr;
1015 FileAssetNapi *obj = nullptr;
1016 string albumUri = "";
1017 napi_value thisVar = nullptr;
1018 napi_get_undefined(env, &jsResult);
1019 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
1020 if (status != napi_ok || thisVar == nullptr) {
1021 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
1022 return jsResult;
1023 }
1024 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1025 if (status == napi_ok && obj != nullptr) {
1026 albumUri = obj->fileAssetPtr->GetAlbumUri();
1027 napi_create_string_utf8(env, albumUri.c_str(), NAPI_AUTO_LENGTH, &jsResult);
1028 }
1029 return jsResult;
1030 }
JSGetDateTaken(napi_env env,napi_callback_info info)1031 napi_value FileAssetNapi::JSGetDateTaken(napi_env env, napi_callback_info info)
1032 {
1033 napi_status status;
1034 napi_value jsResult = nullptr;
1035 FileAssetNapi *obj = nullptr;
1036 int64_t dateTaken;
1037 napi_value thisVar = nullptr;
1038 napi_get_undefined(env, &jsResult);
1039 GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
1040 if (status != napi_ok || thisVar == nullptr) {
1041 NAPI_ERR_LOG("Invalid arguments! status: %{public}d", status);
1042 return jsResult;
1043 }
1044 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1045 if (status == napi_ok && obj != nullptr) {
1046 dateTaken = obj->fileAssetPtr->GetDateTaken();
1047 napi_create_int64(env, dateTaken, &jsResult);
1048 }
1049 return jsResult;
1050 }
1051
BuildCommitModifyValuesBucket(FileAssetAsyncContext * context,DataShareValuesBucket & valuesBucket)1052 void BuildCommitModifyValuesBucket(FileAssetAsyncContext* context, DataShareValuesBucket &valuesBucket)
1053 {
1054 const auto fileAsset = context->objectPtr;
1055 if (context->resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
1056 valuesBucket.Put(MediaColumn::MEDIA_TITLE, fileAsset->GetTitle());
1057 } else if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
1058 valuesBucket.Put(MediaColumn::MEDIA_NAME, fileAsset->GetDisplayName());
1059 } else {
1060 #ifdef MEDIALIBRARY_COMPATIBILITY
1061 valuesBucket.Put(MEDIA_DATA_DB_TITLE, fileAsset->GetTitle());
1062 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, fileAsset->GetRelativePath());
1063 if (fileAsset->GetMediaType() != MediaType::MEDIA_TYPE_AUDIO) {
1064 // IMAGE, VIDEO AND FILES
1065 if (fileAsset->GetOrientation() >= 0) {
1066 valuesBucket.Put(MEDIA_DATA_DB_ORIENTATION, fileAsset->GetOrientation());
1067 }
1068 if ((fileAsset->GetMediaType() != MediaType::MEDIA_TYPE_IMAGE) &&
1069 (fileAsset->GetMediaType() != MediaType::MEDIA_TYPE_VIDEO)) {
1070 // ONLY FILES
1071 valuesBucket.Put(MEDIA_DATA_DB_URI, fileAsset->GetUri());
1072 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, fileAsset->GetMediaType());
1073 }
1074 }
1075 #else
1076 valuesBucket.Put(MEDIA_DATA_DB_URI, fileAsset->GetUri());
1077 valuesBucket.Put(MEDIA_DATA_DB_TITLE, fileAsset->GetTitle());
1078
1079 if (fileAsset->GetOrientation() >= 0) {
1080 valuesBucket.Put(MEDIA_DATA_DB_ORIENTATION, fileAsset->GetOrientation());
1081 }
1082 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, fileAsset->GetRelativePath());
1083 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, fileAsset->GetMediaType());
1084 #endif
1085 valuesBucket.Put(MEDIA_DATA_DB_NAME, fileAsset->GetDisplayName());
1086 }
1087 }
1088
1089 #ifdef MEDIALIBRARY_COMPATIBILITY
BuildCommitModifyUriApi9(FileAssetAsyncContext * context,string & uri)1090 static void BuildCommitModifyUriApi9(FileAssetAsyncContext *context, string &uri)
1091 {
1092 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
1093 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
1094 uri = URI_UPDATE_PHOTO;
1095 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
1096 uri = URI_UPDATE_AUDIO;
1097 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_FILE) {
1098 uri = URI_UPDATE_FILE;
1099 }
1100 }
1101 #endif
1102
BuildCommitModifyUriApi10(FileAssetAsyncContext * context,string & uri)1103 static void BuildCommitModifyUriApi10(FileAssetAsyncContext *context, string &uri)
1104 {
1105 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
1106 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
1107 uri = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) ? UFM_UPDATE_PHOTO : PAH_UPDATE_PHOTO;
1108 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
1109 uri = UFM_UPDATE_AUDIO;
1110 }
1111 }
1112
CheckDisplayNameInCommitModify(FileAssetAsyncContext * context)1113 static bool CheckDisplayNameInCommitModify(FileAssetAsyncContext *context)
1114 {
1115 if (context->resultNapiType != ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
1116 if (context->objectPtr->GetMediaType() != MediaType::MEDIA_TYPE_FILE) {
1117 if (MediaFileUtils::CheckDisplayName(context->objectPtr->GetDisplayName()) != E_OK) {
1118 context->error = JS_E_DISPLAYNAME;
1119 return false;
1120 }
1121 } else {
1122 if (MediaFileUtils::CheckFileDisplayName(context->objectPtr->GetDisplayName()) != E_OK) {
1123 context->error = JS_E_DISPLAYNAME;
1124 return false;
1125 }
1126 }
1127 }
1128 return true;
1129 }
1130
JSCommitModifyExecute(napi_env env,void * data)1131 static void JSCommitModifyExecute(napi_env env, void *data)
1132 {
1133 auto *context = static_cast<FileAssetAsyncContext*>(data);
1134 MediaLibraryTracer tracer;
1135 tracer.Start("JSCommitModifyExecute");
1136 if (!CheckDisplayNameInCommitModify(context)) {
1137 return;
1138 }
1139 string uri;
1140 if (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR ||
1141 context->resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
1142 BuildCommitModifyUriApi10(context, uri);
1143 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
1144 } else {
1145 #ifdef MEDIALIBRARY_COMPATIBILITY
1146 BuildCommitModifyUriApi9(context, uri);
1147 #else
1148 uri = URI_UPDATE_FILE;
1149 #endif
1150 }
1151
1152 Uri updateAssetUri(uri);
1153 MediaType mediaType = context->objectPtr->GetMediaType();
1154 string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
1155 DataSharePredicates predicates;
1156 DataShareValuesBucket valuesBucket;
1157 BuildCommitModifyValuesBucket(context, valuesBucket);
1158 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
1159 predicates.SetWhereArgs({std::to_string(context->objectPtr->GetId())});
1160
1161 int32_t changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
1162 if (changedRows < 0) {
1163 context->SaveError(changedRows);
1164 NAPI_ERR_LOG("File asset modification failed, err: %{public}d", changedRows);
1165 } else {
1166 context->changedRows = changedRows;
1167 Uri modifyNotify(notifyUri);
1168 UserFileClient::NotifyChange(modifyNotify);
1169 }
1170 }
1171
JSCommitModifyCompleteCallback(napi_env env,napi_status status,void * data)1172 static void JSCommitModifyCompleteCallback(napi_env env, napi_status status, void *data)
1173 {
1174 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1175 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1176 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1177 jsContext->status = false;
1178
1179 MediaLibraryTracer tracer;
1180 tracer.Start("JSCommitModifyCompleteCallback");
1181
1182 if (context->error == ERR_DEFAULT) {
1183 if (context->changedRows < 0) {
1184 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
1185 "File asset modification failed");
1186 napi_get_undefined(env, &jsContext->data);
1187 } else {
1188 napi_create_int32(env, context->changedRows, &jsContext->data);
1189 jsContext->status = true;
1190 napi_get_undefined(env, &jsContext->error);
1191 }
1192 } else {
1193 NAPI_ERR_LOG("JSCommitModify fail %{public}d", context->error);
1194 context->HandleError(env, jsContext->error);
1195 napi_get_undefined(env, &jsContext->data);
1196 }
1197 tracer.Finish();
1198 if (context->work != nullptr) {
1199 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1200 context->work, *jsContext);
1201 }
1202 delete context;
1203 }
GetJSArgsForCommitModify(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1204 napi_value GetJSArgsForCommitModify(napi_env env, size_t argc, const napi_value argv[],
1205 FileAssetAsyncContext &asyncContext)
1206 {
1207 const int32_t refCount = 1;
1208 napi_value result = nullptr;
1209 auto context = &asyncContext;
1210 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1211 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1212 for (size_t i = PARAM0; i < argc; i++) {
1213 napi_valuetype valueType = napi_undefined;
1214 napi_typeof(env, argv[i], &valueType);
1215 if (i == PARAM0 && valueType == napi_function) {
1216 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1217 break;
1218 } else {
1219 NAPI_ASSERT(env, false, "type mismatch");
1220 }
1221 }
1222 napi_get_boolean(env, true, &result);
1223 return result;
1224 }
1225
JSCommitModify(napi_env env,napi_callback_info info)1226 napi_value FileAssetNapi::JSCommitModify(napi_env env, napi_callback_info info)
1227 {
1228 napi_status status;
1229 napi_value result = nullptr;
1230 size_t argc = ARGS_ONE;
1231 napi_value argv[ARGS_ONE] = {0};
1232 napi_value thisVar = nullptr;
1233 MediaLibraryTracer tracer;
1234 tracer.Start("JSCommitModify");
1235
1236 GET_JS_ARGS(env, info, argc, argv, thisVar);
1237 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameters maximum");
1238 napi_get_undefined(env, &result);
1239
1240 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1241 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1242 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
1243 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1244 result = GetJSArgsForCommitModify(env, argc, argv, *asyncContext);
1245 ASSERT_NULLPTR_CHECK(env, result);
1246 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1247 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1248
1249 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCommitModify", JSCommitModifyExecute,
1250 JSCommitModifyCompleteCallback);
1251 }
1252
1253 return result;
1254 }
1255
JSOpenExecute(napi_env env,void * data)1256 static void JSOpenExecute(napi_env env, void *data)
1257 {
1258 MediaLibraryTracer tracer;
1259 tracer.Start("JSOpenExecute");
1260
1261 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1262 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1263
1264 bool isValid = false;
1265 string mode = context->valuesBucket.Get(MEDIA_FILEMODE, isValid);
1266 if (!isValid) {
1267 context->error = ERR_INVALID_OUTPUT;
1268 NAPI_ERR_LOG("getting mode invalid");
1269 return;
1270 }
1271 transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
1272
1273 string fileUri = context->objectPtr->GetUri();
1274 Uri openFileUri(fileUri);
1275 int32_t retVal = UserFileClient::OpenFile(openFileUri, mode);
1276 if (retVal <= 0) {
1277 context->SaveError(retVal);
1278 NAPI_ERR_LOG("File open asset failed, ret: %{public}d", retVal);
1279 } else {
1280 context->fd = retVal;
1281 if (mode.find('w') != string::npos) {
1282 context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_WRITE);
1283 } else {
1284 context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_READONLY);
1285 }
1286 }
1287 }
1288
JSOpenCompleteCallback(napi_env env,napi_status status,void * data)1289 static void JSOpenCompleteCallback(napi_env env, napi_status status, void *data)
1290 {
1291 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1292 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1293
1294 MediaLibraryTracer tracer;
1295 tracer.Start("JSOpenCompleteCallback");
1296
1297 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1298 jsContext->status = false;
1299
1300 if (context->error == ERR_DEFAULT) {
1301 NAPI_DEBUG_LOG("return fd = %{public}d", context->fd);
1302 napi_create_int32(env, context->fd, &jsContext->data);
1303 napi_get_undefined(env, &jsContext->error);
1304 jsContext->status = true;
1305 } else {
1306 context->HandleError(env, jsContext->error);
1307 napi_get_undefined(env, &jsContext->data);
1308 }
1309
1310 tracer.Finish();
1311 if (context->work != nullptr) {
1312 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1313 context->work, *jsContext);
1314 }
1315
1316 delete context;
1317 }
1318
GetJSArgsForOpen(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1319 napi_value GetJSArgsForOpen(napi_env env, size_t argc, const napi_value argv[],
1320 FileAssetAsyncContext &asyncContext)
1321 {
1322 const int32_t refCount = 1;
1323 napi_value result = nullptr;
1324 auto context = &asyncContext;
1325 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1326 size_t res = 0;
1327 char buffer[ARG_BUF_SIZE];
1328
1329 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1330
1331 for (size_t i = PARAM0; i < argc; i++) {
1332 napi_valuetype valueType = napi_undefined;
1333 napi_typeof(env, argv[i], &valueType);
1334
1335 if (i == PARAM0 && valueType == napi_string) {
1336 napi_get_value_string_utf8(env, argv[i], buffer, ARG_BUF_SIZE, &res);
1337 } else if (i == PARAM1 && valueType == napi_function) {
1338 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1339 break;
1340 } else {
1341 NAPI_ASSERT(env, false, "type mismatch");
1342 }
1343 }
1344 context->valuesBucket.Put(MEDIA_FILEMODE, string(buffer));
1345 // Return true napi_value if params are successfully obtained
1346 napi_get_boolean(env, true, &result);
1347 return result;
1348 }
1349
JSOpen(napi_env env,napi_callback_info info)1350 napi_value FileAssetNapi::JSOpen(napi_env env, napi_callback_info info)
1351 {
1352 napi_status status;
1353 napi_value result = nullptr;
1354 size_t argc = ARGS_TWO;
1355 napi_value argv[ARGS_TWO] = {0};
1356 napi_value thisVar = nullptr;
1357
1358 MediaLibraryTracer tracer;
1359 tracer.Start("JSOpen");
1360
1361 GET_JS_ARGS(env, info, argc, argv, thisVar);
1362 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
1363 napi_get_undefined(env, &result);
1364
1365 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1366 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1367 if ((status == napi_ok) && (asyncContext->objectInfo != nullptr)) {
1368 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1369 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1370 result = GetJSArgsForOpen(env, argc, argv, *asyncContext);
1371 ASSERT_NULLPTR_CHECK(env, result);
1372 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSOpen", JSOpenExecute,
1373 JSOpenCompleteCallback);
1374 }
1375
1376 return result;
1377 }
1378
CheckFileOpenStatus(FileAssetAsyncContext * context,int fd)1379 static bool CheckFileOpenStatus(FileAssetAsyncContext *context, int fd)
1380 {
1381 auto fileAssetPtr = context->objectPtr;
1382 int ret = fileAssetPtr->GetOpenStatus(fd);
1383 if (ret < 0) {
1384 return false;
1385 } else {
1386 fileAssetPtr->RemoveOpenStatus(fd);
1387 if (ret == OPEN_TYPE_READONLY) {
1388 return false;
1389 } else {
1390 return true;
1391 }
1392 }
1393 }
1394
JSCloseExecute(FileAssetAsyncContext * context)1395 static void JSCloseExecute(FileAssetAsyncContext *context)
1396 {
1397 MediaLibraryTracer tracer;
1398 tracer.Start("JSCloseExecute");
1399
1400 #ifdef MEDIALIBRARY_COMPATIBILITY
1401 string closeUri;
1402 if (MediaFileUtils::IsFileTablePath(context->objectPtr->GetPath()) ||
1403 MediaFileUtils::StartsWith(context->objectPtr->GetRelativePath(), DOC_DIR_VALUES) ||
1404 MediaFileUtils::StartsWith(context->objectPtr->GetRelativePath(), DOWNLOAD_DIR_VALUES)) {
1405 closeUri = MEDIALIBRARY_DATA_URI + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CLOSEASSET;
1406 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
1407 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
1408 closeUri = URI_CLOSE_PHOTO;
1409 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
1410 closeUri = URI_CLOSE_AUDIO;
1411 } else {
1412 closeUri = URI_CLOSE_FILE;
1413 }
1414 #else
1415 string closeUri = URI_CLOSE_FILE;
1416 #endif
1417 Uri closeAssetUri(closeUri);
1418 bool isValid = false;
1419 UniqueFd unifd(context->valuesBucket.Get(MEDIA_FILEDESCRIPTOR, isValid));
1420 if (!isValid) {
1421 context->error = ERR_INVALID_OUTPUT;
1422 NAPI_ERR_LOG("getting fd is invalid");
1423 return;
1424 }
1425
1426 if (!CheckFileOpenStatus(context, unifd.Get())) {
1427 return;
1428 }
1429
1430 string fileUri = context->valuesBucket.Get(MEDIA_DATA_DB_URI, isValid);
1431 if (!isValid) {
1432 context->error = ERR_INVALID_OUTPUT;
1433 NAPI_ERR_LOG("getting file uri is invalid");
1434 return;
1435 }
1436 if (!MediaFileUtils::GetNetworkIdFromUri(fileUri).empty()) {
1437 return;
1438 }
1439
1440 auto retVal = UserFileClient::Insert(closeAssetUri, context->valuesBucket);
1441 if (retVal != E_SUCCESS) {
1442 context->SaveError(retVal);
1443 NAPI_ERR_LOG("File close asset failed %{public}d", retVal);
1444 }
1445 }
1446
JSCloseCompleteCallback(napi_env env,napi_status status,FileAssetAsyncContext * context)1447 static void JSCloseCompleteCallback(napi_env env, napi_status status,
1448 FileAssetAsyncContext *context)
1449 {
1450 MediaLibraryTracer tracer;
1451 tracer.Start("JSCloseCompleteCallback");
1452
1453 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1454 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1455 jsContext->status = false;
1456
1457 if (context->error == ERR_DEFAULT) {
1458 napi_create_int32(env, E_SUCCESS, &jsContext->data);
1459 napi_get_undefined(env, &jsContext->error);
1460 jsContext->status = true;
1461 } else {
1462 context->HandleError(env, jsContext->error);
1463 napi_get_undefined(env, &jsContext->data);
1464 }
1465
1466 tracer.Finish();
1467 if (context->work != nullptr) {
1468 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1469 context->work, *jsContext);
1470 }
1471
1472 delete context;
1473 }
1474
GetJSArgsForClose(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1475 napi_value GetJSArgsForClose(napi_env env, size_t argc, const napi_value argv[],
1476 FileAssetAsyncContext &asyncContext)
1477 {
1478 const int32_t refCount = 1;
1479 napi_value result = nullptr;
1480 auto context = &asyncContext;
1481 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1482 int32_t fd = 0;
1483
1484 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1485
1486 for (size_t i = PARAM0; i < argc; i++) {
1487 napi_valuetype valueType = napi_undefined;
1488 napi_typeof(env, argv[i], &valueType);
1489
1490 if (i == PARAM0 && valueType == napi_number) {
1491 napi_get_value_int32(env, argv[i], &fd);
1492 if (fd <= 0) {
1493 NAPI_ASSERT(env, false, "fd <= 0");
1494 }
1495 } else if (i == PARAM1 && valueType == napi_function) {
1496 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1497 break;
1498 } else {
1499 NAPI_ASSERT(env, false, "type mismatch");
1500 }
1501 }
1502 context->valuesBucket.Put(MEDIA_FILEDESCRIPTOR, fd);
1503 context->valuesBucket.Put(MEDIA_DATA_DB_URI, context->objectInfo->GetFileUri());
1504 // Return true napi_value if params are successfully obtained
1505 napi_get_boolean(env, true, &result);
1506 return result;
1507 }
1508
JSClose(napi_env env,napi_callback_info info)1509 napi_value FileAssetNapi::JSClose(napi_env env, napi_callback_info info)
1510 {
1511 napi_status status;
1512 napi_value result = nullptr;
1513 size_t argc = ARGS_TWO;
1514 napi_value argv[ARGS_TWO] = {0};
1515 napi_value thisVar = nullptr;
1516 napi_value resource = nullptr;
1517
1518 MediaLibraryTracer tracer;
1519 tracer.Start("JSClose");
1520
1521 GET_JS_ARGS(env, info, argc, argv, thisVar);
1522 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
1523 napi_get_undefined(env, &result);
1524 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1525 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1526 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1527 result = GetJSArgsForClose(env, argc, argv, *asyncContext);
1528 ASSERT_NULLPTR_CHECK(env, result);
1529 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1530 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSClose", asyncContext);
1531
1532 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1533 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1534
1535 status = napi_create_async_work(
1536 env, nullptr, resource, [](napi_env env, void *data) {
1537 auto context = static_cast<FileAssetAsyncContext*>(data);
1538 JSCloseExecute(context);
1539 },
1540 reinterpret_cast<CompleteCallback>(JSCloseCompleteCallback),
1541 static_cast<void *>(asyncContext.get()), &asyncContext->work);
1542 if (status != napi_ok) {
1543 napi_get_undefined(env, &result);
1544 } else {
1545 napi_queue_async_work(env, asyncContext->work);
1546 asyncContext.release();
1547 }
1548 }
1549
1550 return result;
1551 }
1552
OpenThumbnail(string & uriStr,const string & path,const Size & size)1553 static int OpenThumbnail(string &uriStr, const string &path, const Size &size)
1554 {
1555 if (!path.empty()) {
1556 string sandboxPath = GetSandboxPath(path, IsThumbnail(size.width, size.height));
1557 int fd = -1;
1558 if (!sandboxPath.empty()) {
1559 fd = open(sandboxPath.c_str(), O_RDONLY);
1560 }
1561 if (fd > 0) {
1562 return fd;
1563 }
1564 if (IsAsciiString(path)) {
1565 uriStr += "&" + THUMBNAIL_PATH + "=" + path;
1566 }
1567 }
1568 Uri openUri(uriStr);
1569 return UserFileClient::OpenFile(openUri, "R");
1570 }
1571
QueryThumbnail(const std::string & uri,Size & size,const bool isApiVersion10,const string & path)1572 static unique_ptr<PixelMap> QueryThumbnail(const std::string &uri, Size &size,
1573 const bool isApiVersion10, const string &path)
1574 {
1575 MediaLibraryTracer tracer;
1576 tracer.Start("QueryThumbnail uri:" + uri);
1577
1578 string openUriStr = uri + "?" + MEDIA_OPERN_KEYWORD + "=" + MEDIA_DATA_DB_THUMBNAIL + "&" + MEDIA_DATA_DB_WIDTH +
1579 "=" + to_string(size.width) + "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(size.height);
1580 if (isApiVersion10) {
1581 MediaLibraryNapiUtils::UriAppendKeyValue(openUriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
1582 }
1583 tracer.Start("DataShare::OpenFile");
1584 UniqueFd uniqueFd(OpenThumbnail(openUriStr, path, size));
1585 if (uniqueFd.Get() < 0) {
1586 NAPI_ERR_LOG("queryThumb is null, errCode is %{public}d", uniqueFd.Get());
1587 return nullptr;
1588 }
1589 tracer.Finish();
1590 tracer.Start("ImageSource::CreateImageSource");
1591 SourceOptions opts;
1592 uint32_t err = 0;
1593 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err);
1594 if (imageSource == nullptr) {
1595 NAPI_ERR_LOG("CreateImageSource err %{public}d", err);
1596 return nullptr;
1597 }
1598
1599 DecodeOptions decodeOpts;
1600 decodeOpts.desiredSize = size;
1601 decodeOpts.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
1602 #ifndef IMAGE_PURGEABLE_PIXELMAP
1603 return imageSource->CreatePixelMap(decodeOpts, err);
1604 #else
1605 unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
1606 PurgeableBuilder::MakePixelMapToBePurgeable(pixelMap, uniqueFd.Get(), opts, decodeOpts);
1607 return pixelMap;
1608 #endif
1609 }
1610
JSGetThumbnailExecute(FileAssetAsyncContext * context)1611 static void JSGetThumbnailExecute(FileAssetAsyncContext* context)
1612 {
1613 MediaLibraryTracer tracer;
1614 tracer.Start("JSGetThumbnailExecute");
1615
1616 Size size = { .width = context->thumbWidth, .height = context->thumbHeight };
1617 bool isApiVersion10 = (context->resultNapiType == ResultNapiType::TYPE_USERFILE_MGR ||
1618 context->resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER);
1619 string path = context->objectPtr->GetPath();
1620 #ifndef MEDIALIBRARY_COMPATIBILITY
1621 if (path.empty()
1622 && !context->objectPtr->GetRelativePath().empty() && !context->objectPtr->GetDisplayName().empty()) {
1623 path = ROOT_MEDIA_DIR + context->objectPtr->GetRelativePath() + context->objectPtr->GetDisplayName();
1624 }
1625 #endif
1626 context->pixelmap = QueryThumbnail(context->objectPtr->GetUri(), size, isApiVersion10, path);
1627 }
1628
JSGetThumbnailCompleteCallback(napi_env env,napi_status status,FileAssetAsyncContext * context)1629 static void JSGetThumbnailCompleteCallback(napi_env env, napi_status status,
1630 FileAssetAsyncContext* context)
1631 {
1632 MediaLibraryTracer tracer;
1633 tracer.Start("JSGetThumbnailCompleteCallback");
1634
1635 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1636
1637 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1638 jsContext->status = false;
1639
1640 if (context->error == ERR_DEFAULT) {
1641 if (context->pixelmap != nullptr) {
1642 jsContext->data = Media::PixelMapNapi::CreatePixelMap(env, context->pixelmap);
1643 napi_get_undefined(env, &jsContext->error);
1644 jsContext->status = true;
1645 } else {
1646 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1647 "Get thumbnail failed");
1648 napi_get_undefined(env, &jsContext->data);
1649 }
1650 } else {
1651 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1652 "Ability helper or thumbnail helper is null");
1653 napi_get_undefined(env, &jsContext->data);
1654 }
1655
1656 tracer.Finish();
1657 if (context->work != nullptr) {
1658 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1659 context->work, *jsContext);
1660 }
1661
1662 delete context;
1663 }
1664
GetSizeInfo(napi_env env,napi_value configObj,std::string type,int32_t & result)1665 static void GetSizeInfo(napi_env env, napi_value configObj, std::string type, int32_t &result)
1666 {
1667 napi_value item = nullptr;
1668 bool exist = false;
1669 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
1670 if (status != napi_ok || !exist) {
1671 NAPI_ERR_LOG("can not find named property, status: %{public}d", status);
1672 return;
1673 }
1674
1675 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
1676 NAPI_ERR_LOG("get named property fail");
1677 return;
1678 }
1679
1680 if (napi_get_value_int32(env, item, &result) != napi_ok) {
1681 NAPI_ERR_LOG("get property value fail");
1682 }
1683 }
1684
GetJSArgsForGetThumbnail(napi_env env,size_t argc,const napi_value argv[],unique_ptr<FileAssetAsyncContext> & asyncContext)1685 napi_value GetJSArgsForGetThumbnail(napi_env env, size_t argc, const napi_value argv[],
1686 unique_ptr<FileAssetAsyncContext> &asyncContext)
1687 {
1688 asyncContext->thumbWidth = DEFAULT_THUMB_SIZE;
1689 asyncContext->thumbHeight = DEFAULT_THUMB_SIZE;
1690
1691 if (argc == ARGS_ONE) {
1692 napi_valuetype valueType = napi_undefined;
1693 if (napi_typeof(env, argv[PARAM0], &valueType) == napi_ok &&
1694 (valueType == napi_undefined || valueType == napi_null)) {
1695 argc -= 1;
1696 }
1697 }
1698
1699 for (size_t i = PARAM0; i < argc; i++) {
1700 napi_valuetype valueType = napi_undefined;
1701 napi_typeof(env, argv[i], &valueType);
1702
1703 if (i == PARAM0 && valueType == napi_object) {
1704 GetSizeInfo(env, argv[PARAM0], "width", asyncContext->thumbWidth);
1705 GetSizeInfo(env, argv[PARAM0], "height", asyncContext->thumbHeight);
1706 } else if (i == PARAM0 && valueType == napi_function) {
1707 napi_create_reference(env, argv[i], NAPI_INIT_REF_COUNT, &asyncContext->callbackRef);
1708 break;
1709 } else if (i == PARAM1 && valueType == napi_function) {
1710 napi_create_reference(env, argv[i], NAPI_INIT_REF_COUNT, &asyncContext->callbackRef);
1711 break;
1712 } else {
1713 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Invalid parameter type");
1714 return nullptr;
1715 }
1716 }
1717
1718 napi_value result = nullptr;
1719 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1720 return result;
1721 }
1722
JSGetThumbnail(napi_env env,napi_callback_info info)1723 napi_value FileAssetNapi::JSGetThumbnail(napi_env env, napi_callback_info info)
1724 {
1725 napi_status status;
1726 napi_value result = nullptr;
1727 size_t argc = ARGS_TWO;
1728 napi_value argv[ARGS_TWO] = {0};
1729 napi_value thisVar = nullptr;
1730 napi_value resource = nullptr;
1731
1732 MediaLibraryTracer tracer;
1733 tracer.Start("JSGetThumbnail");
1734
1735 GET_JS_ARGS(env, info, argc, argv, thisVar);
1736 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE || argc == ARGS_TWO),
1737 "requires 2 parameters maximum");
1738 napi_get_undefined(env, &result);
1739 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1740 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1741 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1742 result = GetJSArgsForGetThumbnail(env, argc, argv, asyncContext);
1743 CHECK_NULLPTR_RET(result);
1744 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1745 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetThumbnail", asyncContext);
1746 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1747 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1748
1749 status = napi_create_async_work(
1750 env, nullptr, resource, [](napi_env env, void *data) {
1751 auto context = static_cast<FileAssetAsyncContext*>(data);
1752 JSGetThumbnailExecute(context);
1753 },
1754 reinterpret_cast<CompleteCallback>(JSGetThumbnailCompleteCallback),
1755 static_cast<void *>(asyncContext.get()), &asyncContext->work);
1756 if (status != napi_ok) {
1757 napi_get_undefined(env, &result);
1758 } else {
1759 napi_queue_async_work(env, asyncContext->work);
1760 asyncContext.release();
1761 }
1762 }
1763
1764 return result;
1765 }
1766
JSFavoriteCallbackComplete(napi_env env,napi_status status,void * data)1767 static void JSFavoriteCallbackComplete(napi_env env, napi_status status, void *data)
1768 {
1769 MediaLibraryTracer tracer;
1770 tracer.Start("JSFavoriteCallbackComplete");
1771
1772 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
1773 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1774 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1775 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1776 jsContext->status = false;
1777 napi_get_undefined(env, &jsContext->data);
1778 if (context->error == ERR_DEFAULT) {
1779 jsContext->status = true;
1780 Media::MediaType mediaType = context->objectPtr->GetMediaType();
1781 string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
1782 Uri modifyNotify(notifyUri);
1783 UserFileClient::NotifyChange(modifyNotify);
1784 } else {
1785 context->HandleError(env, jsContext->error);
1786 napi_get_undefined(env, &jsContext->data);
1787 }
1788
1789 tracer.Finish();
1790 if (context->work != nullptr) {
1791 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1792 context->work, *jsContext);
1793 }
1794
1795 delete context;
1796 }
1797
GetIsDirectoryiteNative(napi_env env,const FileAssetAsyncContext & fileContext)1798 static bool GetIsDirectoryiteNative(napi_env env, const FileAssetAsyncContext &fileContext)
1799 {
1800 MediaLibraryTracer tracer;
1801 tracer.Start("GetIsDirectoryiteNative");
1802
1803 FileAssetAsyncContext *context = const_cast<FileAssetAsyncContext *>(&fileContext);
1804 if (context == nullptr) {
1805 NAPI_ERR_LOG("Async context is null");
1806 return false;
1807 }
1808
1809 #ifdef MEDIALIBRARY_COMPATIBILITY
1810 if ((context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_AUDIO) ||
1811 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_IMAGE) ||
1812 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_VIDEO)) {
1813 context->status = true;
1814 return false;
1815 }
1816
1817 int64_t virtualId = MediaFileUtils::GetVirtualIdByType(context->objectPtr->GetId(), MediaType::MEDIA_TYPE_FILE);
1818 vector<string> selectionArgs = { to_string(virtualId) };
1819 #else
1820 vector<string> selectionArgs = { to_string(context->objectPtr->GetId()) };
1821 #endif
1822 vector<string> columns = { MEDIA_DATA_DB_MEDIA_TYPE };
1823 DataSharePredicates predicates;
1824 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ?");
1825 predicates.SetWhereArgs(selectionArgs);
1826 string queryUri = MEDIALIBRARY_DATA_URI;
1827 Uri uri(queryUri);
1828 int errCode = 0;
1829 shared_ptr<DataShare::DataShareResultSet> resultSet = UserFileClient::Query(uri, predicates, columns, errCode);
1830 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1831 NAPI_ERR_LOG("Query IsDirectory failed");
1832 return false;
1833 }
1834 int32_t index = 0;
1835 if (resultSet->GetColumnIndex(MEDIA_DATA_DB_MEDIA_TYPE, index) != NativeRdb::E_OK) {
1836 NAPI_ERR_LOG("Query Directory failed");
1837 return false;
1838 }
1839 int32_t mediaType = 0;
1840 if (resultSet->GetInt(index, mediaType) != NativeRdb::E_OK) {
1841 NAPI_ERR_LOG("Can not get file path");
1842 return false;
1843 }
1844 context->status = true;
1845 return mediaType == static_cast<int>(MediaType::MEDIA_TYPE_ALBUM);
1846 }
1847
JSIsDirectoryCallbackComplete(napi_env env,napi_status status,FileAssetAsyncContext * context)1848 static void JSIsDirectoryCallbackComplete(napi_env env, napi_status status,
1849 FileAssetAsyncContext* context)
1850 {
1851 MediaLibraryTracer tracer;
1852 tracer.Start("JSIsDirectoryCallbackComplete");
1853
1854 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1855 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1856 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1857 jsContext->status = false;
1858
1859 if (context->status) {
1860 napi_get_boolean(env, context->isDirectory, &jsContext->data);
1861 napi_get_undefined(env, &jsContext->error);
1862 jsContext->status = true;
1863 } else {
1864 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
1865 "UserFileClient is invalid");
1866 napi_get_undefined(env, &jsContext->data);
1867 }
1868
1869 tracer.Finish();
1870 if (context->work != nullptr) {
1871 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1872 context->work, *jsContext);
1873 }
1874
1875 delete context;
1876 }
1877
GetJSArgsForIsDirectory(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1878 static napi_value GetJSArgsForIsDirectory(napi_env env, size_t argc, const napi_value argv[],
1879 FileAssetAsyncContext &asyncContext)
1880 {
1881 const int32_t refCount = 1;
1882 napi_value result;
1883 auto context = &asyncContext;
1884 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1885 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1886 for (size_t i = PARAM0; i < argc; i++) {
1887 napi_valuetype valueType = napi_undefined;
1888 napi_typeof(env, argv[i], &valueType);
1889 if (i == PARAM0 && valueType == napi_function) {
1890 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1891 break;
1892 } else {
1893 NAPI_ASSERT(env, false, "type mismatch");
1894 }
1895 }
1896 napi_get_boolean(env, true, &result);
1897 return result;
1898 }
1899
JSIsDirectory(napi_env env,napi_callback_info info)1900 napi_value FileAssetNapi::JSIsDirectory(napi_env env, napi_callback_info info)
1901 {
1902 size_t argc = ARGS_ONE;
1903 napi_value argv[ARGS_ONE] = {0};
1904 napi_value thisVar = nullptr;
1905 napi_value resource = nullptr;
1906
1907 MediaLibraryTracer tracer;
1908 tracer.Start("JSisDirectory");
1909
1910 GET_JS_ARGS(env, info, argc, argv, thisVar);
1911 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 2 parameters maximum");
1912 napi_value result = nullptr;
1913 napi_get_undefined(env, &result);
1914 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
1915 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
1916 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1917 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1918 result = GetJSArgsForIsDirectory(env, argc, argv, *asyncContext);
1919 ASSERT_NULLPTR_CHECK(env, result);
1920 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1921 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSIsDirectory", asyncContext);
1922 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
1923 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
1924 status = napi_create_async_work(env, nullptr, resource, [](napi_env env, void *data) {
1925 FileAssetAsyncContext* context = static_cast<FileAssetAsyncContext*>(data);
1926 context->status = false;
1927 context->isDirectory = GetIsDirectoryiteNative(env, *context);
1928 },
1929 reinterpret_cast<CompleteCallback>(JSIsDirectoryCallbackComplete),
1930 static_cast<void *>(asyncContext.get()), &asyncContext->work);
1931 if (status != napi_ok) {
1932 napi_get_undefined(env, &result);
1933 } else {
1934 napi_queue_async_work(env, asyncContext->work);
1935 asyncContext.release();
1936 }
1937 }
1938 return result;
1939 }
1940
JSIsFavoriteExecute(FileAssetAsyncContext * context)1941 static void JSIsFavoriteExecute(FileAssetAsyncContext* context)
1942 {
1943 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1944 context->isFavorite = context->objectPtr->IsFavorite();
1945 return;
1946 }
1947
JSIsFavoriteCallbackComplete(napi_env env,napi_status status,FileAssetAsyncContext * context)1948 static void JSIsFavoriteCallbackComplete(napi_env env, napi_status status,
1949 FileAssetAsyncContext* context)
1950 {
1951 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1952 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1953 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
1954 jsContext->status = false;
1955 if (context->error == ERR_DEFAULT) {
1956 napi_get_boolean(env, context->isFavorite, &jsContext->data);
1957 napi_get_undefined(env, &jsContext->error);
1958 jsContext->status = true;
1959 } else {
1960 NAPI_ERR_LOG("Get IsFavorite failed, ret: %{public}d", context->error);
1961 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->error,
1962 "UserFileClient is invalid");
1963 napi_get_undefined(env, &jsContext->data);
1964 }
1965 if (context->work != nullptr) {
1966 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1967 context->work, *jsContext);
1968 }
1969 delete context;
1970 }
1971
GetJSArgsForFavorite(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)1972 napi_value GetJSArgsForFavorite(napi_env env, size_t argc, const napi_value argv[],
1973 FileAssetAsyncContext &asyncContext)
1974 {
1975 const int32_t refCount = 1;
1976 napi_value result = nullptr;
1977 auto context = &asyncContext;
1978 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
1979 bool isFavorite = false;
1980 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
1981 for (size_t i = PARAM0; i < argc; i++) {
1982 napi_valuetype valueType = napi_undefined;
1983 napi_typeof(env, argv[i], &valueType);
1984 if (i == PARAM0 && valueType == napi_boolean) {
1985 napi_get_value_bool(env, argv[i], &isFavorite);
1986 } else if (i == PARAM1 && valueType == napi_function) {
1987 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
1988 break;
1989 } else {
1990 NAPI_ASSERT(env, false, "type mismatch");
1991 }
1992 }
1993 context->isFavorite = isFavorite;
1994 napi_get_boolean(env, true, &result);
1995 return result;
1996 }
1997
1998 #ifdef MEDIALIBRARY_COMPATIBILITY
FavoriteByUpdate(FileAssetAsyncContext * context)1999 static void FavoriteByUpdate(FileAssetAsyncContext *context)
2000 {
2001 DataShareValuesBucket valuesBucket;
2002 string uriString;
2003 if ((context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_IMAGE) ||
2004 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_VIDEO)) {
2005 uriString = URI_UPDATE_PHOTO;
2006 } else {
2007 uriString = URI_UPDATE_AUDIO;
2008 }
2009 valuesBucket.Put(MEDIA_DATA_DB_IS_FAV, (context->isFavorite ? IS_FAV : NOT_FAV));
2010 DataSharePredicates predicates;
2011 int32_t fileId = context->objectPtr->GetId();
2012 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
2013 predicates.SetWhereArgs({ to_string(fileId) });
2014 Uri uri(uriString);
2015 context->changedRows = UserFileClient::Update(uri, predicates, valuesBucket);
2016 }
2017 #endif
2018
FavoriteByInsert(FileAssetAsyncContext * context)2019 static void FavoriteByInsert(FileAssetAsyncContext *context)
2020 {
2021 DataShareValuesBucket valuesBucket;
2022 string uriString = MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/";
2023 uriString += context->isFavorite ? MEDIA_SMARTALBUMMAPOPRN_ADDSMARTALBUM : MEDIA_SMARTALBUMMAPOPRN_REMOVESMARTALBUM;
2024 valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, FAVOURITE_ALBUM_ID_VALUES);
2025 valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, context->objectPtr->GetId());
2026 Uri uri(uriString);
2027 context->changedRows = UserFileClient::Insert(uri, valuesBucket);
2028 }
2029
JSFavouriteExecute(napi_env env,void * data)2030 static void JSFavouriteExecute(napi_env env, void *data)
2031 {
2032 MediaLibraryTracer tracer;
2033 tracer.Start("JSFavouriteExecute");
2034
2035 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2036 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2037
2038 #ifdef MEDIALIBRARY_COMPATIBILITY
2039 string uriString = MEDIALIBRARY_DATA_URI + "/";
2040 if ((context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_IMAGE) ||
2041 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_VIDEO) ||
2042 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_AUDIO)) {
2043 if (MediaFileUtils::IsFileTablePath(context->objectPtr->GetPath())) {
2044 FavoriteByInsert(context);
2045 } else {
2046 FavoriteByUpdate(context);
2047 }
2048 } else {
2049 FavoriteByInsert(context);
2050 }
2051 #else
2052 FavoriteByInsert(context);
2053 #endif
2054 if (context->changedRows >= 0) {
2055 context->objectPtr->SetFavorite(context->isFavorite);
2056 }
2057 context->SaveError(context->changedRows);
2058 }
2059
JSFavorite(napi_env env,napi_callback_info info)2060 napi_value FileAssetNapi::JSFavorite(napi_env env, napi_callback_info info)
2061 {
2062 size_t argc = ARGS_TWO;
2063 napi_value argv[ARGS_TWO] = {0};
2064 napi_value thisVar = nullptr;
2065
2066 MediaLibraryTracer tracer;
2067 tracer.Start("JSFavorite");
2068
2069 GET_JS_ARGS(env, info, argc, argv, thisVar);
2070 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
2071 napi_value result = nullptr;
2072 napi_get_undefined(env, &result);
2073
2074 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2075 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
2076 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
2077 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
2078 if ((status != napi_ok) || (asyncContext->objectInfo == nullptr)) {
2079 NAPI_DEBUG_LOG("get this Var fail");
2080 return result;
2081 }
2082
2083 result = GetJSArgsForFavorite(env, argc, argv, *asyncContext);
2084 if (asyncContext->isFavorite == asyncContext->objectInfo->IsFavorite()) {
2085 NAPI_DEBUG_LOG("favorite state is the same");
2086 return result;
2087 }
2088 ASSERT_NULLPTR_CHECK(env, result);
2089 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2090 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
2091
2092 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSFavorite", JSFavouriteExecute,
2093 JSFavoriteCallbackComplete);
2094 }
2095
GetJSArgsForIsFavorite(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)2096 static napi_value GetJSArgsForIsFavorite(napi_env env, size_t argc, const napi_value argv[],
2097 FileAssetAsyncContext &asyncContext)
2098 {
2099 const int32_t refCount = 1;
2100 napi_value result;
2101 auto context = &asyncContext;
2102 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
2103 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
2104 for (size_t i = PARAM0; i < argc; i++) {
2105 napi_valuetype valueType = napi_undefined;
2106 napi_typeof(env, argv[i], &valueType);
2107 if (i == PARAM0 && valueType == napi_function) {
2108 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
2109 break;
2110 } else {
2111 NAPI_ASSERT(env, false, "type mismatch");
2112 }
2113 }
2114 napi_get_boolean(env, true, &result);
2115 return result;
2116 }
2117
JSIsFavorite(napi_env env,napi_callback_info info)2118 napi_value FileAssetNapi::JSIsFavorite(napi_env env, napi_callback_info info)
2119 {
2120 MediaLibraryTracer tracer;
2121 tracer.Start("JSIsFavorite");
2122
2123 napi_status status;
2124 napi_value result = nullptr;
2125 size_t argc = ARGS_ONE;
2126 napi_value argv[ARGS_ONE] = {0};
2127 napi_value thisVar = nullptr;
2128 napi_value resource = nullptr;
2129 GET_JS_ARGS(env, info, argc, argv, thisVar);
2130 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameters maximum");
2131 napi_get_undefined(env, &result);
2132 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2133 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
2134 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
2135 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2136 result = GetJSArgsForIsFavorite(env, argc, argv, *asyncContext);
2137 ASSERT_NULLPTR_CHECK(env, result);
2138 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
2139 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSIsFavorite", asyncContext);
2140 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2141 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
2142
2143 status = napi_create_async_work(
2144 env, nullptr, resource, [](napi_env env, void *data) {
2145 auto context = static_cast<FileAssetAsyncContext*>(data);
2146 JSIsFavoriteExecute(context);
2147 },
2148 reinterpret_cast<CompleteCallback>(JSIsFavoriteCallbackComplete),
2149 static_cast<void *>(asyncContext.get()), &asyncContext->work);
2150 if (status != napi_ok) {
2151 napi_get_undefined(env, &result);
2152 } else {
2153 napi_queue_async_work(env, asyncContext->work);
2154 asyncContext.release();
2155 }
2156 }
2157 return result;
2158 }
2159
2160 #ifdef MEDIALIBRARY_COMPATIBILITY
TrashByUpdate(FileAssetAsyncContext * context)2161 static void TrashByUpdate(FileAssetAsyncContext *context)
2162 {
2163 DataShareValuesBucket valuesBucket;
2164 string uriString;
2165 if ((context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_IMAGE) ||
2166 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_VIDEO)) {
2167 uriString = URI_UPDATE_PHOTO;
2168 } else {
2169 uriString = URI_UPDATE_AUDIO;
2170 }
2171 valuesBucket.Put(MEDIA_DATA_DB_DATE_TRASHED, (context->isTrash ? MediaFileUtils::UTCTimeSeconds() : NOT_TRASH));
2172 DataSharePredicates predicates;
2173 int32_t fileId = context->objectPtr->GetId();
2174 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
2175 predicates.SetWhereArgs({ to_string(fileId) });
2176 Uri uri(uriString);
2177 context->changedRows = UserFileClient::Update(uri, predicates, valuesBucket);
2178 }
2179 #endif
2180
TrashByInsert(FileAssetAsyncContext * context)2181 static void TrashByInsert(FileAssetAsyncContext *context)
2182 {
2183 DataShareValuesBucket valuesBucket;
2184 string uriString = MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/";
2185 uriString += context->isTrash ? MEDIA_SMARTALBUMMAPOPRN_ADDSMARTALBUM : MEDIA_SMARTALBUMMAPOPRN_REMOVESMARTALBUM;
2186 valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, TRASH_ALBUM_ID_VALUES);
2187 valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, context->objectPtr->GetId());
2188 Uri uri(uriString);
2189 context->changedRows = UserFileClient::Insert(uri, valuesBucket);
2190 }
2191
JSTrashExecute(napi_env env,void * data)2192 static void JSTrashExecute(napi_env env, void *data)
2193 {
2194 MediaLibraryTracer tracer;
2195 tracer.Start("JSTrashExecute");
2196
2197 auto *context = static_cast<FileAssetAsyncContext*>(data);
2198
2199 #ifdef MEDIALIBRARY_COMPATIBILITY
2200 if ((context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_IMAGE) ||
2201 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_VIDEO) ||
2202 (context->objectPtr->GetMediaType() == MediaType::MEDIA_TYPE_AUDIO)) {
2203 if (MediaFileUtils::IsFileTablePath(context->objectPtr->GetPath())) {
2204 TrashByInsert(context);
2205 } else {
2206 TrashByUpdate(context);
2207 }
2208 } else {
2209 TrashByInsert(context);
2210 }
2211 #else
2212 TrashByInsert(context);
2213 #endif
2214 if (context->changedRows >= 0) {
2215 int32_t trashFlag = (context->isTrash ? IS_TRASH : NOT_TRASH);
2216 context->objectPtr->SetIsTrash(trashFlag);
2217 }
2218 context->SaveError(context->changedRows);
2219 }
2220
JSTrashCallbackComplete(napi_env env,napi_status status,void * data)2221 static void JSTrashCallbackComplete(napi_env env, napi_status status, void *data)
2222 {
2223 MediaLibraryTracer tracer;
2224 tracer.Start("JSTrashCallbackComplete");
2225
2226 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2227 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2228 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2229 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
2230 jsContext->status = false;
2231 napi_get_undefined(env, &jsContext->data);
2232 if (context->error == ERR_DEFAULT) {
2233 jsContext->status = true;
2234 Media::MediaType mediaType = context->objectPtr->GetMediaType();
2235 string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
2236 Uri modifyNotify(notifyUri);
2237 UserFileClient::NotifyChange(modifyNotify);
2238 NAPI_DEBUG_LOG("JSTrashCallbackComplete success");
2239 } else {
2240 context->HandleError(env, jsContext->error);
2241 }
2242
2243 tracer.Finish();
2244 if (context->work != nullptr) {
2245 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2246 context->work, *jsContext);
2247 }
2248
2249 delete context;
2250 }
2251
GetJSArgsForTrash(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)2252 napi_value GetJSArgsForTrash(napi_env env, size_t argc, const napi_value argv[],
2253 FileAssetAsyncContext &asyncContext)
2254 {
2255 const int32_t refCount = 1;
2256 napi_value result = nullptr;
2257 auto context = &asyncContext;
2258 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
2259 bool isTrash = false;
2260 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
2261 for (size_t i = PARAM0; i < argc; i++) {
2262 napi_valuetype valueType = napi_undefined;
2263 napi_typeof(env, argv[i], &valueType);
2264 if (i == PARAM0 && valueType == napi_boolean) {
2265 napi_get_value_bool(env, argv[i], &isTrash);
2266 } else if (i == PARAM1 && valueType == napi_function) {
2267 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
2268 break;
2269 } else {
2270 NAPI_ASSERT(env, false, "type mismatch");
2271 }
2272 }
2273 context->isTrash = isTrash;
2274 napi_get_boolean(env, true, &result);
2275 return result;
2276 }
2277
JSTrash(napi_env env,napi_callback_info info)2278 napi_value FileAssetNapi::JSTrash(napi_env env, napi_callback_info info)
2279 {
2280 napi_status status;
2281 napi_value result = nullptr;
2282 size_t argc = ARGS_TWO;
2283 napi_value argv[ARGS_TWO] = {0};
2284 napi_value thisVar = nullptr;
2285
2286 MediaLibraryTracer tracer;
2287 tracer.Start("JSTrash");
2288
2289 GET_JS_ARGS(env, info, argc, argv, thisVar);
2290 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
2291
2292 napi_get_undefined(env, &result);
2293 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2294 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
2295 asyncContext->resultNapiType = ResultNapiType::TYPE_MEDIALIBRARY;
2296 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
2297 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2298 result = GetJSArgsForTrash(env, argc, argv, *asyncContext);
2299 ASSERT_NULLPTR_CHECK(env, result);
2300 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2301 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
2302 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSTrash", JSTrashExecute,
2303 JSTrashCallbackComplete);
2304 }
2305 return result;
2306 }
2307
JSIsTrashExecute(FileAssetAsyncContext * context)2308 static void JSIsTrashExecute(FileAssetAsyncContext* context)
2309 {
2310 MediaLibraryTracer tracer;
2311 tracer.Start("JSIsTrashExecute");
2312
2313 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2314 context->isTrash = (context->objectPtr->GetIsTrash() != NOT_TRASH);
2315 return;
2316 }
2317
JSIsTrashCallbackComplete(napi_env env,napi_status status,FileAssetAsyncContext * context)2318 static void JSIsTrashCallbackComplete(napi_env env, napi_status status,
2319 FileAssetAsyncContext* context)
2320 {
2321 MediaLibraryTracer tracer;
2322 tracer.Start("JSIsTrashCallbackComplete");
2323
2324 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2325 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2326 CHECK_NULL_PTR_RETURN_VOID(jsContext, "jsContext context is null");
2327 jsContext->status = false;
2328 if (context->error == ERR_DEFAULT) {
2329 napi_get_boolean(env, context->isTrash, &jsContext->data);
2330 napi_get_undefined(env, &jsContext->error);
2331 jsContext->status = true;
2332 } else {
2333 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->error,
2334 "UserFileClient is invalid");
2335 napi_get_undefined(env, &jsContext->data);
2336 }
2337
2338 tracer.Finish();
2339 if (context->work != nullptr) {
2340 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2341 context->work, *jsContext);
2342 }
2343
2344 delete context;
2345 }
2346
GetJSArgsForIsTrash(napi_env env,size_t argc,const napi_value argv[],FileAssetAsyncContext & asyncContext)2347 static napi_value GetJSArgsForIsTrash(napi_env env, size_t argc, const napi_value argv[],
2348 FileAssetAsyncContext &asyncContext)
2349 {
2350 const int32_t refCount = 1;
2351 napi_value result;
2352 auto context = &asyncContext;
2353 CHECK_NULL_PTR_RETURN_UNDEFINED(env, context, result, "Async context is null");
2354 NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
2355 for (size_t i = PARAM0; i < argc; i++) {
2356 napi_valuetype valueType = napi_undefined;
2357 napi_typeof(env, argv[i], &valueType);
2358 if (i == PARAM0 && valueType == napi_function) {
2359 napi_create_reference(env, argv[i], refCount, &context->callbackRef);
2360 break;
2361 } else {
2362 NAPI_ASSERT(env, false, "type mismatch");
2363 }
2364 }
2365 napi_get_boolean(env, true, &result);
2366 return result;
2367 }
2368
JSIsTrash(napi_env env,napi_callback_info info)2369 napi_value FileAssetNapi::JSIsTrash(napi_env env, napi_callback_info info)
2370 {
2371 napi_status status;
2372 napi_value result = nullptr;
2373 size_t argc = ARGS_ONE;
2374 napi_value argv[ARGS_ONE] = {0};
2375 napi_value thisVar = nullptr;
2376 napi_value resource = nullptr;
2377
2378 MediaLibraryTracer tracer;
2379 tracer.Start("JSIsTrash");
2380
2381 GET_JS_ARGS(env, info, argc, argv, thisVar);
2382 NAPI_ASSERT(env, (argc == ARGS_ZERO || argc == ARGS_ONE), "requires 1 parameters maximum");
2383 napi_get_undefined(env, &result);
2384 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2385 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
2386 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
2387 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2388 result = GetJSArgsForIsTrash(env, argc, argv, *asyncContext);
2389 ASSERT_NULLPTR_CHECK(env, result);
2390 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
2391 NAPI_CREATE_RESOURCE_NAME(env, resource, "JSIsTrash", asyncContext);
2392 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2393 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
2394
2395 status = napi_create_async_work(
2396 env, nullptr, resource, [](napi_env env, void *data) {
2397 auto context = static_cast<FileAssetAsyncContext*>(data);
2398 JSIsTrashExecute(context);
2399 },
2400 reinterpret_cast<CompleteCallback>(JSIsTrashCallbackComplete),
2401 static_cast<void *>(asyncContext.get()), &asyncContext->work);
2402 if (status != napi_ok) {
2403 napi_get_undefined(env, &result);
2404 } else {
2405 napi_queue_async_work(env, asyncContext->work);
2406 asyncContext.release();
2407 }
2408 }
2409
2410 return result;
2411 }
2412
UpdateFileAssetInfo()2413 void FileAssetNapi::UpdateFileAssetInfo()
2414 {
2415 fileAssetPtr = std::shared_ptr<FileAsset>(sFileAsset_);
2416 }
2417
UserFileMgrGet(napi_env env,napi_callback_info info)2418 napi_value FileAssetNapi::UserFileMgrGet(napi_env env, napi_callback_info info)
2419 {
2420 MediaLibraryTracer tracer;
2421 tracer.Start("UserFileMgrGet");
2422
2423 napi_value ret = nullptr;
2424 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2425 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2426
2427 string inputKey;
2428 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey),
2429 JS_ERR_PARAMETER_INVALID);
2430 napi_value jsResult = nullptr;
2431 auto obj = asyncContext->objectInfo;
2432 napi_get_undefined(env, &jsResult);
2433 if (obj->fileAssetPtr->GetMemberMap().count(inputKey) == 0) {
2434 // no exist throw error
2435 NapiError::ThrowError(env, JS_E_FILE_KEY);
2436 return jsResult;
2437 }
2438 auto m = obj->fileAssetPtr->GetMemberMap().at(inputKey);
2439 if (m.index() == MEMBER_TYPE_STRING) {
2440 napi_create_string_utf8(env, get<string>(m).c_str(), NAPI_AUTO_LENGTH, &jsResult);
2441 } else if (m.index() == MEMBER_TYPE_INT32) {
2442 napi_create_int32(env, get<int32_t>(m), &jsResult);
2443 } else if (m.index() == MEMBER_TYPE_INT64) {
2444 napi_create_int64(env, get<int64_t>(m), &jsResult);
2445 } else {
2446 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
2447 return jsResult;
2448 }
2449 return jsResult;
2450 }
2451
HandleParamSet(const string & inputKey,const string & value,ResultNapiType resultNapiType)2452 bool FileAssetNapi::HandleParamSet(const string &inputKey, const string &value, ResultNapiType resultNapiType)
2453 {
2454 if (resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
2455 if (inputKey == MediaColumn::MEDIA_TITLE) {
2456 fileAssetPtr->SetTitle(value);
2457 } else {
2458 NAPI_ERR_LOG("invalid key %{public}s, no support key", inputKey.c_str());
2459 return false;
2460 }
2461 } else if (resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
2462 if (inputKey == MediaColumn::MEDIA_NAME) {
2463 fileAssetPtr->SetDisplayName(value);
2464 fileAssetPtr->SetTitle(MediaFileUtils::GetTitleFromDisplayName(value));
2465 } else if (inputKey == MediaColumn::MEDIA_TITLE) {
2466 fileAssetPtr->SetTitle(value);
2467 string displayName = fileAssetPtr->GetDisplayName();
2468 if (!displayName.empty()) {
2469 string extention = MediaFileUtils::SplitByChar(displayName, '.');
2470 fileAssetPtr->SetDisplayName(value + "." + extention);
2471 }
2472 } else {
2473 NAPI_ERR_LOG("invalid key %{public}s, no support key", inputKey.c_str());
2474 return false;
2475 }
2476 } else {
2477 NAPI_ERR_LOG("invalid resultNapiType");
2478 return false;
2479 }
2480 return true;
2481 }
2482
UserFileMgrSet(napi_env env,napi_callback_info info)2483 napi_value FileAssetNapi::UserFileMgrSet(napi_env env, napi_callback_info info)
2484 {
2485 MediaLibraryTracer tracer;
2486 tracer.Start("UserFileMgrSet");
2487
2488 napi_value ret = nullptr;
2489 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2490 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
2491 string inputKey;
2492 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, inputKey),
2493 JS_ERR_PARAMETER_INVALID);
2494 string value;
2495 CHECK_ARGS(env, MediaLibraryNapiUtils::GetParamStringPathMax(env, asyncContext->argv[ARGS_ONE], value),
2496 JS_ERR_PARAMETER_INVALID);
2497 napi_value jsResult = nullptr;
2498 napi_get_undefined(env, &jsResult);
2499 auto obj = asyncContext->objectInfo;
2500 if (!obj->HandleParamSet(inputKey, value, obj->fileAssetPtr->GetResultNapiType())) {
2501 NapiError::ThrowError(env, JS_E_FILE_KEY);
2502 return jsResult;
2503 }
2504 return jsResult;
2505 }
2506
UserFileMgrCommitModify(napi_env env,napi_callback_info info)2507 napi_value FileAssetNapi::UserFileMgrCommitModify(napi_env env, napi_callback_info info)
2508 {
2509 MediaLibraryTracer tracer;
2510 tracer.Start("UserFileMgrCommitModify");
2511
2512 napi_value ret = nullptr;
2513 auto asyncContext = make_unique<FileAssetAsyncContext>();
2514 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2515 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
2516 "Failed to parse js args");
2517 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2518 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
2519
2520 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrCommitModify",
2521 JSCommitModifyExecute, JSCommitModifyCompleteCallback);
2522 }
2523
UserFileMgrFavoriteComplete(napi_env env,napi_status status,void * data)2524 static void UserFileMgrFavoriteComplete(napi_env env, napi_status status, void *data)
2525 {
2526 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2527 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2528 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2529 jsContext->status = false;
2530
2531 if (context->error == ERR_DEFAULT) {
2532 napi_create_int32(env, context->changedRows, &jsContext->data);
2533 jsContext->status = true;
2534 napi_get_undefined(env, &jsContext->error);
2535 } else {
2536 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
2537 "Failed to modify favorite state");
2538 napi_get_undefined(env, &jsContext->data);
2539 }
2540
2541 if (context->work != nullptr) {
2542 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2543 context->work, *jsContext);
2544 }
2545 delete context;
2546 }
2547
UserFileMgrFavoriteExecute(napi_env env,void * data)2548 static void UserFileMgrFavoriteExecute(napi_env env, void *data)
2549 {
2550 MediaLibraryTracer tracer;
2551 tracer.Start("UserFileMgrFavoriteExecute");
2552
2553 auto *context = static_cast<FileAssetAsyncContext *>(data);
2554
2555 string uri;
2556 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
2557 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
2558 uri = UFM_UPDATE_PHOTO;
2559 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
2560 uri = UFM_UPDATE_AUDIO;
2561 }
2562
2563 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
2564 Uri updateAssetUri(uri);
2565 DataSharePredicates predicates;
2566 DataShareValuesBucket valuesBucket;
2567 int32_t changedRows;
2568 valuesBucket.Put(MediaColumn::MEDIA_IS_FAV, context->isFavorite ? IS_FAV : NOT_FAV);
2569 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
2570 predicates.SetWhereArgs({ std::to_string(context->objectPtr->GetId()) });
2571
2572 changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
2573 if (changedRows < 0) {
2574 context->SaveError(changedRows);
2575 NAPI_ERR_LOG("Failed to modify favorite state, err: %{public}d", changedRows);
2576 } else {
2577 context->objectPtr->SetFavorite(context->isFavorite);
2578 context->changedRows = changedRows;
2579 }
2580 }
2581
UserFileMgrFavorite(napi_env env,napi_callback_info info)2582 napi_value FileAssetNapi::UserFileMgrFavorite(napi_env env, napi_callback_info info)
2583 {
2584 auto asyncContext = make_unique<FileAssetAsyncContext>();
2585 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2586 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isFavorite),
2587 JS_ERR_PARAMETER_INVALID);
2588 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2589 CHECK_NULLPTR_RET(asyncContext->objectPtr);
2590
2591 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrFavorite",
2592 UserFileMgrFavoriteExecute, UserFileMgrFavoriteComplete);
2593 }
UserFileMgrGetThumbnail(napi_env env,napi_callback_info info)2594 napi_value FileAssetNapi::UserFileMgrGetThumbnail(napi_env env, napi_callback_info info)
2595 {
2596 MediaLibraryTracer tracer;
2597 tracer.Start("UserFileMgrGetThumbnail");
2598
2599 auto asyncContext = make_unique<FileAssetAsyncContext>();
2600 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, asyncContext, ARGS_ZERO, ARGS_TWO),
2601 JS_INNER_FAIL);
2602 CHECK_NULLPTR_RET(GetJSArgsForGetThumbnail(env, asyncContext->argc, asyncContext->argv, asyncContext));
2603
2604 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2605 CHECK_NULLPTR_RET(asyncContext->objectPtr);
2606 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2607
2608 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrGetThumbnail",
2609 [](napi_env env, void *data) {
2610 auto context = static_cast<FileAssetAsyncContext*>(data);
2611 JSGetThumbnailExecute(context);
2612 },
2613 reinterpret_cast<CompleteCallback>(JSGetThumbnailCompleteCallback));
2614 }
2615
ParseArgsUserFileMgrOpen(napi_env env,napi_callback_info info,unique_ptr<FileAssetAsyncContext> & context,bool isReadOnly)2616 static napi_value ParseArgsUserFileMgrOpen(napi_env env, napi_callback_info info,
2617 unique_ptr<FileAssetAsyncContext> &context, bool isReadOnly)
2618 {
2619 size_t minArgs = ARGS_ZERO;
2620 size_t maxArgs = ARGS_ONE;
2621 if (!isReadOnly) {
2622 minArgs++;
2623 maxArgs++;
2624 }
2625 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
2626 JS_ERR_PARAMETER_INVALID);
2627 auto fileUri = context->objectInfo->GetFileUri();
2628 MediaLibraryNapiUtils::UriAppendKeyValue(fileUri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
2629 context->valuesBucket.Put(MEDIA_DATA_DB_URI, fileUri);
2630
2631 if (isReadOnly) {
2632 context->valuesBucket.Put(MEDIA_FILEMODE, MEDIA_FILEMODE_READONLY);
2633 } else {
2634 string mode;
2635 CHECK_ARGS(env, MediaLibraryNapiUtils::GetParamStringPathMax(env, context->argv[PARAM0], mode),
2636 JS_ERR_PARAMETER_INVALID);
2637 transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
2638 if (!MediaFileUtils::CheckMode(mode)) {
2639 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
2640 return nullptr;
2641 }
2642 context->valuesBucket.Put(MEDIA_FILEMODE, mode);
2643 }
2644
2645 napi_value result = nullptr;
2646 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
2647 return result;
2648 }
2649
UserFileMgrOpenExecute(napi_env env,void * data)2650 static void UserFileMgrOpenExecute(napi_env env, void *data)
2651 {
2652 MediaLibraryTracer tracer;
2653 tracer.Start("JSOpenExecute");
2654
2655 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2656 bool isValid = false;
2657 string mode = context->valuesBucket.Get(MEDIA_FILEMODE, isValid);
2658 if (!isValid) {
2659 context->SaveError(-EINVAL);
2660 return;
2661 }
2662 string fileUri = context->valuesBucket.Get(MEDIA_DATA_DB_URI, isValid);
2663 if (!isValid) {
2664 context->SaveError(-EINVAL);
2665 return ;
2666 }
2667
2668 MediaFileUtils::UriAppendKeyValue(fileUri, MediaColumn::MEDIA_TIME_PENDING,
2669 to_string(context->objectPtr->GetTimePending()));
2670 Uri openFileUri(fileUri);
2671 int32_t retVal = UserFileClient::OpenFile(openFileUri, mode);
2672 if (retVal <= 0) {
2673 context->SaveError(retVal);
2674 NAPI_ERR_LOG("File open asset failed, ret: %{public}d", retVal);
2675 } else {
2676 context->fd = retVal;
2677 if (mode.find('w') != string::npos) {
2678 context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_WRITE);
2679 } else {
2680 context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_READONLY);
2681 }
2682 if (context->objectPtr->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
2683 context->objectPtr->SetTimePending(UNCLOSE_FILE_TIMEPENDING);
2684 }
2685 }
2686 }
2687
UserFileMgrOpenCallbackComplete(napi_env env,napi_status status,void * data)2688 static void UserFileMgrOpenCallbackComplete(napi_env env, napi_status status, void *data)
2689 {
2690 MediaLibraryTracer tracer;
2691 tracer.Start("UserFileMgrOpenCallbackComplete");
2692
2693 auto *context = static_cast<FileAssetAsyncContext *>(data);
2694 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2695
2696 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2697 jsContext->status = false;
2698
2699 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
2700 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
2701 if (context->error == ERR_DEFAULT) {
2702 CHECK_ARGS_RET_VOID(env, napi_create_int32(env, context->fd, &jsContext->data), JS_INNER_FAIL);
2703 jsContext->status = true;
2704 } else {
2705 context->HandleError(env, jsContext->error);
2706 }
2707
2708 tracer.Finish();
2709 if (context->work != nullptr) {
2710 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2711 context->work, *jsContext);
2712 }
2713 delete context;
2714 }
2715
UserFileMgrOpen(napi_env env,napi_callback_info info)2716 napi_value FileAssetNapi::UserFileMgrOpen(napi_env env, napi_callback_info info)
2717 {
2718 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2719 CHECK_NULLPTR_RET(ParseArgsUserFileMgrOpen(env, info, asyncContext, false));
2720 if (asyncContext->objectInfo->fileAssetPtr == nullptr) {
2721 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
2722 return nullptr;
2723 }
2724 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2725
2726 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrOpen",
2727 UserFileMgrOpenExecute, UserFileMgrOpenCallbackComplete);
2728 }
2729
JSGetReadOnlyFd(napi_env env,napi_callback_info info)2730 napi_value FileAssetNapi::JSGetReadOnlyFd(napi_env env, napi_callback_info info)
2731 {
2732 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2733 CHECK_NULLPTR_RET(ParseArgsUserFileMgrOpen(env, info, asyncContext, true));
2734 if (asyncContext->objectInfo->fileAssetPtr == nullptr) {
2735 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
2736 return nullptr;
2737 }
2738 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2739
2740 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetPhotoAssets", UserFileMgrOpenExecute,
2741 UserFileMgrOpenCallbackComplete);
2742 }
2743
ParseArgsUserFileMgrClose(napi_env env,napi_callback_info info,unique_ptr<FileAssetAsyncContext> & context)2744 static napi_value ParseArgsUserFileMgrClose(napi_env env, napi_callback_info info,
2745 unique_ptr<FileAssetAsyncContext> &context)
2746 {
2747 size_t minArgs = ARGS_ONE;
2748 size_t maxArgs = ARGS_TWO;
2749 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
2750 JS_ERR_PARAMETER_INVALID);
2751 context->valuesBucket.Put(MEDIA_DATA_DB_URI, context->objectInfo->GetFileUri());
2752
2753 int32_t fd = 0;
2754 CHECK_COND(env, MediaLibraryNapiUtils::GetInt32Arg(env, context->argv[PARAM0], fd), JS_ERR_PARAMETER_INVALID);
2755 if (fd <= 0) {
2756 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
2757 return nullptr;
2758 }
2759 context->fd = fd;
2760
2761 napi_value result = nullptr;
2762 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
2763 return result;
2764 }
2765
UserFileMgrCloseExecute(napi_env env,void * data)2766 static void UserFileMgrCloseExecute(napi_env env, void *data)
2767 {
2768 MediaLibraryTracer tracer;
2769 tracer.Start("UserFileMgrCloseExecute");
2770
2771 auto *context = static_cast<FileAssetAsyncContext*>(data);
2772 UniqueFd unifd(context->fd);
2773 if (!CheckFileOpenStatus(context, unifd.Get())) {
2774 return;
2775 }
2776 string closeUri;
2777 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
2778 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
2779 closeUri = UFM_CLOSE_PHOTO;
2780 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
2781 closeUri = UFM_CLOSE_AUDIO;
2782 } else {
2783 context->SaveError(-EINVAL);
2784 return;
2785 }
2786 MediaLibraryNapiUtils::UriAppendKeyValue(closeUri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
2787 MediaLibraryNapiUtils::UriAppendKeyValue(closeUri, MediaColumn::MEDIA_TIME_PENDING,
2788 to_string(context->objectPtr->GetTimePending()));
2789 Uri closeAssetUri(closeUri);
2790 int32_t ret = UserFileClient::Insert(closeAssetUri, context->valuesBucket);
2791 if (ret != E_SUCCESS) {
2792 context->SaveError(ret);
2793 } else {
2794 if (context->objectPtr->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
2795 context->objectPtr->SetTimePending(0);
2796 }
2797 }
2798 }
2799
UserFileMgrCloseCallbackComplete(napi_env env,napi_status status,void * data)2800 static void UserFileMgrCloseCallbackComplete(napi_env env, napi_status status, void *data)
2801 {
2802 MediaLibraryTracer tracer;
2803 tracer.Start("UserFileMgrCloseCallbackComplete");
2804
2805 auto context = static_cast<FileAssetAsyncContext *>(data);
2806 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2807
2808 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2809 jsContext->status = false;
2810
2811 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
2812 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
2813 if (context->error == ERR_DEFAULT) {
2814 CHECK_ARGS_RET_VOID(env, napi_create_int32(env, E_SUCCESS, &jsContext->data), JS_INNER_FAIL);
2815 jsContext->status = true;
2816 } else {
2817 context->HandleError(env, jsContext->error);
2818 }
2819
2820 tracer.Finish();
2821 if (context->work != nullptr) {
2822 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2823 context->work, *jsContext);
2824 }
2825 delete context;
2826 }
2827
UserFileMgrClose(napi_env env,napi_callback_info info)2828 napi_value FileAssetNapi::UserFileMgrClose(napi_env env, napi_callback_info info)
2829 {
2830 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2831 CHECK_NULLPTR_RET(ParseArgsUserFileMgrClose(env, info, asyncContext));
2832 if (asyncContext->objectInfo->fileAssetPtr == nullptr) {
2833 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
2834 return nullptr;
2835 }
2836 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2837
2838 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetPhotoAssets", UserFileMgrCloseExecute,
2839 UserFileMgrCloseCallbackComplete);
2840 }
2841
UserFileMgrSetHiddenExecute(napi_env env,void * data)2842 static void UserFileMgrSetHiddenExecute(napi_env env, void *data)
2843 {
2844 MediaLibraryTracer tracer;
2845 tracer.Start("UserFileMgrSetHiddenExecute");
2846
2847 auto *context = static_cast<FileAssetAsyncContext *>(data);
2848 if (context->objectPtr->GetMediaType() != MEDIA_TYPE_IMAGE &&
2849 context->objectPtr->GetMediaType() != MEDIA_TYPE_VIDEO) {
2850 context->SaveError(-EINVAL);
2851 return;
2852 }
2853
2854 string uri = UFM_UPDATE_PHOTO;
2855 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
2856 Uri updateAssetUri(uri);
2857 DataSharePredicates predicates;
2858 DataShareValuesBucket valuesBucket;
2859 int32_t changedRows;
2860 valuesBucket.Put(MediaColumn::MEDIA_HIDDEN, context->isHidden ? IS_HIDDEN : NOT_HIDDEN);
2861 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
2862 predicates.SetWhereArgs({ std::to_string(context->objectPtr->GetId()) });
2863
2864 changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
2865 if (changedRows < 0) {
2866 context->SaveError(changedRows);
2867 NAPI_ERR_LOG("Failed to modify hidden state, err: %{public}d", changedRows);
2868 } else {
2869 context->objectPtr->SetHidden(context->isHidden);
2870 context->changedRows = changedRows;
2871 }
2872 }
2873
UserFileMgrSetHiddenComplete(napi_env env,napi_status status,void * data)2874 static void UserFileMgrSetHiddenComplete(napi_env env, napi_status status, void *data)
2875 {
2876 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2877 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2878 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2879 jsContext->status = false;
2880
2881 if (context->error == ERR_DEFAULT) {
2882 napi_create_int32(env, context->changedRows, &jsContext->data);
2883 jsContext->status = true;
2884 napi_get_undefined(env, &jsContext->error);
2885 } else {
2886 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
2887 "Failed to modify hidden state");
2888 napi_get_undefined(env, &jsContext->data);
2889 }
2890
2891 if (context->work != nullptr) {
2892 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2893 context->work, *jsContext);
2894 }
2895 delete context;
2896 }
2897
UserFileMgrSetHidden(napi_env env,napi_callback_info info)2898 napi_value FileAssetNapi::UserFileMgrSetHidden(napi_env env, napi_callback_info info)
2899 {
2900 MediaLibraryTracer tracer;
2901 tracer.Start("UserFileMgrSetHidden");
2902
2903 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2904 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2905 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isHidden),
2906 JS_ERR_PARAMETER_INVALID);
2907 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2908 CHECK_NULLPTR_RET(asyncContext->objectPtr);
2909
2910 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrSetHidden",
2911 UserFileMgrSetHiddenExecute, UserFileMgrSetHiddenComplete);
2912 }
2913
UserFileMgrSetPendingExecute(napi_env env,void * data)2914 static void UserFileMgrSetPendingExecute(napi_env env, void *data)
2915 {
2916 MediaLibraryTracer tracer;
2917 tracer.Start("UserFileMgrSetPendingExecute");
2918 auto *context = static_cast<FileAssetAsyncContext*>(data);
2919
2920 string uri = MEDIALIBRARY_DATA_URI + "/";
2921 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
2922 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
2923 uri += UFM_PHOTO + "/" + OPRN_PENDING;
2924 } else if (context->objectPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
2925 uri += UFM_AUDIO + "/" + OPRN_PENDING;
2926 } else {
2927 context->SaveError(-EINVAL);
2928 return;
2929 }
2930
2931 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
2932 Uri updateAssetUri(uri);
2933 DataSharePredicates predicates;
2934 DataShareValuesBucket valuesBucket;
2935 int32_t changedRows;
2936 valuesBucket.Put(MediaColumn::MEDIA_TIME_PENDING, context->isPending ? 1 : 0);
2937 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
2938 predicates.SetWhereArgs({ std::to_string(context->objectPtr->GetId()) });
2939
2940 changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
2941 if (changedRows < 0) {
2942 context->SaveError(changedRows);
2943 NAPI_ERR_LOG("Failed to modify pending state, err: %{public}d", changedRows);
2944 } else {
2945 context->changedRows = changedRows;
2946 context->objectPtr->SetTimePending((context->isPending) ? 1 : 0);
2947 }
2948 }
2949
UserFileMgrSetPendingComplete(napi_env env,napi_status status,void * data)2950 static void UserFileMgrSetPendingComplete(napi_env env, napi_status status, void *data)
2951 {
2952 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
2953 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2954 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2955 jsContext->status = false;
2956
2957 if (context->error == ERR_DEFAULT) {
2958 napi_create_int32(env, context->changedRows, &jsContext->data);
2959 jsContext->status = true;
2960 napi_get_undefined(env, &jsContext->error);
2961 } else {
2962 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
2963 "Failed to modify pending state");
2964 napi_get_undefined(env, &jsContext->data);
2965 }
2966
2967 if (context->work != nullptr) {
2968 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2969 context->work, *jsContext);
2970 }
2971 delete context;
2972 }
2973
UserFileMgrSetPending(napi_env env,napi_callback_info info)2974 napi_value FileAssetNapi::UserFileMgrSetPending(napi_env env, napi_callback_info info)
2975 {
2976 MediaLibraryTracer tracer;
2977 tracer.Start("UserFileMgrSetPending");
2978
2979 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
2980 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
2981 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isPending),
2982 JS_ERR_PARAMETER_INVALID);
2983 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
2984 CHECK_NULLPTR_RET(asyncContext->objectPtr);
2985
2986 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrSetPending",
2987 UserFileMgrSetPendingExecute, UserFileMgrSetPendingComplete);
2988 }
2989
UserFileMgrGetExifExecute(napi_env env,void * data)2990 static void UserFileMgrGetExifExecute(napi_env env, void *data) {}
2991
UserFileMgrGetExifComplete(napi_env env,napi_status status,void * data)2992 static void UserFileMgrGetExifComplete(napi_env env, napi_status status, void *data)
2993 {
2994 auto *context = static_cast<FileAssetAsyncContext*>(data);
2995 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2996 auto jsContext = make_unique<JSAsyncContextOutput>();
2997 jsContext->status = false;
2998
2999 auto *obj = context->objectInfo;
3000 nlohmann::json allExifJson;
3001 if (!obj->GetAllExif().empty()) {
3002 allExifJson = nlohmann::json::parse(obj->GetAllExif());
3003 }
3004 if (allExifJson.is_discarded() || obj->GetAllExif().empty()) {
3005 NAPI_ERR_LOG("parse json failed");
3006 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, JS_INNER_FAIL,
3007 "parse json failed");
3008 napi_get_undefined(env, &jsContext->data);
3009 } else {
3010 auto err = PermissionUtils::CheckNapiCallerPermission(PERMISSION_NAME_MEDIA_LOCATION);
3011 if (err == false) {
3012 allExifJson.erase(PHOTO_DATA_IMAGE_GPS_LATITUDE);
3013 allExifJson.erase(PHOTO_DATA_IMAGE_GPS_LONGITUDE);
3014 allExifJson.erase(PHOTO_DATA_IMAGE_GPS_LATITUDE_REF);
3015 allExifJson.erase(PHOTO_DATA_IMAGE_GPS_LONGITUDE_REF);
3016 }
3017 allExifJson[PHOTO_DATA_IMAGE_USER_COMMENT] = obj->GetUserComment();
3018 napi_create_string_utf8(env, allExifJson.dump().c_str(), NAPI_AUTO_LENGTH, &jsContext->data);
3019 jsContext->status = true;
3020 napi_get_undefined(env, &jsContext->error);
3021 }
3022
3023 if (context->work != nullptr) {
3024 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3025 context->work, *jsContext);
3026 }
3027 delete context;
3028 }
3029
JSGetExif(napi_env env,napi_callback_info info)3030 napi_value FileAssetNapi::JSGetExif(napi_env env, napi_callback_info info)
3031 {
3032 MediaLibraryTracer tracer;
3033 tracer.Start("JSGetExif");
3034 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3035 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, asyncContext, ARGS_ZERO, ARGS_ONE),
3036 JS_ERR_PARAMETER_INVALID);
3037 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3038 CHECK_NULLPTR_RET(asyncContext->objectPtr);
3039
3040 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetExif", UserFileMgrGetExifExecute,
3041 UserFileMgrGetExifComplete);
3042 }
3043
UserFileMgrSetUserCommentComplete(napi_env env,napi_status status,void * data)3044 static void UserFileMgrSetUserCommentComplete(napi_env env, napi_status status, void *data)
3045 {
3046 auto *context = static_cast<FileAssetAsyncContext*>(data);
3047 auto jsContext = make_unique<JSAsyncContextOutput>();
3048 jsContext->status = false;
3049
3050 if (context->error == ERR_DEFAULT) {
3051 napi_create_int32(env, context->changedRows, &jsContext->data);
3052 jsContext->status = true;
3053 napi_get_undefined(env, &jsContext->error);
3054 } else {
3055 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->error,
3056 "Failed to edit user comment");
3057 napi_get_undefined(env, &jsContext->data);
3058 }
3059
3060 if (context->work != nullptr) {
3061 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3062 context->work, *jsContext);
3063 }
3064 delete context;
3065 }
3066
UserFileMgrSetUserCommentExecute(napi_env env,void * data)3067 static void UserFileMgrSetUserCommentExecute(napi_env env, void *data)
3068 {
3069 MediaLibraryTracer tracer;
3070 tracer.Start("UserFileMgrSetUserCommentExecute");
3071
3072 auto *context = static_cast<FileAssetAsyncContext *>(data);
3073 string uri = UFM_SET_USER_COMMENT;
3074 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
3075 Uri editUserCommentUri(uri);
3076 DataSharePredicates predicates;
3077 DataShareValuesBucket valuesBucket;
3078 valuesBucket.Put(PhotoColumn::PHOTO_USER_COMMENT, context->userComment);
3079 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
3080 predicates.SetWhereArgs({std::to_string(context->objectPtr->GetId())});
3081 int32_t changedRows = UserFileClient::Update(editUserCommentUri, predicates, valuesBucket);
3082 if (changedRows < 0) {
3083 context->SaveError(changedRows);
3084 NAPI_ERR_LOG("Failed to modify user comment, err: %{public}d", changedRows);
3085 } else {
3086 context->objectPtr->SetUserComment(context->userComment);
3087 context->changedRows = changedRows;
3088 }
3089 }
3090
UserFileMgrSetUserComment(napi_env env,napi_callback_info info)3091 napi_value FileAssetNapi::UserFileMgrSetUserComment(napi_env env, napi_callback_info info)
3092 {
3093 MediaLibraryTracer tracer;
3094 tracer.Start("UserFileMgrSetUserComment");
3095
3096 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3097 asyncContext->resultNapiType = ResultNapiType::TYPE_USERFILE_MGR;
3098 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, asyncContext->userComment),
3099 JS_ERR_PARAMETER_INVALID);
3100 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3101 if (asyncContext->objectPtr == nullptr) {
3102 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
3103 return nullptr;
3104 }
3105
3106 if (asyncContext->userComment.length() > USER_COMMENT_MAX_LEN) {
3107 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "user comment too long");
3108 return nullptr;
3109 }
3110
3111 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "UserFileMgrSetUserComment",
3112 UserFileMgrSetUserCommentExecute, UserFileMgrSetUserCommentComplete);
3113 }
3114
ParseArgsPhotoAccessHelperOpen(napi_env env,napi_callback_info info,unique_ptr<FileAssetAsyncContext> & context,bool isReadOnly)3115 static napi_value ParseArgsPhotoAccessHelperOpen(napi_env env, napi_callback_info info,
3116 unique_ptr<FileAssetAsyncContext> &context, bool isReadOnly)
3117 {
3118 size_t minArgs = ARGS_ZERO;
3119 size_t maxArgs = ARGS_ONE;
3120 if (!isReadOnly) {
3121 minArgs++;
3122 maxArgs++;
3123 }
3124 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
3125 JS_ERR_PARAMETER_INVALID);
3126 auto fileUri = context->objectInfo->GetFileUri();
3127 MediaLibraryNapiUtils::UriAppendKeyValue(fileUri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
3128 context->valuesBucket.Put(MEDIA_DATA_DB_URI, fileUri);
3129
3130 if (isReadOnly) {
3131 context->valuesBucket.Put(MEDIA_FILEMODE, MEDIA_FILEMODE_READONLY);
3132 } else {
3133 string mode;
3134 CHECK_ARGS(env, MediaLibraryNapiUtils::GetParamStringPathMax(env, context->argv[PARAM0], mode),
3135 JS_ERR_PARAMETER_INVALID);
3136 transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
3137 if (!MediaFileUtils::CheckMode(mode)) {
3138 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
3139 return nullptr;
3140 }
3141 context->valuesBucket.Put(MEDIA_FILEMODE, mode);
3142 }
3143
3144 napi_value result = nullptr;
3145 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
3146 return result;
3147 }
3148
PhotoAccessHelperOpenExecute(napi_env env,void * data)3149 static void PhotoAccessHelperOpenExecute(napi_env env, void *data)
3150 {
3151 MediaLibraryTracer tracer;
3152 tracer.Start("PhotoAccessHelperOpenExecute");
3153
3154 auto *context = static_cast<FileAssetAsyncContext*>(data);
3155 bool isValid = false;
3156 string mode = context->valuesBucket.Get(MEDIA_FILEMODE, isValid);
3157 if (!isValid) {
3158 context->SaveError(-EINVAL);
3159 return;
3160 }
3161 string fileUri = context->valuesBucket.Get(MEDIA_DATA_DB_URI, isValid);
3162 if (!isValid) {
3163 context->SaveError(-EINVAL);
3164 return ;
3165 }
3166
3167 if (context->objectPtr->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
3168 MediaFileUtils::UriAppendKeyValue(fileUri, MediaColumn::MEDIA_TIME_PENDING,
3169 to_string(context->objectPtr->GetTimePending()));
3170 }
3171 Uri openFileUri(fileUri);
3172 int32_t retVal = UserFileClient::OpenFile(openFileUri, mode);
3173 if (retVal <= 0) {
3174 context->SaveError(retVal);
3175 NAPI_ERR_LOG("File open asset failed, ret: %{public}d", retVal);
3176 } else {
3177 context->fd = retVal;
3178 if (mode.find('w') != string::npos) {
3179 context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_WRITE);
3180 } else {
3181 context->objectPtr->SetOpenStatus(retVal, OPEN_TYPE_READONLY);
3182 }
3183 if (context->objectPtr->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
3184 context->objectPtr->SetTimePending(UNCLOSE_FILE_TIMEPENDING);
3185 }
3186 }
3187 }
3188
PhotoAccessHelperOpenCallbackComplete(napi_env env,napi_status status,void * data)3189 static void PhotoAccessHelperOpenCallbackComplete(napi_env env, napi_status status, void *data)
3190 {
3191 MediaLibraryTracer tracer;
3192 tracer.Start("PhotoAccessHelperOpenCallbackComplete");
3193
3194 auto context = static_cast<FileAssetAsyncContext *>(data);
3195 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
3196
3197 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
3198 jsContext->status = false;
3199
3200 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
3201 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
3202 if (context->error == ERR_DEFAULT) {
3203 CHECK_ARGS_RET_VOID(env, napi_create_int32(env, context->fd, &jsContext->data), JS_INNER_FAIL);
3204 jsContext->status = true;
3205 } else {
3206 context->HandleError(env, jsContext->error);
3207 }
3208
3209 tracer.Finish();
3210 if (context->work != nullptr) {
3211 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3212 context->work, *jsContext);
3213 }
3214 delete context;
3215 }
3216
PhotoAccessHelperOpen(napi_env env,napi_callback_info info)3217 napi_value FileAssetNapi::PhotoAccessHelperOpen(napi_env env, napi_callback_info info)
3218 {
3219 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3220 CHECK_NULLPTR_RET(ParseArgsPhotoAccessHelperOpen(env, info, asyncContext, false));
3221 if (asyncContext->objectInfo->fileAssetPtr == nullptr) {
3222 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
3223 return nullptr;
3224 }
3225 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3226
3227 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperOpen",
3228 PhotoAccessHelperOpenExecute, PhotoAccessHelperOpenCallbackComplete);
3229 }
3230
ParseArgsPhotoAccessHelperClose(napi_env env,napi_callback_info info,unique_ptr<FileAssetAsyncContext> & context)3231 static napi_value ParseArgsPhotoAccessHelperClose(napi_env env, napi_callback_info info,
3232 unique_ptr<FileAssetAsyncContext> &context)
3233 {
3234 size_t minArgs = ARGS_ONE;
3235 size_t maxArgs = ARGS_TWO;
3236 CHECK_ARGS(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
3237 JS_ERR_PARAMETER_INVALID);
3238 context->valuesBucket.Put(MEDIA_DATA_DB_URI, context->objectInfo->GetFileUri());
3239
3240 int32_t fd = 0;
3241 CHECK_COND(env, MediaLibraryNapiUtils::GetInt32Arg(env, context->argv[PARAM0], fd), JS_ERR_PARAMETER_INVALID);
3242 if (fd <= 0) {
3243 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
3244 return nullptr;
3245 }
3246 context->fd = fd;
3247
3248 napi_value result = nullptr;
3249 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
3250 return result;
3251 }
3252
PhotoAccessHelperCloseExecute(napi_env env,void * data)3253 static void PhotoAccessHelperCloseExecute(napi_env env, void *data)
3254 {
3255 MediaLibraryTracer tracer;
3256 tracer.Start("PhotoAccessHelperCloseExecute");
3257
3258 auto *context = static_cast<FileAssetAsyncContext*>(data);
3259 UniqueFd unifd(context->fd);
3260 if (!CheckFileOpenStatus(context, unifd.Get())) {
3261 return;
3262 }
3263 string closeUri;
3264 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
3265 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
3266 closeUri = PAH_CLOSE_PHOTO;
3267 } else {
3268 context->SaveError(-EINVAL);
3269 return;
3270 }
3271 MediaLibraryNapiUtils::UriAppendKeyValue(closeUri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
3272 MediaLibraryNapiUtils::UriAppendKeyValue(closeUri, MediaColumn::MEDIA_TIME_PENDING,
3273 to_string(context->objectPtr->GetTimePending()));
3274 Uri closeAssetUri(closeUri);
3275 int32_t ret = UserFileClient::Insert(closeAssetUri, context->valuesBucket);
3276 if (ret != E_SUCCESS) {
3277 context->SaveError(ret);
3278 } else {
3279 if (context->objectPtr->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
3280 context->objectPtr->SetTimePending(0);
3281 }
3282 }
3283 }
3284
PhotoAccessHelperCloseCallbackComplete(napi_env env,napi_status status,void * data)3285 static void PhotoAccessHelperCloseCallbackComplete(napi_env env, napi_status status, void *data)
3286 {
3287 MediaLibraryTracer tracer;
3288 tracer.Start("PhotoAccessHelperCloseCallbackComplete");
3289
3290 auto context = static_cast<FileAssetAsyncContext *>(data);
3291 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
3292
3293 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
3294 jsContext->status = false;
3295
3296 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
3297 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
3298 if (context->error == ERR_DEFAULT) {
3299 CHECK_ARGS_RET_VOID(env, napi_create_int32(env, E_SUCCESS, &jsContext->data), JS_INNER_FAIL);
3300 jsContext->status = true;
3301 } else {
3302 context->HandleError(env, jsContext->error);
3303 }
3304
3305 tracer.Finish();
3306 if (context->work != nullptr) {
3307 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3308 context->work, *jsContext);
3309 }
3310 delete context;
3311 }
3312
PhotoAccessHelperClose(napi_env env,napi_callback_info info)3313 napi_value FileAssetNapi::PhotoAccessHelperClose(napi_env env, napi_callback_info info)
3314 {
3315 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3316 CHECK_NULLPTR_RET(ParseArgsPhotoAccessHelperClose(env, info, asyncContext));
3317 if (asyncContext->objectInfo->fileAssetPtr == nullptr) {
3318 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
3319 return nullptr;
3320 }
3321 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3322
3323 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperClose",
3324 PhotoAccessHelperCloseExecute, PhotoAccessHelperCloseCallbackComplete);
3325 }
3326
PhotoAccessHelperCommitModify(napi_env env,napi_callback_info info)3327 napi_value FileAssetNapi::PhotoAccessHelperCommitModify(napi_env env, napi_callback_info info)
3328 {
3329 MediaLibraryTracer tracer;
3330 tracer.Start("PhotoAccessHelperCommitModify");
3331
3332 napi_value ret = nullptr;
3333 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3334 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
3335 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
3336 NAPI_ASSERT(env, MediaLibraryNapiUtils::ParseArgsOnlyCallBack(env, info, asyncContext) == napi_ok,
3337 "Failed to parse js args");
3338 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3339 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
3340
3341 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperCommitModify",
3342 JSCommitModifyExecute, JSCommitModifyCompleteCallback);
3343 }
3344
PhotoAccessHelperFavoriteComplete(napi_env env,napi_status status,void * data)3345 static void PhotoAccessHelperFavoriteComplete(napi_env env, napi_status status, void *data)
3346 {
3347 FileAssetAsyncContext *context = static_cast<FileAssetAsyncContext*>(data);
3348 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
3349 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
3350 jsContext->status = false;
3351
3352 if (context->error == ERR_DEFAULT) {
3353 napi_create_int32(env, context->changedRows, &jsContext->data);
3354 jsContext->status = true;
3355 napi_get_undefined(env, &jsContext->error);
3356 } else {
3357 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
3358 "Failed to modify favorite state");
3359 napi_get_undefined(env, &jsContext->data);
3360 }
3361
3362 if (context->work != nullptr) {
3363 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3364 context->work, *jsContext);
3365 }
3366 delete context;
3367 }
3368
PhotoAccessHelperFavoriteExecute(napi_env env,void * data)3369 static void PhotoAccessHelperFavoriteExecute(napi_env env, void *data)
3370 {
3371 MediaLibraryTracer tracer;
3372 tracer.Start("PhotoAccessHelperFavoriteExecute");
3373
3374 auto *context = static_cast<FileAssetAsyncContext *>(data);
3375 string uri;
3376 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
3377 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
3378 uri = PAH_UPDATE_PHOTO;
3379 } else {
3380 context->SaveError(-EINVAL);
3381 return;
3382 }
3383
3384 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
3385 Uri updateAssetUri(uri);
3386 DataSharePredicates predicates;
3387 DataShareValuesBucket valuesBucket;
3388 int32_t changedRows = 0;
3389 valuesBucket.Put(MediaColumn::MEDIA_IS_FAV, context->isFavorite ? IS_FAV : NOT_FAV);
3390 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
3391 predicates.SetWhereArgs({ std::to_string(context->objectPtr->GetId()) });
3392
3393 changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
3394 if (changedRows < 0) {
3395 context->SaveError(changedRows);
3396 NAPI_ERR_LOG("Failed to modify favorite state, err: %{public}d", changedRows);
3397 } else {
3398 context->objectPtr->SetFavorite(context->isFavorite);
3399 context->changedRows = changedRows;
3400 }
3401 }
3402
PhotoAccessHelperFavorite(napi_env env,napi_callback_info info)3403 napi_value FileAssetNapi::PhotoAccessHelperFavorite(napi_env env, napi_callback_info info)
3404 {
3405 MediaLibraryTracer tracer;
3406 tracer.Start("PhotoAccessHelperFavorite");
3407
3408 napi_value ret = nullptr;
3409 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3410 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
3411 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
3412 NAPI_ASSERT(
3413 env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isFavorite) == napi_ok,
3414 "Failed to parse js args");
3415 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3416 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
3417
3418 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperFavorite",
3419 PhotoAccessHelperFavoriteExecute, PhotoAccessHelperFavoriteComplete);
3420 }
3421
PhotoAccessHelperGetThumbnail(napi_env env,napi_callback_info info)3422 napi_value FileAssetNapi::PhotoAccessHelperGetThumbnail(napi_env env, napi_callback_info info)
3423 {
3424 MediaLibraryTracer tracer;
3425 tracer.Start("PhotoAccessHelperGetThumbnail");
3426
3427 napi_value result = nullptr;
3428 NAPI_CALL(env, napi_get_undefined(env, &result));
3429 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3430 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
3431
3432 CHECK_COND_RET(MediaLibraryNapiUtils::AsyncContextSetObjectInfo(env, info, asyncContext, ARGS_ZERO, ARGS_TWO) ==
3433 napi_ok, result, "Failed to get object info");
3434 result = GetJSArgsForGetThumbnail(env, asyncContext->argc, asyncContext->argv, asyncContext);
3435 ASSERT_NULLPTR_CHECK(env, result);
3436 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3437 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "FileAsset is nullptr");
3438 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
3439 result = MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperGetThumbnail",
3440 [](napi_env env, void *data) {
3441 auto context = static_cast<FileAssetAsyncContext*>(data);
3442 JSGetThumbnailExecute(context);
3443 },
3444 reinterpret_cast<CompleteCallback>(JSGetThumbnailCompleteCallback));
3445
3446 return result;
3447 }
3448
PhotoAccessHelperSetHiddenExecute(napi_env env,void * data)3449 static void PhotoAccessHelperSetHiddenExecute(napi_env env, void *data)
3450 {
3451 MediaLibraryTracer tracer;
3452 tracer.Start("PhotoAccessHelperSetHiddenExecute");
3453
3454 auto *context = static_cast<FileAssetAsyncContext *>(data);
3455 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
3456 if (context->objectPtr->GetMediaType() != MEDIA_TYPE_IMAGE &&
3457 context->objectPtr->GetMediaType() != MEDIA_TYPE_VIDEO) {
3458 context->SaveError(-EINVAL);
3459 return;
3460 }
3461
3462 string uri = PAH_UPDATE_PHOTO;
3463 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
3464 Uri updateAssetUri(uri);
3465 DataSharePredicates predicates;
3466 DataShareValuesBucket valuesBucket;
3467 int32_t changedRows = 0;
3468 valuesBucket.Put(MediaColumn::MEDIA_HIDDEN, context->isHidden ? IS_HIDDEN : NOT_HIDDEN);
3469 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
3470 predicates.SetWhereArgs({ std::to_string(context->objectPtr->GetId()) });
3471
3472 changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
3473 if (changedRows < 0) {
3474 context->SaveError(changedRows);
3475 NAPI_ERR_LOG("Failed to modify hidden state, err: %{public}d", changedRows);
3476 } else {
3477 context->objectPtr->SetHidden(context->isHidden);
3478 context->changedRows = changedRows;
3479 }
3480 }
3481
PhotoAccessHelperSetHiddenComplete(napi_env env,napi_status status,void * data)3482 static void PhotoAccessHelperSetHiddenComplete(napi_env env, napi_status status, void *data)
3483 {
3484 auto *context = static_cast<FileAssetAsyncContext*>(data);
3485 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
3486 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
3487 jsContext->status = false;
3488
3489 if (context->error == ERR_DEFAULT) {
3490 napi_create_int32(env, context->changedRows, &jsContext->data);
3491 jsContext->status = true;
3492 napi_get_undefined(env, &jsContext->error);
3493 } else {
3494 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
3495 "Failed to modify hidden state");
3496 napi_get_undefined(env, &jsContext->data);
3497 }
3498
3499 if (context->work != nullptr) {
3500 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3501 context->work, *jsContext);
3502 }
3503 delete context;
3504 }
3505
PhotoAccessHelperSetHidden(napi_env env,napi_callback_info info)3506 napi_value FileAssetNapi::PhotoAccessHelperSetHidden(napi_env env, napi_callback_info info)
3507 {
3508 MediaLibraryTracer tracer;
3509 tracer.Start("PhotoAccessHelperSetHidden");
3510
3511 napi_value ret = nullptr;
3512 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3513 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
3514 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
3515 NAPI_ASSERT(
3516 env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isHidden) == napi_ok,
3517 "Failed to parse js args");
3518 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3519 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
3520
3521 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperSetHidden",
3522 PhotoAccessHelperSetHiddenExecute, PhotoAccessHelperSetHiddenComplete);
3523 }
3524
PhotoAccessHelperSetPendingExecute(napi_env env,void * data)3525 static void PhotoAccessHelperSetPendingExecute(napi_env env, void *data)
3526 {
3527 MediaLibraryTracer tracer;
3528 tracer.Start("PhotoAccessHelperSetPendingExecute");
3529
3530 auto *context = static_cast<FileAssetAsyncContext *>(data);
3531 string uri = MEDIALIBRARY_DATA_URI + "/";
3532 if (context->objectPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
3533 context->objectPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
3534 uri += PAH_PHOTO + "/" + OPRN_PENDING;
3535 } else {
3536 context->SaveError(-EINVAL);
3537 return;
3538 }
3539
3540 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
3541 Uri updateAssetUri(uri);
3542 DataSharePredicates predicates;
3543 DataShareValuesBucket valuesBucket;
3544 int32_t changedRows = 0;
3545 valuesBucket.Put(MediaColumn::MEDIA_TIME_PENDING, context->isPending ? 1 : 0);
3546 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
3547 predicates.SetWhereArgs({ std::to_string(context->objectPtr->GetId()) });
3548
3549 changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
3550 if (changedRows < 0) {
3551 context->SaveError(changedRows);
3552 NAPI_ERR_LOG("Failed to modify pending state, err: %{public}d", changedRows);
3553 } else {
3554 context->changedRows = changedRows;
3555 context->objectPtr->SetTimePending((context->isPending) ? 1 : 0);
3556 }
3557 }
3558
PhotoAccessHelperSetPendingComplete(napi_env env,napi_status status,void * data)3559 static void PhotoAccessHelperSetPendingComplete(napi_env env, napi_status status, void *data)
3560 {
3561 auto *context = static_cast<FileAssetAsyncContext*>(data);
3562 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
3563 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
3564 jsContext->status = false;
3565
3566 if (context->error == ERR_DEFAULT) {
3567 napi_create_int32(env, context->changedRows, &jsContext->data);
3568 jsContext->status = true;
3569 napi_get_undefined(env, &jsContext->error);
3570 } else {
3571 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->changedRows,
3572 "Failed to modify pending state");
3573 napi_get_undefined(env, &jsContext->data);
3574 }
3575
3576 if (context->work != nullptr) {
3577 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3578 context->work, *jsContext);
3579 }
3580 delete context;
3581 }
3582
PhotoAccessHelperSetPending(napi_env env,napi_callback_info info)3583 napi_value FileAssetNapi::PhotoAccessHelperSetPending(napi_env env, napi_callback_info info)
3584 {
3585 MediaLibraryTracer tracer;
3586 tracer.Start("PhotoAccessHelperSetPending");
3587
3588 napi_value ret = nullptr;
3589 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3590 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, ret, "asyncContext context is null");
3591 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
3592 NAPI_ASSERT(
3593 env, MediaLibraryNapiUtils::ParseArgsBoolCallBack(env, info, asyncContext, asyncContext->isPending) == napi_ok,
3594 "Failed to parse js args");
3595 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3596 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, ret, "FileAsset is nullptr");
3597
3598 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperSetPending",
3599 PhotoAccessHelperSetPendingExecute, PhotoAccessHelperSetPendingComplete);
3600 }
3601
PhotoAccessHelperSetUserCommentComplete(napi_env env,napi_status status,void * data)3602 static void PhotoAccessHelperSetUserCommentComplete(napi_env env, napi_status status, void *data)
3603 {
3604 auto *context = static_cast<FileAssetAsyncContext*>(data);
3605 auto jsContext = make_unique<JSAsyncContextOutput>();
3606 jsContext->status = false;
3607
3608 if (context->error == ERR_DEFAULT) {
3609 napi_create_int32(env, context->changedRows, &jsContext->data);
3610 jsContext->status = true;
3611 napi_get_undefined(env, &jsContext->error);
3612 } else {
3613 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, context->error,
3614 "Failed to edit user comment");
3615 napi_get_undefined(env, &jsContext->data);
3616 }
3617
3618 if (context->work != nullptr) {
3619 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
3620 context->work, *jsContext);
3621 }
3622 delete context;
3623 }
3624
PhotoAccessHelperSetUserCommentExecute(napi_env env,void * data)3625 static void PhotoAccessHelperSetUserCommentExecute(napi_env env, void *data)
3626 {
3627 MediaLibraryTracer tracer;
3628 tracer.Start("PhotoAccessHelperSetUserCommentExecute");
3629
3630 auto *context = static_cast<FileAssetAsyncContext *>(data);
3631 if (context->objectPtr->GetMediaType() != MEDIA_TYPE_IMAGE) {
3632 context->error = -EINVAL;
3633 return;
3634 }
3635
3636 string uri = PAH_EDIT_USER_COMMENT_PHOTO;
3637 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
3638 Uri editUserCommentUri(uri);
3639 DataSharePredicates predicates;
3640 DataShareValuesBucket valuesBucket;
3641 valuesBucket.Put(PhotoColumn::PHOTO_USER_COMMENT, context->userComment);
3642 predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
3643 predicates.SetWhereArgs({std::to_string(context->objectPtr->GetId())});
3644 int32_t changedRows = UserFileClient::Update(editUserCommentUri, predicates, valuesBucket);
3645 if (changedRows < 0) {
3646 context->SaveError(changedRows);
3647 NAPI_ERR_LOG("Failed to modify user comment, err: %{public}d", changedRows);
3648 } else {
3649 context->objectPtr->SetUserComment(context->userComment);
3650 context->changedRows = changedRows;
3651 }
3652 }
3653
PhotoAccessHelperSetUserComment(napi_env env,napi_callback_info info)3654 napi_value FileAssetNapi::PhotoAccessHelperSetUserComment(napi_env env, napi_callback_info info)
3655 {
3656 MediaLibraryTracer tracer;
3657 tracer.Start("PhotoAccessHelperSetUserComment");
3658
3659 unique_ptr<FileAssetAsyncContext> asyncContext = make_unique<FileAssetAsyncContext>();
3660 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
3661 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, asyncContext->userComment),
3662 JS_ERR_PARAMETER_INVALID);
3663 asyncContext->objectPtr = asyncContext->objectInfo->fileAssetPtr;
3664 if (asyncContext->objectPtr == nullptr) {
3665 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
3666 return nullptr;
3667 }
3668
3669 if (asyncContext->userComment.length() > USER_COMMENT_MAX_LEN) {
3670 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "user comment too long");
3671 return nullptr;
3672 }
3673
3674 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PhotoAccessHelperSetUserComment",
3675 PhotoAccessHelperSetUserCommentExecute, PhotoAccessHelperSetUserCommentComplete);
3676 }
3677
3678 } // namespace Media
3679 } // namespace OHOS
3680