• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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_utils.h"
17 
18 #include "napi/native_api.h"
19 #include "napi/native_node_api.h"
20 #include "time_common.h"
21 
22 namespace OHOS {
23 namespace MiscServices {
24 namespace Time {
25 static constexpr int32_t STR_MAX_LENGTH = 4096;
26 static constexpr size_t STR_TAIL_LENGTH = 1;
27 static constexpr const char *SYSTEM_ERROR = "system error";
ConvertErrorCode(int32_t timeErrorCode)28 int32_t NapiUtils::ConvertErrorCode(int32_t timeErrorCode)
29 {
30     switch (timeErrorCode) {
31         case MiscServices::E_TIME_NOT_SYSTEM_APP:
32             return JsErrorCode::SYSTEM_APP_ERROR;
33         case MiscServices::E_TIME_NO_PERMISSION:
34             return JsErrorCode::PERMISSION_ERROR;
35         case MiscServices::E_TIME_PARAMETERS_INVALID:
36             return JsErrorCode::PARAMETER_ERROR;
37         default:
38             return JsErrorCode::ERROR;
39     }
40 }
41 
CreateNapiNumber(napi_env env,int32_t objName)42 napi_value NapiUtils::CreateNapiNumber(napi_env env, int32_t objName)
43 {
44     napi_value prop = nullptr;
45     napi_create_int32(env, objName, &prop);
46     return prop;
47 }
48 
GetUndefinedValue(napi_env env)49 napi_value NapiUtils::GetUndefinedValue(napi_env env)
50 {
51     napi_value result{};
52     napi_get_undefined(env, &result);
53     return result;
54 }
55 
GetValue(napi_env env,napi_value in,std::string & out)56 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::string &out)
57 {
58     napi_valuetype type = napi_undefined;
59     napi_status status = napi_typeof(env, in, &type);
60     CHECK_RETURN(TIME_MODULE_JS_NAPI, (status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg);
61     size_t maxLen = STR_MAX_LENGTH;
62     napi_get_value_string_utf8(env, in, nullptr, 0, &maxLen);
63     if (maxLen >= STR_MAX_LENGTH) {
64         return napi_invalid_arg;
65     }
66     char buf[STR_MAX_LENGTH + STR_TAIL_LENGTH]{};
67     size_t len = 0;
68     napi_status getStringStatus = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len);
69     if (getStringStatus == napi_ok) {
70         out = std::string(buf);
71     }
72     return status;
73 }
74 
SetTimerCallback(const napi_env & env,const napi_ref & callbackIn,const int32_t & errorCode,const char * message,const napi_value & result)75 void NapiUtils::SetTimerCallback(const napi_env &env, const napi_ref &callbackIn, const int32_t &errorCode,
76     const char *message, const napi_value &result)
77 {
78     napi_value undefined = nullptr;
79     napi_get_undefined(env, &undefined);
80 
81     napi_value callback = nullptr;
82     napi_value resultOut = nullptr;
83     napi_get_reference_value(env, callbackIn, &callback);
84     napi_value results[2] = { 0 };
85 
86     auto innerCode = ConvertErrorCode(errorCode);
87     napi_value eCode = nullptr;
88     napi_create_int32(env, innerCode, &eCode);
89     napi_set_named_property(env, result, "code", eCode);
90 
91     napi_value str;
92     napi_create_string_utf8(env, CODE_TO_MESSAGE.find(innerCode)->second.c_str(), NAPI_AUTO_LENGTH, &str);
93     napi_set_named_property(env, results[0], "message", str);
94     results[1] = result;
95     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGC_TWO, &results[0], &resultOut));
96 }
97 
ThrowError(napi_env env,const char * napiMessage,int32_t napiCode)98 napi_status NapiUtils::ThrowError(napi_env env, const char *napiMessage, int32_t napiCode)
99 {
100     napi_value message = nullptr;
101     napi_value code = nullptr;
102     napi_value result = nullptr;
103     napi_create_string_utf8(env, napiMessage, NAPI_AUTO_LENGTH, &message);
104     napi_create_error(env, nullptr, message, &result);
105     napi_create_int32(env, napiCode, &code);
106     napi_set_named_property(env, result, "code", code);
107     napi_throw(env, result);
108     return napi_ok;
109 }
110 
GetErrorMessage(int32_t errCode)111 std::string NapiUtils::GetErrorMessage(int32_t errCode)
112 {
113     auto it = CODE_TO_MESSAGE.find(errCode);
114     if (it != CODE_TO_MESSAGE.end()) {
115         return it->second;
116     }
117     return std::string(SYSTEM_ERROR);
118 }
119 
GetCallbackErrorValue(napi_env env,int32_t errCode,const std::string & message)120 napi_value NapiUtils::GetCallbackErrorValue(napi_env env, int32_t errCode, const std::string &message)
121 {
122     napi_value result = nullptr;
123     napi_value eCode = nullptr;
124     if (errCode == JsErrorCode::ERROR_OK) {
125         napi_get_undefined(env, &result);
126         return result;
127     }
128     NAPI_CALL(env, napi_create_object(env, &result));
129     if (errCode == JsErrorCode::ERROR) {
130         NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
131         NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode));
132 
133         napi_value str;
134         size_t str_len = strlen(message.c_str());
135         NAPI_CALL(env, napi_create_string_utf8(env, message.c_str(), str_len, &str));
136         NAPI_CALL(env, napi_set_named_property(env, result, "message", str));
137     }
138     return result;
139 }
140 
NapiGetNull(napi_env env)141 napi_value NapiUtils::NapiGetNull(napi_env env)
142 {
143     napi_value result = nullptr;
144     napi_get_null(env, &result);
145     return result;
146 }
147 
SetPromise(napi_env env,napi_deferred deferred,int32_t errorCode,const std::string & message,napi_value result)148 void NapiUtils::SetPromise(napi_env env, napi_deferred deferred, int32_t errorCode, const std::string &message,
149     napi_value result)
150 {
151     if (errorCode == JsErrorCode::ERROR_OK) {
152         NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result));
153         return;
154     }
155     NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, GetCallbackErrorValue(env, errorCode, message)));
156 }
157 
SetCallback(napi_env env,napi_ref callbackIn,int32_t errorCode,const std::string & message,napi_value result)158 void NapiUtils::SetCallback(napi_env env, napi_ref callbackIn, int32_t errorCode, const std::string &message,
159     napi_value result)
160 {
161     napi_value undefined = nullptr;
162     napi_get_undefined(env, &undefined);
163 
164     napi_value callback = nullptr;
165     napi_value resultOut = nullptr;
166     napi_get_reference_value(env, callbackIn, &callback);
167     napi_value results[2] = { 0 };
168     results[0] = GetCallbackErrorValue(env, errorCode, message);
169     results[1] = result;
170     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGC_TWO, &results[0], &resultOut));
171 }
172 
ReturnCallbackPromise(napi_env env,const CallbackPromiseInfo & info,napi_value result)173 void NapiUtils::ReturnCallbackPromise(napi_env env, const CallbackPromiseInfo &info, napi_value result)
174 {
175     if (info.isCallback) {
176         SetCallback(env, info.callback, info.errorCode, info.message, result);
177     } else {
178         SetPromise(env, info.deferred, info.errorCode, info.message, result);
179     }
180 }
181 
JSParaError(napi_env env,napi_ref callback)182 napi_value NapiUtils::JSParaError(napi_env env, napi_ref callback)
183 {
184     if (callback) {
185         return GetCallbackErrorValue(env, ERROR, NapiUtils::GetErrorMessage(JsErrorCode::PARAMETER_ERROR));
186     } else {
187         napi_value promise = nullptr;
188         napi_deferred deferred = nullptr;
189         napi_create_promise(env, &deferred, &promise);
190         SetPromise(env, deferred, ERROR, NapiUtils::GetErrorMessage(JsErrorCode::PARAMETER_ERROR), NapiGetNull(env));
191         return promise;
192     }
193 }
194 
ParseParametersBySetTime(napi_env env,const napi_value (& argv)[SET_TIME_MAX_PARA],size_t argc,int64_t & times,napi_ref & callback)195 napi_value NapiUtils::ParseParametersBySetTime(napi_env env, const napi_value (&argv)[SET_TIME_MAX_PARA], size_t argc,
196     int64_t &times, napi_ref &callback)
197 {
198     NAPI_ASSERTP(env, argc >= SET_TIME_MAX_PARA - 1, "Wrong number of arguments");
199     napi_valuetype valueType = napi_undefined;
200 
201     // argv[0]: times or date object
202     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
203     NAPI_ASSERTP(env, valueType == napi_number || valueType == napi_object,
204         "Parameter error. The type of time must be number or date.");
205     if (valueType == napi_number) {
206         napi_get_value_int64(env, argv[0], &times);
207         NAPI_ASSERTP(env, times >= 0, "Wrong argument timer. Positive number expected.");
208     } else {
209         bool hasProperty = false;
210         napi_valuetype resValueType = napi_undefined;
211         NAPI_CALL(env, napi_has_named_property(env, argv[0], "getTime", &hasProperty));
212         NAPI_ASSERTP(env, hasProperty, "type expected.");
213         napi_value getTimeFunc = nullptr;
214         napi_get_named_property(env, argv[0], "getTime", &getTimeFunc);
215         napi_value getTimeResult = nullptr;
216         napi_call_function(env, argv[0], getTimeFunc, 0, nullptr, &getTimeResult);
217         NAPI_CALL(env, napi_typeof(env, getTimeResult, &resValueType));
218         NAPI_ASSERTP(env, resValueType == napi_number, "type mismatch");
219         napi_get_value_int64(env, getTimeResult, &times);
220     }
221 
222     // argv[1]:callback
223     if (argc >= SET_TIME_MAX_PARA) {
224         NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
225         NAPI_ASSERTP(env, valueType == napi_function, "Parameter error. The type of callback must be function.");
226         napi_create_reference(env, argv[1], 1, &callback);
227     }
228     return NapiGetNull(env);
229 }
230 
ParseParametersBySetTimezone(napi_env env,const napi_value (& argv)[SET_TIMEZONE_MAX_PARA],size_t argc,std::string & timezoneId,napi_ref & callback)231 napi_value NapiUtils::ParseParametersBySetTimezone(napi_env env, const napi_value (&argv)[SET_TIMEZONE_MAX_PARA],
232     size_t argc, std::string &timezoneId, napi_ref &callback)
233 {
234     NAPI_ASSERTP(env, argc >= SET_TIMEZONE_MAX_PARA - 1, "Wrong number of arguments");
235     napi_valuetype valueType = napi_undefined;
236 
237     // argv[0]: timezoneid
238     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
239     NAPI_ASSERTP(env, valueType == napi_string, "Parameter error. The type of timezone must be string.");
240     char timeZoneChars[MAX_TIME_ZONE_ID];
241     size_t copied;
242     napi_get_value_string_utf8(env, argv[0], timeZoneChars, MAX_TIME_ZONE_ID - 1, &copied);
243     TIME_HILOGD(TIME_MODULE_JNI, "timezone str: %{public}s", timeZoneChars);
244 
245     timezoneId = std::string(timeZoneChars);
246 
247     // argv[1]:callback
248     if (argc >= SET_TIMEZONE_MAX_PARA) {
249         NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
250         NAPI_ASSERTP(env, valueType == napi_function, "Parameter error. The type of callback must be function.");
251         napi_create_reference(env, argv[1], 1, &callback);
252     }
253     return NapiGetNull(env);
254 }
255 
ParseParametersGet(napi_env env,const napi_value (& argv)[SET_TIMEZONE_MAX_PARA],size_t argc,napi_ref & callback)256 napi_value NapiUtils::ParseParametersGet(napi_env env, const napi_value (&argv)[SET_TIMEZONE_MAX_PARA], size_t argc,
257     napi_ref &callback)
258 {
259     napi_valuetype valueType = napi_undefined;
260     if (argc == 1) {
261         NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
262         NAPI_ASSERTP(env, valueType == napi_function, "Parameter error. The type of callback must be function.");
263         napi_create_reference(env, argv[0], 1, &callback);
264     }
265     return NapiGetNull(env);
266 }
267 
ParseParametersGetNA(napi_env env,const napi_value (& argv)[SET_TIMEZONE_MAX_PARA],size_t argc,napi_ref & callback,bool * isNano)268 napi_value NapiUtils::ParseParametersGetNA(napi_env env, const napi_value (&argv)[SET_TIMEZONE_MAX_PARA], size_t argc,
269     napi_ref &callback, bool *isNano)
270 {
271     napi_valuetype valueType = napi_undefined;
272     if (argc == 1) {
273         NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
274         if (valueType == napi_function) {
275             napi_create_reference(env, argv[0], 1, &callback);
276         } else if (valueType == napi_boolean) {
277             napi_get_value_bool(env, argv[0], isNano);
278         }
279     } else if (argc == ARGC_TWO) {
280         napi_get_value_bool(env, argv[0], isNano);
281         napi_create_reference(env, argv[1], 1, &callback);
282     }
283     return NapiGetNull(env);
284 }
285 } // namespace Time
286 } // namespace MiscServices
287 } // namespace OHOS