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