1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "js_utils.h"
17 #include "js_util.h"
18
19 namespace OHOS {
20 namespace MiscServices {
21 constexpr int32_t STR_MAX_LENGTH = 4096;
22 constexpr size_t STR_TAIL_LENGTH = 1;
23 constexpr size_t ARGC_MAX = 6;
24 const std::map<int32_t, int32_t> JsUtils::ERROR_CODE_MAP = {
25 { ErrorCode::ERROR_CONTROLLER_INVOKING_FAILED, EXCEPTION_CONTROLLER },
26 { ErrorCode::ERROR_STATUS_PERMISSION_DENIED, EXCEPTION_PERMISSION },
27 { ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION, EXCEPTION_SYSTEM_PERMISSION },
28 { ErrorCode::ERROR_REMOTE_CLIENT_DIED, EXCEPTION_IMCLIENT },
29 { ErrorCode::ERROR_CLIENT_NOT_FOUND, EXCEPTION_IMCLIENT },
30 { ErrorCode::ERROR_CLIENT_NULL_POINTER, EXCEPTION_IMCLIENT },
31 { ErrorCode::ERROR_CLIENT_NOT_FOCUSED, EXCEPTION_IMCLIENT },
32 { ErrorCode::ERROR_CLIENT_NOT_EDITABLE, EXCEPTION_IMCLIENT },
33 { ErrorCode::ERROR_CLIENT_NOT_BOUND, EXCEPTION_DETACHED },
34 { ErrorCode::ERROR_CLIENT_ADD_FAILED, EXCEPTION_IMCLIENT },
35 { ErrorCode::ERROR_NULL_POINTER, EXCEPTION_IMMS },
36 { ErrorCode::ERROR_BAD_PARAMETERS, EXCEPTION_IMMS },
37 { ErrorCode::ERROR_SERVICE_START_FAILED, EXCEPTION_IMMS },
38 { ErrorCode::ERROR_IME_START_FAILED, EXCEPTION_IMMS },
39 { ErrorCode::ERROR_KBD_SHOW_FAILED, EXCEPTION_IMMS },
40 { ErrorCode::ERROR_KBD_HIDE_FAILED, EXCEPTION_IMMS },
41 { ErrorCode::ERROR_IME_NOT_STARTED, EXCEPTION_IMMS },
42 { ErrorCode::ERROR_EX_NULL_POINTER, EXCEPTION_IMMS },
43 { ErrorCode::ERROR_PERSIST_CONFIG, EXCEPTION_CONFPERSIST },
44 { ErrorCode::ERROR_PACKAGE_MANAGER, EXCEPTION_PACKAGEMANAGER },
45 { ErrorCode::ERROR_EX_UNSUPPORTED_OPERATION, EXCEPTION_IMMS },
46 { ErrorCode::ERROR_EX_SERVICE_SPECIFIC, EXCEPTION_IMMS },
47 { ErrorCode::ERROR_EX_PARCELABLE, EXCEPTION_IMMS },
48 { ErrorCode::ERROR_EX_ILLEGAL_ARGUMENT, EXCEPTION_IMMS },
49 { ErrorCode::ERROR_EX_ILLEGAL_STATE, EXCEPTION_IMMS },
50 { ErrorCode::ERROR_NOT_IME, EXCEPTION_IME },
51 { ErrorCode::ERROR_IME_NOT_READY, EXCEPTION_IMENGINE },
52 { ErrorCode::ERROR_IME, EXCEPTION_IMENGINE },
53 };
54
55 const std::map<int32_t, std::string> JsUtils::ERROR_CODE_CONVERT_MESSAGE_MAP = {
56 { EXCEPTION_PERMISSION, "the permissions check fails." },
57 { EXCEPTION_SYSTEM_PERMISSION, "not system application." },
58 { EXCEPTION_PARAMCHECK, "the parameters check fails." },
59 { EXCEPTION_UNSUPPORTED, "call unsupported api." },
60 { EXCEPTION_PACKAGEMANAGER, "package manager error." },
61 { EXCEPTION_IMENGINE, "input method engine error." },
62 { EXCEPTION_IMCLIENT, "input method client error." },
63 { EXCEPTION_IME, "not an input method extension." },
64 { EXCEPTION_CONFPERSIST, "configuration persisting error." },
65 { EXCEPTION_CONTROLLER, "input method controller error." },
66 { EXCEPTION_SETTINGS, "input method settings extension error." },
67 { EXCEPTION_IMMS, "input method manager service error." },
68 { EXCEPTION_DETACHED, "input method not attached." },
69 };
70
71 const std::map<int32_t, std::string> JsUtils::PARAMETER_TYPE = {
72 { TYPE_UNDEFINED, "napi_undefine." },
73 { TYPE_NULL, "napi_null." },
74 { TYPE_BOOLEAN, "napi_boolean." },
75 { TYPE_NUMBER, "napi_number." },
76 { TYPE_STRING, "napi_string." },
77 { TYPE_SYMBOL, "napi_symbol." },
78 { TYPE_OBJECT, "napi_object." },
79 { TYPE_FUNCTION, "napi_function." },
80 { TYPE_EXTERNAL, "napi_external." },
81 { TYPE_BIGINT, "napi_bigint." },
82 };
83
ThrowException(napi_env env,int32_t err,const std::string & msg,TypeCode type)84 void JsUtils::ThrowException(napi_env env, int32_t err, const std::string &msg, TypeCode type)
85 {
86 std::string errMsg = ToMessage(err);
87 napi_value error;
88 napi_value code;
89 napi_value message;
90 if (type == TypeCode::TYPE_NONE) {
91 errMsg = errMsg + msg;
92 IMSA_HILOGE("THROW_ERROR message: %{public}s", errMsg.c_str());
93 } else {
94 auto iter = PARAMETER_TYPE.find(type);
95 if (iter != PARAMETER_TYPE.end()) {
96 errMsg = errMsg + "The type of " + msg + " must be " + iter->second;
97 IMSA_HILOGE("THROW_ERROR message: %{public}s", errMsg.c_str());
98 }
99 }
100 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message));
101 NAPI_CALL_RETURN_VOID(env, napi_create_error(env, nullptr, message, &error));
102 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, err, &code));
103 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, error, "code", code));
104 NAPI_CALL_RETURN_VOID(env, napi_throw(env, error));
105 }
106
ToError(napi_env env,int32_t code)107 napi_value JsUtils::ToError(napi_env env, int32_t code)
108 {
109 IMSA_HILOGE("ToError start");
110 napi_value errorObj;
111 NAPI_CALL(env, napi_create_object(env, &errorObj));
112 napi_value errorCode = nullptr;
113 NAPI_CALL(env, napi_create_int32(env, Convert(code), &errorCode));
114 napi_value errorMessage = nullptr;
115 NAPI_CALL(env, napi_create_string_utf8(env, ToMessage(Convert(code)).c_str(), NAPI_AUTO_LENGTH, &errorMessage));
116 NAPI_CALL(env, napi_set_named_property(env, errorObj, "code", errorCode));
117 NAPI_CALL(env, napi_set_named_property(env, errorObj, "message", errorMessage));
118 IMSA_HILOGE("ToError end");
119 return errorObj;
120 }
121
Convert(int32_t code)122 int32_t JsUtils::Convert(int32_t code)
123 {
124 IMSA_HILOGI("Convert start");
125 auto iter = ERROR_CODE_MAP.find(code);
126 if (iter != ERROR_CODE_MAP.end()) {
127 IMSA_HILOGE("ErrorCode: %{public}d", iter->second);
128 return iter->second;
129 }
130 IMSA_HILOGI("Convert end");
131 return ERROR_CODE_QUERY_FAILED;
132 }
133
ToMessage(int32_t code)134 const std::string JsUtils::ToMessage(int32_t code)
135 {
136 IMSA_HILOGI("ToMessage start");
137 auto iter = ERROR_CODE_CONVERT_MESSAGE_MAP.find(code);
138 if (iter != ERROR_CODE_CONVERT_MESSAGE_MAP.end()) {
139 IMSA_HILOGI("ErrorMessage: %{public}s", (iter->second).c_str());
140 return iter->second;
141 }
142 return "error is out of definition.";
143 }
144
Equals(napi_env env,napi_value value,napi_ref copy,std::thread::id threadId)145 bool JsUtils::Equals(napi_env env, napi_value value, napi_ref copy, std::thread::id threadId)
146 {
147 if (copy == nullptr) {
148 return value == nullptr;
149 }
150
151 if (threadId != std::this_thread::get_id()) {
152 IMSA_HILOGD("napi_value can not be compared");
153 return false;
154 }
155
156 napi_value copyValue = nullptr;
157 napi_get_reference_value(env, copy, ©Value);
158
159 bool isEquals = false;
160 napi_strict_equals(env, value, copyValue, &isEquals);
161 IMSA_HILOGD("value compare result: %{public}d", isEquals);
162 return isEquals;
163 }
164
GetNativeSelf(napi_env env,napi_callback_info info)165 void *JsUtils::GetNativeSelf(napi_env env, napi_callback_info info)
166 {
167 size_t argc = ARGC_MAX;
168 void *native = nullptr;
169 napi_value self = nullptr;
170 napi_value argv[ARGC_MAX] = { nullptr };
171 napi_status status = napi_invalid_arg;
172 napi_get_cb_info(env, info, &argc, argv, &self, nullptr);
173 CHECK_RETURN((self != nullptr && argc <= ARGC_MAX), "napi_get_cb_info failed!", nullptr);
174
175 status = napi_unwrap(env, self, &native);
176 CHECK_RETURN((status == napi_ok && native != nullptr), "napi_unwrap failed!", nullptr);
177 return native;
178 }
179
GetValue(napi_env env,napi_value in,int32_t & out)180 napi_status JsUtils::GetValue(napi_env env, napi_value in, int32_t &out)
181 {
182 napi_valuetype type = napi_undefined;
183 napi_status status = napi_typeof(env, in, &type);
184 CHECK_RETURN((status == napi_ok) && (type == napi_number), "invalid type", napi_generic_failure);
185 return napi_get_value_int32(env, in, &out);
186 }
187
188 /* napi_value <-> uint32_t */
GetValue(napi_env env,napi_value in,uint32_t & out)189 napi_status JsUtils::GetValue(napi_env env, napi_value in, uint32_t &out)
190 {
191 napi_valuetype type = napi_undefined;
192 napi_status status = napi_typeof(env, in, &type);
193 CHECK_RETURN((status == napi_ok) && (type == napi_number), "invalid type", napi_generic_failure);
194 return napi_get_value_uint32(env, in, &out);
195 }
196
GetValue(napi_env env,napi_value in,bool & out)197 napi_status JsUtils::GetValue(napi_env env, napi_value in, bool &out)
198 {
199 napi_valuetype type = napi_undefined;
200 napi_status status = napi_typeof(env, in, &type);
201 CHECK_RETURN((status == napi_ok) && (type == napi_boolean), "invalid type", napi_generic_failure);
202 return napi_get_value_bool(env, in, &out);
203 }
204
GetValue(napi_env env,napi_value in,double & out)205 napi_status JsUtils::GetValue(napi_env env, napi_value in, double &out)
206 {
207 napi_valuetype type = napi_undefined;
208 napi_status status = napi_typeof(env, in, &type);
209 CHECK_RETURN((status == napi_ok) && (type == napi_number), "invalid double type", napi_generic_failure);
210 return napi_get_value_double(env, in, &out);
211 }
212
213 /* napi_value <-> std::string */
GetValue(napi_env env,napi_value in,std::string & out)214 napi_status JsUtils::GetValue(napi_env env, napi_value in, std::string &out)
215 {
216 IMSA_HILOGD("JsUtils get string value in.");
217 napi_valuetype type = napi_undefined;
218 napi_status status = napi_typeof(env, in, &type);
219 CHECK_RETURN((status == napi_ok) && (type == napi_string), "invalid type", napi_generic_failure);
220
221 size_t maxLen = STR_MAX_LENGTH;
222 status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen);
223 if (maxLen <= 0) {
224 return status;
225 }
226 IMSA_HILOGD("napi_value -> std::string get length %{public}zu", maxLen);
227 char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH];
228 if (buf != nullptr) {
229 size_t len = 0;
230 status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len);
231 if (status == napi_ok) {
232 buf[len] = 0;
233 out = std::string(buf);
234 }
235 delete[] buf;
236 } else {
237 status = napi_generic_failure;
238 }
239 return status;
240 }
241
GetValue(napi_env env,napi_value in,const std::string & type,napi_value & out)242 napi_status JsUtils::GetValue(napi_env env, napi_value in, const std::string &type, napi_value &out)
243 {
244 napi_valuetype valueType = napi_undefined;
245 napi_status status = napi_typeof(env, in, &valueType);
246 if ((status == napi_ok) && (valueType == napi_object)) {
247 status = napi_get_named_property(env, in, type.c_str(), &out);
248 return status;
249 }
250 return napi_generic_failure;
251 }
252
253 /* napi_value <-> PanelInfo */
GetValue(napi_env env,napi_value in,PanelInfo & out)254 napi_status JsUtils::GetValue(napi_env env, napi_value in, PanelInfo &out)
255 {
256 IMSA_HILOGD("napi_value -> PanelInfo ");
257 napi_value propType = nullptr;
258 napi_status status = napi_get_named_property(env, in, "type", &propType);
259 CHECK_RETURN((status == napi_ok), "no property type ", status);
260 int32_t panelType = 0;
261 status = GetValue(env, propType, panelType);
262 CHECK_RETURN((status == napi_ok), "no value of type ", status);
263
264 // flag is optional. flag isn't need when panelType is status_bar.
265 int32_t panelFlag = 0;
266 if (panelType != PanelType::STATUS_BAR) {
267 napi_value propFlag = nullptr;
268 status = napi_get_named_property(env, in, "flag", &propFlag);
269 CHECK_RETURN((status == napi_ok), "no property flag ", status);
270 status = JsUtils::GetValue(env, propFlag, panelFlag);
271 CHECK_RETURN((status == napi_ok), "no value of flag ", status);
272 }
273
274 out.panelType = PanelType(panelType);
275 out.panelFlag = PanelFlag(panelFlag);
276 return status;
277 }
278
GetValue(napi_env env,const std::vector<InputWindowInfo> & in)279 napi_value JsUtils::GetValue(napi_env env, const std::vector<InputWindowInfo> &in)
280 {
281 napi_value array = nullptr;
282 uint32_t index = 0;
283 napi_create_array(env, &array);
284 if (array == nullptr) {
285 IMSA_HILOGE("create array failed");
286 return array;
287 }
288 for (const auto &info : in) {
289 napi_value jsInfo = GetValue(env, info);
290 napi_set_element(env, array, index, jsInfo);
291 ++index;
292 }
293 return array;
294 }
295
GetValue(napi_env env,const InputWindowInfo & in)296 napi_value JsUtils::GetValue(napi_env env, const InputWindowInfo &in)
297 {
298 napi_value info = nullptr;
299 napi_create_object(env, &info);
300
301 napi_value name = nullptr;
302 napi_create_string_utf8(env, in.name.c_str(), in.name.size(), &name);
303 napi_set_named_property(env, info, "name", name);
304
305 napi_value left = nullptr;
306 napi_create_int32(env, in.left, &left);
307 napi_set_named_property(env, info, "left", left);
308
309 napi_value top = nullptr;
310 napi_create_int32(env, in.top, &top);
311 napi_set_named_property(env, info, "top", top);
312
313 napi_value width = nullptr;
314 napi_create_uint32(env, in.width, &width);
315 napi_set_named_property(env, info, "width", width);
316
317 napi_value height = nullptr;
318 napi_create_uint32(env, in.height, &height);
319 napi_set_named_property(env, info, "height", height);
320
321 return info;
322 }
323
GetValue(napi_env env,const InputAttribute & attribute)324 napi_value JsUtils::GetValue(napi_env env, const InputAttribute &attribute)
325 {
326 napi_value editorAttribute = nullptr;
327 napi_create_object(env, &editorAttribute);
328
329 auto ret = JsUtil::Object::WriteProperty(env, editorAttribute, "inputPattern", attribute.inputPattern);
330 ret = ret && JsUtil::Object::WriteProperty(env, editorAttribute, "enterKeyType", attribute.enterKeyType);
331 return ret ? editorAttribute : JsUtil::Const::Null(env);
332 }
333
GetValue(napi_env env,const std::string & in,napi_value & out)334 napi_status JsUtils::GetValue(napi_env env, const std::string &in, napi_value &out)
335 {
336 return napi_create_string_utf8(env, in.c_str(), in.size(), &out);
337 }
338 } // namespace MiscServices
339 } // namespace OHOS
340