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