• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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_tag_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 & param,napi_value args)25 bool ParseString(napi_env env, std::string &param, 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 & param,napi_value args)51 bool ParseInt32(napi_env env, int32_t &param, 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, &param);
62     return true;
63 }
64 
ParseBool(napi_env env,bool & param,napi_value args)65 bool ParseBool(napi_env env, bool &param, 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, &param);
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 
ParseElementName(napi_env & env,ElementName & element,napi_value & args)135 bool ParseElementName(napi_env &env, ElementName &element, napi_value &args)
136 {
137     napi_valuetype valueType = napi_undefined;
138     napi_typeof(env, args, &valueType);
139     if (valueType != napi_object) {
140         ErrorLog("ParseElementName, not object!");
141         return false;
142     }
143     napi_value param = nullptr;
144     napi_get_named_property(env, args, "bundleName", &param);
145     std::string bundleName;
146     ParseString(env, bundleName, param);
147 
148     param = nullptr;
149     napi_get_named_property(env, args, "moduleName", &param);
150     std::string moduleName;
151     ParseString(env, moduleName, param);
152 
153     param = nullptr;
154     napi_get_named_property(env, args, "abilityName", &param);
155     std::string abilityName;
156     ParseString(env, abilityName, param);
157 
158     DebugLog("ParseElementName: bundleName:%{public}s, moduleName:%{public}s, abilityName:%{public}s",
159         bundleName.c_str(), moduleName.c_str(), abilityName.c_str());
160     ElementName elementName("", bundleName, abilityName, moduleName);
161     element = elementName;
162     return true;
163 }
164 
ParseArrayBuffer(napi_env env,uint8_t ** data,size_t & size,napi_value args)165 bool ParseArrayBuffer(napi_env env, uint8_t **data, size_t &size, napi_value args)
166 {
167     napi_status status;
168     napi_valuetype valuetype;
169     napi_typeof(env, args, &valuetype);
170 
171     DebugLog("param=%{public}d.", valuetype);
172     if (valuetype != napi_object) {
173         ErrorLog("Wrong argument type. object expected.");
174         return false;
175     }
176 
177     status = napi_get_arraybuffer_info(env, args, reinterpret_cast<void **>(data), &size);
178     if (status != napi_ok) {
179         ErrorLog("can not get arraybuffer, error is %{public}d", status);
180         (*data)[0] = 0;
181         return false;
182     }
183     DebugLog("arraybuffer size is %{public}zu,buffer is %{public}d", size, (*data)[0]);
184     return true;
185 }
186 
UndefinedNapiValue(const napi_env & env)187 napi_value UndefinedNapiValue(const napi_env &env)
188 {
189     napi_value result;
190     napi_get_undefined(env, &result);
191     return result;
192 }
193 
ConvertStringVector(napi_env env,napi_value jsValue)194 std::vector<std::string> ConvertStringVector(napi_env env, napi_value jsValue)
195 {
196     bool isTypedArray = false;
197     napi_status status = napi_is_typedarray(env, jsValue, &isTypedArray);
198     if (status != napi_ok || !isTypedArray) {
199         ErrorLog("%{public}s called, napi_is_typedarray error", __func__);
200         return {};
201     }
202 
203     napi_typedarray_type type;
204     size_t length = 0;
205     napi_value buffer = nullptr;
206     size_t offset = 0;
207     NAPI_CALL_BASE(env, napi_get_typedarray_info(env, jsValue, &type, &length, nullptr, &buffer, &offset), {});
208     if (type != napi_uint8_array) {
209         ErrorLog("%{public}s called, napi_uint8_array is null", __func__);
210         return {};
211     }
212     std::string *data = nullptr;
213     size_t total = 0;
214     NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, buffer, reinterpret_cast<void **>(&data), &total), {});
215     length = std::min<size_t>(length, total - offset);
216     std::vector<std::string> result(sizeof(std::string) + length);
217     int retCode = memcpy_s(result.data(), result.size(), &data[offset], length);
218     if (retCode != 0) {
219         return {};
220     }
221     return result;
222 }
223 
CreateErrorMessage(napi_env env,const std::string & msg,int32_t errorCode)224 napi_value CreateErrorMessage(napi_env env, const std::string &msg, int32_t errorCode)
225 {
226     napi_value result = nullptr;
227     napi_value message = nullptr;
228     NAPI_CALL(env, napi_create_string_utf8(env, msg.c_str(), msg.length(), &message));
229     napi_value codeValue = nullptr;
230     std::string errCode = std::to_string(errorCode);
231     NAPI_CALL(env, napi_create_string_utf8(env, errCode.c_str(), errCode.length(), &codeValue));
232     NAPI_CALL(env, napi_create_error(env, codeValue, message, &result));
233     return result;
234 }
235 
CreateUndefined(napi_env env)236 napi_value CreateUndefined(napi_env env)
237 {
238     napi_value result = nullptr;
239     NAPI_CALL(env, napi_get_undefined(env, &result));
240     return result;
241 }
242 
GetNapiStringValue(napi_env env,napi_value napiValue,const std::string & name,const std::string & defValue)243 std::string GetNapiStringValue(
244     napi_env env, napi_value napiValue, const std::string &name, const std::string &defValue)
245 {
246     napi_value value = GetNamedProperty(env, napiValue, name);
247     if (value != nullptr) {
248         return GetStringFromValue(env, value);
249     } else {
250         return defValue;
251     }
252 }
GetStringFromValue(napi_env env,napi_value value)253 std::string GetStringFromValue(napi_env env, napi_value value)
254 {
255     constexpr int32_t maxTextLength = 4096;
256     char msgChars[maxTextLength] = {0};
257     size_t msgLength = 0;
258     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, msgChars, maxTextLength, &msgLength), "");
259     if (msgLength > 0) {
260         return std::string(msgChars, 0, msgLength);
261     } else {
262         return "";
263     }
264 }
265 
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)266 napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
267 {
268     napi_value value = nullptr;
269     bool hasProperty = false;
270     NAPI_CALL(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty));
271     if (hasProperty) {
272         NAPI_CALL(env, napi_get_named_property(env, object, propertyName.data(), &value));
273     }
274     return value;
275 }
276 
GetNapiInt32Value(napi_env env,napi_value napiValue,const std::string & name,const int32_t & defValue)277 int32_t GetNapiInt32Value(napi_env env, napi_value napiValue, const std::string &name, const int32_t &defValue)
278 {
279     napi_value value = GetNamedProperty(env, napiValue, name);
280     if (value != nullptr) {
281         int32_t intValue = 0;
282         napi_status getIntStatus = napi_get_value_int32(env, value, &intValue);
283         if (getIntStatus == napi_ok) {
284             return intValue;
285         }
286     }
287     return defValue;
288 }
289 
UnwrapStringFromJS(napi_env env,napi_value param)290 std::string UnwrapStringFromJS(napi_env env, napi_value param)
291 {
292     constexpr size_t maxTextLength = 1024;
293     char msgChars[maxTextLength] = {0};
294     size_t msgLength = 0;
295     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, param, msgChars, maxTextLength, &msgLength), "");
296     DebugLog("NapiUtil GetStringFromValue msgLength = %{public}zu", msgLength);
297     if (msgLength > 0) {
298         return std::string(msgChars, 0, msgLength);
299     } else {
300         return "";
301     }
302 }
303 
JsStringToBytesVector(napi_env env,napi_value & src,std::vector<unsigned char> & values)304 void JsStringToBytesVector(napi_env env, napi_value &src, std::vector<unsigned char> &values)
305 {
306     napi_valuetype valueType = napi_undefined;
307     napi_typeof(env, src, &valueType);
308     if (valueType != napi_string) {
309         return;
310     }
311 
312     std::string data;
313     ParseString(env, data, src);
314     NfcSdkCommon::HexStringToBytes(data, values);
315 }
316 
ConvertStringVectorToJS(napi_env env,napi_value & result,std::vector<std::string> & stringVector)317 void ConvertStringVectorToJS(napi_env env, napi_value &result, std::vector<std::string>& stringVector)
318 {
319     DebugLog("ConvertStringVectorToJS called");
320     size_t idx = 0;
321 
322     if (stringVector.empty()) {
323         WarnLog("ConvertStringVectorToJS stringVector empty");
324         napi_create_array_with_length(env, 0, &result);
325         return;
326     }
327     DebugLog("ConvertStringVectorToJS size is %{public}zu", stringVector.size());
328     for (auto& str : stringVector) {
329         napi_value obj = nullptr;
330         napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &obj);
331         napi_set_element(env, result, idx, obj);
332         idx++;
333     }
334 }
335 
BytesVectorToJS(napi_env env,napi_value & result,std::vector<unsigned char> & src)336 void BytesVectorToJS(napi_env env, napi_value &result, std::vector<unsigned char>& src)
337 {
338     if (src.empty()) {
339         WarnLog("BytesVectorToJS src empty");
340         napi_create_array_with_length(env, 0, &result);
341         return;
342     }
343     size_t idx = 0;
344     DebugLog("BytesVectorToJS size is %{public}zu", src.size());
345     napi_create_array_with_length(env, src.size(), &result);
346     for (auto& num : src) {
347         napi_value obj = nullptr;
348         napi_create_uint32(env, num, &obj);
349         napi_set_element(env, result, idx, obj);
350         idx++;
351     }
352 }
353 
ConvertStringToNumberArray(napi_env env,napi_value & result,std::string srcValue)354 void ConvertStringToNumberArray(napi_env env, napi_value &result, std::string srcValue)
355 {
356     if (srcValue.empty()) {
357         WarnLog("ConvertStringToNumberArray srcValue empty");
358         napi_create_array_with_length(env, 0, &result);
359         return;
360     }
361     uint32_t strLength = srcValue.length();
362     if (strLength % HEX_BYTE_LEN != 0) {
363         srcValue = '0' + srcValue;
364         strLength++;
365     }
366 
367     napi_create_array_with_length(env, (strLength / HEX_BYTE_LEN), &result);
368     unsigned int srcIntValue;
369     for (uint32_t i = 0; i < strLength; i += HEX_BYTE_LEN) {
370         // parse the hex string bytes into array.
371         std::string oneByte = srcValue.substr(i, HEX_BYTE_LEN);
372         if (sscanf_s(oneByte.c_str(), "%x", &srcIntValue) <= 0) {
373             ErrorLog("ConvertStringToNumberArray, sscanf_s failed.");
374             return;
375         }
376         unsigned char hexByte = static_cast<unsigned char>(srcIntValue & 0xFF);
377         napi_value hexByteValue = nullptr;
378         napi_create_int32(env, hexByte, &hexByteValue);
379         napi_set_element(env, result, (i / HEX_BYTE_LEN), hexByteValue);
380     }
381 }
382 
ConvertNdefRecordVectorToJS(napi_env env,napi_value & result,std::vector<std::shared_ptr<NdefRecord>> & ndefRecords)383 void ConvertNdefRecordVectorToJS(napi_env env, napi_value &result,
384                                  std::vector<std::shared_ptr<NdefRecord>> &ndefRecords)
385 {
386     napi_create_array(env, &result);
387     if (ndefRecords.empty()) {
388         WarnLog("ConvertNdefRecordVectorToJS ndefRecords is empty.");
389         return;
390     }
391     size_t idx = 0;
392     for (auto& ndefRecord : ndefRecords) {
393         napi_value obj = nullptr;
394         ConvertNdefRecordToJS(env, obj, ndefRecord);
395         napi_set_element(env, result, idx, obj);
396         idx++;
397     }
398 }
399 
ConvertNdefRecordToJS(napi_env env,napi_value & result,std::shared_ptr<NdefRecord> & ndefRecord)400 void ConvertNdefRecordToJS(napi_env env, napi_value &result, std::shared_ptr<NdefRecord> &ndefRecord)
401 {
402     napi_create_object(env, &result);
403     if (ndefRecord == nullptr) {
404         WarnLog("ConvertNdefRecordToJS ndefRecord is null.");
405         return;
406     }
407 
408     napi_value tnf;
409     napi_create_int32(env, ndefRecord->tnf_, &tnf);
410     napi_set_named_property(env, result, "tnf", tnf);
411 
412     napi_value rtdType;
413     napi_create_string_utf8(env, ndefRecord->tagRtdType_.c_str(), NAPI_AUTO_LENGTH, &rtdType);
414     napi_set_named_property(env, result, "rtdType", rtdType);
415 
416     napi_value id;
417     napi_create_string_utf8(env, ndefRecord->id_.c_str(), NAPI_AUTO_LENGTH, &id);
418     napi_set_named_property(env, result, "id", id);
419 
420     napi_value payload;
421     napi_create_string_utf8(env, ndefRecord->payload_.c_str(), NAPI_AUTO_LENGTH, &payload);
422     napi_set_named_property(env, result, "payload", payload);
423 }
424 
MatchValueType(napi_env env,napi_value value,napi_valuetype targetType)425 bool MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)
426 {
427     napi_valuetype valueType = napi_undefined;
428     NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
429     return valueType == targetType;
430 }
431 
MatchParameters(napi_env env,const napi_value parameters[],std::initializer_list<napi_valuetype> valueTypes)432 bool MatchParameters(napi_env env, const napi_value parameters[], std::initializer_list<napi_valuetype> valueTypes)
433 {
434     if (parameters == nullptr) {
435         return false;
436     }
437     int i = 0;
438     for (auto beg = valueTypes.begin(); beg != valueTypes.end(); ++beg) {
439         if (!MatchValueType(env, parameters[i], *beg)) {
440             return false;
441         }
442         ++i;
443     }
444     return true;
445 }
446 
HandleAsyncWork(napi_env env,BaseContext * baseContext,const std::string & workName,napi_async_execute_callback execute,napi_async_complete_callback complete)447 napi_value HandleAsyncWork(napi_env env, BaseContext *baseContext, const std::string &workName,
448     napi_async_execute_callback execute, napi_async_complete_callback complete)
449 {
450     DebugLog("NfcUtil HandleAsyncWork workName = %{public}s", workName.c_str());
451     std::unique_ptr<BaseContext> context(baseContext);
452     if (context == nullptr) {
453         std::string errorCode = std::to_string(napi_invalid_arg);
454         NAPI_CALL(env, napi_throw_error(env, errorCode.c_str(), ERR_INIT_CONTEXT.c_str()));
455     }
456     napi_value result = nullptr;
457     if (context != nullptr && context->callbackRef == nullptr) {
458         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
459     } else {
460         NAPI_CALL(env, napi_get_undefined(env, &result));
461     }
462     napi_value resource = CreateUndefined(env);
463     napi_value resourceName = nullptr;
464     NAPI_CALL(env, napi_create_string_utf8(env, workName.data(), NAPI_AUTO_LENGTH, &resourceName));
465     NAPI_CALL(env,
466         napi_create_async_work(env, resource, resourceName, execute, complete, static_cast<void *>(context.get()),
467             &context->work));
468     napi_status queueWorkStatus = napi_queue_async_work(env, context->work);
469     if (queueWorkStatus == napi_ok) {
470         context.release();
471         DebugLog("NapiUtil HandleAsyncWork napi_queue_async_work ok");
472     } else {
473         std::string errorCode = std::to_string(queueWorkStatus);
474         NAPI_CALL(env, napi_throw_error(env, errorCode.c_str(), ERR_INIT_CONTEXT.c_str()));
475     }
476     DebugLog("NfcUtil HandleAsyncWork end");
477     return result;
478 }
479 
DoAsyncCallbackOrPromise(const napi_env & env,BaseContext * baseContext,napi_value callbackValue)480 void DoAsyncCallbackOrPromise(const napi_env &env, BaseContext *baseContext, napi_value callbackValue)
481 {
482     if (baseContext == nullptr) {
483         ErrorLog("DoAsyncCallbackOrPromise serious error baseContext nullptr");
484         return;
485     }
486     if (baseContext->callbackRef != nullptr) {
487         DebugLog("DoAsyncCallbackOrPromise for callback");
488         napi_value recv = CreateUndefined(env);
489         napi_value callbackFunc = nullptr;
490         NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, baseContext->callbackRef, &callbackFunc));
491         napi_value callbackValues[] = {nullptr, nullptr};
492         callbackValues[0] = baseContext->resolved ? CreateUndefined(env) : callbackValue;
493         callbackValues[1] = baseContext->resolved ? callbackValue : CreateUndefined(env);
494         napi_value result = nullptr;
495         NAPI_CALL_RETURN_VOID(
496             env, napi_call_function(env, recv, callbackFunc, std::size(callbackValues), callbackValues, &result));
497         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, baseContext->callbackRef));
498     } else if (baseContext->deferred != nullptr) {
499         DebugLog("DoAsyncCallbackOrPromise for promise");
500         if (baseContext->resolved) {
501             NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, baseContext->deferred, callbackValue));
502         } else {
503             NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, baseContext->deferred, callbackValue));
504         }
505     }
506     napi_delete_async_work(env, baseContext->work);
507     delete baseContext;
508     baseContext = nullptr;
509 }
510 
ThrowAsyncError(const napi_env & env,BaseContext * baseContext,int errCode,const std::string & errMsg)511 void ThrowAsyncError(const napi_env &env, BaseContext *baseContext, int errCode, const std::string &errMsg)
512 {
513     if (baseContext == nullptr) {
514         ErrorLog("ThrowAsyncError serious error baseContext nullptr");
515         return;
516     }
517     napi_value businessError = CreateErrorMessage(env, errMsg, errCode);
518     if (baseContext->callbackRef != nullptr) {
519         DebugLog("ThrowAsyncError for callback");
520         napi_value recv = CreateUndefined(env);
521         napi_value callbackFunc = nullptr;
522         NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, baseContext->callbackRef, &callbackFunc));
523         napi_value callbackValues[] = {nullptr, nullptr};
524         callbackValues[0] = businessError; // parameter "error"
525         callbackValues[1] = CreateUndefined(env); // parameter "callback"
526         napi_value result = nullptr;
527         NAPI_CALL_RETURN_VOID(
528             env, napi_call_function(env, recv, callbackFunc, std::size(callbackValues), callbackValues, &result));
529         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, baseContext->callbackRef));
530     } else if (baseContext->deferred != nullptr) {
531         DebugLog("ThrowAsyncError for promise");
532         NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, baseContext->deferred, businessError));
533     }
534 
535     if (baseContext != nullptr) {
536         if (baseContext->work != nullptr) {
537             napi_delete_async_work(env, baseContext->work);
538         }
539         delete baseContext;
540         baseContext = nullptr;
541     }
542 }
543 
IsNumberArray(const napi_env & env,const napi_value & param)544 bool IsNumberArray(const napi_env &env, const napi_value &param)
545 {
546     if (!IsArray(env, param)) {
547         return false;
548     }
549 
550     uint32_t arrayLength = 0;
551     napi_get_array_length(env, param, &arrayLength);
552     napi_value elementValue = nullptr;
553     for (uint32_t i = 0; i < arrayLength; ++i) {
554         napi_get_element(env, param, i, &elementValue);
555         napi_valuetype elementType = napi_undefined;
556         napi_typeof(env, elementValue, &elementType);
557         if (elementType != napi_number) {
558             return false;
559         }
560     }
561     return true;
562 }
563 
IsObjectArray(const napi_env & env,const napi_value & param)564 bool IsObjectArray(const napi_env &env, const napi_value &param)
565 {
566     if (!IsArray(env, param)) {
567         return false;
568     }
569 
570     uint32_t arrayLength = 0;
571     napi_get_array_length(env, param, &arrayLength);
572     napi_value elementValue = nullptr;
573     for (uint32_t i = 0; i < arrayLength; ++i) {
574         napi_get_element(env, param, i, &elementValue);
575         napi_valuetype elementType = napi_undefined;
576         napi_typeof(env, elementValue, &elementType);
577         if (elementType != napi_object) {
578             return false;
579         }
580     }
581     return true;
582 }
583 
IsArray(const napi_env & env,const napi_value & param)584 bool IsArray(const napi_env &env, const napi_value &param)
585 {
586     bool arrayType = false;
587     napi_status status = napi_is_array(env, param, &arrayType);
588     if (status != napi_ok || !arrayType) {
589         return false;
590     }
591 
592     uint32_t arrayLength = 0;
593     napi_get_array_length(env, param, &arrayLength);
594     if (arrayLength == 0) {
595         return false;
596     }
597     return true;
598 }
599 
IsNumber(const napi_env & env,const napi_value & param)600 bool IsNumber(const napi_env &env, const napi_value &param)
601 {
602     napi_valuetype valueType = napi_undefined;
603     napi_typeof(env, param, &valueType);
604     return valueType == napi_number;
605 }
606 
IsString(const napi_env & env,const napi_value & param)607 bool IsString(const napi_env &env, const napi_value &param)
608 {
609     napi_valuetype valueType = napi_undefined;
610     napi_typeof(env, param, &valueType);
611     return valueType == napi_string;
612 }
613 
IsObject(const napi_env & env,const napi_value & param)614 bool IsObject(const napi_env &env, const napi_value &param)
615 {
616     napi_valuetype valueType = napi_undefined;
617     napi_typeof(env, param, &valueType);
618     return valueType == napi_object;
619 }
620 
BuildOutputErrorCode(int errCode)621 int BuildOutputErrorCode(int errCode)
622 {
623     if (errCode == BUSI_ERR_PERM) {
624         return BUSI_ERR_PERM;
625     } else if (errCode == BUSI_ERR_PARAM) {
626         return BUSI_ERR_PARAM;
627     } else if (errCode >= ERR_TAG_BASE && errCode < ERR_CE_BASE) {
628         return BUSI_ERR_TAG_STATE_INVALID;
629     }
630     return errCode;
631 }
632 
BuildErrorMessage(int errCode,std::string funcName,std::string forbiddenPerm,std::string paramName,std::string expertedType)633 std::string BuildErrorMessage(int errCode, std::string funcName, std::string forbiddenPerm,
634     std::string paramName, std::string expertedType)
635 {
636     std::string errMsg;
637     if (errCode == BUSI_ERR_PERM) {
638         return errMsg.append("Permission denied. An attempt was made to ${")
639             .append(funcName)
640             .append("} forbidden by permission: ${")
641             .append(forbiddenPerm)
642             .append("}.");
643     } else if (errCode == BUSI_ERR_PARAM) {
644         if (paramName.length() > 0) {
645             return errMsg.append("Parameter error. The type of \"${")
646                 .append(paramName)
647                 .append("}\" must be ${")
648                 .append(expertedType)
649                 .append("}.");
650         } else {
651             return "Parameter error. The parameter number is invalid.";
652         }
653     } else if (errCode == BUSI_ERR_TAG_STATE_INVALID) {
654         return "Tag running state is abnormal in service.";
655     }
656     return "Unknown error message";
657 }
658 
GenerateBusinessError(const napi_env & env,int errCode,const std::string & errMessage)659 napi_value GenerateBusinessError(const napi_env &env, int errCode, const std::string &errMessage)
660 {
661     napi_value code = nullptr;
662     napi_create_uint32(env, errCode, &code);
663     napi_value message = nullptr;
664     napi_create_string_utf8(env, errMessage.c_str(), NAPI_AUTO_LENGTH, &message);
665     napi_value businessError = nullptr;
666     napi_create_error(env, nullptr, message, &businessError);
667     napi_set_named_property(env, businessError, KEY_CODE.c_str(), code);
668     return businessError;
669 }
670 
CheckUnwrapStatusAndThrow(const napi_env & env,napi_status status,int errCode)671 bool CheckUnwrapStatusAndThrow(const napi_env &env, napi_status status, int errCode)
672 {
673     if (status != napi_ok) {
674         napi_throw(env, GenerateBusinessError(env, errCode, BuildErrorMessage(errCode, "", "", "", "")));
675         return false;
676     }
677     return true;
678 }
CheckContextAndThrow(const napi_env & env,const BaseContext * context,int errCode)679 bool CheckContextAndThrow(const napi_env &env, const BaseContext *context, int errCode)
680 {
681     if (context == nullptr) {
682         napi_throw(env, GenerateBusinessError(env, errCode, BuildErrorMessage(errCode, "", "", "", "")));
683         return false;
684     }
685     return true;
686 }
CheckParametersAndThrow(const napi_env & env,const napi_value parameters[],std::initializer_list<napi_valuetype> types,const std::string & argName,const std::string & argType)687 bool CheckParametersAndThrow(const napi_env &env, const napi_value parameters[],
688     std::initializer_list<napi_valuetype> types, const std::string &argName, const std::string &argType)
689 {
690     if (!MatchParameters(env, parameters, types)) {
691         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
692             "", "", argName, argType)));
693         return false;
694     }
695     return true;
696 }
CheckArrayNumberAndThrow(const napi_env & env,const napi_value & param,const std::string & argName,const std::string & argType)697 bool CheckArrayNumberAndThrow(const napi_env &env, const napi_value &param, const std::string &argName,
698     const std::string &argType)
699 {
700     if (!IsNumberArray(env, param)) {
701         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
702             "", "", argName, argType)));
703         return false;
704     }
705     return true;
706 }
CheckNumberAndThrow(const napi_env & env,const napi_value & param,const std::string & argName,const std::string & argType)707 bool CheckNumberAndThrow(const napi_env &env, const napi_value &param, const std::string &argName,
708     const std::string &argType)
709 {
710     if (!IsNumber(env, param)) {
711         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
712             "", "", argName, argType)));
713         return false;
714     }
715     return true;
716 }
CheckStringAndThrow(const napi_env & env,const napi_value & param,const std::string & argName,const std::string & argType)717 bool CheckStringAndThrow(const napi_env &env, const napi_value &param, const std::string &argName,
718     const std::string &argType)
719 {
720     if (!IsString(env, param)) {
721         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
722             "", "", argName, argType)));
723         return false;
724     }
725     return true;
726 }
CheckObjectAndThrow(const napi_env & env,const napi_value & param,const std::string & argName,const std::string & argType)727 bool CheckObjectAndThrow(const napi_env &env, const napi_value &param, const std::string &argName,
728     const std::string &argType)
729 {
730     if (!IsObject(env, param)) {
731         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
732             "", "", argName, argType)));
733         return false;
734     }
735     return true;
736 }
CheckArgCountAndThrow(const napi_env & env,int argCount,int expCount)737 bool CheckArgCountAndThrow(const napi_env &env, int argCount, int expCount)
738 {
739     if (argCount != expCount) {
740         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM, BuildErrorMessage(BUSI_ERR_PARAM,
741             "", "", "", "")));
742         return false;
743     }
744     return true;
745 }
CheckTagStatusCodeAndThrow(const napi_env & env,int statusCode,const std::string & funcName)746 bool CheckTagStatusCodeAndThrow(const napi_env &env, int statusCode, const std::string &funcName)
747 {
748     if (statusCode == BUSI_ERR_PERM) {
749         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PERM,
750             BuildErrorMessage(BUSI_ERR_PERM, funcName, TAG_PERM_DESC, "", "")));
751         return false;
752     } else if (statusCode >= ErrorCode::ERR_TAG_BASE && statusCode < ErrorCode::ERR_CE_BASE) {
753         napi_throw(env, GenerateBusinessError(env, BUSI_ERR_TAG_STATE_INVALID,
754             BuildErrorMessage(BUSI_ERR_TAG_STATE_INVALID, "", "", "", "")));
755         return false;
756     }
757     return true;
758 }
759 } // namespace KITS
760 } // namespace NFC
761 } // namespace OHOS
762