1 /* 2 * Copyright (C) 2021 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 16 #ifndef MEDIALIBRARY_NAPI_UTILS_H 17 #define MEDIALIBRARY_NAPI_UTILS_H 18 19 #include <tuple> 20 #include <memory> 21 #include <vector> 22 #include "napi/native_api.h" 23 #include "napi/native_node_api.h" 24 #include "media_lib_service_const.h" 25 #include "media_data_ability_const.h" 26 #include "hilog/log.h" 27 28 using OHOS::HiviewDFX::HiLog; 29 using OHOS::HiviewDFX::HiLogLabel; 30 31 #define GET_JS_ARGS(env, info, argc, argv, thisVar) \ 32 do { \ 33 void* data; \ 34 napi_get_cb_info(env, info, &(argc), argv, &(thisVar), &(data)); \ 35 } while (0) 36 37 #define GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar) \ 38 do { \ 39 void* data; \ 40 status = napi_get_cb_info(env, info, nullptr, nullptr, &(thisVar), &(data)); \ 41 } while (0) 42 43 #define GET_JS_ASYNC_CB_REF(env, arg, count, cbRef) \ 44 do { \ 45 napi_valuetype valueType = napi_undefined; \ 46 if ((napi_typeof(env, arg, &valueType) == napi_ok) && (valueType == napi_function)) { \ 47 napi_create_reference(env, arg, count, &(cbRef)); \ 48 } else { \ 49 HiLog::Error(LABEL, "invalid arguments"); \ 50 NAPI_ASSERT(env, false, "type mismatch"); \ 51 } \ 52 } while (0) 53 54 #define ASSERT_NULLPTR_CHECK(env, result) \ 55 do { \ 56 if ((result) == nullptr) { \ 57 napi_get_undefined(env, &(result)); \ 58 return result; \ 59 } \ 60 } while (0) 61 62 #define NAPI_CREATE_PROMISE(env, callbackRef, deferred, result) \ 63 do { \ 64 if ((callbackRef) == nullptr) { \ 65 napi_create_promise(env, &(deferred), &(result)); \ 66 } \ 67 } while (0) 68 69 #define NAPI_CREATE_RESOURCE_NAME(env, resource, resourceName) \ 70 do { \ 71 napi_create_string_utf8(env, resourceName, NAPI_AUTO_LENGTH, &(resource)); \ 72 } while (0) 73 74 #define CHECK_NULL_PTR_RETURN_UNDEFINED(env, ptr, ret, message) \ 75 do { \ 76 if ((ptr) == nullptr) { \ 77 HiLog::Error(LABEL, message); \ 78 napi_get_undefined(env, &(ret)); \ 79 return ret; \ 80 } \ 81 } while (0) 82 83 #define CHECK_NULL_PTR_RETURN_VOID(ptr, message) \ 84 do { \ 85 if ((ptr) == nullptr) { \ 86 HiLog::Error(LABEL, message); \ 87 return; \ 88 } \ 89 } while (0) 90 91 #define CHECK_IF_EQUAL(condition, errMsg) \ 92 do { \ 93 if (!(condition)) { \ 94 HiLog::Error(LABEL, errMsg); \ 95 return; \ 96 } \ 97 } while (0) 98 namespace OHOS { 99 namespace Media { 100 /* Constants for array index */ 101 const int32_t PARAM0 = 0; 102 const int32_t PARAM1 = 1; 103 const int32_t PARAM2 = 2; 104 const int32_t PARAM3 = 3; 105 106 /* Constants for array size */ 107 const int32_t ARGS_ZERO = 0; 108 const int32_t ARGS_ONE = 1; 109 const int32_t ARGS_TWO = 2; 110 const int32_t ARGS_THREE = 3; 111 const int32_t ARGS_FORE = 4; 112 const int32_t SIZE = 100; 113 const int32_t REFERENCE_COUNT_ONE = 1; 114 115 // Error codes 116 const int32_t ERR_DEFAULT = 0; 117 const int32_t ERR_MEM_ALLOCATION = 2; 118 const int32_t ERR_INVALID_OUTPUT = 3; 119 const int32_t ERR_PERMISSION_DENIED = 4; 120 const int32_t ERR_DISPLAY_NAME_INVALID = 5; 121 const int32_t ERR_RELATIVE_PATH_NOT_EXIST_OR_INVALID = 6; 122 123 const int32_t FAVORIT_SMART_ALBUM_ID = -1; 124 const std::string FAVORIT_SMART_ALBUM_NAME = "FavoritAlbum"; 125 const int32_t TRASH_SMART_ALBUM_ID = -10; 126 const std::string TRASH_SMART_ALBUM_NAME = "TrashAlbum"; 127 128 enum NapiAssetType { 129 TYPE_AUDIO = 0, 130 TYPE_VIDEO = 1, 131 TYPE_IMAGE = 2, 132 TYPE_ALBUM = 3, 133 }; 134 135 enum AlbumType { 136 TYPE_VIDEO_ALBUM = 0, 137 TYPE_IMAGE_ALBUM = 1, 138 TYPE_NONE = 2, 139 }; 140 141 enum PrivateAlbumType { 142 TYPE_FAVORITE = 0, 143 TYPE_TRASH, 144 TYPE_USER 145 }; 146 147 const std::vector<std::string> privateAlbumTypeNameEnum { 148 "TYPE_FAVORITE", "TYPE_TRASH", "TYPE_USER" 149 }; 150 151 const std::vector<std::string> mediaTypesEnum { 152 "DEFAULT", "FILE", "MEDIA", "IMAGE", "VIDEO", "AUDIO", "ALBUM_LIST", "ALBUM_LIST_INFO" 153 }; 154 155 const std::vector<std::string> fileKeyEnum { 156 "ID", "RELATIVE_PATH", "DISPLAY_NAME", "PARENT", "MIME_TYPE", "MEDIA_TYPE", "SIZE", 157 "DATE_ADDED", "DATE_MODIFIED", "DATE_TAKEN", "TITLE", "ARTIST", "AUDIOALBUM", "DURATION", 158 "WIDTH", "HEIGHT", "ORIENTATION", "ALBUM_ID", "ALBUM_NAME" 159 }; 160 161 const std::vector<std::string> directoryEnum { 162 "DIR_CAMERA", "DIR_VIDEO", "DIR_IMAGE", "DIR_AUDIO", "DIR_DOCUMENTS", "DIR_DOWNLOAD" 163 }; 164 165 const std::vector<std::string> directoryEnumValues { 166 "Camera/", 167 "Videos/", 168 "Pictures/", 169 "Audios/", 170 "Documents/", 171 "Download/" 172 }; 173 174 const std::vector<std::string> fileKeyEnumValues { 175 MEDIA_DATA_DB_ID, 176 MEDIA_DATA_DB_RELATIVE_PATH, 177 MEDIA_DATA_DB_NAME, 178 MEDIA_DATA_DB_PARENT_ID, 179 MEDIA_DATA_DB_MIME_TYPE, 180 MEDIA_DATA_DB_MEDIA_TYPE, 181 MEDIA_DATA_DB_SIZE, 182 MEDIA_DATA_DB_DATE_ADDED, 183 MEDIA_DATA_DB_DATE_MODIFIED, 184 MEDIA_DATA_DB_DATE_TAKEN, 185 MEDIA_DATA_DB_TITLE, 186 MEDIA_DATA_DB_ARTIST, 187 MEDIA_DATA_DB_AUDIO_ALBUM, 188 MEDIA_DATA_DB_DURATION, 189 MEDIA_DATA_DB_WIDTH, 190 MEDIA_DATA_DB_HEIGHT, 191 MEDIA_DATA_DB_ORIENTATION, 192 MEDIA_DATA_DB_BUCKET_ID, 193 MEDIA_DATA_DB_BUCKET_NAME 194 }; 195 196 struct JSAsyncContextOutput { 197 napi_value error; 198 napi_value data; 199 bool status; 200 }; 201 202 /* Util class used by napi asynchronous methods for making call to js callback function */ 203 class MediaLibraryNapiUtils { 204 public: GetAssetType(MediaType type)205 static AssetType GetAssetType(MediaType type) 206 { 207 AssetType result; 208 209 switch (type) { 210 case MEDIA_TYPE_AUDIO: 211 result = ASSET_AUDIO; 212 break; 213 case MEDIA_TYPE_VIDEO: 214 result = ASSET_VIDEO; 215 break; 216 case MEDIA_TYPE_IMAGE: 217 result = ASSET_IMAGE; 218 break; 219 case MEDIA_TYPE_MEDIA: 220 result = ASSET_MEDIA; 221 break; 222 default: 223 result = ASSET_NONE; 224 break; 225 } 226 227 return result; 228 } UpdateFetchOptionSelection(std::string & selection,const std::string & prefix)229 static void UpdateFetchOptionSelection(std::string &selection, const std::string &prefix) 230 { 231 if (!prefix.empty()) { 232 if (!selection.empty()) { 233 selection = prefix + "AND (" + selection + ")"; 234 } else { 235 selection = prefix; 236 } 237 } 238 } GetMediaTypeUri(MediaType mediaType)239 static std::string GetMediaTypeUri(MediaType mediaType) 240 { 241 switch (mediaType) { 242 case MEDIA_TYPE_AUDIO: 243 return MEDIALIBRARY_AUDIO_URI; 244 break; 245 case MEDIA_TYPE_VIDEO: 246 return MEDIALIBRARY_VIDEO_URI; 247 break; 248 case MEDIA_TYPE_IMAGE: 249 return MEDIALIBRARY_IMAGE_URI; 250 break; 251 case MEDIA_TYPE_SMARTALBUM: 252 return MEDIALIBRARY_SMARTALBUM_CHANGE_URI; 253 break; 254 case MEDIA_TYPE_DEVICE: 255 return MEDIALIBRARY_DEVICE_URI; 256 break; 257 case MEDIA_TYPE_FILE: 258 default: 259 return MEDIALIBRARY_FILE_URI; 260 break; 261 } 262 } CreateNapiErrorObject(napi_env env,napi_value & errorObj,const int32_t errCode,const std::string errMsg)263 static void CreateNapiErrorObject(napi_env env, napi_value &errorObj, 264 const int32_t errCode, const std::string errMsg) 265 { 266 HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MediaLibraryNapiUtils"}; 267 napi_status statusError; 268 napi_value napiErrorCode = nullptr; 269 napi_value napiErrorMsg = nullptr; 270 statusError = napi_create_string_utf8(env, std::to_string(errCode).c_str(), NAPI_AUTO_LENGTH, &napiErrorCode); 271 if (statusError == napi_ok) { 272 statusError = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &napiErrorMsg); 273 if (statusError == napi_ok) { 274 statusError = napi_create_error(env, napiErrorCode, napiErrorMsg, &errorObj); 275 if (statusError == napi_ok) { 276 HiLog::Debug(LABEL, "napi_create_error success"); 277 } 278 } 279 } 280 } 281 InvokeJSAsyncMethod(napi_env env,napi_deferred deferred,napi_ref callbackRef,napi_async_work work,const JSAsyncContextOutput & asyncContext)282 static void InvokeJSAsyncMethod(napi_env env, napi_deferred deferred, 283 napi_ref callbackRef, napi_async_work work, const JSAsyncContextOutput &asyncContext) 284 { 285 HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MediaLibraryNapiUtils"}; 286 HiLog::Debug(LABEL, "InvokeJSAsyncMethod IN"); 287 napi_value retVal; 288 napi_value callback = nullptr; 289 290 /* Deferred is used when JS Callback method expects a promise value */ 291 if (deferred) { 292 HiLog::Debug(LABEL, "InvokeJSAsyncMethod promise"); 293 if (asyncContext.status) { 294 napi_resolve_deferred(env, deferred, asyncContext.data); 295 } else { 296 napi_reject_deferred(env, deferred, asyncContext.error); 297 } 298 } else { 299 HiLog::Debug(LABEL, "InvokeJSAsyncMethod callback"); 300 napi_value result[ARGS_TWO]; 301 result[PARAM0] = asyncContext.error; 302 result[PARAM1] = asyncContext.data; 303 napi_get_reference_value(env, callbackRef, &callback); 304 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal); 305 napi_delete_reference(env, callbackRef); 306 } 307 napi_delete_async_work(env, work); 308 HiLog::Debug(LABEL, "InvokeJSAsyncMethod OUT"); 309 } 310 ToUTF8String(napi_env env,napi_value value)311 static std::tuple<bool, std::unique_ptr<char[]>, size_t> ToUTF8String(napi_env env, napi_value value) 312 { 313 size_t strLen = 0; 314 HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MediaLibraryNapiUtils"}; 315 napi_status status = napi_get_value_string_utf8(env, value, nullptr, -1, &strLen); 316 if (status != napi_ok) { 317 HiLog::Error(LABEL, "ToUTF8String get fail, %{public}d", status); 318 return { false, nullptr, 0 }; 319 } 320 321 size_t bufLen = strLen + 1; 322 std::unique_ptr<char[]> str = std::make_unique<char[]>(bufLen); 323 if (str == nullptr) { 324 HiLog::Error(LABEL, "ToUTF8String get memory fail"); 325 return { false, nullptr, 0 }; 326 } 327 status = napi_get_value_string_utf8(env, value, str.get(), bufLen, &strLen); 328 return std::make_tuple(status == napi_ok, move(str), strLen); 329 } 330 IsExistsByPropertyName(napi_env env,napi_value jsObject,const char * propertyName)331 static bool IsExistsByPropertyName(napi_env env, napi_value jsObject, const char *propertyName) 332 { 333 bool result = false; 334 HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MediaLibraryNapiUtils"}; 335 if (napi_has_named_property(env, jsObject, propertyName, &result) == napi_ok) { 336 return result; 337 } else { 338 HiLog::Error(LABEL, "IsExistsByPropertyName not exist %{public}s", propertyName); 339 return false; 340 } 341 } 342 GetPropertyValueByName(napi_env env,napi_value jsObject,const char * propertyName)343 static napi_value GetPropertyValueByName(napi_env env, napi_value jsObject, const char *propertyName) 344 { 345 napi_value value = nullptr; 346 HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MediaLibraryNapiUtils"}; 347 if (IsExistsByPropertyName(env, jsObject, propertyName) == false) { 348 HiLog::Error(LABEL, "GetPropertyValueByName not exist %{public}s", propertyName); 349 return nullptr; 350 } 351 if (napi_get_named_property(env, jsObject, propertyName, &value) != napi_ok) { 352 HiLog::Error(LABEL, "GetPropertyValueByName get fail %{public}s", propertyName); 353 return nullptr; 354 } 355 return value; 356 } 357 CheckJSArgsTypeAsFunc(napi_env env,napi_value arg)358 static bool CheckJSArgsTypeAsFunc(napi_env env, napi_value arg) 359 { 360 napi_valuetype valueType = napi_undefined; 361 napi_typeof(env, arg, &valueType); 362 return (valueType == napi_function); 363 } 364 IsArrayForNapiValue(napi_env env,napi_value param,uint32_t & arraySize)365 static bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize) 366 { 367 bool isArray = false; 368 arraySize = 0; 369 if ((napi_is_array(env, param, &isArray) != napi_ok) || (isArray == false)) { 370 return false; 371 } 372 if (napi_get_array_length(env, param, &arraySize) != napi_ok) { 373 return false; 374 } 375 return true; 376 } 377 }; 378 } // namespace Media 379 } // namespace OHOS 380 #endif /* MEDIALIBRARY_NAPI_UTILS_H */ 381