• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "napi_account_common.h"
17 
18 #include "account_log_wrapper.h"
19 #include "js_native_api.h"
20 #include "js_native_api_types.h"
21 #include "napi_account_error.h"
22 #include "napi/native_api.h"
23 #include "napi/native_common.h"
24 #include "napi/native_node_api.h"
25 #include "securec.h"
26 
27 namespace OHOS {
28 namespace AccountJsKit {
29 namespace {
30 constexpr int32_t BUSINESS_ERROR_ARG_SIZE = 2;
31 }
32 
33 using namespace AccountSA;
34 
ProcessCallbackOrPromise(napi_env env,const CommonAsyncContext * asyncContext,napi_value err,napi_value data)35 void ProcessCallbackOrPromise(napi_env env, const CommonAsyncContext *asyncContext, napi_value err, napi_value data)
36 {
37     napi_value args[BUSINESS_ERROR_ARG_SIZE] = {0};
38     if (asyncContext->errCode == ERR_OK) {
39         napi_get_null(env, &args[0]);
40         args[1] = data;
41     } else {
42         napi_get_null(env, &args[1]);
43         args[0] = err;
44     }
45     if (asyncContext->deferred) {
46         if (asyncContext->errCode == ERR_OK) {
47             napi_resolve_deferred(env, asyncContext->deferred, args[1]);
48         } else {
49             napi_reject_deferred(env, asyncContext->deferred, args[0]);
50         }
51     } else {
52         napi_value callback = nullptr;
53         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
54         napi_value returnVal = nullptr;
55         napi_call_function(env, nullptr, callback, BUSINESS_ERROR_ARG_SIZE, &args[0], &returnVal);
56         if (asyncContext->callbackRef != nullptr) {
57             napi_delete_reference(env, asyncContext->callbackRef);
58         }
59     }
60 }
61 
NapiCallVoidFunction(napi_env env,napi_value * argv,size_t argc,napi_ref funcRef)62 void NapiCallVoidFunction(napi_env env, napi_value *argv, size_t argc, napi_ref funcRef)
63 {
64     napi_value undefined = nullptr;
65     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
66     napi_value returnVal;
67     napi_value func = nullptr;
68     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, funcRef, &func));
69     napi_call_function(env, undefined, func, argc, argv, &returnVal);
70 }
71 
InitUvWorkCallbackEnv(uv_work_t * work,napi_handle_scope & scope)72 bool InitUvWorkCallbackEnv(uv_work_t *work, napi_handle_scope &scope)
73 {
74     if (work == nullptr) {
75         ACCOUNT_LOGE("work is nullptr");
76         return false;
77     }
78     if (work->data == nullptr) {
79         ACCOUNT_LOGE("data is nullptr");
80         return false;
81     }
82     CommonAsyncContext *data = reinterpret_cast<CommonAsyncContext *>(work->data);
83     napi_open_handle_scope(data->env, &scope);
84     if (scope == nullptr) {
85         ACCOUNT_LOGE("fail to open scope");
86         return false;
87     }
88     return true;
89 }
90 
ReleaseNapiRefAsync(napi_env env,napi_ref napiRef)91 void ReleaseNapiRefAsync(napi_env env, napi_ref napiRef)
92 {
93     ReleaseNapiRefArray(env, {napiRef});
94 }
95 
ReleaseNapiRefArray(napi_env env,const std::vector<napi_ref> & napiRefVec)96 void ReleaseNapiRefArray(napi_env env, const std::vector<napi_ref> &napiRefVec)
97 {
98     if (env == nullptr) {
99         ACCOUNT_LOGE("invalid env");
100         return;
101     }
102     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
103     std::unique_ptr<NapiRefArrayContext> context = std::make_unique<NapiRefArrayContext>();
104     uv_loop_s *loop = nullptr;
105     napi_get_uv_event_loop(env, &loop);
106     if ((loop == nullptr) || (work == nullptr) || (context == nullptr)) {
107         ACCOUNT_LOGE("fail to init execution environment");
108         return;
109     }
110     context->env = env;
111     context->napiRefVec = napiRefVec;
112     work->data = reinterpret_cast<void *>(context.get());
113     NAPI_CALL_RETURN_VOID(env, uv_queue_work(loop, work.get(), [] (uv_work_t *work) {},
114         [] (uv_work_t *work, int status) {
115             if (work == nullptr) {
116                 ACCOUNT_LOGE("work is nullptr");
117                 return;
118             }
119             auto context = reinterpret_cast<NapiRefArrayContext *>(work->data);
120             if (context == nullptr) {
121                 ACCOUNT_LOGE("context is nullptr");
122                 delete work;
123                 return;
124             }
125             for (auto &napiRef : context->napiRefVec) {
126                 if (napiRef != nullptr) {
127                     napi_delete_reference(context->env, napiRef);
128                 }
129             }
130             delete context;
131             delete work;
132         }));
133     context.release();
134     work.release();
135 }
136 
GetIntProperty(napi_env env,napi_value obj,int32_t & property)137 bool GetIntProperty(napi_env env, napi_value obj, int32_t &property)
138 {
139     napi_valuetype valueType = napi_undefined;
140     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
141     if (valueType != napi_number) {
142         return false;
143     }
144 
145     NAPI_CALL_BASE(env, napi_get_value_int32(env, obj, &property), false);
146     return true;
147 }
148 
GetLongIntProperty(napi_env env,napi_value obj,int64_t & property)149 bool GetLongIntProperty(napi_env env, napi_value obj, int64_t &property)
150 {
151     napi_valuetype valueType = napi_undefined;
152     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
153     if (valueType != napi_number) {
154         return false;
155     }
156 
157     NAPI_CALL_BASE(env, napi_get_value_int64(env, obj, &property), false);
158     return true;
159 }
160 
GetBoolProperty(napi_env env,napi_value obj,bool & property)161 bool GetBoolProperty(napi_env env, napi_value obj, bool &property)
162 {
163     napi_valuetype valueType = napi_undefined;
164     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
165     if (valueType != napi_boolean) {
166         return false;
167     }
168     NAPI_CALL_BASE(env, napi_get_value_bool(env, obj, &property), false);
169     return true;
170 }
171 
GetStringProperty(napi_env env,napi_value obj,std::string & property)172 bool GetStringProperty(napi_env env, napi_value obj, std::string &property)
173 {
174     napi_valuetype valuetype = napi_undefined;
175     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valuetype), false);
176     if (valuetype != napi_string) {
177         return false;
178     }
179 
180     size_t propLen;
181     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, obj, nullptr, 0, &propLen), false);
182     property.reserve(propLen + 1);
183     property.resize(propLen);
184     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, obj, property.data(), propLen + 1, &propLen), false);
185     return true;
186 }
187 
GetStringArrayProperty(napi_env env,napi_value obj,std::vector<std::string> & property,bool allowEmpty)188 bool GetStringArrayProperty(napi_env env, napi_value obj, std::vector<std::string> &property, bool allowEmpty)
189 {
190     bool isArray = false;
191     NAPI_CALL_BASE(env, napi_is_array(env, obj, &isArray), false);
192     if (!isArray) {
193         return false;
194     }
195     uint32_t length = 0;
196     NAPI_CALL_BASE(env, napi_get_array_length(env, obj, &length), false);
197     if (!allowEmpty && (length == 0)) {
198         return false;
199     }
200 
201     for (size_t i = 0; i < length; i++) {
202         napi_value strJs = nullptr;
203         NAPI_CALL_BASE(env, napi_get_element(env, obj, i, &strJs), false);
204         std::string str;
205         if (!GetStringProperty(env, strJs, str)) {
206             return false;
207         }
208         property.emplace_back(str);
209     }
210     return true;
211 }
212 
GetCallbackProperty(napi_env env,napi_value obj,napi_ref & property,int argNum)213 bool GetCallbackProperty(napi_env env, napi_value obj, napi_ref &property, int argNum)
214 {
215     napi_valuetype valueType = napi_undefined;
216     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
217     if (valueType != napi_function) {
218         return false;
219     }
220     NAPI_CALL_BASE(env, napi_create_reference(env, obj, argNum, &property), false);
221     return true;
222 }
223 
GetStringPropertyByKey(napi_env env,napi_value obj,const std::string & propertyName,std::string & property)224 bool GetStringPropertyByKey(napi_env env, napi_value obj, const std::string &propertyName, std::string &property)
225 {
226     napi_value value = nullptr;
227     NAPI_CALL_BASE(env, napi_get_named_property(env, obj, propertyName.c_str(), &value), false);
228 
229     return GetStringProperty(env, value, property);
230 }
231 
GetOptionalStringPropertyByKey(napi_env env,napi_value obj,const std::string & propertyName,std::string & property)232 bool GetOptionalStringPropertyByKey(napi_env env, napi_value obj, const std::string &propertyName,
233     std::string &property)
234 {
235     bool hasProp = false;
236     napi_has_named_property(env, obj, propertyName.c_str(), &hasProp);
237     if (!hasProp) {
238         return true;
239     }
240 
241     return GetStringPropertyByKey(env, obj, propertyName, property);
242 }
243 
CreateStringArray(napi_env env,const std::vector<std::string> & strVec)244 napi_value CreateStringArray(napi_env env, const std::vector<std::string> &strVec)
245 {
246     napi_value result = nullptr;
247     napi_create_array(env, &result);
248     for (size_t i = 0; i < strVec.size(); ++i) {
249         napi_value value = nullptr;
250         napi_create_string_utf8(env, strVec[i].c_str(), NAPI_AUTO_LENGTH, &value);
251         napi_set_element(env, result, i, value);
252     }
253     return result;
254 }
255 
CreateUint8Array(napi_env env,const uint8_t * srcData,size_t length)256 napi_value CreateUint8Array(napi_env env, const uint8_t *srcData, size_t length)
257 {
258     napi_value result = nullptr;
259     void* dstData = nullptr;
260     napi_value napiArr = nullptr;
261     NAPI_CALL(env, napi_create_arraybuffer(env, length, &dstData, &napiArr));
262     if ((length > 0) && (memcpy_s(dstData, length, srcData, length) != EOK)) {
263         return result;
264     }
265     NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, length, napiArr, 0, &result));
266     return result;
267 }
268 
ParseUint8TypedArray(napi_env env,napi_value value,uint8_t ** data,size_t * length)269 napi_status ParseUint8TypedArray(napi_env env, napi_value value, uint8_t **data, size_t *length)
270 {
271     *data = nullptr;
272     *length = 0;
273     bool isTypedArray = false;
274     napi_is_typedarray(env, value, &isTypedArray);
275     if (!isTypedArray) {
276         ACCOUNT_LOGE("invalid uint8 array");
277         return napi_ok;
278     }
279     napi_typedarray_type arrayType;
280     napi_value buffer = nullptr;
281     size_t offset = 0;
282     napi_get_typedarray_info(env, value, &arrayType, length, reinterpret_cast<void **>(data), &buffer, &offset);
283     if (arrayType != napi_uint8_array) {
284         ACCOUNT_LOGE("invalid uint8 array");
285         *data = nullptr;
286         *length = 0;
287     }
288     return napi_ok;
289 }
290 
ParseUint8TypedArrayToVector(napi_env env,napi_value value,std::vector<uint8_t> & vec)291 napi_status ParseUint8TypedArrayToVector(napi_env env, napi_value value, std::vector<uint8_t> &vec)
292 {
293     uint8_t *data = nullptr;
294     size_t length = 0;
295     napi_status status = ParseUint8TypedArray(env, value, &data, &length);
296     if (status != napi_ok) {
297         ACCOUNT_LOGE("failed to ParseUint8TypedArray");
298         return status;
299     }
300     vec.assign(data, data + length);
301     return napi_ok;
302 }
303 
ParseUint8TypedArrayToUint64(napi_env env,napi_value value,uint64_t & result)304 napi_status ParseUint8TypedArrayToUint64(napi_env env, napi_value value, uint64_t &result)
305 {
306     uint8_t *data = nullptr;
307     size_t length = 0;
308     napi_status status = ParseUint8TypedArray(env, value, &data, &length);
309     if (status != napi_ok) {
310         ACCOUNT_LOGE("failed to ParseUint8TypedArray");
311         return status;
312     }
313     if (data == nullptr) {
314         result = 0;
315         return napi_invalid_arg;
316     }
317     if (length != sizeof(uint64_t)) {
318         ACCOUNT_LOGE("failed to convert to uint64_t value");
319         return napi_invalid_arg;
320     }
321     result = *(reinterpret_cast<uint64_t *>(data));
322     return napi_ok;
323 }
324 } // namespace AccountJsKit
325 } // namespace OHOS