1 /*
2  * Copyright (c) 2021-2024 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_monitor_module.h"
17 
18 #include <cinttypes>
19 #include <string>
20 #include <unordered_set>
21 #include <uv.h>
22 
23 #include "define_multimodal.h"
24 #include "js_input_monitor_manager.h"
25 #include "napi_constants.h"
26 #include "proto.h"
27 #include "util_napi_error.h"
28 
29 #undef MMI_LOG_TAG
30 #define MMI_LOG_TAG "JsInputMonitorModule"
31 
32 namespace OHOS {
33 namespace MMI {
34 namespace {
35 const std::unordered_set<std::string> ACTION_TYPE = {
36     "touch", "mouse", "pinch", "threeFingersSwipe", "fourFingersSwipe", "rotate", "threeFingersTap", "fingerprint",
37     "swipeInward"
38 };
39 constexpr int32_t TWO_PARAMETERS { 2 };
40 constexpr int32_t THREE_PARAMETERS { 3 };
41 constexpr int32_t RECT_LIST_SIZE { 2 };
42 } // namespace
43 
JsOnApi9(napi_env env,napi_callback_info info)44 static napi_value JsOnApi9(napi_env env, napi_callback_info info)
45 {
46     CALL_DEBUG_ENTER;
47     size_t argc = 2;
48     napi_value argv[2] = { 0 };
49 
50     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
51     napi_valuetype valueType = napi_undefined;
52     CHKRP(napi_typeof(env, argv[0], &valueType), TYPEOF);
53     if (valueType != napi_string) {
54         MMI_HILOGE("First Parameter type error");
55         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "EventType", "string");
56         return nullptr;
57     }
58     char typeName[MAX_STRING_LEN] = { 0 };
59     size_t len = 0;
60     CHKRP(napi_get_value_string_utf8(env, argv[0], typeName, MAX_STRING_LEN - 1, &len), GET_VALUE_STRING_UTF8);
61     if (ACTION_TYPE.find(typeName) == ACTION_TYPE.end()) {
62         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "EventType is invalid");
63         return nullptr;
64     }
65     CHKRP(napi_typeof(env, argv[1], &valueType), TYPEOF);
66     if (valueType != napi_function) {
67         MMI_HILOGE("Second Parameter type error");
68         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Second Parameter type error");
69         return nullptr;
70     }
71     if (!JS_INPUT_MONITOR_MGR.AddEnv(env, info)) {
72         MMI_HILOGE("AddEnv failed");
73         return nullptr;
74     }
75     JS_INPUT_MONITOR_MGR.AddMonitor(env, typeName, argv[1]);
76     return nullptr;
77 }
78 
AddMouseMonitor(napi_env env,napi_callback_info info,napi_value napiRect,napi_value napiCallback)79 static void AddMouseMonitor(napi_env env, napi_callback_info info, napi_value napiRect, napi_value napiCallback)
80 {
81     std::vector<Rect> hotRectAreaList;
82     uint32_t rectArrayLength = 0;
83     CHKRV(napi_get_array_length(env, napiRect, &rectArrayLength), GET_ARRAY_LENGTH);
84     if (rectArrayLength <= 0 || rectArrayLength > RECT_LIST_SIZE) {
85         MMI_HILOGE("Hot Rect Area Parameter error");
86         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Hot Rect Area Parameter error");
87         return;
88     }
89     hotRectAreaList = JS_INPUT_MONITOR_MGR.GetHotRectAreaList(env, napiRect, rectArrayLength);
90     if (hotRectAreaList.size() != rectArrayLength) {
91         MMI_HILOGE("Hot Rect Area Parameter error");
92         return;
93     }
94     napi_valuetype valueType = napi_undefined;
95     CHKRV(napi_typeof(env, napiCallback, &valueType), TYPEOF);
96     if (valueType != napi_function) {
97         MMI_HILOGE("Third Parameter type error");
98         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Third Parameter type error");
99         return;
100     }
101     if (!JS_INPUT_MONITOR_MGR.AddEnv(env, info)) {
102         MMI_HILOGE("AddEnv failed");
103         return;
104     }
105     JS_INPUT_MONITOR_MGR.AddMonitor(env, "mouse", hotRectAreaList, rectArrayLength, napiCallback);
106     return;
107 }
108 
AddMonitor(napi_env env,napi_callback_info info)109 static napi_value AddMonitor(napi_env env, napi_callback_info info)
110 {
111     CALL_DEBUG_ENTER;
112     size_t argc = 3;
113     napi_value argv[3] = { 0 };
114     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
115     napi_valuetype valueType = napi_undefined;
116     CHKRP(napi_typeof(env, argv[0], &valueType), TYPEOF);
117     if (valueType != napi_string) {
118         MMI_HILOGE("First Parameter type error");
119         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "EventType", "string");
120         return nullptr;
121     }
122     char typeName[MAX_STRING_LEN] = { 0 };
123     size_t len = 0;
124     CHKRP(napi_get_value_string_utf8(env, argv[0], typeName, MAX_STRING_LEN - 1, &len), GET_VALUE_STRING_UTF8);
125     if (ACTION_TYPE.find(typeName) == ACTION_TYPE.end()) {
126         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "EventType is invalid");
127         return nullptr;
128     }
129     if (strcmp(typeName, "mouse") == 0) {
130         AddMouseMonitor(env, info, argv[1], argv[TWO_PARAMETERS]);
131     } else {
132         CHKRP(napi_typeof(env, argv[1], &valueType), TYPEOF);
133         if (valueType != napi_number) {
134             THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Second Parameter type error");
135             return nullptr;
136         }
137         int32_t fingers = 0;
138         CHKRP(napi_get_value_int32(env, argv[1], &fingers), GET_VALUE_INT32);
139         if (fingers < 0) {
140             THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "fingers is invalid");
141             return nullptr;
142         }
143 
144         CHKRP(napi_typeof(env, argv[TWO_PARAMETERS], &valueType), TYPEOF);
145         if (valueType != napi_function) {
146             THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Third Parameter type error");
147             return nullptr;
148         }
149         if (!JS_INPUT_MONITOR_MGR.AddEnv(env, info)) {
150             MMI_HILOGE("AddEnv failed");
151             return nullptr;
152         }
153         JS_INPUT_MONITOR_MGR.AddMonitor(env, typeName, argv[TWO_PARAMETERS], fingers);
154     }
155     return nullptr;
156 }
157 
JsOn(napi_env env,napi_callback_info info)158 static napi_value JsOn(napi_env env, napi_callback_info info)
159 {
160     CALL_DEBUG_ENTER;
161     size_t argc = 3;
162     napi_value argv[3] = { 0 };
163     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
164     if (argc < TWO_PARAMETERS) {
165         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "parameter number error");
166         return nullptr;
167     }
168     if (argc == TWO_PARAMETERS) {
169         JsOnApi9(env, info);
170     } else if (argc == THREE_PARAMETERS) {
171         AddMonitor(env, info);
172     }
173     return nullptr;
174 }
175 
JsOffApi9(napi_env env,napi_callback_info info)176 static napi_value JsOffApi9(napi_env env, napi_callback_info info)
177 {
178     CALL_DEBUG_ENTER;
179     size_t argc = 2;
180     napi_value argv[2] = { 0 };
181     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
182     napi_valuetype valueType = napi_undefined;
183     CHKRP(napi_typeof(env, argv[0], &valueType), TYPEOF);
184     if (valueType != napi_string) {
185         MMI_HILOGE("First Parameter type error");
186         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "EventType", "string");
187         return nullptr;
188     }
189     char typeName[MAX_STRING_LEN] = { 0 };
190     size_t len = 0;
191     CHKRP(napi_get_value_string_utf8(env, argv[0], typeName, MAX_STRING_LEN - 1, &len), GET_VALUE_STRING_UTF8);
192     if (ACTION_TYPE.find(typeName) == ACTION_TYPE.end()) {
193         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "EventType is invalid");
194         return nullptr;
195     }
196     if (argc < TWO_PARAMETERS) {
197         JS_INPUT_MONITOR_MGR.RemoveMonitor(env, typeName);
198         MMI_HILOGD("Remove all monitor");
199         return nullptr;
200     }
201 
202     CHKRP(napi_typeof(env, argv[1], &valueType), TYPEOF);
203     if (valueType != napi_function) {
204         MMI_HILOGE("Second Parameter type error");
205         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Second Parameter type error");
206         return nullptr;
207     }
208 
209     if (!JS_INPUT_MONITOR_MGR.AddEnv(env, info)) {
210         JS_INPUT_MONITOR_MGR.RemoveMonitor(env, typeName);
211         return nullptr;
212     }
213 
214     JS_INPUT_MONITOR_MGR.RemoveMonitor(env, typeName, argv[1]);
215     return nullptr;
216 }
217 
RemoveMonitor(napi_env env,napi_callback_info info)218 static napi_value RemoveMonitor(napi_env env, napi_callback_info info)
219 {
220     CALL_DEBUG_ENTER;
221     size_t argc = 3;
222     napi_value argv[3] = { 0 };
223     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
224     napi_valuetype valueType = napi_undefined;
225     CHKRP(napi_typeof(env, argv[0], &valueType), TYPEOF);
226     if (valueType != napi_string) {
227         MMI_HILOGE("First Parameter type error");
228         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "EventType", "string");
229         return nullptr;
230     }
231     char typeName[MAX_STRING_LEN] = { 0 };
232     size_t len = 0;
233     CHKRP(napi_get_value_string_utf8(env, argv[0], typeName, MAX_STRING_LEN - 1, &len), GET_VALUE_STRING_UTF8);
234     if (ACTION_TYPE.find(typeName) == ACTION_TYPE.end()) {
235         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "EventType is invalid");
236         return nullptr;
237     }
238     CHKRP(napi_typeof(env, argv[1], &valueType), TYPEOF);
239     if (valueType != napi_number) {
240         MMI_HILOGE("Second Parameter type error");
241         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Second Parameter type error");
242         return nullptr;
243     }
244     int32_t fingers = 0;
245     CHKRP(napi_get_value_int32(env, argv[1], &fingers), GET_VALUE_INT32);
246     if (fingers < 0) {
247         MMI_HILOGE("Invalid fingers");
248         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "fingers is invalid");
249         return nullptr;
250     }
251     if (argc < THREE_PARAMETERS) {
252         JS_INPUT_MONITOR_MGR.RemoveMonitor(env, typeName, fingers);
253         MMI_HILOGD("Remove all monitor");
254         return nullptr;
255     }
256     CHKRP(napi_typeof(env, argv[TWO_PARAMETERS], &valueType), TYPEOF);
257     if (valueType != napi_function) {
258         MMI_HILOGE("Second Parameter type error");
259         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Second Parameter type error");
260         return nullptr;
261     }
262     if (!JS_INPUT_MONITOR_MGR.AddEnv(env, info)) {
263         JS_INPUT_MONITOR_MGR.RemoveMonitor(env, typeName, fingers);
264         return nullptr;
265     }
266 
267     JS_INPUT_MONITOR_MGR.RemoveMonitor(env, typeName, argv[TWO_PARAMETERS], fingers);
268     return nullptr;
269 }
270 
JsOff(napi_env env,napi_callback_info info)271 static napi_value JsOff(napi_env env, napi_callback_info info)
272 {
273     CALL_DEBUG_ENTER;
274     size_t argc = 2;
275     napi_value argv[2] = { 0 };
276 
277     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
278     if (argc < 1) {
279         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "parameter number error");
280         return nullptr;
281     }
282     napi_valuetype valueType = napi_undefined;
283     napi_typeof(env, argv[1], &valueType);
284 
285     if (argc == 1 || napi_function == valueType) {
286         JsOffApi9(env, info);
287     } else {
288         RemoveMonitor(env, info);
289     }
290     return nullptr;
291 }
292 
293 EXTERN_C_START
MmiInputMonitorInit(napi_env env,napi_value exports)294 static napi_value MmiInputMonitorInit(napi_env env, napi_value exports)
295 {
296     CALL_DEBUG_ENTER;
297     napi_property_descriptor desc[] = {
298         DECLARE_NAPI_FUNCTION("on", JsOn),
299         DECLARE_NAPI_FUNCTION("off", JsOff),
300     };
301     CHKRP(napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc), DEFINE_PROPERTIES);
302     return exports;
303 }
304 EXTERN_C_END
305 
306 static napi_module mmiInputMonitorModule = {
307     .nm_version = 1,
308     .nm_flags = 0,
309     .nm_filename = nullptr,
310     .nm_register_func = MmiInputMonitorInit,
311     .nm_modname = "multimodalInput.inputMonitor",
312     .nm_priv = ((void*)0),
313     .reserved = { 0 },
314 };
315 
RegisterModule(void)316 extern "C" __attribute__((constructor)) void RegisterModule(void)
317 {
318     napi_module_register(&mmiInputMonitorModule);
319 }
320 } // namespace MMI
321 } // namespace OHOS
322