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