• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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