1 /*
2 * Copyright (C) 2023 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 "nfc_napi_common_utils.h"
17 #include <cstring>
18 #include "loghelper.h"
19 #include "nfc_sdk_common.h"
20 #include "securec.h"
21
22 namespace OHOS {
23 namespace NFC {
24 namespace KITS {
ParseString(napi_env env, std::string ¶m, napi_value args)25 bool ParseString(napi_env env, std::string ¶m, napi_value args)
26 {
27 napi_valuetype valuetype;
28 napi_typeof(env, args, &valuetype);
29
30 DebugLog("param=%{public}d.", valuetype);
31 if (valuetype != napi_string) {
32 DebugLog("Wrong argument type. String expected.");
33 return false;
34 }
35 size_t size = 0;
36
37 if (napi_get_value_string_utf8(env, args, nullptr, 0, &size) != napi_ok) {
38 ErrorLog("can not get string size");
39 param = "";
40 return false;
41 }
42 param.reserve(size + 1);
43 param.resize(size);
44 if (napi_get_value_string_utf8(env, args, param.data(), (size + 1), &size) != napi_ok) {
45 ErrorLog("can not get string value");
46 param = "";
47 return false;
48 }
49 return true;
50 }
ParseInt32(napi_env env, int32_t ¶m, napi_value args)51 bool ParseInt32(napi_env env, int32_t ¶m, napi_value args)
52 {
53 napi_valuetype valuetype;
54 napi_typeof(env, args, &valuetype);
55
56 DebugLog("ParseInt32, valuetype %{public}d.", valuetype);
57 if (valuetype != napi_number) {
58 ErrorLog("Wrong argument type. Int32 expected.");
59 return false;
60 }
61 napi_get_value_int32(env, args, ¶m);
62 return true;
63 }
64
ParseBool(napi_env env, bool ¶m, napi_value args)65 bool ParseBool(napi_env env, bool ¶m, napi_value args)
66 {
67 napi_valuetype valuetype;
68 napi_typeof(env, args, &valuetype);
69
70 DebugLog("param=%{public}d.", valuetype);
71 if (valuetype != napi_boolean) {
72 ErrorLog("Wrong argument type. bool expected.");
73 return false;
74 }
75 napi_get_value_bool(env, args, ¶m);
76 return true;
77 }
78
ParseBytesVector(napi_env env, std::vector<unsigned char> &vec, napi_value args)79 bool ParseBytesVector(napi_env env, std::vector<unsigned char> &vec, napi_value args)
80 {
81 bool isArray = false;
82 napi_status status = napi_is_array(env, args, &isArray);
83 if (status != napi_ok || !isArray) {
84 ErrorLog("ParseBytesVector, not array");
85 return false;
86 }
87 uint32_t arrayLength = 0;
88 napi_get_array_length(env, args, &arrayLength);
89 for (uint32_t i = 0; i < arrayLength; i++) {
90 napi_value element = nullptr;
91 napi_get_element(env, args, i, &element);
92
93 napi_valuetype valueType = napi_undefined;
94 napi_typeof(env, element, &valueType);
95 if (valueType != napi_number) {
96 ErrorLog("ParseBytesVector, not number!");
97 return false;
98 }
99
100 uint32_t byteValue = 0x0;
101 napi_get_value_uint32(env, element, &byteValue);
102 vec.push_back(static_cast<unsigned char>(byteValue));
103 }
104 return true;
105 }
106
ParseUInt32Vector(napi_env& env, std::vector<uint32_t>& vec, napi_value &args)107 bool ParseUInt32Vector(napi_env& env, std::vector<uint32_t>& vec, napi_value &args)
108 {
109 bool isArray = false;
110 napi_status status = napi_is_array(env, args, &isArray);
111 if (status != napi_ok || !isArray) {
112 ErrorLog("ParseUInt32Vector: not array");
113 return false;
114 }
115 uint32_t arrayLen = 0;
116 napi_get_array_length(env, args, &arrayLen);
117 for (uint32_t i = 0; i < arrayLen; i++) {
118 napi_value element = nullptr;
119 napi_get_element(env, args, i, &element);
120
121 napi_valuetype valueType = napi_undefined;
122 napi_typeof(env, element, &valueType);
123 if (valueType != napi_number) {
124 ErrorLog("ParseUInt32Vector, not number!");
125 return false;
126 }
127
128 uint32_t uint32Value = 0;
129 napi_get_value_uint32(env, element, &uint32Value);
130 vec.push_back(static_cast<uint32_t>(uint32Value));
131 }
132 return true;
133 }
134
ParseStringVector(napi_env &env, std::vector<std::string> &vec, napi_value &args, uint32_t maxLen)135 bool ParseStringVector(napi_env &env, std::vector<std::string> &vec, napi_value &args, uint32_t maxLen)
136 {
137 bool isArray = false;
138 napi_status status = napi_is_array(env, args, &isArray);
139 if (status != napi_ok || !isArray) {
140 ErrorLog("ParseStringVector: not array");
141 return false;
142 }
143 uint32_t arrayLen = 0;
144 napi_get_array_length(env, args, &arrayLen);
145 if (arrayLen > maxLen) {
146 ErrorLog("ParseStringVector, too big array!");
147 return false;
148 }
149 for (uint32_t i = 0; i < arrayLen; i++) {
150 napi_value element = nullptr;
151 napi_get_element(env, args, i, &element);
152
153 napi_valuetype valueType;
154 napi_typeof(env, element, &valueType);
155 if (valueType != napi_string) {
156 ErrorLog("ParseStringVector, not string!");
157 return false;
158 }
159
160 std::string stringValue;
161 ParseString(env, stringValue, element);
162 vec.push_back(stringValue);
163 }
164 return true;
165 }
166
ParseElementName(napi_env &env, ElementName &element, napi_value &args)167 bool ParseElementName(napi_env &env, ElementName &element, napi_value &args)
168 {
169 napi_valuetype valueType = napi_undefined;
170 napi_typeof(env, args, &valueType);
171 if (valueType != napi_object) {
172 ErrorLog("ParseElementName, not object!");
173 return false;
174 }
175 napi_value param = nullptr;
176 napi_get_named_property(env, args, "bundleName", ¶m);
177 std::string bundleName;
178 ParseString(env, bundleName, param);
179
180 param = nullptr;
181 napi_get_named_property(env, args, "moduleName", ¶m);
182 std::string moduleName;
183 ParseString(env, moduleName, param);
184
185 param = nullptr;
186 napi_get_named_property(env, args, "abilityName", ¶m);
187 std::string abilityName;
188 ParseString(env, abilityName, param);
189
190 DebugLog("ParseElementName: bundleName:%{public}s, moduleName:%{public}s, abilityName:%{public}s",
191 bundleName.c_str(), moduleName.c_str(), abilityName.c_str());
192 element.SetBundleName(bundleName);
193 element.SetModuleName(moduleName);
194 element.SetAbilityName(abilityName);
195 return true;
196 }
197
ParseArrayBuffer(napi_env env, uint8_t **data, size_t &size, napi_value args)198 bool ParseArrayBuffer(napi_env env, uint8_t **data, size_t &size, napi_value args)
199 {
200 napi_status status;
201 napi_valuetype valuetype;
202 napi_typeof(env, args, &valuetype);
203
204 DebugLog("param=%{public}d.", valuetype);
205 if (valuetype != napi_object) {
206 ErrorLog("Wrong argument type. object expected.");
207 return false;
208 }
209
210 status = napi_get_arraybuffer_info(env, args, reinterpret_cast<void **>(data), &size);
211 if (status != napi_ok) {
212 ErrorLog("can not get arraybuffer, error is %{public}d", status);
213 (*data)[0] = 0;
214 return false;
215 }
216 DebugLog("arraybuffer size is %{public}zu,buffer is %{public}d", size, (*data)[0]);
217 return true;
218 }
219
UndefinedNapiValue(const napi_env &env)220 napi_value UndefinedNapiValue(const napi_env &env)
221 {
222 napi_value result;
223 napi_get_undefined(env, &result);
224 return result;
225 }
226
ConvertStringVector(napi_env env, napi_value jsValue)227 std::vector<std::string> ConvertStringVector(napi_env env, napi_value jsValue)
228 {
229 bool isTypedArray = false;
230 napi_status status = napi_is_typedarray(env, jsValue, &isTypedArray);
231 if (status != napi_ok || !isTypedArray) {
232 ErrorLog("%{public}s called, napi_is_typedarray error", __func__);
233 return {};
234 }
235
236 napi_typedarray_type type;
237 size_t length = 0;
238 napi_value buffer = nullptr;
239 size_t offset = 0;
240 NAPI_CALL_BASE(env, napi_get_typedarray_info(env, jsValue, &type, &length, nullptr, &buffer, &offset), {});
241 if (type != napi_uint8_array) {
242 ErrorLog("%{public}s called, napi_uint8_array is null", __func__);
243 return {};
244 }
245 std::string *data = nullptr;
246 size_t total = 0;
247 NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, buffer, reinterpret_cast<void **>(&data), &total), {});
248 length = std::min<size_t>(length, total - offset);
249 std::vector<std::string> result(sizeof(std::string) + length);
250 int retCode = memcpy_s(result.data(), result.size(), &data[offset], length);
251 if (retCode != 0) {
252 return {};
253 }
254 return result;
255 }
256
CreateErrorMessage(napi_env env, const std::string &msg, int32_t errorCode)257 napi_value CreateErrorMessage(napi_env env, const std::string &msg, int32_t errorCode)
258 {
259 napi_value result = nullptr;
260 napi_value message = nullptr;
261 NAPI_CALL(env, napi_create_string_utf8(env, msg.c_str(), msg.length(), &message));
262 napi_value codeValue = nullptr;
263 std::string errCode = std::to_string(errorCode);
264 NAPI_CALL(env, napi_create_string_utf8(env, errCode.c_str(), errCode.length(), &codeValue));
265 NAPI_CALL(env, napi_create_error(env, codeValue, message, &result));
266 return result;
267 }
268
CreateUndefined(napi_env env)269 napi_value CreateUndefined(napi_env env)
270 {
271 napi_value result = nullptr;
272 NAPI_CALL(env, napi_get_undefined(env, &result));
273 return result;
274 }
275
GetNapiStringValue( napi_env env, napi_value napiValue, const std::string &name, const std::string &defValue)276 std::string GetNapiStringValue(
277 napi_env env, napi_value napiValue, const std::string &name, const std::string &defValue)
278 {
279 napi_value value = GetNamedProperty(env, napiValue, name);
280 if (value != nullptr) {
281 return GetStringFromValue(env, value);
282 } else {
283 return defValue;
284 }
285 }
286
GetStringFromValue(napi_env env, napi_value value)287 std::string GetStringFromValue(napi_env env, napi_value value)
288 {
289 constexpr int32_t maxTextLength = 4096;
290 char msgChars[maxTextLength] = {0};
291 size_t msgLength = 0;
292 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, msgChars, maxTextLength, &msgLength), "");
293 if (msgLength > 0) {
294 return std::string(msgChars, 0, msgLength);
295 } else {
296 return "";
297 }
298 }
299
GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)300 napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
301 {
302 napi_value value = nullptr;
303 bool hasProperty = false;
304 NAPI_CALL(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty));
305 if (hasProperty) {
306 NAPI_CALL(env, napi_get_named_property(env, object, propertyName.data(), &value));
307 }
308 return value;
309 }
310
GetNapiInt32Value(napi_env env, napi_value napiValue, const std::string &name, const int32_t &defValue)311 int32_t GetNapiInt32Value(napi_env env, napi_value napiValue, const std::string &name, const int32_t &defValue)
312 {
313 napi_value value = GetNamedProperty(env, napiValue, name);
314 if (value != nullptr) {
315 int32_t intValue = 0;
316 napi_status getIntStatus = napi_get_value_int32(env, value, &intValue);
317 if (getIntStatus == napi_ok) {
318 return intValue;
319 }
320 }
321 return defValue;
322 }
323
UnwrapStringFromJS(napi_env env, napi_value param)324 std::string UnwrapStringFromJS(napi_env env, napi_value param)
325 {
326 constexpr size_t maxTextLength = 1024;
327 char msgChars[maxTextLength] = {0};
328 size_t msgLength = 0;
329 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, param, msgChars, maxTextLength, &msgLength), "");
330 DebugLog("NapiUtil GetStringFromValue msgLength = %{public}zu", msgLength);
331 if (msgLength > 0) {
332 return std::string(msgChars, 0, msgLength);
333 } else {
334 return "";
335 }
336 }
337
JsStringToBytesVector(napi_env env, napi_value &src, std::vector<unsigned char> &values)338 void JsStringToBytesVector(napi_env env, napi_value &src, std::vector<unsigned char> &values)
339 {
340 napi_valuetype valueType = napi_undefined;
341 napi_typeof(env, src, &valueType);
342 if (valueType != napi_string) {
343 return;
344 }
345
346 std::string data;
347 ParseString(env, data, src);
348 NfcSdkCommon::HexStringToBytes(data, values);
349 }
350
ConvertStringVectorToJS(napi_env env, napi_value &result, std::vector<std::string>& stringVector)351 void ConvertStringVectorToJS(napi_env env, napi_value &result, std::vector<std::string>& stringVector)
352 {
353 DebugLog("ConvertStringVectorToJS called");
354 size_t idx = 0;
355
356 if (stringVector.empty()) {
357 WarnLog("ConvertStringVectorToJS stringVector empty");
358 napi_create_array_with_length(env, 0, &result);
359 return;
360 }
361 DebugLog("ConvertStringVectorToJS size is %{public}zu", stringVector.size());
362 for (auto& str : stringVector) {
363 napi_value obj = nullptr;
364 napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &obj);
365 napi_set_element(env, result, idx, obj);
366 idx++;
367 }
368 }
369
BytesVectorToJS(napi_env env, napi_value &result, std::vector<unsigned char>& src)370 void BytesVectorToJS(napi_env env, napi_value &result, std::vector<unsigned char>& src)
371 {
372 if (src.empty()) {
373 WarnLog("BytesVectorToJS src empty");
374 napi_create_array_with_length(env, 0, &result);
375 return;
376 }
377 size_t idx = 0;
378 DebugLog("BytesVectorToJS size is %{public}zu", src.size());
379 napi_create_array_with_length(env, src.size(), &result);
380 for (auto& num : src) {
381 napi_value obj = nullptr;
382 napi_create_uint32(env, num, &obj);
383 napi_set_element(env, result, idx, obj);
384 idx++;
385 }
386 }
387
ConvertStringToNumberArray(napi_env env, napi_value &result, std::string srcValue)388 void ConvertStringToNumberArray(napi_env env, napi_value &result, std::string srcValue)
389 {
390 if (srcValue.empty()) {
391 WarnLog("ConvertStringToNumberArray srcValue empty");
392 napi_create_array_with_length(env, 0, &result);
393 return;
394 }
395 uint32_t strLength = srcValue.length();
396 if (strLength % HEX_BYTE_LEN != 0) {
397 srcValue = '0' + srcValue;
398 strLength++;
399 }
400
401 napi_create_array_with_length(env, (strLength / HEX_BYTE_LEN), &result);
402 unsigned int srcIntValue;
403 for (uint32_t i = 0; i < strLength; i += HEX_BYTE_LEN) {
404 // parse the hex string bytes into array.
405 std::string oneByte = srcValue.substr(i, HEX_BYTE_LEN);
406 if (sscanf_s(oneByte.c_str(), "%x", &srcIntValue) <= 0) {
407 ErrorLog("ConvertStringToNumberArray, sscanf_s failed.");
408 return;
409 }
410 unsigned char hexByte = static_cast<unsigned char>(srcIntValue & 0xFF);
411 napi_value hexByteValue = nullptr;
412 napi_create_int32(env, hexByte, &hexByteValue);
413 napi_set_element(env, result, (i / HEX_BYTE_LEN), hexByteValue);
414 }
415 }
416
IsAirTouch(std::vector<std::shared_ptr<NdefRecord>> &ndefRecords)417 bool IsAirTouch(std::vector<std::shared_ptr<NdefRecord>> &ndefRecords)
418 {
419 std::string airTouchFlag = "616972746F756368"; // "airtouch"
420 std::string::size_type idx;
421 for (auto& ndefRecord : ndefRecords) {
422 idx = ndefRecord->payload_.find(airTouchFlag);
423 if (idx != std::string::npos) {
424 WarnLog("IsAirTouch is airtouch.");
425 return true;
426 }
427 }
428 return false;
429 }
430
ConvertAirTouchNdefRecordToJS(napi_env env, napi_value &result, std::shared_ptr<NdefRecord> &ndefRecord)431 void ConvertAirTouchNdefRecordToJS(napi_env env, napi_value &result, std::shared_ptr<NdefRecord> &ndefRecord)
432 {
433 napi_create_object(env, &result);
434 if (ndefRecord == nullptr) {
435 WarnLog("ConvertNdefRecordToJS ndefRecord is null.");
436 return;
437 }
438
439 napi_value tnf;
440 napi_create_int32(env, ndefRecord->tnf_, &tnf);
441 napi_set_named_property(env, result, "tnf", tnf);
442
443 napi_value rtdType;
444 napi_create_string_utf8(env, ndefRecord->tagRtdType_.c_str(), NAPI_AUTO_LENGTH, &rtdType);
445 napi_set_named_property(env, result, "rtdType", rtdType);
446
447 napi_value id;
448 napi_create_string_utf8(env, ndefRecord->id_.c_str(), NAPI_AUTO_LENGTH, &id);
449 napi_set_named_property(env, result, "id", id);
450
451 napi_value payload;
452 napi_create_string_utf8(env, ndefRecord->payload_.c_str(), NAPI_AUTO_LENGTH, &payload);
453 napi_set_named_property(env, result, "payload", payload);
454 }
455
ConvertNdefRecordVectorToJS(napi_env env, napi_value &result, std::vector<std::shared_ptr<NdefRecord>> &ndefRecords)456 void ConvertNdefRecordVectorToJS(napi_env env, napi_value &result,
457 std::vector<std::shared_ptr<NdefRecord>> &ndefRecords)
458 {
459 napi_create_array(env, &result);
460 if (ndefRecords.empty()) {
461 WarnLog("ConvertNdefRecordVectorToJS ndefRecords is empty.");
462 return;
463 }
464 bool isAirtouchFlag = IsAirTouch(ndefRecords);
465 size_t idx = 0;
466 for (auto& ndefRecord : ndefRecords) {
467 napi_value obj = nullptr;
468 if (isAirtouchFlag) {
469 ConvertAirTouchNdefRecordToJS(env, obj, ndefRecord);
470 } else {
471 ConvertNdefRecordToJS(env, obj, ndefRecord);
472 }
473 napi_set_element(env, result, idx, obj);
474 idx++;
475 }
476 }
477
ConvertNdefRecordToJS(napi_env env, napi_value &result, std::shared_ptr<NdefRecord> &ndefRecord)478 void ConvertNdefRecordToJS(napi_env env, napi_value &result, std::shared_ptr<NdefRecord> &ndefRecord)
479 {
480 napi_create_object(env, &result);
481 if (ndefRecord == nullptr) {
482 WarnLog("ConvertNdefRecordToJS ndefRecord is null.");
483 return;
484 }
485
486 napi_value tnf;
487 napi_create_int32(env, ndefRecord->tnf_, &tnf);
488 napi_set_named_property(env, result, "tnf", tnf);
489
490 napi_value rtdType;
491 std::vector<unsigned char> rtdTypeBytes;
492 NfcSdkCommon::HexStringToBytes(ndefRecord->tagRtdType_, rtdTypeBytes);
493 BytesVectorToJS(env, rtdType, rtdTypeBytes);
494 napi_set_named_property(env, result, "rtdType", rtdType);
495
496 napi_value id;
497 std::vector<unsigned char> idBytes;
498 NfcSdkCommon::HexStringToBytes(ndefRecord->id_, idBytes);
499 BytesVectorToJS(env, id, idBytes);
500 napi_set_named_property(env, result, "id", id);
501
502 napi_value payload;
503 std::vector<unsigned char> payloadBytes;
504 NfcSdkCommon::HexStringToBytes(ndefRecord->payload_, payloadBytes);
505 BytesVectorToJS(env, payload, payloadBytes);
506 napi_set_named_property(env, result, "payload", payload);
507 }
508
MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)509 bool MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)
510 {
511 napi_valuetype valueType = napi_undefined;
512 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
513 return valueType == targetType;
514 }
515
MatchParameters(napi_env env, const napi_value parameters[], std::initializer_list<napi_valuetype> valueTypes)516 bool MatchParameters(napi_env env, const napi_value parameters[], std::initializer_list<napi_valuetype> valueTypes)
517 {
518 if (parameters == nullptr) {
519 return false;
520 }
521 int i = 0;
522 for (auto beg = valueTypes.begin(); beg != valueTypes.end(); ++beg) {
523 if (!MatchValueType(env, parameters[i], *beg)) {
524 return false;
525 }
526 ++i;
527 }
528 return true;
529 }
530
HandleAsyncWork(napi_env env, BaseContext *baseContext, const std::string &workName, napi_async_execute_callback execute, napi_async_complete_callback complete)531 napi_value HandleAsyncWork(napi_env env, BaseContext *baseContext, const std::string &workName,
532 napi_async_execute_callback execute, napi_async_complete_callback complete)
533 {
534 DebugLog("NfcUtil HandleAsyncWork workName = %{public}s", workName.c_str());
535 std::unique_ptr<BaseContext> context(baseContext);
536 if (context == nullptr) {
537 std::string errorCode = std::to_string(napi_invalid_arg);
538 NAPI_CALL(env, napi_throw_error(env, errorCode.c_str(), ERR_INIT_CONTEXT.c_str()));
539 }
540 napi_value result = nullptr;
541 if (context != nullptr && context->callbackRef == nullptr) {
542 NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
543 } else {
544 NAPI_CALL(env, napi_get_undefined(env, &result));
545 }
546 napi_value resource = CreateUndefined(env);
547 napi_value resourceName = nullptr;
548 NAPI_CALL(env, napi_create_string_utf8(env, workName.data(), NAPI_AUTO_LENGTH, &resourceName));
549 NAPI_CALL(env,
550 napi_create_async_work(env, resource, resourceName, execute, complete, static_cast<void *>(context.get()),
551 &context->work));
552 napi_status queueWorkStatus = napi_queue_async_work(env, context->work);
553 if (queueWorkStatus == napi_ok) {
554 context.release();
555 DebugLog("NapiUtil HandleAsyncWork napi_queue_async_work ok");
556 } else {
557 std::string errorCode = std::to_string(queueWorkStatus);
558 NAPI_CALL(env, napi_throw_error(env, errorCode.c_str(), ERR_INIT_CONTEXT.c_str()));
559 }
560 DebugLog("NfcUtil HandleAsyncWork end");
561 return result;
562 }
563
DoAsyncCallbackOrPromise(const napi_env &env, BaseContext *baseContext, napi_value callbackValue)564 void DoAsyncCallbackOrPromise(const napi_env &env, BaseContext *baseContext, napi_value callbackValue)
565 {
566 if (baseContext == nullptr) {
567 ErrorLog("DoAsyncCallbackOrPromise serious error baseContext nullptr");
568 return;
569 }
570 if (baseContext->callbackRef != nullptr) {
571 DebugLog("DoAsyncCallbackOrPromise for callback");
572 napi_value recv = CreateUndefined(env);
573 napi_value callbackFunc = nullptr;
574 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, baseContext->callbackRef, &callbackFunc));
575 napi_value callbackValues[] = {nullptr, nullptr};
576 callbackValues[0] = baseContext->resolved ? CreateUndefined(env) : callbackValue;
577 callbackValues[1] = baseContext->resolved ? callbackValue : CreateUndefined(env);
578 napi_value result = nullptr;
579 NAPI_CALL_RETURN_VOID(
580 env, napi_call_function(env, recv, callbackFunc, std::size(callbackValues), callbackValues, &result));
581 NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, baseContext->callbackRef));
582 } else if (baseContext->deferred != nullptr) {
583 DebugLog("DoAsyncCallbackOrPromise for promise");
584 if (baseContext->resolved) {
585 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, baseContext->deferred, callbackValue));
586 } else {
587 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, baseContext->deferred, callbackValue));
588 }
589 }
590 napi_delete_async_work(env, baseContext->work);
591 delete baseContext;
592 baseContext = nullptr;
593 }
594
ThrowAsyncError(const napi_env &env, BaseContext *baseContext, int errCode, const std::string &errMsg)595 void ThrowAsyncError(const napi_env &env, BaseContext *baseContext, int errCode, const std::string &errMsg)
596 {
597 if (baseContext == nullptr) {
598 ErrorLog("ThrowAsyncError serious error baseContext nullptr");
599 return;
600 }
601 napi_value businessError = CreateErrorMessage(env, errMsg, errCode);
602 if (baseContext->callbackRef != nullptr) {
603 DebugLog("ThrowAsyncError for callback");
604 napi_value recv = CreateUndefined(env);
605 napi_value callbackFunc = nullptr;
606 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, baseContext->callbackRef, &callbackFunc));
607 napi_value callbackValues[] = {nullptr, nullptr};
608 callbackValues[0] = businessError; // parameter "error"
609 callbackValues[1] = CreateUndefined(env); // parameter "callback"
610 napi_value result = nullptr;
611 NAPI_CALL_RETURN_VOID(
612 env, napi_call_function(env, recv, callbackFunc, std::size(callbackValues), callbackValues, &result));
613 NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, baseContext->callbackRef));
614 } else if (baseContext->deferred != nullptr) {
615 DebugLog("ThrowAsyncError for promise");
616 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, baseContext->deferred, businessError));
617 }
618 if (baseContext->work != nullptr) {
619 napi_delete_async_work(env, baseContext->work);
620 }
621 delete baseContext;
622 baseContext = nullptr;
623 }
624
IsNumberArray(const napi_env &env, const napi_value ¶m)625 bool IsNumberArray(const napi_env &env, const napi_value ¶m)
626 {
627 if (!IsArray(env, param)) {
628 return false;
629 }
630
631 uint32_t arrayLength = 0;
632 napi_get_array_length(env, param, &arrayLength);
633 napi_value elementValue = nullptr;
634 for (uint32_t i = 0; i < arrayLength; ++i) {
635 napi_get_element(env, param, i, &elementValue);
636 napi_valuetype elementType = napi_undefined;
637 napi_typeof(env, elementValue, &elementType);
638 if (elementType != napi_number) {
639 return false;
640 }
641 }
642 return true;
643 }
644
IsObjectArray(const napi_env &env, const napi_value ¶m)645 bool IsObjectArray(const napi_env &env, const napi_value ¶m)
646 {
647 if (!IsArray(env, param)) {
648 return false;
649 }
650
651 uint32_t arrayLength = 0;
652 napi_get_array_length(env, param, &arrayLength);
653 napi_value elementValue = nullptr;
654 for (uint32_t i = 0; i < arrayLength; ++i) {
655 napi_get_element(env, param, i, &elementValue);
656 napi_valuetype elementType = napi_undefined;
657 napi_typeof(env, elementValue, &elementType);
658 if (elementType != napi_object) {
659 return false;
660 }
661 }
662 return true;
663 }
664
IsArray(const napi_env &env, const napi_value ¶m)665 bool IsArray(const napi_env &env, const napi_value ¶m)
666 {
667 bool arrayType = false;
668 napi_status status = napi_is_array(env, param, &arrayType);
669 if (status != napi_ok || !arrayType) {
670 return false;
671 }
672
673 uint32_t arrayLength = 0;
674 napi_get_array_length(env, param, &arrayLength);
675 if (arrayLength == 0) {
676 return false;
677 }
678 return true;
679 }
680
IsNumber(const napi_env &env, const napi_value ¶m)681 bool IsNumber(const napi_env &env, const napi_value ¶m)
682 {
683 napi_valuetype valueType = napi_undefined;
684 napi_typeof(env, param, &valueType);
685 return valueType == napi_number;
686 }
687
IsString(const napi_env &env, const napi_value ¶m)688 bool IsString(const napi_env &env, const napi_value ¶m)
689 {
690 napi_valuetype valueType = napi_undefined;
691 napi_typeof(env, param, &valueType);
692 return valueType == napi_string;
693 }
694
IsObject(const napi_env &env, const napi_value ¶m)695 bool IsObject(const napi_env &env, const napi_value ¶m)
696 {
697 napi_valuetype valueType = napi_undefined;
698 napi_typeof(env, param, &valueType);
699 return valueType == napi_object;
700 }
701
IsFunction(const napi_env &env, const napi_value ¶m)702 bool IsFunction(const napi_env &env, const napi_value ¶m)
703 {
704 napi_valuetype valueType = napi_undefined;
705 napi_typeof(env, param, &valueType);
706 return valueType == napi_function;
707 }
708
BuildOutputErrorCode(int errCode)709 int BuildOutputErrorCode(int errCode)
710 {
711 if (errCode == BUSI_ERR_PERM) {
712 return BUSI_ERR_PERM;
713 } else if (errCode == BUSI_ERR_PARAM) {
714 return BUSI_ERR_PARAM;
715 } else if (errCode == ERR_TAG_STATE_IO_FAILED) {
716 return BUSI_ERR_IO_OPERATION_INVALID;
717 } else if (errCode >= ERR_TAG_BASE && errCode < ERR_CE_BASE) {
718 return BUSI_ERR_TAG_STATE_INVALID;
719 }
720 return errCode;
721 }
722
BuildOutputErrorCodeHce(int errCode)723 int BuildOutputErrorCodeHce(int errCode)
724 {
725 if (errCode == BUSI_ERR_PERM) {
726 return BUSI_ERR_PERM;
727 }
728 if (errCode == BUSI_ERR_PARAM) {
729 return BUSI_ERR_PARAM;
730 }
731 if (errCode == BUSI_ERR_NOT_SYSTEM_APP) {
732 return BUSI_ERR_NOT_SYSTEM_APP;
733 }
734 return BUSI_ERR_HCE_STATE_INVALID;
735 }
736
BuildErrorMessage(int errCode, std::string funcName, std::string forbiddenPerm, std::string paramName, std::string expertedType)737 std::string BuildErrorMessage(int errCode, std::string funcName, std::string forbiddenPerm,
738 std::string paramName, std::string expertedType)
739 {
740 std::string errMsg;
741 if (errCode == BUSI_ERR_PERM) {
742 return errMsg.append("Permission denied. An attempt was made to ${")
743 .append(funcName)
744 .append("} forbidden by permission: ${")
745 .append(forbiddenPerm)
746 .append("}.");
747 } else if (errCode == BUSI_ERR_PARAM) {
748 if (paramName.length() > 0) {
749 return errMsg.append("Parameter error. The type of \"${")
750 .append(paramName)
751 .append("}\" must be ${")
752 .append(expertedType)
753 .append("}.");
754 } else {
755 return "Parameter error. The parameter number is invalid.";
756 }
757 } else if (errCode == BUSI_ERR_TAG_STATE_INVALID) {
758 return "Tag running state is abnormal in service.";
759 } else if (errCode == BUSI_ERR_ELEMENT_STATE_INVALID) {
760 return "The element state is invalid.";
761 } else if (errCode == BUSI_ERR_REGISTER_STATE_INVALID) {
762 return "The off() can be called only when the on() has been called.";
763 } else if (errCode == BUSI_ERR_HCE_STATE_INVALID) {
764 return "HCE running state is abnormal in service.";
765 } else if (errCode == BUSI_ERR_NOT_SYSTEM_APP) {
766 return "Not system application.";
767 }
768 return "Unknown error message";
769 }
770
GenerateBusinessError(const napi_env &env, int errCode, const std::string &errMessage)771 napi_value GenerateBusinessError(const napi_env &env, int errCode, const std::string &errMessage)
772 {
773 napi_value code = nullptr;
774 napi_create_uint32(env, errCode, &code);
775 napi_value message = nullptr;
776 napi_create_string_utf8(env, errMessage.c_str(), NAPI_AUTO_LENGTH, &message);
777 napi_value businessError = nullptr;
778 napi_create_error(env, nullptr, message, &businessError);
779 napi_set_named_property(env, businessError, KEY_CODE.c_str(), code);
780 return businessError;
781 }
782
CheckUnwrapStatusAndThrow(const napi_env &env, napi_status status, int errCode)783 bool CheckUnwrapStatusAndThrow(const napi_env &env, napi_status status, int errCode)
784 {
785 if (status != napi_ok) {
786 napi_throw(env, GenerateBusinessError(env, errCode, BuildErrorMessage(errCode, "", "", "", "")));
787 return false;
788 }
789 return true;
790 }
CheckContextAndThrow(const napi_env &env, const BaseContext *context, int errCode)791 bool CheckContextAndThrow(const napi_env &env, const BaseContext *context, int errCode)
792 {
793 if (context == nullptr) {
794 napi_throw(env, GenerateBusinessError(env, errCode, BuildErrorMessage(errCode, "", "", "", "")));
795 return false;
796 }
797 return true;
798 }
CheckParametersAndThrow(const napi_env &env, const napi_value parameters[], std::initializer_list<napi_valuetype> types, const std::string &argName, const std::string &argType)799 bool CheckParametersAndThrow(const napi_env &env, const napi_value parameters[],
800 std::initializer_list<napi_valuetype> types, const std::string &argName, const std::string &argType)
801 {
802 if (!MatchParameters(env, parameters, types)) {
803 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
804 "", "", argName, argType)));
805 return false;
806 }
807 return true;
808 }
CheckArrayNumberAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName, const std::string &argType)809 bool CheckArrayNumberAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName,
810 const std::string &argType)
811 {
812 if (!IsNumberArray(env, param)) {
813 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
814 "", "", argName, argType)));
815 return false;
816 }
817 return true;
818 }
CheckNumberAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName, const std::string &argType)819 bool CheckNumberAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName,
820 const std::string &argType)
821 {
822 if (!IsNumber(env, param)) {
823 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
824 "", "", argName, argType)));
825 return false;
826 }
827 return true;
828 }
CheckStringAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName, const std::string &argType)829 bool CheckStringAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName,
830 const std::string &argType)
831 {
832 if (!IsString(env, param)) {
833 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
834 "", "", argName, argType)));
835 return false;
836 }
837 return true;
838 }
CheckObjectAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName, const std::string &argType)839 bool CheckObjectAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName,
840 const std::string &argType)
841 {
842 if (!IsObject(env, param)) {
843 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
844 "", "", argName, argType)));
845 return false;
846 }
847 return true;
848 }
849
CheckFunctionAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName, const std::string &argType)850 bool CheckFunctionAndThrow(const napi_env &env, const napi_value ¶m, const std::string &argName,
851 const std::string &argType)
852 {
853 if (!IsFunction(env, param)) {
854 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
855 "", "", argName, argType)));
856 return false;
857 }
858 return true;
859 }
860
CheckArgCountAndThrow(const napi_env &env, int argCount, int expCount)861 bool CheckArgCountAndThrow(const napi_env &env, int argCount, int expCount)
862 {
863 if (argCount != expCount) {
864 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
865 "", "", "", "")));
866 return false;
867 }
868 return true;
869 }
CheckTagStatusCodeAndThrow(const napi_env &env, int statusCode, const std::string &funcName)870 bool CheckTagStatusCodeAndThrow(const napi_env &env, int statusCode, const std::string &funcName)
871 {
872 if (statusCode == BUSI_ERR_PERM) {
873 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PERM,
874 BuildErrorMessage(BUSI_ERR_PERM, funcName, TAG_PERM_DESC, "", "")));
875 return false;
876 } else if (statusCode == ERR_TAG_STATE_IO_FAILED) {
877 napi_throw(env, GenerateBusinessError(env, ERR_TAG_STATE_IO_FAILED,
878 BuildErrorMessage(BUSI_ERR_IO_OPERATION_INVALID, funcName, "", "", "")));
879 return false;
880 } else if (statusCode >= ErrorCode::ERR_TAG_PARAMETERS && statusCode < ErrorCode::ERR_CE_BASE) {
881 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_TAG_STATE_INVALID,
882 BuildErrorMessage(BUSI_ERR_TAG_STATE_INVALID, "", "", "", "")));
883 return false;
884 }
885 return true;
886 }
887
CheckHceStatusCodeAndThrow(const napi_env &env, int statusCode, const std::string &funcName)888 bool CheckHceStatusCodeAndThrow(const napi_env &env, int statusCode, const std::string &funcName)
889 {
890 if (statusCode == KITS::ERR_NONE) {
891 return true;
892 }
893 if (statusCode == BUSI_ERR_NOT_SYSTEM_APP) {
894 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_NOT_SYSTEM_APP,
895 BuildErrorMessage(BUSI_ERR_NOT_SYSTEM_APP, funcName, "", "", "")));
896 return false;
897 }
898 if (statusCode == BUSI_ERR_PERM) {
899 napi_value busErr = GenerateBusinessError(
900 env, BUSI_ERR_PERM, BuildErrorMessage(BUSI_ERR_PERM, funcName, CARD_EMULATION_PERM_DESC, "", ""));
901 napi_throw(env, busErr);
902 return false;
903 }
904
905 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_HCE_STATE_INVALID,
906 BuildErrorMessage(BUSI_ERR_HCE_STATE_INVALID, "", "", "", "")));
907 return false;
908 }
909 } // namespace KITS
910 } // namespace NFC
911 } // namespace OHOS
912