1 /*
2  * Copyright (c) 2022-2024 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 #include "ipc_skeleton.h"
16 #include "napi_account_common.h"
17 
18 #include "account_log_wrapper.h"
19 #include "bundle_mgr_proxy.h"
20 #include "iservice_registry.h"
21 #include "js_native_api.h"
22 #include "js_native_api_types.h"
23 #include "napi_account_error.h"
24 #include "napi/native_api.h"
25 #include "napi/native_common.h"
26 #include "napi/native_node_api.h"
27 #include "securec.h"
28 #include "system_ability_definition.h"
29 #include "tokenid_kit.h"
30 
31 namespace OHOS {
32 namespace AccountJsKit {
33 namespace {
34 constexpr int32_t BUSINESS_ERROR_ARG_SIZE = 2;
35 const char BUSINESS_ERROR_CODE_NAME[] = "code";
36 const char BUSINESS_ERROR_DATA_NAME[] = "data";
37 }
38 
39 using namespace AccountSA;
40 
~CommonAsyncContext()41 CommonAsyncContext::~CommonAsyncContext()
42 {
43     if (env == nullptr) {
44         return;
45     }
46     if (callbackRef != nullptr) {
47         napi_delete_reference(env, callbackRef);
48         callbackRef = nullptr;
49     }
50     if (work != nullptr) {
51         napi_delete_async_work(env, work);
52         work = nullptr;
53     }
54 }
55 
CreateExecEnv(napi_env env,uv_loop_s ** loop,uv_work_t ** work)56 bool CreateExecEnv(napi_env env, uv_loop_s **loop, uv_work_t **work)
57 {
58     *loop = nullptr;
59     napi_get_uv_event_loop(env, loop);
60     if (*loop == nullptr) {
61         ACCOUNT_LOGE("failed to get uv event loop");
62         return false;
63     }
64     *work = new (std::nothrow) uv_work_t;
65     if (*work == nullptr) {
66         ACCOUNT_LOGE("failed to create uv_work_t");
67         return false;
68     }
69     return true;
70 }
71 
ProcessCallbackOrPromise(napi_env env,const CommonAsyncContext * asyncContext,napi_value err,napi_value data)72 void ProcessCallbackOrPromise(napi_env env, const CommonAsyncContext *asyncContext, napi_value err, napi_value data)
73 {
74     napi_value args[BUSINESS_ERROR_ARG_SIZE] = {0};
75     if (asyncContext->errCode == ERR_OK) {
76         napi_get_null(env, &args[0]);
77         args[1] = data;
78     } else {
79         napi_get_null(env, &args[1]);
80         args[0] = err;
81     }
82     if (asyncContext->deferred) {
83         if (asyncContext->errCode == ERR_OK) {
84             napi_resolve_deferred(env, asyncContext->deferred, args[1]);
85         } else {
86             napi_reject_deferred(env, asyncContext->deferred, args[0]);
87         }
88     } else {
89         NapiCallVoidFunction(env, args, BUSINESS_ERROR_ARG_SIZE, asyncContext->callbackRef);
90     }
91 }
92 
ReturnCallbackOrPromise(napi_env env,const CommonAsyncContext * asyncContext,napi_value err,napi_value data)93 void ReturnCallbackOrPromise(napi_env env, const CommonAsyncContext *asyncContext, napi_value err, napi_value data)
94 {
95     napi_value args[BUSINESS_ERROR_ARG_SIZE] = {err, data};
96     if (asyncContext->errCode == ERR_OK) {
97         NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &args[0]));
98     } else {
99         NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &args[1]));
100     }
101     if (asyncContext->deferred != nullptr) {
102         if (asyncContext->errCode == ERR_OK) {
103             NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncContext->deferred, args[1]));
104         } else {
105             NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncContext->deferred, args[0]));
106         }
107         return;
108     }
109     if (asyncContext->callbackRef != nullptr) {
110         NapiCallVoidFunction(env, args, BUSINESS_ERROR_ARG_SIZE, asyncContext->callbackRef);
111     }
112 }
113 
GetIntProperty(napi_env env,napi_value obj,int32_t & property)114 bool GetIntProperty(napi_env env, napi_value obj, int32_t &property)
115 {
116     napi_valuetype valueType = napi_undefined;
117     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
118     if (valueType != napi_number) {
119         return false;
120     }
121 
122     NAPI_CALL_BASE(env, napi_get_value_int32(env, obj, &property), false);
123     return true;
124 }
125 
GetOptionIntProperty(napi_env env,napi_value obj,int32_t & property,bool & hasProperty)126 bool GetOptionIntProperty(napi_env env, napi_value obj, int32_t &property, bool &hasProperty)
127 {
128     napi_valuetype valueType = napi_undefined;
129     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
130     if ((valueType == napi_undefined) || (valueType == napi_null)) {
131         ACCOUNT_LOGI("This value is undefined or null");
132         return true;
133     }
134     if (valueType != napi_number) {
135         return false;
136     }
137     NAPI_CALL_BASE(env, napi_get_value_int32(env, obj, &property), false);
138     hasProperty = true;
139     return true;
140 }
141 
GetLongIntProperty(napi_env env,napi_value obj,int64_t & property)142 bool GetLongIntProperty(napi_env env, napi_value obj, int64_t &property)
143 {
144     napi_valuetype valueType = napi_undefined;
145     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
146     if (valueType != napi_number) {
147         return false;
148     }
149 
150     NAPI_CALL_BASE(env, napi_get_value_int64(env, obj, &property), false);
151     return true;
152 }
153 
GetBoolProperty(napi_env env,napi_value obj,bool & property)154 bool GetBoolProperty(napi_env env, napi_value obj, bool &property)
155 {
156     napi_valuetype valueType = napi_undefined;
157     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
158     if (valueType != napi_boolean) {
159         return false;
160     }
161     NAPI_CALL_BASE(env, napi_get_value_bool(env, obj, &property), false);
162     return true;
163 }
164 
GetStringProperty(napi_env env,napi_value obj,std::string & property)165 bool GetStringProperty(napi_env env, napi_value obj, std::string &property)
166 {
167     napi_valuetype valuetype = napi_undefined;
168     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valuetype), false);
169     if (valuetype != napi_string) {
170         return false;
171     }
172 
173     size_t propLen;
174     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, obj, nullptr, 0, &propLen), false);
175     property.reserve(propLen + 1);
176     property.resize(propLen);
177     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, obj, property.data(), propLen + 1, &propLen), false);
178     return true;
179 }
180 
GetStringArrayProperty(napi_env env,napi_value obj,std::vector<std::string> & property,bool allowEmpty)181 bool GetStringArrayProperty(napi_env env, napi_value obj, std::vector<std::string> &property, bool allowEmpty)
182 {
183     bool isArray = false;
184     NAPI_CALL_BASE(env, napi_is_array(env, obj, &isArray), false);
185     if (!isArray) {
186         return false;
187     }
188     uint32_t length = 0;
189     NAPI_CALL_BASE(env, napi_get_array_length(env, obj, &length), false);
190     if (!allowEmpty && (length == 0)) {
191         return false;
192     }
193 
194     for (size_t i = 0; i < length; i++) {
195         napi_value strJs = nullptr;
196         NAPI_CALL_BASE(env, napi_get_element(env, obj, i, &strJs), false);
197         std::string str;
198         if (!GetStringProperty(env, strJs, str)) {
199             return false;
200         }
201         property.emplace_back(str);
202     }
203     return true;
204 }
205 
GetStringArrayPropertyByKey(napi_env env,napi_value obj,const std::string & propertyName,std::vector<std::string> & property,bool allowEmpty)206 bool GetStringArrayPropertyByKey(napi_env env, napi_value obj, const std::string &propertyName,
207     std::vector<std::string> &property, bool allowEmpty)
208 {
209     napi_value value = nullptr;
210     NAPI_CALL_BASE(env, napi_get_named_property(env, obj, propertyName.c_str(), &value), false);
211     return GetStringArrayProperty(env, value, property, allowEmpty);
212 }
213 
GetCallbackProperty(napi_env env,napi_value obj,napi_ref & property,int argNum)214 bool GetCallbackProperty(napi_env env, napi_value obj, napi_ref &property, int argNum)
215 {
216     napi_valuetype valueType = napi_undefined;
217     NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
218     if ((valueType == napi_undefined) || (valueType == napi_null)) {
219         ACCOUNT_LOGI("the callback is undefined or null");
220         return true;
221     } else if (valueType == napi_function) {
222         NAPI_CALL_BASE(env, napi_create_reference(env, obj, argNum, &property), false);
223         return true;
224     }
225     ACCOUNT_LOGE("the callback is not a napi_function");
226     return false;
227 }
228 
GetStringPropertyByKey(napi_env env,napi_value obj,const std::string & propertyName,std::string & property)229 bool GetStringPropertyByKey(napi_env env, napi_value obj, const std::string &propertyName, std::string &property)
230 {
231     napi_value value = nullptr;
232     NAPI_CALL_BASE(env, napi_get_named_property(env, obj, propertyName.c_str(), &value), false);
233     return GetStringProperty(env, value, property);
234 }
235 
GetOptionalStringPropertyByKey(napi_env env,napi_value obj,const std::string & propertyName,std::string & property)236 bool GetOptionalStringPropertyByKey(napi_env env, napi_value obj, const std::string &propertyName,
237     std::string &property)
238 {
239     bool hasProp = false;
240     napi_has_named_property(env, obj, propertyName.c_str(), &hasProp);
241     if (!hasProp) {
242         return true;
243     }
244     napi_value value = nullptr;
245     NAPI_CALL_BASE(env, napi_get_named_property(env, obj, propertyName.c_str(), &value), false);
246     napi_valuetype valuetype = napi_undefined;
247     NAPI_CALL_BASE(env, napi_typeof(env, value, &valuetype), false);
248     if ((valuetype == napi_undefined) || (valuetype == napi_null)) {
249         ACCOUNT_LOGI("this key's value is undefined or null");
250         return true;
251     }
252     return GetStringProperty(env, value, property);
253 }
254 
GetOptionalStringPropertyByKey(napi_env env,napi_value obj,const std::string & propertyName,std::string & property,bool & hasProperty)255 bool GetOptionalStringPropertyByKey(napi_env env, napi_value obj, const std::string &propertyName,
256     std::string &property, bool &hasProperty)
257 {
258     bool hasProp = false;
259     napi_has_named_property(env, obj, propertyName.c_str(), &hasProp);
260     if (!hasProp) {
261         return true;
262     }
263     napi_value value = nullptr;
264     NAPI_CALL_BASE(env, napi_get_named_property(env, obj, propertyName.c_str(), &value), false);
265     napi_valuetype valuetype = napi_undefined;
266     NAPI_CALL_BASE(env, napi_typeof(env, value, &valuetype), false);
267     if ((valuetype == napi_undefined) || (valuetype == napi_null)) {
268         ACCOUNT_LOGI("this key's value is undefined or null");
269         return true;
270     }
271     if (!GetStringProperty(env, value, property)) {
272         return false;
273     }
274     hasProperty = true;
275     return true;
276 }
277 
IsOptionalPropertyExist(napi_env env,napi_value obj,const std::string & propertyName)278 bool IsOptionalPropertyExist(napi_env env, napi_value obj, const std::string &propertyName)
279 {
280     bool hasProp = false;
281     napi_has_named_property(env, obj, propertyName.c_str(), &hasProp);
282     if (!hasProp) {
283         return false;
284     }
285     napi_value value = nullptr;
286     NAPI_CALL_BASE(env, napi_get_named_property(env, obj, propertyName.c_str(), &value), false);
287     napi_valuetype valuetype = napi_undefined;
288     NAPI_CALL_BASE(env, napi_typeof(env, value, &valuetype), false);
289     if ((valuetype == napi_undefined) || (valuetype == napi_null)) {
290         ACCOUNT_LOGI("This key's value is undefined or null");
291         return false;
292     }
293     return true;
294 }
295 
GetOptionalNumberPropertyByKey(napi_env env,napi_value obj,const std::string & propertyName,int32_t & numberProperty,bool & hasProperty)296 bool GetOptionalNumberPropertyByKey(napi_env env, napi_value obj, const std::string &propertyName,
297     int32_t &numberProperty, bool &hasProperty)
298 {
299     bool hasProp = false;
300     napi_has_named_property(env, obj, propertyName.c_str(), &hasProp);
301     if (!hasProp) {
302         ACCOUNT_LOGI("This property has no '%{public}s' key", propertyName.c_str());
303         return true;
304     }
305     napi_value value = nullptr;
306     NAPI_CALL_BASE(env, napi_get_named_property(env, obj, propertyName.c_str(), &value), false);
307     napi_valuetype valuetype = napi_undefined;
308     NAPI_CALL_BASE(env, napi_typeof(env, value, &valuetype), false);
309     if ((valuetype == napi_undefined) || (valuetype == napi_null)) {
310         ACCOUNT_LOGI("This key's value is undefined or null");
311         return true;
312     }
313     if (!GetIntProperty(env, value, numberProperty)) {
314         return false;
315     }
316     hasProperty = true;
317     return true;
318 }
319 
CompareOnAndOffRef(const napi_env env,napi_ref subscriberRef,napi_ref unsubscriberRef)320 bool CompareOnAndOffRef(const napi_env env, napi_ref subscriberRef, napi_ref unsubscriberRef)
321 {
322     napi_value subscriberCallback;
323     napi_get_reference_value(env, subscriberRef, &subscriberCallback);
324     napi_value unsubscriberCallback;
325     napi_get_reference_value(env, unsubscriberRef, &unsubscriberCallback);
326     bool result = false;
327     napi_strict_equals(env, subscriberCallback, unsubscriberCallback, &result);
328     return result;
329 }
330 
IsSystemApp(napi_env env)331 bool IsSystemApp(napi_env env)
332 {
333     uint64_t tokenId = IPCSkeleton::GetSelfTokenID();
334     bool isSystemApp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
335     if (!isSystemApp) {
336         std::string errMsg = ConvertToJsErrMsg(ERR_JS_IS_NOT_SYSTEM_APP);
337         AccountNapiThrow(env, ERR_JS_IS_NOT_SYSTEM_APP, errMsg, true);
338         return false;
339     }
340     return true;
341 }
342 
CreateStringArray(napi_env env,const std::vector<std::string> & strVec)343 napi_value CreateStringArray(napi_env env, const std::vector<std::string> &strVec)
344 {
345     napi_value result = nullptr;
346     napi_create_array(env, &result);
347     for (size_t i = 0; i < strVec.size(); ++i) {
348         napi_value value = nullptr;
349         napi_create_string_utf8(env, strVec[i].c_str(), NAPI_AUTO_LENGTH, &value);
350         napi_set_element(env, result, i, value);
351     }
352     return result;
353 }
CreateUint8Array(napi_env env,const uint8_t * srcData,size_t length)354 napi_value CreateUint8Array(napi_env env, const uint8_t *srcData, size_t length)
355 {
356     napi_value result = nullptr;
357     void* dstData = nullptr;
358     napi_value napiArr = nullptr;
359     NAPI_CALL(env, napi_create_arraybuffer(env, length, &dstData, &napiArr));
360     if ((length > 0) && (memcpy_s(dstData, length, srcData, length) != EOK)) {
361         return result;
362     }
363     NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, length, napiArr, 0, &result));
364     return result;
365 }
366 
ParseUint8TypedArray(napi_env env,napi_value value,uint8_t ** data,size_t * length)367 napi_status ParseUint8TypedArray(napi_env env, napi_value value, uint8_t **data, size_t *length)
368 {
369     *data = nullptr;
370     *length = 0;
371     bool isTypedArray = false;
372     napi_is_typedarray(env, value, &isTypedArray);
373     if (!isTypedArray) {
374         ACCOUNT_LOGE("invalid uint8 array");
375         return napi_ok;
376     }
377     napi_typedarray_type arrayType = static_cast<napi_typedarray_type>(-1);  // -1 indicates invalid type
378     napi_value buffer = nullptr;
379     size_t offset = 0;
380     napi_get_typedarray_info(env, value, &arrayType, length, reinterpret_cast<void **>(data), &buffer, &offset);
381     if (arrayType != napi_uint8_array) {
382         ACCOUNT_LOGE("invalid uint8 array");
383         *data = nullptr;
384         *length = 0;
385     }
386     return napi_ok;
387 }
388 
ParseUint8TypedArrayToVector(napi_env env,napi_value value,std::vector<uint8_t> & vec)389 napi_status ParseUint8TypedArrayToVector(napi_env env, napi_value value, std::vector<uint8_t> &vec)
390 {
391     uint8_t *data = nullptr;
392     size_t length = 0;
393     napi_status status = ParseUint8TypedArray(env, value, &data, &length);
394     if (status != napi_ok) {
395         ACCOUNT_LOGE("failed to ParseUint8TypedArray");
396         return status;
397     }
398     vec.assign(data, data + length);
399     return napi_ok;
400 }
401 
ParseUint8TypedArrayToUint64(napi_env env,napi_value value,uint64_t & result)402 napi_status ParseUint8TypedArrayToUint64(napi_env env, napi_value value, uint64_t &result)
403 {
404     uint8_t *data = nullptr;
405     size_t length = 0;
406     napi_status status = ParseUint8TypedArray(env, value, &data, &length);
407     if (status != napi_ok) {
408         ACCOUNT_LOGE("failed to ParseUint8TypedArray");
409         return status;
410     }
411     if (data == nullptr) {
412         result = 0;
413         return napi_invalid_arg;
414     }
415     if (length != sizeof(uint64_t)) {
416         ACCOUNT_LOGE("failed to convert to uint64_t value");
417         return napi_invalid_arg;
418     }
419     result = *(reinterpret_cast<uint64_t *>(data));
420     return napi_ok;
421 }
422 
ParseUint8ArrayToNativeUint8Array(napi_env env,napi_value value,uint8_t ** data,size_t * length)423 napi_status ParseUint8ArrayToNativeUint8Array(napi_env env, napi_value value, uint8_t **data, size_t *length)
424 {
425     *data = nullptr;
426     *length = 0;
427     bool isTypedArray = false;
428     napi_is_typedarray(env, value, &isTypedArray);
429     if (!isTypedArray) {
430         ACCOUNT_LOGE("Invalid uint8 array");
431         return napi_invalid_arg;
432     }
433     napi_typedarray_type arrayType = static_cast<napi_typedarray_type>(-1);  // -1 indicates invalid type
434     napi_value buffer = nullptr;
435     size_t offset = 0;
436     napi_get_typedarray_info(env, value, &arrayType, length, reinterpret_cast<void **>(data), &buffer, &offset);
437     if (arrayType != napi_uint8_array) {
438         ACCOUNT_LOGE("Invalid uint8 array");
439         *data = nullptr;
440         *length = 0;
441         return napi_invalid_arg;
442     }
443     return napi_ok;
444 }
445 
ParseBusinessError(napi_env env,napi_value value,BusinessError & error)446 bool ParseBusinessError(napi_env env, napi_value value, BusinessError &error)
447 {
448     napi_valuetype valueType = napi_undefined;
449     NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
450     if (valueType == napi_null || (valueType == napi_undefined)) {
451         error.code = 0;
452         return true;
453     }
454     napi_value napiCode = nullptr;
455     NAPI_CALL_BASE(env, napi_get_named_property(env, value, BUSINESS_ERROR_CODE_NAME, &napiCode), false);
456     if (napiCode == nullptr) {
457         ACCOUNT_LOGE("code is undefined");
458         return false;
459     }
460     NAPI_CALL_BASE(env, napi_get_value_int32(env, napiCode, &error.code), false);
461     bool hasData = false;
462     napi_has_named_property(env, value, BUSINESS_ERROR_DATA_NAME, &hasData);
463     if (hasData) {
464         napi_value napiData = nullptr;
465         napi_get_named_property(env, value, BUSINESS_ERROR_DATA_NAME, &napiData);
466         return GetStringProperty(env, napiData, error.data);
467     }
468     return true;
469 }
470 
GetNamedJsFunction(napi_env env,napi_value object,const std::string & name,napi_ref & callback)471 bool GetNamedJsFunction(napi_env env, napi_value object, const std::string &name, napi_ref &callback)
472 {
473     napi_valuetype valueType = napi_undefined;
474     NAPI_CALL_BASE(env, napi_typeof(env, object, &valueType), false);
475     if (valueType != napi_object) {
476         ACCOUNT_LOGE("invalid object");
477         return false;
478     }
479     napi_value result = nullptr;
480     NAPI_CALL_BASE(env, napi_get_named_property(env, object, name.c_str(), &result), false);
481     return GetCallbackProperty(env, result, callback, 1);
482 }
483 
NapiCallVoidFunction(napi_env env,napi_value * argv,size_t argc,napi_ref funcRef)484 void NapiCallVoidFunction(napi_env env, napi_value *argv, size_t argc, napi_ref funcRef)
485 {
486     napi_value undefined = nullptr;
487     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
488     napi_value returnVal;
489     napi_value func = nullptr;
490     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, funcRef, &func));
491     napi_status status = napi_call_function(env, undefined, func, argc, argv, &returnVal);
492     ACCOUNT_LOGI("call js function finish, status: %{public}d", status);
493 }
494 
SetInt32ToJsProperty(napi_env env,int32_t number,const std::string & propertyName,napi_value & dataJs)495 void SetInt32ToJsProperty(napi_env env, int32_t number, const std::string &propertyName, napi_value &dataJs)
496 {
497     napi_value napiNum = nullptr;
498     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, number, &napiNum));
499     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, dataJs, propertyName.c_str(), napiNum));
500 }
501 
CreateAuthResult(napi_env env,const std::vector<uint8_t> & token,int32_t remainTimes,int32_t freezingTime)502 napi_value CreateAuthResult(
503     napi_env env, const std::vector<uint8_t> &token, int32_t remainTimes, int32_t freezingTime)
504 {
505     napi_value object = nullptr;
506     NAPI_CALL(env, napi_create_object(env, &object));
507     if (remainTimes >= 0) {
508         napi_value napiRemainTimes = 0;
509         NAPI_CALL(env, napi_create_uint32(env, remainTimes, &napiRemainTimes));
510         NAPI_CALL(env, napi_set_named_property(env, object, "remainTimes", napiRemainTimes));
511     }
512     if (freezingTime >= 0) {
513         napi_value napiFreezingTimes = 0;
514         NAPI_CALL(env, napi_create_uint32(env, freezingTime, &napiFreezingTimes));
515         NAPI_CALL(env, napi_set_named_property(env, object, "freezingTime", napiFreezingTimes));
516     }
517     if (token.size() > 0) {
518         napi_value napiToken = CreateUint8Array(env, token.data(), token.size());
519         NAPI_CALL(env, napi_set_named_property(env, object, "token", napiToken));
520     }
521     return object;
522 }
523 
ReleaseNapiRefAsync(napi_env env,napi_ref napiRef)524 void ReleaseNapiRefAsync(napi_env env, napi_ref napiRef)
525 {
526     ReleaseNapiRefArray(env, {napiRef});
527 }
528 
ReleaseNapiRefArray(napi_env env,const std::vector<napi_ref> & napiRefVec)529 void ReleaseNapiRefArray(napi_env env, const std::vector<napi_ref> &napiRefVec)
530 {
531     if (env == nullptr) {
532         ACCOUNT_LOGE("invalid env");
533         return;
534     }
535     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
536     std::unique_ptr<NapiRefArrayContext> context = std::make_unique<NapiRefArrayContext>();
537     uv_loop_s *loop = nullptr;
538     napi_get_uv_event_loop(env, &loop);
539     if ((loop == nullptr) || (work == nullptr) || (context == nullptr)) {
540         ACCOUNT_LOGE("fail to init execution environment");
541         return;
542     }
543     context->env = env;
544     context->napiRefVec = napiRefVec;
545     work->data = reinterpret_cast<void *>(context.get());
546     NAPI_CALL_RETURN_VOID(env, uv_queue_work_with_qos(loop, work.get(), [] (uv_work_t *work) {},
547         [] (uv_work_t *work, int status) {
548             if (work == nullptr) {
549                 ACCOUNT_LOGE("work is nullptr");
550                 return;
551             }
552             auto context = reinterpret_cast<NapiRefArrayContext *>(work->data);
553             if (context == nullptr) {
554                 ACCOUNT_LOGE("context is nullptr");
555                 delete work;
556                 return;
557             }
558             for (auto &napiRef : context->napiRefVec) {
559                 if (napiRef != nullptr) {
560                     napi_delete_reference(context->env, napiRef);
561                 }
562             }
563             delete context;
564             delete work;
565         }, uv_qos_default));
566     context.release();
567     work.release();
568 }
569 
~NapiCallbackRef()570 NapiCallbackRef::~NapiCallbackRef()
571 {
572     if (callbackRef == nullptr) {
573         return;
574     }
575     ReleaseNapiRefArray(env, {callbackRef});
576     callbackRef = nullptr;
577 }
578 
InitUvWorkCallbackEnv(uv_work_t * work,napi_handle_scope & scope)579 bool InitUvWorkCallbackEnv(uv_work_t *work, napi_handle_scope &scope)
580 {
581     if (work == nullptr) {
582         ACCOUNT_LOGE("work is nullptr");
583         return false;
584     }
585     if (work->data == nullptr) {
586         ACCOUNT_LOGE("data is nullptr");
587         return false;
588     }
589     CommonAsyncContext *data = reinterpret_cast<CommonAsyncContext *>(work->data);
590     napi_open_handle_scope(data->env, &scope);
591     if (scope == nullptr) {
592         ACCOUNT_LOGE("fail to open scope");
593         delete data;
594         work->data = nullptr;
595         return false;
596     }
597     return true;
598 }
599 
JsObjectToNativeString(napi_env env,napi_value jsData,std::string & nativeData)600 bool JsObjectToNativeString(napi_env env, napi_value jsData, std::string &nativeData)
601 {
602     napi_valuetype valueType = napi_undefined;
603     napi_typeof(env, jsData, &valueType);
604     if (valueType != napi_object) {
605         ACCOUNT_LOGI("The parameters is not object");
606         return false;
607     }
608     napi_value globalValue = nullptr;
609     napi_get_global(env, &globalValue);
610     napi_value jsonValue;
611     napi_get_named_property(env, globalValue, "JSON", &jsonValue);
612 
613     napi_value stringifyValue = nullptr;
614     napi_get_named_property(env, jsonValue, "stringify", &stringifyValue);
615     napi_value funcArgv[1] = { jsData };
616     napi_value transValue = nullptr;
617     napi_status status = napi_call_function(env, jsonValue, stringifyValue, 1, funcArgv, &transValue);
618     if (status != napi_ok) {
619         ACCOUNT_LOGE("Fail to call function, %{public}d", status);
620         return false;
621     }
622 
623     if (!GetStringProperty(env, transValue, nativeData)) {
624         ACCOUNT_LOGE("Get native data failed");
625         std::string errMsg = "The type of arg 2 must be string";
626         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, false);
627         return false;
628     }
629     return true;
630 }
631 
NativeStringToJsObject(napi_env env,const std::string & nativeData)632 napi_value NativeStringToJsObject(napi_env env, const std::string &nativeData)
633 {
634     napi_value jsObjData = nullptr;
635     if (nativeData.empty()) {
636         napi_create_object(env, &jsObjData);
637         return jsObjData;
638     }
639     napi_value globalValue = nullptr;
640     napi_get_global(env, &globalValue);
641     napi_value jsonValue;
642     napi_get_named_property(env, globalValue, "JSON", &jsonValue);
643     napi_value parseValue = nullptr;
644     napi_get_named_property(env, jsonValue, "parse", &parseValue);
645     napi_value jsStringDate = nullptr;
646     NAPI_CALL(env, napi_create_string_utf8(env, nativeData.c_str(), NAPI_AUTO_LENGTH, &jsStringDate));
647     napi_value funcArgv[1] = { jsStringDate };
648     napi_status status = napi_call_function(env, jsonValue, parseValue, 1, funcArgv, &jsObjData);
649     if (status != napi_ok) {
650         ACCOUNT_LOGE("Fail to call function, status: %{public}d", status);
651     }
652     return jsObjData;
653 }
654 
GetSelfTargetVersion(uint32_t & targetVersion)655 bool GetSelfTargetVersion(uint32_t &targetVersion)
656 {
657     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
658     if (samgr == nullptr) {
659         ACCOUNT_LOGE("Samgr error");
660         return false;
661     }
662     auto bundleObj = samgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
663     if (bundleObj == nullptr) {
664         ACCOUNT_LOGE("BundleObj error");
665         return false;
666     }
667     auto bundleMgrProxy = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
668     if (bundleMgrProxy == nullptr) {
669         ACCOUNT_LOGE("BundleMgrProxy error");
670         return false;
671     }
672     AppExecFwk::BundleInfo bundleInfo;
673     ErrCode ret = bundleMgrProxy->GetBundleInfoForSelf(OHOS::AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo);
674     if (ret != ERR_OK) {
675         ACCOUNT_LOGE("GetBundleInfoForSelf error");
676         return false;
677     }
678     ACCOUNT_LOGI("Bundle targetVersion is %{public}d", bundleInfo.targetVersion);
679     targetVersion = bundleInfo.targetVersion;
680     return true;
681 }
682 } // namespace AccountJsKit
683 } // namespace OHOS