• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "js_input_method.h"
17 
18 #include "event_handler.h"
19 #include "event_runner.h"
20 #include "input_method_controller.h"
21 #include "input_method_property.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 #include "string_ex.h"
25 
26 namespace OHOS {
27 namespace MiscServices {
Init(napi_env env,napi_value exports)28 napi_value JsInputMethod::Init(napi_env env, napi_value exports)
29 {
30     napi_property_descriptor descriptor[] = {
31         DECLARE_NAPI_FUNCTION("switchInputMethod", SwitchInputMethod),
32         DECLARE_NAPI_FUNCTION("getCurrentInputMethod", GetCurrentInputMethod),
33         DECLARE_NAPI_FUNCTION("getCurrentInputMethodSubtype", GetCurrentInputMethodSubtype),
34         DECLARE_NAPI_FUNCTION("switchCurrentInputMethodSubtype", SwitchCurrentInputMethodSubtype),
35         DECLARE_NAPI_FUNCTION("switchCurrentInputMethodAndSubtype", SwitchCurrentInputMethodAndSubtype),
36     };
37     NAPI_CALL(
38         env, napi_define_properties(env, exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor));
39     return exports;
40 };
41 
GetInputMethodProperty(napi_env env,napi_value argv,std::shared_ptr<SwitchInputMethodContext> ctxt)42 napi_status JsInputMethod::GetInputMethodProperty(
43     napi_env env, napi_value argv, std::shared_ptr<SwitchInputMethodContext> ctxt)
44 {
45     napi_valuetype valueType = napi_undefined;
46     napi_status status = napi_generic_failure;
47     napi_typeof(env, argv, &valueType);
48     if (valueType != napi_object) {
49         IMSA_HILOGE("valueType error");
50         return status;
51     }
52     napi_value result = nullptr;
53     napi_get_named_property(env, argv, "name", &result);
54     status = JsUtils::GetValue(env, result, ctxt->packageName);
55     CHECK_RETURN(status == napi_ok, "get ctxt->packageName failed!", status);
56     result = nullptr;
57     napi_get_named_property(env, argv, "id", &result);
58     status = JsUtils::GetValue(env, result, ctxt->methodId);
59     CHECK_RETURN(status == napi_ok, "get ctxt->methodId failed!", status);
60     if (ctxt->packageName.empty() || ctxt->methodId.empty()) {
61         result = nullptr;
62         napi_get_named_property(env, argv, "packageName", &result);
63         status = JsUtils::GetValue(env, result, ctxt->packageName);
64         CHECK_RETURN(status == napi_ok, "get ctxt->packageName failed!", status);
65 
66         result = nullptr;
67         napi_get_named_property(env, argv, "methodId", &result);
68         status = JsUtils::GetValue(env, result, ctxt->methodId);
69         CHECK_RETURN(status == napi_ok, "get ctxt->methodId failed!", status);
70     }
71     PARAM_CHECK_RETURN(env, (!ctxt->packageName.empty() && !ctxt->methodId.empty()), "JsInputMethod, Parameter error.",
72         TYPE_NONE, napi_invalid_arg);
73     IMSA_HILOGI("methodId:%{public}s and packageName:%{public}s", ctxt->methodId.c_str(), ctxt->packageName.c_str());
74     return napi_ok;
75 }
76 
GetInputMethodSubProperty(napi_env env,napi_value argv,std::shared_ptr<SwitchInputMethodContext> ctxt)77 napi_status JsInputMethod::GetInputMethodSubProperty(
78     napi_env env, napi_value argv, std::shared_ptr<SwitchInputMethodContext> ctxt)
79 {
80     napi_valuetype valueType = napi_undefined;
81     napi_status status = napi_generic_failure;
82     status = napi_typeof(env, argv, &valueType);
83     if (valueType == napi_object) {
84         napi_value result = nullptr;
85         status = napi_get_named_property(env, argv, "name", &result);
86         PARAM_CHECK_RETURN(env, status == napi_ok, " name ", TYPE_STRING, status);
87         status = JsUtils::GetValue(env, result, ctxt->name);
88         CHECK_RETURN(status == napi_ok, "get ctxt->name failed!", status);
89         result = nullptr;
90         status = napi_get_named_property(env, argv, "id", &result);
91         PARAM_CHECK_RETURN(env, status == napi_ok, " id ", TYPE_STRING, status);
92         status = JsUtils::GetValue(env, result, ctxt->id);
93         CHECK_RETURN(status == napi_ok, "get ctxt->id failed!", status);
94         IMSA_HILOGI("name:%{public}s and id:%{public}s", ctxt->name.c_str(), ctxt->id.c_str());
95     }
96     return status;
97 }
98 
GetJsInputMethodProperty(napi_env env,const Property & property)99 napi_value JsInputMethod::GetJsInputMethodProperty(napi_env env, const Property &property)
100 {
101     napi_value prop = nullptr;
102     napi_create_object(env, &prop);
103 
104     napi_value packageName = nullptr;
105     napi_create_string_utf8(env, property.name.c_str(), NAPI_AUTO_LENGTH, &packageName);
106     napi_set_named_property(env, prop, "packageName", packageName);
107     napi_set_named_property(env, prop, "name", packageName);
108 
109     napi_value methodId = nullptr;
110     napi_create_string_utf8(env, property.id.c_str(), NAPI_AUTO_LENGTH, &methodId);
111     napi_set_named_property(env, prop, "methodId", methodId);
112     napi_set_named_property(env, prop, "id", methodId);
113 
114     napi_value icon = nullptr;
115     napi_create_string_utf8(env, property.icon.c_str(), NAPI_AUTO_LENGTH, &icon);
116     napi_set_named_property(env, prop, "icon", icon);
117 
118     napi_value iconId = nullptr;
119     napi_create_int32(env, property.iconId, &iconId);
120     napi_set_named_property(env, prop, "iconId", iconId);
121 
122     napi_value label = nullptr;
123     napi_create_string_utf8(env, property.label.c_str(), NAPI_AUTO_LENGTH, &label);
124     napi_set_named_property(env, prop, "label", label);
125 
126     napi_value labelId = nullptr;
127     napi_create_int32(env, property.labelId, &labelId);
128     napi_set_named_property(env, prop, "labelId", labelId);
129     return prop;
130 }
131 
GetJsInputMethodSubProperty(napi_env env,const SubProperty & subProperty)132 napi_value JsInputMethod::GetJsInputMethodSubProperty(napi_env env, const SubProperty &subProperty)
133 {
134     napi_value prop = nullptr;
135     napi_create_object(env, &prop);
136 
137     napi_value id = nullptr;
138     napi_create_string_utf8(env, subProperty.id.c_str(), NAPI_AUTO_LENGTH, &id);
139     napi_set_named_property(env, prop, "id", id);
140 
141     napi_value label = nullptr;
142     napi_create_string_utf8(env, subProperty.label.c_str(), NAPI_AUTO_LENGTH, &label);
143     napi_set_named_property(env, prop, "label", label);
144 
145     napi_value labelId = nullptr;
146     napi_create_int32(env, subProperty.labelId, &labelId);
147     napi_set_named_property(env, prop, "labelId", labelId);
148 
149     napi_value name = nullptr;
150     napi_create_string_utf8(env, subProperty.name.c_str(), NAPI_AUTO_LENGTH, &name);
151     napi_set_named_property(env, prop, "name", name);
152 
153     napi_value mode = nullptr;
154     napi_create_string_utf8(env, subProperty.mode.c_str(), NAPI_AUTO_LENGTH, &mode);
155     napi_set_named_property(env, prop, "mode", mode);
156 
157     napi_value locale = nullptr;
158     napi_create_string_utf8(env, subProperty.locale.c_str(), NAPI_AUTO_LENGTH, &locale);
159     napi_set_named_property(env, prop, "locale", locale);
160 
161     napi_value language = nullptr;
162     napi_create_string_utf8(env, subProperty.language.c_str(), NAPI_AUTO_LENGTH, &language);
163     napi_set_named_property(env, prop, "language", language);
164 
165     napi_value icon = nullptr;
166     napi_create_string_utf8(env, subProperty.icon.c_str(), NAPI_AUTO_LENGTH, &icon);
167     napi_set_named_property(env, prop, "icon", icon);
168 
169     napi_value iconId = nullptr;
170     napi_create_int32(env, subProperty.iconId, &iconId);
171     napi_set_named_property(env, prop, "iconId", iconId);
172     return prop;
173 }
174 
GetJSInputMethodSubProperties(napi_env env,const std::vector<SubProperty> & subProperties)175 napi_value JsInputMethod::GetJSInputMethodSubProperties(napi_env env, const std::vector<SubProperty> &subProperties)
176 {
177     uint32_t index = 0;
178     napi_value prop = nullptr;
179     napi_create_array(env, &prop);
180     if (prop == nullptr) {
181         IMSA_HILOGE("create array failed");
182         return prop;
183     }
184     for (const auto &subproperty : subProperties) {
185         napi_value pro = GetJsInputMethodSubProperty(env, subproperty);
186         napi_set_element(env, prop, index, pro);
187         index++;
188     }
189     return prop;
190 }
191 
GetJSInputMethodProperties(napi_env env,const std::vector<Property> & properties)192 napi_value JsInputMethod::GetJSInputMethodProperties(napi_env env, const std::vector<Property> &properties)
193 {
194     uint32_t index = 0;
195     napi_value prop = nullptr;
196     napi_create_array(env, &prop);
197     if (prop == nullptr) {
198         IMSA_HILOGE("create array failed");
199         return prop;
200     }
201     for (const auto &property : properties) {
202         napi_value pro = GetJsInputMethodProperty(env, property);
203         napi_set_element(env, prop, index, pro);
204         index++;
205     }
206     return prop;
207 }
208 
SwitchInputMethod(napi_env env,napi_callback_info info)209 napi_value JsInputMethod::SwitchInputMethod(napi_env env, napi_callback_info info)
210 {
211     auto ctxt = std::make_shared<SwitchInputMethodContext>();
212     auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
213         PARAM_CHECK_RETURN(env, argc > 0, "should has 1 parameters!", TYPE_NONE, napi_invalid_arg);
214         napi_valuetype valueType = napi_undefined;
215         napi_typeof(env, argv[0], &valueType);
216         PARAM_CHECK_RETURN(env, valueType == napi_object, " target: ", TYPE_OBJECT, napi_invalid_arg);
217         napi_status status = GetInputMethodProperty(env, argv[0], ctxt);
218         return status;
219     };
220     auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
221         napi_status status = napi_get_boolean(env, ctxt->isSwitchInput, result);
222         IMSA_HILOGE("output  napi_get_boolean != nullptr[%{public}d]", result != nullptr);
223         return status;
224     };
225     auto exec = [ctxt](AsyncCall::Context *ctx) {
226         int32_t errCode = InputMethodController::GetInstance()->SwitchInputMethod(ctxt->packageName);
227         if (errCode == ErrorCode::NO_ERROR) {
228             IMSA_HILOGI("exec SwitchInputMethod success");
229             ctxt->status = napi_ok;
230             ctxt->SetState(ctxt->status);
231             ctxt->isSwitchInput = true;
232         } else if (errCode == ErrorCode::ERROR_SWITCH_IME) {
233             IMSA_HILOGE("exec SwitchInputMethod failed");
234             ctxt->status = napi_ok;
235             ctxt->SetState(ctxt->status);
236             ctxt->isSwitchInput = false;
237         } else {
238             ctxt->SetErrorCode(errCode);
239         }
240     };
241     ctxt->SetAction(std::move(input), std::move(output));
242     // 2 means JsAPI:switchInputMethod has 2 params at most.
243     AsyncCall asyncCall(env, info, ctxt, 2);
244     return asyncCall.Call(env, exec, "switchInputMethod");
245 }
246 
GetCurrentInputMethod(napi_env env,napi_callback_info info)247 napi_value JsInputMethod::GetCurrentInputMethod(napi_env env, napi_callback_info info)
248 {
249     std::shared_ptr<Property> property = InputMethodController::GetInstance()->GetCurrentInputMethod();
250     if (property == nullptr) {
251         IMSA_HILOGE("get current inputmethod is nullptr");
252         napi_value result = nullptr;
253         napi_get_null(env, &result);
254         return result;
255     }
256     return GetJsInputMethodProperty(env, *property);
257 }
258 
GetCurrentInputMethodSubtype(napi_env env,napi_callback_info info)259 napi_value JsInputMethod::GetCurrentInputMethodSubtype(napi_env env, napi_callback_info info)
260 {
261     std::shared_ptr<SubProperty> subProperty = InputMethodController::GetInstance()->GetCurrentInputMethodSubtype();
262     if (subProperty == nullptr) {
263         IMSA_HILOGE("get current inputmethodsubtype is nullptr");
264         napi_value result = nullptr;
265         napi_get_null(env, &result);
266         return result;
267     }
268     return GetJsInputMethodSubProperty(env, *subProperty);
269 }
270 
SwitchCurrentInputMethodSubtype(napi_env env,napi_callback_info info)271 napi_value JsInputMethod::SwitchCurrentInputMethodSubtype(napi_env env, napi_callback_info info)
272 {
273     auto ctxt = std::make_shared<SwitchInputMethodContext>();
274     auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
275         PARAM_CHECK_RETURN(env, argc > 0, "should has one parameter. ", TYPE_NONE, napi_invalid_arg);
276         napi_valuetype valueType = napi_undefined;
277         napi_typeof(env, argv[0], &valueType);
278         PARAM_CHECK_RETURN(env, valueType == napi_object, "inputMethodSubtype: ", TYPE_OBJECT, napi_object_expected);
279         napi_status status = GetInputMethodSubProperty(env, argv[0], ctxt);
280         return status;
281     };
282     auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
283         napi_status status = napi_get_boolean(env, ctxt->isSwitchInput, result);
284         IMSA_HILOGE("output napi_get_boolean != nullptr[%{public}d]", result != nullptr);
285         return status;
286     };
287     auto exec = [ctxt](AsyncCall::Context *ctx) {
288         int32_t errCode = InputMethodController::GetInstance()->SwitchInputMethod(ctxt->name, ctxt->id);
289         if (errCode == ErrorCode::NO_ERROR) {
290             IMSA_HILOGI("exec SwitchInputMethod success");
291             ctxt->status = napi_ok;
292             ctxt->SetState(ctxt->status);
293             ctxt->isSwitchInput = true;
294         } else if (errCode == ErrorCode::ERROR_SWITCH_IME) {
295             IMSA_HILOGE("exec SwitchInputMethod failed");
296             ctxt->status = napi_ok;
297             ctxt->SetState(ctxt->status);
298             ctxt->isSwitchInput = false;
299         } else {
300             ctxt->SetErrorCode(errCode);
301         }
302     };
303     ctxt->SetAction(std::move(input), std::move(output));
304     // 2 means JsAPI:switchCurrentInputMethodSubtype has 2 params at most.
305     AsyncCall asyncCall(env, info, ctxt, 2);
306     return asyncCall.Call(env, exec, "switchCurrentInputMethodSubtype");
307 }
308 
SwitchCurrentInputMethodAndSubtype(napi_env env,napi_callback_info info)309 napi_value JsInputMethod::SwitchCurrentInputMethodAndSubtype(napi_env env, napi_callback_info info)
310 {
311     auto ctxt = std::make_shared<SwitchInputMethodContext>();
312     auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
313         PARAM_CHECK_RETURN(env, argc > 1, "should has two parameter.", TYPE_NONE, napi_invalid_arg);
314         napi_valuetype valueType = napi_undefined;
315         napi_typeof(env, argv[0], &valueType);
316         PARAM_CHECK_RETURN(env, valueType == napi_object, "inputMethodProperty: ", TYPE_OBJECT, napi_object_expected);
317         napi_typeof(env, argv[1], &valueType);
318         PARAM_CHECK_RETURN(env, valueType == napi_object, "inputMethodSubtype: ", TYPE_OBJECT, napi_object_expected);
319         napi_status status = GetInputMethodSubProperty(env, argv[1], ctxt);
320         return status;
321     };
322     auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
323         napi_status status = napi_get_boolean(env, ctxt->isSwitchInput, result);
324         IMSA_HILOGE("output  napi_get_boolean != nullptr[%{public}d]", result != nullptr);
325         return status;
326     };
327     auto exec = [ctxt](AsyncCall::Context *ctx) {
328         int32_t errCode = InputMethodController::GetInstance()->SwitchInputMethod(ctxt->name, ctxt->id);
329         if (errCode == ErrorCode::NO_ERROR) {
330             IMSA_HILOGI("exec SwitchInputMethod success");
331             ctxt->status = napi_ok;
332             ctxt->SetState(ctxt->status);
333             ctxt->isSwitchInput = true;
334         } else if (errCode == ErrorCode::ERROR_SWITCH_IME) {
335             IMSA_HILOGE("exec SwitchInputMethod failed");
336             ctxt->status = napi_ok;
337             ctxt->SetState(ctxt->status);
338             ctxt->isSwitchInput = false;
339         } else {
340             ctxt->SetErrorCode(errCode);
341         }
342     };
343     ctxt->SetAction(std::move(input), std::move(output));
344     // 3 means JsAPI:switchCurrentInputMethodAndSubtype has 3 params at most.
345     AsyncCall asyncCall(env, info, ctxt, 3);
346     return asyncCall.Call(env, exec, "switchCurrentInputMethodAndSubtype");
347 }
348 } // namespace MiscServices
349 } // namespace OHOS