• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2022 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 INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIALIBRARY_NAPI_UTILS_H_
17 #define INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIALIBRARY_NAPI_UTILS_H_
18 
19 #include <tuple>
20 #include <memory>
21 #include <vector>
22 #include <unordered_map>
23 #include "datashare_result_set.h"
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "hitrace_meter.h"
27 #include "medialibrary_client_errno.h"
28 #include "medialibrary_db_const.h"
29 #include "medialibrary_errno.h"
30 #include "medialibrary_napi_log.h"
31 #include "medialibrary_tracer.h"
32 #include "medialibrary_type_const.h"
33 #include "datashare_predicates.h"
34 
35 #define GET_JS_ARGS(env, info, argc, argv, thisVar)                         \
36     do {                                                                    \
37         void* data;                                                         \
38         napi_get_cb_info(env, info, &(argc), argv, &(thisVar), &(data));    \
39     } while (0)
40 
41 #define GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar)                           \
42     do {                                                                                \
43         void* data;                                                                     \
44         status = napi_get_cb_info(env, info, nullptr, nullptr, &(thisVar), &(data));    \
45     } while (0)
46 
47 #define GET_JS_ASYNC_CB_REF(env, arg, count, cbRef)                                             \
48     do {                                                                                        \
49         napi_valuetype valueType = napi_undefined;                                              \
50         if ((napi_typeof(env, arg, &valueType) == napi_ok) && (valueType == napi_function)) {   \
51             napi_create_reference(env, arg, count, &(cbRef));                                   \
52         } else {                                                                                \
53             NAPI_ERR_LOG("invalid arguments");                                           \
54             NAPI_ASSERT(env, false, "type mismatch");                                           \
55         }                                                                                       \
56     } while (0)
57 
58 #define ASSERT_NULLPTR_CHECK(env, result)       \
59     do {                                        \
60         if ((result) == nullptr) {              \
61             napi_get_undefined(env, &(result)); \
62             return result;                      \
63         }                                       \
64     } while (0)
65 
66 #define NAPI_CREATE_PROMISE(env, callbackRef, deferred, result)     \
67     do {                                                            \
68         if ((callbackRef) == nullptr) {                             \
69             napi_create_promise(env, &(deferred), &(result));       \
70         }                                                           \
71     } while (0)
72 
73 #define NAPI_CREATE_RESOURCE_NAME(env, resource, resourceName, context)         \
74     do {                                                                            \
75         napi_create_string_utf8(env, resourceName, NAPI_AUTO_LENGTH, &(resource));  \
76         (context)->SetApiName(resourceName);                                        \
77     } while (0)
78 
79 #define CHECK_NULL_PTR_RETURN_UNDEFINED(env, ptr, ret, message)     \
80     do {                                                            \
81         if ((ptr) == nullptr) {                                     \
82             NAPI_ERR_LOG(message);                           \
83             napi_get_undefined(env, &(ret));                        \
84             return ret;                                             \
85         }                                                           \
86     } while (0)
87 
88 #define CHECK_NULL_PTR_RETURN_VOID(ptr, message)   \
89     do {                                           \
90         if ((ptr) == nullptr) {                    \
91             NAPI_ERR_LOG(message);          \
92             return;                                \
93         }                                          \
94     } while (0)
95 #define CHECK_IF_EQUAL(condition, errMsg)   \
96     do {                                    \
97         if (!(condition)) {                 \
98             NAPI_ERR_LOG(errMsg);    \
99             return;                         \
100         }                                   \
101     } while (0)
102 
103 #define CHECK_COND_RET(cond, ret, message)                          \
104     do {                                                            \
105         if (!(cond)) {                                              \
106             NAPI_ERR_LOG(message);                                  \
107             return ret;                                             \
108         }                                                           \
109     } while (0)
110 
111 #define CHECK_STATUS_RET(cond, message)                             \
112     do {                                                            \
113         napi_status __ret = (cond);                                 \
114         if (__ret != napi_ok) {                                     \
115             NAPI_ERR_LOG(message);                                  \
116             return __ret;                                           \
117         }                                                           \
118     } while (0)
119 
120 #define CHECK_ARGS(env, cond, context, err)                         \
121     do {                                                            \
122         if ((cond) != napi_ok) {                                    \
123             NAPI_THROW(env, context, err);                          \
124             return nullptr;                                         \
125         }                                                           \
126     } while (0)
127 
128 #define NAPI_THROW(env, context, err)                               \
129     do {                                                            \
130         (context)->ThrowError(env, err);                            \
131     } while (0)
132 
133 namespace OHOS {
134 namespace Media {
135 /* Constants for array index */
136 const int32_t PARAM0 = 0;
137 const int32_t PARAM1 = 1;
138 const int32_t PARAM2 = 2;
139 const int32_t PARAM3 = 3;
140 
141 /* Constants for array size */
142 const int32_t ARGS_ZERO = 0;
143 const int32_t ARGS_ONE = 1;
144 const int32_t ARGS_TWO = 2;
145 const int32_t ARGS_THREE = 3;
146 const int32_t ARGS_FOUR = 4;
147 const int32_t ARG_BUF_SIZE = 100;
148 constexpr uint32_t NAPI_INIT_REF_COUNT = 1;
149 
150 constexpr size_t NAPI_ARGC_MAX = 4;
151 
152 // Error codes
153 const int32_t ERR_DEFAULT = 0;
154 const int32_t ERR_MEM_ALLOCATION = 2;
155 const int32_t ERR_INVALID_OUTPUT = 3;
156 
157 const int32_t TRASH_SMART_ALBUM_ID = 1;
158 const std::string TRASH_SMART_ALBUM_NAME = "TrashAlbum";
159 const int32_t FAVORIT_SMART_ALBUM_ID = 2;
160 const std::string FAVORIT_SMART_ALBUM_NAME = "FavoritAlbum";
161 
162 enum NapiAssetType {
163     TYPE_AUDIO = 0,
164     TYPE_VIDEO = 1,
165     TYPE_IMAGE = 2,
166     TYPE_ALBUM = 3,
167 };
168 
169 enum AlbumType {
170     TYPE_VIDEO_ALBUM = 0,
171     TYPE_IMAGE_ALBUM = 1,
172     TYPE_NONE = 2,
173 };
174 
175 const std::vector<std::string> privateAlbumTypeNameEnum {
176     "TYPE_FAVORITE", "TYPE_TRASH", "TYPE_HIDE", "TYPE_SMART", "TYPE_SEARCH"
177 };
178 
179 const std::vector<std::string> mediaTypesEnum {
180     "FILE", "IMAGE", "VIDEO", "AUDIO", "MEDIA", "ALBUM_LIST", "ALBUM_LIST_INFO"
181 };
182 
183 const std::vector<std::string> mediaTypesUserFileEnum {
184     "IMAGE", "VIDEO", "AUDIO"
185 };
186 
187 const std::vector<std::string> fileKeyEnum {
188     "ID", "RELATIVE_PATH", "DISPLAY_NAME", "PARENT", "MIME_TYPE", "MEDIA_TYPE", "SIZE",
189     "DATE_ADDED", "DATE_MODIFIED", "DATE_TAKEN", "TITLE", "ARTIST", "AUDIOALBUM", "DURATION",
190     "WIDTH", "HEIGHT", "ORIENTATION", "ALBUM_ID", "ALBUM_NAME"
191 };
192 
193 const std::vector<std::string> directoryEnum {
194     "DIR_CAMERA", "DIR_VIDEO", "DIR_IMAGE", "DIR_AUDIO", "DIR_DOCUMENTS", "DIR_DOWNLOAD"
195 };
196 
197 const std::vector<std::string> virtualAlbumTypeEnum {
198     "TYPE_FAVORITE", "TYPE_TRASH"
199 };
200 
201 const std::vector<std::string> directoryEnumValues {
202     "Camera/",
203     "Videos/",
204     "Pictures/",
205     "Audios/",
206     "Documents/",
207     "Download/"
208 };
209 
210 const std::vector<std::string> fileKeyEnumValues {
211     MEDIA_DATA_DB_ID,
212     MEDIA_DATA_DB_RELATIVE_PATH,
213     MEDIA_DATA_DB_NAME,
214     MEDIA_DATA_DB_PARENT_ID,
215     MEDIA_DATA_DB_MIME_TYPE,
216     MEDIA_DATA_DB_MEDIA_TYPE,
217     MEDIA_DATA_DB_SIZE,
218     MEDIA_DATA_DB_DATE_ADDED,
219     MEDIA_DATA_DB_DATE_MODIFIED,
220     MEDIA_DATA_DB_DATE_TAKEN,
221     MEDIA_DATA_DB_TITLE,
222     MEDIA_DATA_DB_ARTIST,
223     MEDIA_DATA_DB_AUDIO_ALBUM,
224     MEDIA_DATA_DB_DURATION,
225     MEDIA_DATA_DB_WIDTH,
226     MEDIA_DATA_DB_HEIGHT,
227     MEDIA_DATA_DB_ORIENTATION,
228     MEDIA_DATA_DB_BUCKET_ID,
229     MEDIA_DATA_DB_BUCKET_NAME
230 };
231 
232 const std::vector<std::pair<std::string, std::string>> FILE_KEY_ENUM_PROPERTIES = {
233     std::make_pair("ID",                        MEDIA_DATA_DB_ID),
234     std::make_pair("RELATIVE_PATH",             MEDIA_DATA_DB_RELATIVE_PATH),
235     std::make_pair("DISPLAY_NAME",              MEDIA_DATA_DB_NAME),
236     std::make_pair("PARENT",                    MEDIA_DATA_DB_PARENT_ID),
237     std::make_pair("MIME_TYPE",                 MEDIA_DATA_DB_MIME_TYPE),
238     std::make_pair("MEDIA_TYPE",                MEDIA_DATA_DB_MEDIA_TYPE),
239     std::make_pair("SIZE",                      MEDIA_DATA_DB_SIZE),
240     std::make_pair("DATE_ADDED",                MEDIA_DATA_DB_DATE_ADDED),
241     std::make_pair("DATE_MODIFIED",             MEDIA_DATA_DB_DATE_MODIFIED),
242     std::make_pair("DATE_TAKEN",                MEDIA_DATA_DB_DATE_TAKEN),
243     std::make_pair("TITLE",                     MEDIA_DATA_DB_TITLE),
244     std::make_pair("ARTIST",                    MEDIA_DATA_DB_ARTIST),
245     std::make_pair("AUDIOALBUM",                MEDIA_DATA_DB_AUDIO_ALBUM),
246     std::make_pair("DURATION",                  MEDIA_DATA_DB_DURATION),
247     std::make_pair("WIDTH",                     MEDIA_DATA_DB_WIDTH),
248     std::make_pair("HEIGHT",                    MEDIA_DATA_DB_HEIGHT),
249     std::make_pair("ORIENTATION",               MEDIA_DATA_DB_ORIENTATION),
250     std::make_pair("ALBUM_ID",                  MEDIA_DATA_DB_BUCKET_ID),
251     std::make_pair("ALBUM_NAME",                MEDIA_DATA_DB_BUCKET_NAME)
252 };
253 
254 const std::vector<std::pair<std::string, std::string>> USERFILEMGR_FILEKEY_ENUM_PROPERTIES = {
255     std::make_pair("URI",                       MEDIA_DATA_DB_URI),
256     std::make_pair("RELATIVE_PATH",             MEDIA_DATA_DB_RELATIVE_PATH),
257     std::make_pair("DISPLAY_NAME",              MEDIA_DATA_DB_NAME),
258     std::make_pair("DATE_ADDED",                MEDIA_DATA_DB_DATE_ADDED),
259     std::make_pair("DATE_MODIFIED",             MEDIA_DATA_DB_DATE_MODIFIED),
260     std::make_pair("TITLE",                     MEDIA_DATA_DB_TITLE)
261 };
262 
263 const std::vector<std::pair<std::string, std::string>> AUDIOKEY_ENUM_PROPERTIES = {
264     std::make_pair("URI",                       MEDIA_DATA_DB_URI),
265     std::make_pair("DISPLAY_NAME",              MEDIA_DATA_DB_NAME),
266     std::make_pair("DATE_ADDED",                MEDIA_DATA_DB_DATE_ADDED),
267     std::make_pair("DATE_MODIFIED",             MEDIA_DATA_DB_DATE_MODIFIED),
268     std::make_pair("TITLE",                     MEDIA_DATA_DB_TITLE),
269     std::make_pair("ARTIST",                    MEDIA_DATA_DB_ARTIST),
270     std::make_pair("AUDIOALBUM",                MEDIA_DATA_DB_AUDIO_ALBUM),
271     std::make_pair("DURATION",                  MEDIA_DATA_DB_DURATION),
272     std::make_pair("FAVORITE",                  MEDIA_DATA_DB_IS_FAV)
273 };
274 
275 const std::vector<std::pair<std::string, std::string>> IMAGEVIDEOKEY_ENUM_PROPERTIES = {
276     std::make_pair("URI",                       MEDIA_DATA_DB_URI),
277     std::make_pair("DISPLAY_NAME",              MEDIA_DATA_DB_NAME),
278     std::make_pair("DATE_ADDED",                MEDIA_DATA_DB_DATE_ADDED),
279     std::make_pair("FILE_TYPE",                 MEDIA_DATA_DB_MEDIA_TYPE),
280     std::make_pair("DATE_MODIFIED",             MEDIA_DATA_DB_DATE_MODIFIED),
281     std::make_pair("TITLE",                     MEDIA_DATA_DB_TITLE),
282     std::make_pair("DURATION",                  MEDIA_DATA_DB_DURATION),
283     std::make_pair("WIDTH",                     MEDIA_DATA_DB_WIDTH),
284     std::make_pair("HEIGHT",                    MEDIA_DATA_DB_HEIGHT),
285     std::make_pair("DATE_TAKEN",                MEDIA_DATA_DB_DATE_TAKEN),
286     std::make_pair("ORIENTATION",               MEDIA_DATA_DB_ORIENTATION),
287     std::make_pair("FAVORITE",                  MEDIA_DATA_DB_IS_FAV),
288     std::make_pair("MEDIA_TYPE",                MEDIA_DATA_DB_MEDIA_TYPE)
289 };
290 
291 const std::vector<std::pair<std::string, std::string>> ALBUMKEY_ENUM_PROPERTIES = {
292     std::make_pair("URI",                       MEDIA_DATA_DB_URI),
293     std::make_pair("ALBUM_NAME",                MEDIA_DATA_DB_BUCKET_NAME),
294     std::make_pair("FILE_TYPE",                 MEDIA_DATA_DB_MEDIA_TYPE),
295     std::make_pair("DATE_ADDED",                MEDIA_DATA_DB_DATE_ADDED),
296     std::make_pair("DATE_MODIFIED",             MEDIA_DATA_DB_DATE_MODIFIED)
297 };
298 
299 struct JSAsyncContextOutput {
300     napi_value error;
301     napi_value data;
302     bool status;
303 };
304 
305 struct NapiClassInfo {
306     std::string name;
307     napi_ref *ref;
308     napi_value (*constructor)(napi_env, napi_callback_info);
309     std::vector<napi_property_descriptor> props;
310 };
311 
312 /* Util class used by napi asynchronous methods for making call to js callback function */
313 class MediaLibraryNapiUtils {
314 public:
315     static napi_value NapiDefineClass(napi_env env, napi_value exports, const NapiClassInfo &info);
316     static napi_value NapiAddStaticProps(napi_env env, napi_value exports,
317         const std::vector<napi_property_descriptor> &staticProps);
318 
319     static napi_status GetUInt32(napi_env env, napi_value arg, uint32_t &value);
320     static napi_status GetInt32(napi_env env, napi_value arg, int32_t &value);
321     static napi_status GetParamBool(napi_env env, napi_value arg, bool &result);
322     static napi_status GetUInt32Array(napi_env env, napi_value arg, std::vector<uint32_t> &param);
323     static napi_status GetParamFunction(napi_env env, napi_value arg, napi_ref &callbackRef);
324     static napi_status GetParamString(napi_env env, napi_value arg, std::string &str);
325     static napi_status GetParamStringPathMax(napi_env env, napi_value arg, std::string &str);
326     static napi_status GetProperty(napi_env env, const napi_value arg, const std::string &propName,
327         std::string &propValue);
328     static napi_status GetArrayProperty(napi_env env, napi_value arg, const std::string &propName,
329         std::vector<std::string> &array);
330     static void GenTypeMaskFromArray(const std::vector<uint32_t> types, std::string &typeMask);
331     static void UriAddFragmentTypeMask(std::string &uri, const std::string &typeMask);
332     static void UriRemoveAllFragment(std::string &uri);
333     static std::string GetFileIdFromUri(const std::string &uri);
334     static MediaType GetMediaTypeFromUri(const std::string &uri);
335     template <class AsyncContext>
336     static napi_status GetPredicate(napi_env env, const napi_value arg, const std::string &propName,
337         AsyncContext &context, bool isAlbum);
338     template <class AsyncContext>
339     static napi_status ParseAlbumFetchOptCallback(napi_env env, napi_callback_info info, AsyncContext &context);
340     template <class AsyncContext>
341     static bool HandleSpecialPredicate(AsyncContext &context,
342         std::shared_ptr<DataShare::DataShareAbsPredicates> &predicate, bool isAlbum);
343     template <class AsyncContext>
344     static void UpdateMediaTypeSelections(AsyncContext *context);
345     static void GetNetworkIdAndFileIdFromUri(const std::string &uri, std::string &networkId, std::string &fileId);
346 
347     template <class AsyncContext>
AsyncContextSetObjectInfo(napi_env env,napi_callback_info info,AsyncContext & asyncContext,const size_t minArgs,const size_t maxArgs)348     static napi_status AsyncContextSetObjectInfo(napi_env env, napi_callback_info info, AsyncContext &asyncContext,
349         const size_t minArgs, const size_t maxArgs)
350     {
351         napi_value thisVar = nullptr;
352         asyncContext->argc = maxArgs;
353         CHECK_STATUS_RET(napi_get_cb_info(env, info, &asyncContext->argc, &(asyncContext->argv[ARGS_ZERO]), &thisVar,
354             nullptr), "Failed to get cb info");
355         CHECK_COND_RET(((asyncContext->argc >= minArgs) && (asyncContext->argc <= maxArgs)), napi_invalid_arg,
356             "Number of args is invalid");
357         if (minArgs > 0) {
358             CHECK_COND_RET(asyncContext->argv[ARGS_ZERO] != nullptr, napi_invalid_arg, "Argument list is empty");
359         }
360         CHECK_STATUS_RET(napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo)),
361             "Failed to unwrap thisVar");
362         CHECK_COND_RET(asyncContext->objectInfo != nullptr, napi_invalid_arg, "Failed to get object info");
363         return napi_ok;
364     }
365 
366     template <class AsyncContext>
GetFetchOption(napi_env env,napi_value arg,AsyncContext & context)367     static napi_status GetFetchOption(napi_env env, napi_value arg, AsyncContext &context)
368     {
369         /* Parse the argument into fetchOption if any */
370         bool hasOpt = false;
371         CHECK_STATUS_RET(hasFetchOpt(env, arg, hasOpt), "Failed to get fetchopt");
372         if (hasOpt) {
373             CHECK_STATUS_RET(GetProperty(env, arg, "selections", context->selection), "Failed to parse selections");
374             CHECK_STATUS_RET(GetProperty(env, arg, "order", context->order), "Failed to parse order");
375             CHECK_STATUS_RET(GetArrayProperty(env, arg, "selectionArgs", context->selectionArgs),
376                 "Failed to parse selectionArgs");
377             CHECK_STATUS_RET(GetProperty(env, arg, "uri", context->uri), "Failed to parse uri");
378             CHECK_STATUS_RET(GetProperty(env, arg, "networkId", context->networkId), "Failed to parse networkId");
379         }
380         return napi_ok;
381     }
382 
383     template <class AsyncContext>
384     static napi_status GetAssetFetchOption(napi_env env, napi_value arg, AsyncContext &context);
385 
386     template <class AsyncContext>
GetParamCallback(napi_env env,AsyncContext & context)387     static napi_status GetParamCallback(napi_env env, AsyncContext &context)
388     {
389         /* Parse the last argument into callbackref if any */
390         bool isCallback = false;
391         CHECK_STATUS_RET(hasCallback(env, context->argc, context->argv, isCallback), "Failed to check callback");
392         if (isCallback) {
393             CHECK_STATUS_RET(GetParamFunction(env, context->argv[context->argc - 1], context->callbackRef),
394                 "Failed to get callback");
395         }
396         return napi_ok;
397     }
398 
399     template <class AsyncContext>
400     static napi_status ParseAssetFetchOptCallback(napi_env env, napi_callback_info info,
401         AsyncContext &context);
402 
403     template <class AsyncContext>
ParseArgsTypeFetchOptCallback(napi_env env,napi_callback_info info,AsyncContext & context)404     static napi_status ParseArgsTypeFetchOptCallback(napi_env env, napi_callback_info info, AsyncContext &context)
405     {
406         constexpr size_t minArgs = ARGS_TWO;
407         constexpr size_t maxArgs = ARGS_THREE;
408         CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
409             "Failed to get object info");
410         /* Parse the first argument into typeMask */
411         CHECK_STATUS_RET(GetUInt32Array(env, context->argv[ARGS_ZERO], context->mediaTypes),
412             "Failed to get param array");
413         CHECK_COND_RET(context->mediaTypes.size() > 0, napi_invalid_arg, "Require at least one type");
414         GenTypeMaskFromArray(context->mediaTypes, context->typeMask);
415         CHECK_STATUS_RET(GetFetchOption(env, context->argv[ARGS_ONE], context), "Failed to get fetch option");
416         CHECK_STATUS_RET(GetParamCallback(env, context), "Failed to get callback");
417         return napi_ok;
418     }
419 
420     template <class AsyncContext>
ParseArgsBoolCallBack(napi_env env,napi_callback_info info,AsyncContext & context,bool & param)421     static napi_status ParseArgsBoolCallBack(napi_env env, napi_callback_info info, AsyncContext &context, bool &param)
422     {
423         constexpr size_t minArgs = ARGS_ONE;
424         constexpr size_t maxArgs = ARGS_TWO;
425         CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
426             "Failed to get object info");
427 
428         /* Parse the first argument into param */
429         CHECK_STATUS_RET(GetParamBool(env, context->argv[ARGS_ZERO], param), "Failed to get parameter");
430         CHECK_STATUS_RET(GetParamCallback(env, context), "Failed to get callback");
431         return napi_ok;
432     }
433 
434     template <class AsyncContext>
ParseArgsStringCallback(napi_env env,napi_callback_info info,AsyncContext & context,std::string & param)435     static napi_status ParseArgsStringCallback(napi_env env, napi_callback_info info, AsyncContext &context,
436         std::string &param)
437     {
438         constexpr size_t minArgs = ARGS_ONE;
439         constexpr size_t maxArgs = ARGS_TWO;
440         CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
441             "Failed to get object info");
442 
443         CHECK_STATUS_RET(GetParamStringPathMax(env, context->argv[ARGS_ZERO], param), "Failed to get string argument");
444         CHECK_STATUS_RET(GetParamCallback(env, context), "Failed to get callback");
445         return napi_ok;
446     }
447 
448     template <class AsyncContext>
ParseArgsNumberCallback(napi_env env,napi_callback_info info,AsyncContext & context,int32_t & value)449     static napi_status ParseArgsNumberCallback(napi_env env, napi_callback_info info, AsyncContext &context,
450         int32_t &value)
451     {
452         constexpr size_t minArgs = ARGS_ONE;
453         constexpr size_t maxArgs = ARGS_TWO;
454         CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
455             "Failed to get object info");
456 
457         CHECK_STATUS_RET(GetInt32(env, context->argv[ARGS_ZERO], value), "Failed to get number argument");
458         CHECK_STATUS_RET(GetParamCallback(env, context), "Failed to get callback");
459         return napi_ok;
460     }
461 
462     template <class AsyncContext>
ParseArgsOnlyCallBack(napi_env env,napi_callback_info info,AsyncContext & context)463     static napi_status ParseArgsOnlyCallBack(napi_env env, napi_callback_info info, AsyncContext &context)
464     {
465         constexpr size_t minArgs = ARGS_ZERO;
466         constexpr size_t maxArgs = ARGS_ONE;
467         CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
468             "Failed to get object info");
469 
470         CHECK_STATUS_RET(GetParamCallback(env, context), "Failed to get callback");
471         return napi_ok;
472     }
473 
GetAssetType(MediaType type)474     static AssetType GetAssetType(MediaType type)
475     {
476         AssetType result;
477 
478         switch (type) {
479             case MEDIA_TYPE_AUDIO:
480                 result = ASSET_AUDIO;
481                 break;
482             case MEDIA_TYPE_VIDEO:
483                 result = ASSET_VIDEO;
484                 break;
485             case MEDIA_TYPE_IMAGE:
486                 result = ASSET_IMAGE;
487                 break;
488             case MEDIA_TYPE_MEDIA:
489                 result = ASSET_MEDIA;
490                 break;
491             default:
492                 result = ASSET_NONE;
493                 break;
494         }
495 
496         return result;
497     }
498 
AppendFetchOptionSelection(std::string & selection,const std::string & newCondition)499     static void AppendFetchOptionSelection(std::string &selection, const std::string &newCondition)
500     {
501         if (!newCondition.empty()) {
502             if (!selection.empty()) {
503                 selection = "(" + selection + ") AND " + newCondition;
504             } else {
505                 selection = newCondition;
506             }
507         }
508     }
509 
GetMediaTypeUri(MediaType mediaType)510     static std::string GetMediaTypeUri(MediaType mediaType)
511     {
512         switch (mediaType) {
513             case MEDIA_TYPE_AUDIO:
514                 return MEDIALIBRARY_AUDIO_URI;
515             case MEDIA_TYPE_VIDEO:
516                 return MEDIALIBRARY_VIDEO_URI;
517             case MEDIA_TYPE_IMAGE:
518                 return MEDIALIBRARY_IMAGE_URI;
519             case MEDIA_TYPE_SMARTALBUM:
520                 return MEDIALIBRARY_SMARTALBUM_CHANGE_URI;
521             case MEDIA_TYPE_DEVICE:
522                 return MEDIALIBRARY_DEVICE_URI;
523             case MEDIA_TYPE_FILE:
524             default:
525                 return MEDIALIBRARY_FILE_URI;
526         }
527     }
528 
TransErrorCode(const std::string & Name,std::shared_ptr<DataShare::DataShareResultSet> resultSet)529     static int TransErrorCode(const std::string &Name, std::shared_ptr<DataShare::DataShareResultSet> resultSet)
530     {
531         NAPI_ERR_LOG("interface: %{public}s, server return nullptr", Name.c_str());
532         // Query can't return errorcode, so assume nullptr as permission deny
533         if (resultSet == nullptr) {
534             return JS_ERR_PERMISSION_DENIED;
535         }
536         return ERR_DEFAULT;
537     }
538 
TransErrorCode(const std::string & Name,int error)539     static int TransErrorCode(const std::string &Name, int error)
540     {
541         NAPI_ERR_LOG("interface: %{public}s, server errcode:%{public}d ", Name.c_str(), error);
542         // Transfer Server error to napi error code
543         if (error <= E_COMMON_START && error >= E_COMMON_END) {
544             error = JS_INNER_FAIL;
545         } else if (trans2JsError.count(error)) {
546             error = trans2JsError.at(error);
547         }
548         return error;
549     }
550 
HandleError(napi_env env,int error,napi_value & errorObj,const std::string & Name)551     static void HandleError(napi_env env, int error, napi_value &errorObj, const std::string &Name)
552     {
553         if (error == ERR_DEFAULT) {
554             return;
555         }
556 
557         std::string errMsg = "operation fail";
558         if (jsErrMap.count(error) > 0) {
559             errMsg = jsErrMap.at(error);
560         }
561         CreateNapiErrorObject(env, errorObj, error, errMsg);
562         errMsg = Name + " " + errMsg;
563         NAPI_ERR_LOG("Error: %{public}s, js errcode:%{public}d ", errMsg.c_str(), error);
564     }
565 
CreateNapiErrorObject(napi_env env,napi_value & errorObj,const int32_t errCode,const std::string errMsg)566     static void CreateNapiErrorObject(napi_env env, napi_value &errorObj,
567         const int32_t errCode, const std::string errMsg)
568     {
569         napi_status statusError;
570         napi_value napiErrorCode = nullptr;
571         napi_value napiErrorMsg = nullptr;
572         statusError = napi_create_string_utf8(env, std::to_string(errCode).c_str(), NAPI_AUTO_LENGTH, &napiErrorCode);
573         if (statusError == napi_ok) {
574             statusError = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &napiErrorMsg);
575             if (statusError == napi_ok) {
576                 statusError = napi_create_error(env, napiErrorCode, napiErrorMsg, &errorObj);
577                 if (statusError == napi_ok) {
578                     NAPI_DEBUG_LOG("napi_create_error success");
579                 }
580             }
581         }
582     }
583 
InvokeJSAsyncMethod(napi_env env,napi_deferred deferred,napi_ref callbackRef,napi_async_work work,const JSAsyncContextOutput & asyncContext)584     static void InvokeJSAsyncMethod(napi_env env, napi_deferred deferred,
585         napi_ref callbackRef, napi_async_work work, const JSAsyncContextOutput &asyncContext)
586     {
587         MediaLibraryTracer tracer;
588         tracer.Start("InvokeJSAsyncMethod");
589 
590         NAPI_DEBUG_LOG("InvokeJSAsyncMethod IN");
591         napi_value retVal;
592         napi_value callback = nullptr;
593 
594         /* Deferred is used when JS Callback method expects a promise value */
595         if (deferred) {
596             NAPI_DEBUG_LOG("InvokeJSAsyncMethod promise");
597             if (asyncContext.status) {
598                 napi_resolve_deferred(env, deferred, asyncContext.data);
599             } else {
600                 napi_reject_deferred(env, deferred, asyncContext.error);
601             }
602         } else {
603             NAPI_DEBUG_LOG("InvokeJSAsyncMethod callback");
604             napi_value result[ARGS_TWO];
605             result[PARAM0] = asyncContext.error;
606             result[PARAM1] = asyncContext.data;
607             napi_get_reference_value(env, callbackRef, &callback);
608             napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
609             napi_delete_reference(env, callbackRef);
610         }
611         napi_delete_async_work(env, work);
612         NAPI_DEBUG_LOG("InvokeJSAsyncMethod OUT");
613     }
614 
615     template <class AsyncContext>
NapiCreateAsyncWork(napi_env env,std::unique_ptr<AsyncContext> & asyncContext,const std::string & resourceName,void (* execute)(napi_env,void *),void (* complete)(napi_env,napi_status,void *))616     static napi_value NapiCreateAsyncWork(napi_env env, std::unique_ptr<AsyncContext> &asyncContext,
617         const std::string &resourceName,  void (*execute)(napi_env, void *),
618         void (*complete)(napi_env, napi_status, void *))
619     {
620         napi_value result = nullptr;
621         napi_value resource = nullptr;
622         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
623         NAPI_CREATE_RESOURCE_NAME(env, resource, resourceName.c_str(), asyncContext);
624 
625         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, execute, complete,
626             static_cast<void*>(asyncContext.get()), &asyncContext->work));
627         NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
628         asyncContext.release();
629 
630         return result;
631     }
632 
ToUTF8String(napi_env env,napi_value value)633     static std::tuple<bool, std::unique_ptr<char[]>, size_t> ToUTF8String(napi_env env, napi_value value)
634     {
635         size_t strLen = 0;
636         napi_status status = napi_get_value_string_utf8(env, value, nullptr, -1, &strLen);
637         if (status != napi_ok) {
638             NAPI_ERR_LOG("ToUTF8String get fail, %{public}d", status);
639             return { false, nullptr, 0 };
640         }
641 
642         size_t bufLen = strLen + 1;
643         std::unique_ptr<char[]> str = std::make_unique<char[]>(bufLen);
644         if (str == nullptr) {
645             NAPI_ERR_LOG("ToUTF8String get memory fail");
646             return { false, nullptr, 0 };
647         }
648         status = napi_get_value_string_utf8(env, value, str.get(), bufLen, &strLen);
649         return std::make_tuple(status == napi_ok, move(str), strLen);
650     }
651 
IsExistsByPropertyName(napi_env env,napi_value jsObject,const char * propertyName)652     static bool IsExistsByPropertyName(napi_env env, napi_value jsObject, const char *propertyName)
653     {
654         bool result = false;
655         if (napi_has_named_property(env, jsObject, propertyName, &result) == napi_ok) {
656             return result;
657         } else {
658             NAPI_ERR_LOG("IsExistsByPropertyName not exist %{public}s", propertyName);
659             return false;
660         }
661     }
662 
GetPropertyValueByName(napi_env env,napi_value jsObject,const char * propertyName)663     static napi_value GetPropertyValueByName(napi_env env, napi_value jsObject, const char *propertyName)
664     {
665         napi_value value = nullptr;
666         if (IsExistsByPropertyName(env, jsObject, propertyName) == false) {
667             NAPI_ERR_LOG("GetPropertyValueByName not exist %{public}s", propertyName);
668             return nullptr;
669         }
670         if (napi_get_named_property(env, jsObject, propertyName, &value) != napi_ok) {
671             NAPI_ERR_LOG("GetPropertyValueByName get fail %{public}s", propertyName);
672             return nullptr;
673         }
674         return value;
675     }
676 
CheckJSArgsTypeAsFunc(napi_env env,napi_value arg)677     static bool CheckJSArgsTypeAsFunc(napi_env env, napi_value arg)
678     {
679         napi_valuetype valueType = napi_undefined;
680         napi_typeof(env, arg, &valueType);
681         return (valueType == napi_function);
682     }
683 
IsArrayForNapiValue(napi_env env,napi_value param,uint32_t & arraySize)684     static bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize)
685     {
686         bool isArray = false;
687         arraySize = 0;
688         if ((napi_is_array(env, param, &isArray) != napi_ok) || (isArray == false)) {
689             return false;
690         }
691         if (napi_get_array_length(env, param, &arraySize) != napi_ok) {
692             return false;
693         }
694         return true;
695     }
696 private:
697     static napi_status hasCallback(napi_env env, const size_t argc, const napi_value argv[],
698         bool &isCallback);
699     static napi_status hasFetchOpt(napi_env env, const napi_value arg, bool &hasFetchOpt);
700 };
701 } // namespace Media
702 } // namespace OHOS
703 
704 #endif  // INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIALIBRARY_NAPI_UTILS_H_
705