1 /*
2 * Copyright (c) 2021-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 "js_input_device_context.h"
17
18 namespace OHOS {
19 namespace MMI {
20 namespace {
21 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "JsInputDeviceContext" }; // namespace
22 }
23
JsInputDeviceContext()24 JsInputDeviceContext::JsInputDeviceContext()
25 {
26 mager_ = std::make_shared<JsInputDeviceManager>();
27 CHKPL(mager_);
28 }
29
~JsInputDeviceContext()30 JsInputDeviceContext::~JsInputDeviceContext()
31 {
32 std::lock_guard<std::mutex> guard(mtx_);
33 auto jsInputDeviceMgr = mager_;
34 mager_.reset();
35 if (jsInputDeviceMgr) {
36 jsInputDeviceMgr->ResetEnv();
37 }
38 }
39
CreateInstance(napi_env env)40 napi_value JsInputDeviceContext::CreateInstance(napi_env env)
41 {
42 MMI_LOGD("begin");
43 napi_value global = nullptr;
44 napi_status status = napi_get_global(env, &global);
45 if (status != napi_ok) {
46 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to call napi_get_global");
47 MMI_LOGE("failed to call napi_get_global");
48 return nullptr;
49 }
50
51 constexpr char className[] = "JsInputDeviceContext";
52 napi_value jsClass = nullptr;
53 napi_property_descriptor desc[] = {};
54 status = napi_define_class(env, className, sizeof(className), JsInputDeviceContext::JsConstructor, nullptr,
55 sizeof(desc) / sizeof(desc[0]), nullptr, &jsClass);
56 if (status != napi_ok) {
57 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to call napi_define_class");
58 MMI_LOGE("failed to call napi_define_class");
59 return nullptr;
60 }
61
62 status = napi_set_named_property(env, global, "multimodalinput_input_device_class", jsClass);
63 if (status != napi_ok) {
64 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to set jsClass property");
65 MMI_LOGE("failed to set jsClass property");
66 return nullptr;
67 }
68
69 napi_value jsInstance = nullptr;
70 status = napi_new_instance(env, jsClass, 0, nullptr, &jsInstance);
71 if (status != napi_ok) {
72 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to create jsInstance");
73 MMI_LOGE("failed to create jsInstance");
74 return nullptr;
75 }
76 status = napi_set_named_property(env, global, "multimodal_input_device", jsInstance);
77 if (status != napi_ok) {
78 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to set jsInstance property");
79 MMI_LOGE("failed to set jsInstance property");
80 return nullptr;
81 }
82
83 JsInputDeviceContext *jsContext = nullptr;
84 status = napi_unwrap(env, jsInstance, (void**)&jsContext);
85 if (status != napi_ok) {
86 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get jsContext");
87 MMI_LOGE("failed to get jsContext");
88 return nullptr;
89 }
90 CHKPP(jsContext);
91 status = napi_create_reference(env, jsInstance, 1, &(jsContext->contextRef_));
92 if (status != napi_ok) {
93 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to create contextRef_");
94 MMI_LOGE("failed to create contextRef_");
95 return nullptr;
96 }
97
98 uint32_t refCount = 0;
99 status = napi_reference_ref(env, jsContext->contextRef_, &refCount);
100 if (status != napi_ok) {
101 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to create contextRef_ reference");
102 MMI_LOGE("failed to create contextRef_ reference");
103 return nullptr;
104 }
105 MMI_LOGD("end");
106 return jsInstance;
107 }
108
JsConstructor(napi_env env,napi_callback_info info)109 napi_value JsInputDeviceContext::JsConstructor(napi_env env, napi_callback_info info)
110 {
111 MMI_LOGD("begin");
112 napi_value thisVar = nullptr;
113 void *data = nullptr;
114 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
115 if (status != napi_ok) {
116 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get thisVar");
117 MMI_LOGE("failed to get thisVar");
118 return nullptr;
119 }
120
121 JsInputDeviceContext *jsContext = new (std::nothrow) JsInputDeviceContext();
122 CHKPP(jsContext);
123 status = napi_wrap(env, thisVar, jsContext, [](napi_env env, void* data, void* hin) {
124 MMI_LOGI("jsvm ends");
125 JsInputDeviceContext *context = (JsInputDeviceContext*)data;
126 delete context;
127 }, nullptr, nullptr);
128 if (status != napi_ok) {
129 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to wrap jsContext");
130 MMI_LOGE("failed to wrap jsContext");
131 return nullptr;
132 }
133 MMI_LOGD("end");
134 return thisVar;
135 }
136
GetInstance(napi_env env)137 JsInputDeviceContext* JsInputDeviceContext::GetInstance(napi_env env)
138 {
139 MMI_LOGD("begin");
140 napi_value global = nullptr;
141 napi_status status = napi_get_global(env, &global);
142 if (status != napi_ok) {
143 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get global");
144 MMI_LOGE("failed to get global");
145 return nullptr;
146 }
147
148 bool result = false;
149 napi_has_named_property(env, global, "multimodal_input_device", &result);
150 if (!result) {
151 napi_throw_error(env, nullptr, "JsInputDeviceContext: multimodal_input_device was not found");
152 MMI_LOGE("multimodal_input_device was not found");
153 return nullptr;
154 }
155
156 napi_value object = nullptr;
157 status = napi_get_named_property(env, global, "multimodal_input_device", &object);
158 if (status != napi_ok) {
159 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get multimodal_input_device");
160 MMI_LOGE("failed to get multimodal_input_device");
161 return nullptr;
162 }
163 if (object == nullptr) {
164 napi_throw_error(env, nullptr, "JsInputDeviceContext: object is nullptr");
165 MMI_LOGE("object is nullptr");
166 return nullptr;
167 }
168
169 JsInputDeviceContext *instance = nullptr;
170 status = napi_unwrap(env, object, (void**)&instance);
171 if (status != napi_ok) {
172 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get instance");
173 MMI_LOGE("failed to get instance");
174 return nullptr;
175 }
176 if (instance == nullptr) {
177 napi_throw_error(env, nullptr, "JsInputDeviceContext: instance is nullptr");
178 MMI_LOGE("instance is nullptr");
179 return nullptr;
180 }
181 MMI_LOGD("end");
182 return instance;
183 }
184
GetJsInputDeviceMgr()185 std::shared_ptr<JsInputDeviceManager> JsInputDeviceContext::GetJsInputDeviceMgr()
186 {
187 return mager_;
188 }
189
GetDeviceIds(napi_env env,napi_callback_info info)190 napi_value JsInputDeviceContext::GetDeviceIds(napi_env env, napi_callback_info info)
191 {
192 MMI_LOGD("begin");
193 size_t argc = 1;
194 napi_value argv[1];
195 napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
196 if (status != napi_ok) {
197 MMI_LOGE("parameter acquisition failed");
198 napi_throw_error(env, nullptr, "JsInputDeviceContext: parameter acquisition failed");
199 return nullptr;
200 }
201 if (argc > 1) {
202 MMI_LOGE("too many parameters");
203 napi_throw_error(env, nullptr, "JsInputDeviceContext: too many parameters");
204 return nullptr;
205 }
206
207 JsInputDeviceContext *jsIds = JsInputDeviceContext::GetInstance(env);
208 auto jsInputDeviceMgr = jsIds->GetJsInputDeviceMgr();
209 if (argc == 0) {
210 return jsInputDeviceMgr->GetDeviceIds(env);
211 }
212
213 napi_valuetype valueType = napi_undefined;
214 status = napi_typeof(env, argv[0], &valueType);
215 if (status != napi_ok) {
216 MMI_LOGE("failed to get the first parameter type");
217 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get the first parameter type");
218 return nullptr;
219 }
220 if (valueType != napi_function) {
221 MMI_LOGE("the first parameter is not a function");
222 napi_throw_error(env, nullptr, "JsInputDeviceContext: the first parameter is not a function");
223 return nullptr;
224 }
225 jsInputDeviceMgr->GetDeviceIds(env, argv[0]);
226 MMI_LOGD("end");
227 return nullptr;
228 }
229
GetDevice(napi_env env,napi_callback_info info)230 napi_value JsInputDeviceContext::GetDevice(napi_env env, napi_callback_info info)
231 {
232 MMI_LOGD("begin");
233 size_t argc = 2;
234 napi_value argv[2];
235 napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
236 if (status != napi_ok) {
237 napi_throw_error(env, nullptr, "JsInputDeviceContext: parameter acquisition failed");
238 return nullptr;
239 }
240 if (argc < 1 || argc > 2) {
241 MMI_LOGE("the number of parameters is not as expected");
242 napi_throw_error(env, nullptr, "JsInputDeviceContext: the number of parameters is not as expected");
243 return nullptr;
244 }
245
246 napi_valuetype valueType = napi_undefined;
247 status = napi_typeof(env, argv[0], &valueType);
248 if (status != napi_ok) {
249 MMI_LOGE("failed to get the first parameter type");
250 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get the first parameter type");
251 return nullptr;
252 }
253 if (valueType != napi_number) {
254 MMI_LOGE("the first parameter is not a number");
255 napi_throw_error(env, nullptr, "JsInputDeviceContext: the first parameter is not a number");
256 return nullptr;
257 }
258 int32_t id = 0;
259 status = napi_get_value_int32(env, argv[0], &id);
260 if (status != napi_ok) {
261 MMI_LOGE("failed to get id");
262 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get id");
263 return nullptr;
264 }
265
266 JsInputDeviceContext *jsDev = JsInputDeviceContext::GetInstance(env);
267 auto jsInputDeviceMgr = jsDev->GetJsInputDeviceMgr();
268 if (argc == 1) {
269 MMI_LOGD("promise end");
270 return jsInputDeviceMgr->GetDevice(id, env);
271 }
272 status = napi_typeof(env, argv[1], &valueType);
273 if (status != napi_ok) {
274 MMI_LOGE("failed to get the second parameter type");
275 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to get the second parameter type");
276 return nullptr;
277 }
278 if (valueType != napi_function) {
279 MMI_LOGE("the second parameter is not a function");
280 napi_throw_error(env, nullptr, "JsInputDeviceContext: the second parameter is not a function");
281 return nullptr;
282 }
283 jsInputDeviceMgr->GetDevice(id, env, argv[1]);
284 MMI_LOGD("end");
285 return nullptr;
286 }
287
Export(napi_env env,napi_value exports)288 napi_value JsInputDeviceContext::Export(napi_env env, napi_value exports)
289 {
290 MMI_LOGD("begin");
291 auto instance = CreateInstance(env);
292 if (instance == nullptr) {
293 napi_throw_error(env, nullptr, "JsInputDeviceContext: failed to create instance");
294 MMI_LOGE("failed to create instance");
295 return nullptr;
296 }
297 napi_property_descriptor desc[] = {
298 DECLARE_NAPI_STATIC_FUNCTION("getDevice", GetDevice),
299 DECLARE_NAPI_STATIC_FUNCTION("getDeviceIds", GetDeviceIds),
300 };
301 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
302 MMI_LOGD("end");
303 return exports;
304 }
305 } // namespace MMI
306 } // namespace OHOS
307