1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_util.h"
17 
18 #include <codecvt>
19 #include <cstdio>
20 #include <cstring>
21 #include <locale>
22 #include <memory>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "core_service_errors.h"
27 #include "enum_convert_for_js.h"
28 #include "state_registry_errors.h"
29 #include "telephony_log_wrapper.h"
30 
31 namespace OHOS {
32 namespace Telephony {
33 static constexpr int32_t MAX_TEXT_LENGTH = 4096;
34 static constexpr const char *JS_ERROR_TELEPHONY_PERMISSION_DENIED_STRING = "Permission denied.";
35 static constexpr const char *JS_ERROR_ILLEGAL_USE_OF_SYSTEM_API_STRING = "Non-system applications use system APIs.";
36 static constexpr const char *JS_ERROR_TELEPHONY_INVALID_INPUT_PARAMETER_STRING =
37     "Parameter error. The type of parameter should match or the number of parameters must match.";
38 static constexpr const char *JS_ERROR_DEVICE_NOT_SUPPORT_THIS_API_STRING = "The device does not support this API.";
39 static constexpr const char *JS_ERROR_TELEPHONY_SUCCESS_STRING = "Success.";
40 static constexpr const char *JS_ERROR_TELEPHONY_ARGUMENT_ERROR_STRING = "Invalid parameter value.";
41 static constexpr const char *JS_ERROR_TELEPHONY_SERVICE_ERROR_STRING = "Operation failed. Cannot connect to service.";
42 static constexpr const char *JS_ERROR_TELEPHONY_SYSTEM_ERROR_STRING = "System internal error.";
43 static constexpr const char *JS_ERROR_TELEPHONY_NO_SIM_CARD_STRING = "Do not have sim card.";
44 static constexpr const char *JS_ERROR_TELEPHONY_UNKNOW_ERROR_STRING = "Unknown error code.";
45 static constexpr const char *JS_ERROR_SIM_BASE_ERROR_STRING = "Sim module base error.";
46 static constexpr const char *JS_ERROR_SIM_CARD_IS_NOT_ACTIVE_STRING = "SIM card is not activated.";
47 static constexpr const char *JS_ERROR_SIM_CARD_OPERATION_ERROR_STRING = "SIM card operation error.";
48 static constexpr const char *JS_ERROR_OPERATOR_CONFIG_ERROR_STRING = "Operator config error.";
49 static constexpr const char *JS_ERROR_NETWORK_SEARCH_BASE_ERROR_STRING = "Network search module base error.";
50 static constexpr const char *JS_ERROR_CALL_MANAGER_BASE_ERROR_STRING = "Call manager module base error.";
51 static constexpr const char *JS_ERROR_CELLULAR_CALL_CS_BASE_ERROR_STRING = "Cellular call module cs base error.";
52 static constexpr const char *JS_ERROR_CELLULAR_CALL_IMS_BASE_ERROR_STRING = "Cellular call module ims base error.";
53 static constexpr const char *JS_ERROR_CELLULAR_DATA_BASE_ERROR_STRING = "Cellular data module base error.";
54 static constexpr const char *JS_ERROR_SMS_MMS_BASE_ERROR_STRING = "Sms mms module base error.";
55 static constexpr const char *JS_ERROR_STATE_REGISTRY_BASE_ERROR_STRING = "State registry module base error.";
56 static constexpr const char *JS_ERROR_AIRPLANE_MODE_ON_STRING = "Airplane mode is on.";
57 static constexpr const char *JS_ERROR_NETWORK_NOT_IN_SERVICE = "Network not in service.";
58 static constexpr const char *JS_ERROR_CONFERENCE_EXCEED_LIMIT_STRING = "Conference call is exceed limit.";
59 static constexpr const char *JS_ERROR_CONFERENCE_CALL_IS_NOT_ACTIVE_STRING = "Conference call is not active.";
60 static constexpr const char *JS_ERROR_TELEPHONY_CALL_COUNTS_EXCEED_LIMIT_STRING = "call count exceeds limit";
61 static constexpr const char *JS_ERROR_TELEPHONY_DIAL_IS_BUSY_STRING =
62     "Current on a call, unable to initiate a new call";
63 
64 static std::unordered_map<int32_t, const char *> errorMap_ = {
65     { JsErrorCode::JS_ERROR_TELEPHONY_PERMISSION_DENIED, JS_ERROR_TELEPHONY_PERMISSION_DENIED_STRING },
66     { JsErrorCode::JS_ERROR_ILLEGAL_USE_OF_SYSTEM_API, JS_ERROR_ILLEGAL_USE_OF_SYSTEM_API_STRING },
67     { JsErrorCode::JS_ERROR_TELEPHONY_INVALID_INPUT_PARAMETER, JS_ERROR_TELEPHONY_INVALID_INPUT_PARAMETER_STRING },
68     { JsErrorCode::JS_ERROR_DEVICE_NOT_SUPPORT_THIS_API, JS_ERROR_DEVICE_NOT_SUPPORT_THIS_API_STRING },
69     { JsErrorCode::JS_ERROR_TELEPHONY_SUCCESS, JS_ERROR_TELEPHONY_SUCCESS_STRING },
70     { JsErrorCode::JS_ERROR_TELEPHONY_ARGUMENT_ERROR, JS_ERROR_TELEPHONY_ARGUMENT_ERROR_STRING },
71     { JsErrorCode::JS_ERROR_TELEPHONY_SERVICE_ERROR, JS_ERROR_TELEPHONY_SERVICE_ERROR_STRING },
72     { JsErrorCode::JS_ERROR_TELEPHONY_SYSTEM_ERROR, JS_ERROR_TELEPHONY_SYSTEM_ERROR_STRING },
73     { JsErrorCode::JS_ERROR_TELEPHONY_NO_SIM_CARD, JS_ERROR_TELEPHONY_NO_SIM_CARD_STRING },
74     { JsErrorCode::JS_ERROR_TELEPHONY_UNKNOW_ERROR, JS_ERROR_TELEPHONY_UNKNOW_ERROR_STRING },
75     { JsErrorCode::JS_ERROR_SIM_BASE_ERROR, JS_ERROR_SIM_BASE_ERROR_STRING },
76     { JsErrorCode::JS_ERROR_SIM_CARD_IS_NOT_ACTIVE, JS_ERROR_SIM_CARD_IS_NOT_ACTIVE_STRING },
77     { JsErrorCode::JS_ERROR_SIM_CARD_OPERATION_ERROR, JS_ERROR_SIM_CARD_OPERATION_ERROR_STRING },
78     { JsErrorCode::JS_ERROR_OPERATOR_CONFIG_ERROR, JS_ERROR_OPERATOR_CONFIG_ERROR_STRING },
79     { JsErrorCode::JS_ERROR_NETWORK_SEARCH_BASE_ERROR, JS_ERROR_NETWORK_SEARCH_BASE_ERROR_STRING },
80     { JsErrorCode::JS_ERROR_CALL_MANAGER_BASE_ERROR, JS_ERROR_CALL_MANAGER_BASE_ERROR_STRING },
81     { JsErrorCode::JS_ERROR_CELLULAR_CALL_CS_BASE_ERROR, JS_ERROR_CELLULAR_CALL_CS_BASE_ERROR_STRING },
82     { JsErrorCode::JS_ERROR_CELLULAR_CALL_IMS_BASE_ERROR, JS_ERROR_CELLULAR_CALL_IMS_BASE_ERROR_STRING },
83     { JsErrorCode::JS_ERROR_CELLULAR_DATA_BASE_ERROR, JS_ERROR_CELLULAR_DATA_BASE_ERROR_STRING },
84     { JsErrorCode::JS_ERROR_SMS_MMS_BASE_ERROR, JS_ERROR_SMS_MMS_BASE_ERROR_STRING },
85     { JsErrorCode::JS_ERROR_STATE_REGISTRY_BASE_ERROR, JS_ERROR_STATE_REGISTRY_BASE_ERROR_STRING },
86     { JsErrorCode::JS_ERROR_TELEPHONY_AIRPLANE_MODE_ON, JS_ERROR_AIRPLANE_MODE_ON_STRING },
87     { JsErrorCode::JS_ERROR_TELEPHONY_NETWORK_NOT_IN_SERVICE, JS_ERROR_NETWORK_NOT_IN_SERVICE },
88     { JsErrorCode::JS_ERROR_TELEPHONY_CONFERENCE_EXCEED_LIMIT, JS_ERROR_CONFERENCE_EXCEED_LIMIT_STRING },
89     { JsErrorCode::JS_ERROR_TELEPHONY_CONFERENCE_CALL_NOT_ACTIVE, JS_ERROR_CONFERENCE_CALL_IS_NOT_ACTIVE_STRING },
90     { JsErrorCode::JS_ERROR_TELEPHONY_CALL_COUNTS_EXCEED_LIMIT, JS_ERROR_TELEPHONY_CALL_COUNTS_EXCEED_LIMIT_STRING },
91     { JsErrorCode::JS_ERROR_TELEPHONY_DIAL_IS_BUSY, JS_ERROR_TELEPHONY_DIAL_IS_BUSY_STRING },
92 };
93 const std::string ERROR_STRING = "error";
94 const std::u16string ERROR_USTRING = u"error";
95 
GetErrorMessage(int32_t errorCode)96 std::string NapiUtil::GetErrorMessage(int32_t errorCode)
97 {
98     std::string result = "";
99     auto iter = errorMap_.find(errorCode);
100     if (iter == errorMap_.end()) {
101         TELEPHONY_LOGE("NapiUtil::GetErrorMessage return null.");
102         return result;
103     }
104     TELEPHONY_LOGD("NapiUtil::GetErrorMessage errorCode %{public}d, message = %{public}s", errorCode, iter->second);
105     result = iter->second;
106     return result;
107 }
108 
ToUtf8(std::u16string str16)109 std::string NapiUtil::ToUtf8(std::u16string str16)
110 {
111     if (str16 == ERROR_USTRING) {
112         return ERROR_STRING;
113     }
114     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(ERROR_STRING);
115     std::string result = convert.to_bytes(str16);
116     return result == ERROR_STRING ? "" : result;
117 }
118 
ToUtf16(std::string str)119 std::u16string NapiUtil::ToUtf16(std::string str)
120 {
121     if (str == ERROR_STRING) {
122         return ERROR_USTRING;
123     }
124     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(ERROR_STRING, ERROR_USTRING);
125     std::u16string result = convert.from_bytes(str);
126     return result == ERROR_USTRING ? u"" : result;
127 }
128 
CreateErrorMessage(napi_env env,const std::string & msg,int32_t errorCode)129 napi_value NapiUtil::CreateErrorMessage(napi_env env, const std::string &msg, int32_t errorCode)
130 {
131     napi_value result = nullptr;
132     napi_value message = nullptr;
133     NAPI_CALL(env, napi_create_string_utf8(env, msg.c_str(), msg.length(), &message));
134     napi_value codeValue = nullptr;
135     NAPI_CALL(env, napi_create_int32(env, errorCode, &codeValue));
136     NAPI_CALL(env, napi_create_object(env, &result));
137     NAPI_CALL(env, napi_set_named_property(env, result, "code", codeValue));
138     NAPI_CALL(env, napi_set_named_property(env, result, "message", message));
139     return result;
140 }
141 
CreateUndefined(napi_env env)142 napi_value NapiUtil::CreateUndefined(napi_env env)
143 {
144     napi_value result = nullptr;
145     NAPI_CALL(env, napi_get_undefined(env, &result));
146     return result;
147 }
148 
MatchValueType(napi_env env,napi_value value,napi_valuetype targetType)149 bool NapiUtil::MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)
150 {
151     napi_valuetype valueType = napi_undefined;
152     NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
153     return valueType == targetType;
154 }
155 
MatchParameters(napi_env env,const napi_value parameters[],std::initializer_list<napi_valuetype> valueTypes)156 bool NapiUtil::MatchParameters(
157     napi_env env, const napi_value parameters[], std::initializer_list<napi_valuetype> valueTypes)
158 {
159     if (parameters == nullptr) {
160         return false;
161     }
162     int i = 0;
163     for (auto beg = valueTypes.begin(); beg != valueTypes.end(); ++beg) {
164         if (!MatchValueType(env, parameters[i], *beg)) {
165             return false;
166         }
167         ++i;
168     }
169     return true;
170 }
171 
SetPropertyInt32(napi_env env,napi_value object,const std::string & name,int32_t value)172 void NapiUtil::SetPropertyInt32(napi_env env, napi_value object, const std::string &name, int32_t value)
173 {
174     napi_value propertyValue = nullptr;
175     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, value, &propertyValue));
176     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), propertyValue));
177 }
178 
SetPropertyInt64(napi_env env,napi_value object,const std::string & name,int64_t value)179 void NapiUtil::SetPropertyInt64(napi_env env, napi_value object, const std::string &name, int64_t value)
180 {
181     napi_value propertyValue = nullptr;
182     NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, value, &propertyValue));
183     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), propertyValue));
184 }
185 
SetPropertyStringUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)186 void NapiUtil::SetPropertyStringUtf8(napi_env env, napi_value object, const std::string &name, const std::string &value)
187 {
188     napi_value propertyValue = nullptr;
189     NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, value.c_str(), value.length(), &propertyValue));
190     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), propertyValue));
191 }
192 
SetPropertyBoolean(napi_env env,napi_value object,const std::string & name,bool value)193 void NapiUtil::SetPropertyBoolean(napi_env env, napi_value object, const std::string &name, bool value)
194 {
195     napi_value propertyValue = nullptr;
196     NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &propertyValue));
197     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), propertyValue));
198 }
199 
ToInt32Value(napi_env env,int32_t value)200 napi_value NapiUtil::ToInt32Value(napi_env env, int32_t value)
201 {
202     napi_value staticValue = nullptr;
203     NAPI_CALL(env, napi_create_int32(env, value, &staticValue));
204     return staticValue;
205 }
206 
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)207 bool NapiUtil::HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
208 {
209     bool hasProperty = false;
210     NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty), false);
211     return hasProperty;
212 }
213 
HasNamedTypeProperty(napi_env env,napi_value object,napi_valuetype type,const std::string & propertyName)214 bool NapiUtil::HasNamedTypeProperty(
215     napi_env env, napi_value object, napi_valuetype type, const std::string &propertyName)
216 {
217     bool hasProperty = false;
218     NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty), false);
219     if (hasProperty) {
220         napi_value value = nullptr;
221         NAPI_CALL_BASE(env, napi_get_named_property(env, object, propertyName.data(), &value), false);
222         return MatchValueType(env, value, type);
223     }
224     return false;
225 }
226 
MatchObjectProperty(napi_env env,napi_value object,std::initializer_list<std::pair<std::string,napi_valuetype>> pairList)227 bool NapiUtil::MatchObjectProperty(
228     napi_env env, napi_value object, std::initializer_list<std::pair<std::string, napi_valuetype>> pairList)
229 {
230     if (object == nullptr) {
231         return false;
232     }
233     for (auto beg = pairList.begin(); beg != pairList.end(); ++beg) {
234         if (!HasNamedTypeProperty(env, object, beg->second, beg->first)) {
235             return false;
236         }
237     }
238     return true;
239 }
240 
MatchOptionPropertyType(napi_env env,napi_value object,napi_valuetype type,const std::string & propertyName)241 bool NapiUtil::MatchOptionPropertyType(
242     napi_env env, napi_value object, napi_valuetype type, const std::string &propertyName)
243 {
244     bool hasProperty = false;
245     NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty), false);
246     if (hasProperty) {
247         napi_value value = nullptr;
248         NAPI_CALL_BASE(env, napi_get_named_property(env, object, propertyName.data(), &value), false);
249         return MatchValueType(env, value, type);
250     }
251     return true;
252 }
253 
GetStringFromValue(napi_env env,napi_value value)254 std::string NapiUtil::GetStringFromValue(napi_env env, napi_value value)
255 {
256     char msgChars[MAX_TEXT_LENGTH] = {0};
257     size_t msgLength = 0;
258     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, msgChars, MAX_TEXT_LENGTH, &msgLength), "");
259     TELEPHONY_LOGI("msgLength = %{public}zu", msgLength);
260     if (msgLength > 0) {
261         return std::string(msgChars, 0, msgLength);
262     } else {
263         return "";
264     }
265 }
266 
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)267 napi_value NapiUtil::GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
268 {
269     napi_value value = nullptr;
270     bool hasProperty = false;
271     NAPI_CALL(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty));
272     if (hasProperty) {
273         NAPI_CALL(env, napi_get_named_property(env, object, propertyName.data(), &value));
274     }
275     return value;
276 }
277 
HandleAsyncWork(napi_env env,BaseContext * baseContext,const std::string & workName,napi_async_execute_callback execute,napi_async_complete_callback complete)278 napi_value NapiUtil::HandleAsyncWork(napi_env env, BaseContext *baseContext, const std::string &workName,
279     napi_async_execute_callback execute, napi_async_complete_callback complete)
280 {
281     TELEPHONY_LOGD("workName = %{public}s", workName.c_str());
282     std::unique_ptr<BaseContext> context(baseContext);
283     if (context == nullptr) {
284         ThrowParameterError(env);
285         return nullptr;
286     }
287     napi_value result = nullptr;
288     if (context->callbackRef == nullptr) {
289         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
290     } else {
291         NAPI_CALL(env, napi_get_undefined(env, &result));
292     }
293     napi_value resource = CreateUndefined(env);
294     napi_value resourceName = nullptr;
295     NAPI_CALL(env, napi_create_string_utf8(env, workName.data(), NAPI_AUTO_LENGTH, &resourceName));
296     NAPI_CALL(env,
297         napi_create_async_work(env, resource, resourceName, execute, complete, (void *)context.get(), &context->work));
298     napi_status queueWorkStatus = napi_queue_async_work_with_qos(env, context->work, napi_qos_default);
299     if (queueWorkStatus == napi_ok) {
300         context.release();
301     } else {
302         std::string errorCode = std::to_string(queueWorkStatus);
303         std::string errorMessage = "error at napi_queue_async_work_with_qos";
304         NAPI_CALL(env, napi_throw_error(env, errorCode.c_str(), errorMessage.c_str()));
305     }
306     TELEPHONY_LOGD("NapiUtil HandleAsyncWork end");
307     return result;
308 }
309 
Handle1ValueCallback(napi_env env,BaseContext * baseContext,napi_value callbackValue)310 void NapiUtil::Handle1ValueCallback(napi_env env, BaseContext *baseContext, napi_value callbackValue)
311 {
312     TELEPHONY_LOGD("Handle1ValueCallback start");
313     if (baseContext == nullptr) {
314         TELEPHONY_LOGE("Handle1ValueCallback baseContext is nullptr");
315         NapiUtil::ThrowParameterError(env);
316         return;
317     }
318     if (baseContext->callbackRef != nullptr) {
319         TELEPHONY_LOGI("start normal callback");
320         napi_value recv = CreateUndefined(env);
321         napi_value callbackFunc = nullptr;
322         NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, baseContext->callbackRef, &callbackFunc));
323         napi_value callbackValues[] = {callbackValue};
324         napi_value result = nullptr;
325         NAPI_CALL_RETURN_VOID(
326             env, napi_call_function(env, recv, callbackFunc, std::size(callbackValues), callbackValues, &result));
327         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, baseContext->callbackRef));
328         TELEPHONY_LOGD("normal callback end");
329     } else if (baseContext->deferred != nullptr) {
330         TELEPHONY_LOGI("start promise callback");
331         if (baseContext->resolved) {
332             NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, baseContext->deferred, callbackValue));
333             TELEPHONY_LOGI("napi_resolve_deferred end");
334         } else {
335             NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, baseContext->deferred, callbackValue));
336             TELEPHONY_LOGI("napi_reject_deferred end");
337         }
338         TELEPHONY_LOGD("promise callback end");
339     }
340     napi_delete_async_work(env, baseContext->work);
341     delete baseContext;
342     baseContext = nullptr;
343     TELEPHONY_LOGD("end");
344 }
345 
Handle2ValueCallback(napi_env env,BaseContext * baseContext,napi_value callbackValue)346 void NapiUtil::Handle2ValueCallback(napi_env env, BaseContext *baseContext, napi_value callbackValue)
347 {
348     TELEPHONY_LOGD("Handle2ValueCallback start");
349     if (baseContext == nullptr) {
350         TELEPHONY_LOGI("Handle2ValueCallback serious error baseContext nullptr");
351         ThrowParameterError(env);
352         return;
353     }
354     if (baseContext->callbackRef != nullptr) {
355         TELEPHONY_LOGD("Handle2ValueCallback start normal callback");
356         napi_value recv = CreateUndefined(env);
357         napi_value callbackFunc = nullptr;
358         NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, baseContext->callbackRef, &callbackFunc));
359         napi_value callbackValues[] = {nullptr, nullptr};
360         callbackValues[0] = baseContext->resolved ? CreateUndefined(env) : callbackValue;
361         callbackValues[1] = baseContext->resolved ? callbackValue : CreateUndefined(env);
362         napi_value result = nullptr;
363         NAPI_CALL_RETURN_VOID(
364             env, napi_call_function(env, recv, callbackFunc, std::size(callbackValues), callbackValues, &result));
365         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, baseContext->callbackRef));
366         TELEPHONY_LOGD("Handle2ValueCallback normal callback end");
367     } else if (baseContext->deferred != nullptr) {
368         TELEPHONY_LOGD("Handle2ValueCallback start promise callback");
369         if (baseContext->resolved) {
370             NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, baseContext->deferred, callbackValue));
371         } else {
372             NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, baseContext->deferred, callbackValue));
373         }
374         TELEPHONY_LOGD("Handle2ValueCallback promise callback end");
375     }
376     napi_delete_async_work(env, baseContext->work);
377     delete baseContext;
378     baseContext = nullptr;
379     TELEPHONY_LOGD("Handle2ValueCallback end");
380 }
381 
DefineEnumClassByName(napi_env env,napi_value exports,std::string_view enumName,size_t arrSize,const napi_property_descriptor * desc)382 void NapiUtil::DefineEnumClassByName(
383     napi_env env, napi_value exports, std::string_view enumName, size_t arrSize, const napi_property_descriptor *desc)
384 {
385     auto construct = [](napi_env env, napi_callback_info info) -> napi_value { return nullptr; };
386     napi_value result = nullptr;
387     napi_status status =
388         napi_define_class(env, enumName.data(), NAPI_AUTO_LENGTH, construct, nullptr, arrSize, desc, &result);
389     if (status != napi_ok) {
390         TELEPHONY_LOGE("DefineEnumClassByName napi_define_class failed ret = %d", status);
391     }
392     status = napi_set_named_property(env, exports, enumName.data(), result);
393     if (status != napi_ok) {
394         TELEPHONY_LOGE("DefineEnumClassByName napi_set_named_property failed ret = %d", status);
395     }
396 }
397 
ConverErrorMessageForJs(int32_t errorCode)398 JsError NapiUtil::ConverErrorMessageForJs(int32_t errorCode)
399 {
400     JsError error = {};
401     if (errorCode == TELEPHONY_ERR_SUCCESS) {
402         error.errorCode = JS_ERROR_TELEPHONY_SUCCESS;
403         error.errorMessage = GetErrorMessage(JS_ERROR_TELEPHONY_SUCCESS);
404         return error;
405     }
406 
407     if (CreateParameterErrorMessageForJs(errorCode, error.errorCode)) {
408         error.errorMessage = GetErrorMessage(error.errorCode);
409         return error;
410     }
411 
412     if (!CreateCommonErrorMessageForJs(errorCode, error.errorCode) &&
413         !CreateCallErrorMessageForJs(errorCode, error.errorCode) &&
414         !CreateDataErrorMessageForJs(errorCode, error.errorCode) &&
415         !CreateNetworkSearchErrorMessageForJs(errorCode, error.errorCode) &&
416         !CreateVcardErrorMessageForJs(errorCode, error.errorCode) &&
417         !CreateSimErrorMessageForJs(errorCode, error.errorCode) &&
418         !CreateSmsErrorMessageForJs(errorCode, error.errorCode) &&
419         !CreateObserverErrorMessageForJs(errorCode, error.errorCode)) {
420         error.errorCode = JS_ERROR_TELEPHONY_UNKNOW_ERROR;
421         TELEPHONY_LOGE("NapiUtil::ConverErrorMessageForJs errorCode is out of range");
422     }
423     error.errorMessage = GetErrorMessage(error.errorCode);
424     TELEPHONY_LOGI("errorCode from %{public}d to %{public}d", errorCode, error.errorCode);
425     return error;
426 }
427 
CreateParameterErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)428 bool NapiUtil::CreateParameterErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
429 {
430     bool flag = true;
431     switch (errorCode) {
432         case ERROR_SERVICE_UNAVAILABLE:
433         case ERROR_NATIVE_API_EXECUTE_FAIL:
434             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
435             break;
436         case ERROR_PARAMETER_COUNTS_INVALID:
437         case ERROR_PARAMETER_TYPE_INVALID:
438         case napi_status::napi_generic_failure:
439         case napi_status::napi_invalid_arg:
440             jsErrorCode = JS_ERROR_TELEPHONY_INVALID_INPUT_PARAMETER;
441             break;
442         case ERROR_SLOT_ID_INVALID:
443             jsErrorCode = JS_ERROR_TELEPHONY_ARGUMENT_ERROR;
444             break;
445         default:
446             flag = false;
447             break;
448     }
449 
450     return flag;
451 }
452 
CreateNetworkSearchErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)453 bool NapiUtil::CreateNetworkSearchErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
454 {
455     if ((errorCode < CORE_SERVICE_NETWORK_SEARCH_ERR_OFFSET || errorCode >= CORE_SERVICE_CORE_ERR_OFFSET)) {
456         return false;
457     }
458     bool flag = true;
459     switch (errorCode) {
460         case CORE_SERVICE_SEND_CALLBACK_FAILED:
461         case CORE_SERVICE_RADIO_PROTOCOL_TECH_UNKNOWN:
462             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
463             break;
464         default:
465             flag = false;
466             break;
467     }
468 
469     return flag;
470 }
471 
CreateVcardErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)472 bool NapiUtil::CreateVcardErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
473 {
474     bool flag = true;
475     switch (errorCode) {
476         case TELEPHONY_ERR_VCARD_FILE_INVALID:
477             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
478             break;
479         default:
480             flag = false;
481             break;
482     }
483 
484     return flag;
485 }
486 
CreateSimErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)487 bool NapiUtil::CreateSimErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
488 {
489     if ((errorCode < CORE_SERVICE_SIM_ERR_OFFSET || errorCode >= CORE_SERVICE_NETWORK_SEARCH_ERR_OFFSET)) {
490         return false;
491     }
492     bool flag = true;
493     switch (errorCode) {
494         case CORE_SERVICE_SIM_CARD_IS_NOT_ACTIVE:
495             jsErrorCode = JS_ERROR_SIM_CARD_IS_NOT_ACTIVE;
496             break;
497         case CORE_ERR_SIM_CARD_LOAD_FAILED:
498         case CORE_ERR_SIM_CARD_UPDATE_FAILED:
499             jsErrorCode = JS_ERROR_SIM_CARD_OPERATION_ERROR;
500             break;
501         case CORE_ERR_OPERATOR_KEY_NOT_EXIT:
502         case CORE_ERR_OPERATOR_CONF_NOT_EXIT:
503             jsErrorCode = JS_ERROR_OPERATOR_CONFIG_ERROR;
504             break;
505         default:
506             flag = false;
507             break;
508     }
509 
510     return flag;
511 }
512 
CreateSmsErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)513 bool NapiUtil::CreateSmsErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
514 {
515     if ((errorCode < SMS_MMS_ERR_OFFSET || errorCode >= STATE_REGISTRY_ERR_OFFSET)) {
516         return false;
517     }
518     bool flag = true;
519     switch (errorCode) {
520         case TELEPHONY_SMS_MMS_DECODE_DATA_EMPTY:
521         case TELEPHONY_SMS_MMS_UNKNOWN_SIM_MESSAGE_STATUS:
522         case TELEPHONY_SMS_MMS_MESSAGE_LENGTH_OUT_OF_RANGE:
523             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
524             break;
525         default:
526             flag = false;
527             break;
528     }
529 
530     return flag;
531 }
532 
CreateObserverErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)533 bool NapiUtil::CreateObserverErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
534 {
535     if ((errorCode < STATE_REGISTRY_ERR_OFFSET || errorCode >= NET_MANAGER_ERR_OFFSET)) {
536         return false;
537     }
538     bool flag = true;
539     switch (errorCode) {
540         case TELEPHONY_STATE_REGISTRY_SLODID_ERROR:
541             jsErrorCode = JS_ERROR_TELEPHONY_ARGUMENT_ERROR;
542             break;
543         case TELEPHONY_STATE_REGISTRY_PERMISSION_DENIED:
544             jsErrorCode = JS_ERROR_TELEPHONY_PERMISSION_DENIED;
545             break;
546         case TELEPHONY_STATE_REGISTRY_DATA_NOT_EXIST:
547         case TELEPHONY_STATE_UNREGISTRY_DATA_NOT_EXIST:
548         case TELEPHONY_STATE_REGISTRY_DATA_EXIST:
549         case TELEPHONY_STATE_REGISTRY_NOT_IMPLEMENTED:
550             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
551             break;
552         default:
553             flag = false;
554             break;
555     }
556 
557     return flag;
558 }
559 
CreateCommonErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)560 bool NapiUtil::CreateCommonErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
561 {
562     if ((errorCode < COMMON_ERR_OFFSET || errorCode >= CALL_ERR_OFFSET)) {
563         return false;
564     }
565     if (CreateCommonArgumentErrorMessageForJs(errorCode, jsErrorCode) ||
566         CreateCommonServiceErrorMessageForJs(errorCode, jsErrorCode) ||
567         CreateCommonSystemErrorMessageForJs(errorCode, jsErrorCode)) {
568         return true;
569     }
570     return false;
571 }
572 
CreateCommonArgumentErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)573 bool NapiUtil::CreateCommonArgumentErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
574 {
575     bool flag = true;
576 
577     switch (errorCode) {
578         case TELEPHONY_ERR_ARGUMENT_MISMATCH:
579         case TELEPHONY_ERR_ARGUMENT_INVALID:
580         case TELEPHONY_ERR_ARGUMENT_NULL:
581         case TELEPHONY_ERR_SLOTID_INVALID:
582             jsErrorCode = JS_ERROR_TELEPHONY_ARGUMENT_ERROR;
583             break;
584         default:
585             flag = false;
586             break;
587     }
588     return flag;
589 }
590 
CreateCommonServiceErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)591 bool NapiUtil::CreateCommonServiceErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
592 {
593     bool flag = true;
594 
595     switch (errorCode) {
596         case TELEPHONY_ERR_DESCRIPTOR_MISMATCH:
597         case TELEPHONY_ERR_WRITE_DESCRIPTOR_TOKEN_FAIL:
598         case TELEPHONY_ERR_WRITE_DATA_FAIL:
599         case TELEPHONY_ERR_WRITE_REPLY_FAIL:
600         case TELEPHONY_ERR_READ_DATA_FAIL:
601         case TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL:
602         case TELEPHONY_ERR_REGISTER_CALLBACK_FAIL:
603         case TELEPHONY_ERR_CALLBACK_ALREADY_REGISTERED:
604         case TELEPHONY_ERR_UNINIT:
605         case TELEPHONY_ERR_UNREGISTER_CALLBACK_FAIL:
606             jsErrorCode = JS_ERROR_TELEPHONY_SERVICE_ERROR;
607             break;
608         default:
609             flag = false;
610             break;
611     }
612     return flag;
613 }
614 
CreateCommonSystemErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)615 bool NapiUtil::CreateCommonSystemErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
616 {
617     bool flag = true;
618 
619     switch (errorCode) {
620         case TELEPHONY_ERR_FAIL:
621         case TELEPHONY_ERR_MEMCPY_FAIL:
622         case TELEPHONY_ERR_MEMSET_FAIL:
623         case TELEPHONY_ERR_STRCPY_FAIL:
624         case TELEPHONY_ERR_LOCAL_PTR_NULL:
625         case TELEPHONY_ERR_SUBSCRIBE_BROADCAST_FAIL:
626         case TELEPHONY_ERR_PUBLISH_BROADCAST_FAIL:
627         case TELEPHONY_ERR_ADD_DEATH_RECIPIENT_FAIL:
628         case TELEPHONY_ERR_STRTOINT_FAIL:
629         case TELEPHONY_ERR_RIL_CMD_FAIL:
630         case TELEPHONY_ERR_DATABASE_WRITE_FAIL:
631         case TELEPHONY_ERR_DATABASE_READ_FAIL:
632         case TELEPHONY_ERR_UNKNOWN_NETWORK_TYPE:
633             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
634             break;
635         case TELEPHONY_ERR_NO_SIM_CARD:
636             jsErrorCode = JS_ERROR_TELEPHONY_NO_SIM_CARD;
637             break;
638         case TELEPHONY_ERR_ILLEGAL_USE_OF_SYSTEM_API:
639             jsErrorCode = JS_ERROR_ILLEGAL_USE_OF_SYSTEM_API;
640             break;
641         case TELEPHONY_ERR_AIRPLANE_MODE_ON:
642             jsErrorCode = JS_ERROR_TELEPHONY_AIRPLANE_MODE_ON;
643             break;
644         case TELEPHONY_ERR_NETWORK_NOT_IN_SERVICE:
645             jsErrorCode = JS_ERROR_TELEPHONY_NETWORK_NOT_IN_SERVICE;
646             break;
647         default:
648             flag = false;
649             break;
650     }
651     return flag;
652 }
653 
CreateCallErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)654 bool NapiUtil::CreateCallErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
655 {
656     if ((errorCode < CALL_ERR_OFFSET || errorCode >= CELLULAR_DATA_ERR_OFFSET)) {
657         return false;
658     }
659     if (CreateCommonCallErrorMessageForJs(errorCode, jsErrorCode) ||
660         CreateVideoCallErrorMessageForJs(errorCode, jsErrorCode) ||
661         CreateSupplementServiceCallErrorMessageForJs(errorCode, jsErrorCode)) {
662         return true;
663     }
664     return false;
665 }
666 
CreateCommonCallErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)667 bool NapiUtil::CreateCommonCallErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
668 {
669     bool flag = true;
670 
671     switch (errorCode) {
672         case TELEPHONY_CALL_ERR_NUMBER_OUT_OF_RANGE:
673         case TELEPHONY_CALL_ERR_PHONE_NUMBER_EMPTY:
674         case TELEPHONY_CALL_ERR_FORMAT_PHONE_NUMBER_FAILED:
675             jsErrorCode = JS_ERROR_TELEPHONY_ARGUMENT_ERROR;
676             break;
677         case TELEPHONY_CALL_ERR_PARAMETER_OUT_OF_RANGE:
678         case TELEPHONY_CALL_ERR_INVALID_SLOT_ID:
679             jsErrorCode = JS_ERROR_TELEPHONY_ARGUMENT_ERROR;
680             break;
681         case TELEPHONY_CALL_ERR_CONFERENCE_CALL_EXCEED_LIMIT:
682             jsErrorCode = JS_ERROR_TELEPHONY_CONFERENCE_EXCEED_LIMIT;
683             break;
684         case TELEPHONY_CALL_ERR_CONFERENCE_CALL_IS_NOT_ACTIVE:
685             jsErrorCode = JS_ERROR_TELEPHONY_CONFERENCE_CALL_NOT_ACTIVE;
686             break;
687         case TELEPHONY_CALL_ERR_CALL_COUNTS_EXCEED_LIMIT:
688             jsErrorCode = JS_ERROR_TELEPHONY_CALL_COUNTS_EXCEED_LIMIT;
689             break;
690         case TELEPHONY_CALL_ERR_CALL_IS_NOT_ACTIVATED:
691         case TELEPHONY_CALL_ERR_ILLEGAL_CALL_OPERATION:
692         case TELEPHONY_CALL_ERR_AUDIO_SETTING_MUTE_FAILED:
693         case TELEPHONY_CALL_ERR_CALL_IS_NOT_ON_HOLDING:
694         case TELEPHONY_CALL_ERR_PHONE_CALLS_TOO_FEW:
695         case TELEPHONY_CALL_ERR_VIDEO_ILLEGAL_CALL_TYPE:
696         case TELEPHONY_CALL_ERR_CONFERENCE_NOT_EXISTS:
697         case TELEPHONY_CALL_ERR_CONFERENCE_SEPERATE_FAILED:
698         case TELEPHONY_CALL_ERR_EMERGENCY_UNSUPPORT_CONFERENCEABLE:
699         case TELEPHONY_CALL_ERR_VOLTE_NOT_SUPPORT:
700         case TELEPHONY_CALL_ERR_VOLTE_PROVISIONING_DISABLED:
701             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
702             break;
703         case TELEPHONY_CALL_ERR_DIAL_IS_BUSY:
704             jsErrorCode = JS_ERROR_TELEPHONY_DIAL_IS_BUSY;
705             break;
706         default:
707             flag = false;
708             break;
709     }
710     return flag;
711 }
712 
CreateVideoCallErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)713 bool NapiUtil::CreateVideoCallErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
714 {
715     bool flag = true;
716 
717     switch (errorCode) {
718         case TELEPHONY_CALL_ERR_VIDEO_ILLEGAL_MEDIA_TYPE:
719         case TELEPHONY_CALL_ERR_VIDEO_IN_PROGRESS:
720         case TELEPHONY_CALL_ERR_VIDEO_ILLEAGAL_SCENARIO:
721         case TELEPHONY_CALL_ERR_VIDEO_MODE_CHANGE_NOTIFY_FAILED:
722         case TELEPHONY_CALL_ERR_VIDEO_NOT_SUPPORTED:
723         case TELEPHONY_CALL_ERR_SETTING_AUDIO_DEVICE_FAILED:
724         case TELEPHONY_CALL_ERR_VIDEO_INVALID_COORDINATES:
725         case TELEPHONY_CALL_ERR_VIDEO_INVALID_ZOOM:
726         case TELEPHONY_CALL_ERR_VIDEO_INVALID_ROTATION:
727         case TELEPHONY_CALL_ERR_VIDEO_INVALID_CAMERA_ID:
728         case TELEPHONY_CALL_ERR_INVALID_PATH:
729         case TELEPHONY_CALL_ERR_CAMERA_NOT_TURNED_ON:
730         case TELEPHONY_CALL_ERR_INVALID_DIAL_SCENE:
731         case TELEPHONY_CALL_ERR_INVALID_VIDEO_STATE:
732         case TELEPHONY_CALL_ERR_UNKNOW_DIAL_TYPE:
733             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
734             break;
735         default:
736             flag = false;
737             break;
738     }
739     return flag;
740 }
741 
CreateSupplementServiceCallErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)742 bool NapiUtil::CreateSupplementServiceCallErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
743 {
744     bool flag = true;
745 
746     switch (errorCode) {
747         case TELEPHONY_CALL_ERR_INVALID_RESTRICTION_TYPE:
748         case TELEPHONY_CALL_ERR_INVALID_RESTRICTION_MODE:
749         case TELEPHONY_CALL_ERR_INVALID_TRANSFER_TYPE:
750         case TELEPHONY_CALL_ERR_INVALID_TRANSFER_SETTING_TYPE:
751             jsErrorCode = JS_ERROR_TELEPHONY_ARGUMENT_ERROR;
752             break;
753         case TELEPHONY_CALL_ERR_FUNCTION_NOT_SUPPORTED:
754             jsErrorCode = JS_ERROR_DEVICE_NOT_SUPPORT_THIS_API;
755             break;
756         case TELEPHONY_CALL_ERR_INVALID_TRANSFER_TIME:
757         case TELEPHONY_CALL_ERR_NAPI_INTERFACE_FAILED:
758         case TELEPHONY_CALL_ERR_CALLBACK_ALREADY_EXIST:
759         case TELEPHONY_CALL_ERR_RESOURCE_UNAVAILABLE:
760             jsErrorCode = JS_ERROR_TELEPHONY_SYSTEM_ERROR;
761             break;
762         case TELEPHONY_CALL_ERR_UT_NO_CONNECTION:
763             jsErrorCode = JS_ERROR_CALL_UT_NO_CONNECTION;
764             break;
765         default:
766             flag = false;
767             break;
768     }
769     return flag;
770 }
771 
CreateDataErrorMessageForJs(int32_t errorCode,JsErrorCode & jsErrorCode)772 bool NapiUtil::CreateDataErrorMessageForJs(int32_t errorCode, JsErrorCode &jsErrorCode)
773 {
774     if ((errorCode < CELLULAR_DATA_ERR_OFFSET || errorCode >= SMS_MMS_ERR_OFFSET)) {
775         return false;
776     }
777     bool flag = true;
778 
779     switch (errorCode) {
780         case TELEPHONY_CELLULAR_DATA_INVALID_PARAM:
781             jsErrorCode = JS_ERROR_CELLULAR_DATA_BASE_ERROR;
782             break;
783         default:
784             flag = false;
785             break;
786     }
787     return flag;
788 }
789 
ConverErrorMessageWithPermissionForJs(int32_t errorCode,const std::string & funcName,const std::string & permission)790 JsError NapiUtil::ConverErrorMessageWithPermissionForJs(
791     int32_t errorCode, const std::string &funcName, const std::string &permission)
792 {
793     if (errorCode == TELEPHONY_ERR_PERMISSION_ERR) {
794         JsError error = {};
795         error.errorCode = JS_ERROR_TELEPHONY_PERMISSION_DENIED;
796         error.errorMessage = "BusinessError 201: Permission denied. An attempt was made to " + funcName +
797                              " forbidden by permission: " + permission;
798         return error;
799     }
800     return ConverErrorMessageForJs(errorCode);
801 }
802 
CreateError(napi_env env,int32_t err,const std::string & msg)803 napi_value NapiUtil::CreateError(napi_env env, int32_t err, const std::string &msg)
804 {
805     napi_value businessError = nullptr;
806     napi_value errorCode = nullptr;
807     NAPI_CALL(env, napi_create_int32(env, err, &errorCode));
808     napi_value errorMessage = nullptr;
809     NAPI_CALL(env, napi_create_string_utf8(env, msg.c_str(), NAPI_AUTO_LENGTH, &errorMessage));
810     napi_create_error(env, nullptr, errorMessage, &businessError);
811     napi_set_named_property(env, businessError, "code", errorCode);
812     return businessError;
813 }
814 
ThrowError(napi_env env,int32_t errorCode,const std::string & message)815 void NapiUtil::ThrowError(napi_env env, int32_t errorCode, const std::string &message)
816 {
817     napi_value error = CreateError(env, errorCode, message);
818     napi_throw(env, error);
819 }
820 
ThrowParameterError(napi_env env)821 void NapiUtil::ThrowParameterError(napi_env env)
822 {
823     ThrowError(
824         env, JS_ERROR_TELEPHONY_INVALID_INPUT_PARAMETER, GetErrorMessage(JS_ERROR_TELEPHONY_INVALID_INPUT_PARAMETER));
825 }
826 } // namespace Telephony
827 } // namespace OHOS
828