1 /*
2  * Copyright (c) 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_short_key_context.h"
17 
18 #undef MMI_LOG_TAG
19 #define MMI_LOG_TAG "JsShortKeyContext"
20 
21 namespace OHOS {
22 namespace MMI {
23 namespace {
24 constexpr int32_t MAX_DELAY { 4000 };
25 constexpr int32_t MIN_DELAY { 0 };
26 const std::string SHORT_KEY_CLASS { "multimodalinput_short_key_class" };
27 const std::string SHORT_KEY_INSTANCE { "multimodalinput_short_key" };
28 
29 enum class FingerprintAction : int32_t {
30     DOWN = 0,
31     UP = 1,
32     SLIDE = 2,
33     RETOUCH = 3,
34     CLICK = 4,
35     CANCEL = 5,
36 };
37 } // namespace
38 
JsShortKeyContext()39 JsShortKeyContext::JsShortKeyContext() : mgr_(std::make_shared<JsShortKeyManager>()) {}
40 
CreateInstance(napi_env env)41 napi_value JsShortKeyContext::CreateInstance(napi_env env)
42 {
43     CALL_DEBUG_ENTER;
44     napi_value global = nullptr;
45     CHKRP(napi_get_global(env, &global), GET_GLOBAL);
46 
47     constexpr char className[] = "JsShortKeyContext";
48     napi_value jsClass = nullptr;
49     napi_property_descriptor desc[] = {};
50     napi_status status = napi_define_class(env, className, sizeof(className), JsShortKeyContext::CreateJsObject,
51         nullptr, sizeof(desc) / sizeof(desc[0]), nullptr, &jsClass);
52     CHKRP(status, DEFINE_CLASS);
53 
54     status = napi_set_named_property(env, global, SHORT_KEY_CLASS.c_str(), jsClass);
55     CHKRP(status, SET_NAMED_PROPERTY);
56 
57     napi_value jsInstance = nullptr;
58     CHKRP(napi_new_instance(env, jsClass, 0, nullptr, &jsInstance), NEW_INSTANCE);
59     CHKRP(napi_set_named_property(env, global, SHORT_KEY_INSTANCE.c_str(), jsInstance), SET_NAMED_PROPERTY);
60 
61     JsShortKeyContext *jsContext = nullptr;
62     CHKRP(napi_unwrap(env, jsInstance, (void**)&jsContext), UNWRAP);
63     CHKPP(jsContext);
64     CHKRP(napi_create_reference(env, jsInstance, 1, &(jsContext->contextRef_)), CREATE_REFERENCE);
65 
66     uint32_t refCount = 0;
67     if (napi_reference_ref(env, jsContext->contextRef_, &refCount) != napi_ok) {
68         CHKRP(napi_delete_reference(env, jsContext->contextRef_), DELETE_REFERENCE);
69         return nullptr;
70     }
71     return jsInstance;
72 }
73 
CreateJsObject(napi_env env,napi_callback_info info)74 napi_value JsShortKeyContext::CreateJsObject(napi_env env, napi_callback_info info)
75 {
76     CALL_DEBUG_ENTER;
77     napi_value thisVar = nullptr;
78     void *data = nullptr;
79     CHKRP(napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data), GET_CB_INFO);
80 
81     JsShortKeyContext *jsContext = new (std::nothrow) JsShortKeyContext();
82     CHKPP(jsContext);
83     napi_status status = napi_wrap(env, thisVar, jsContext, [](napi_env env, void* data, void* hin) {
84         MMI_HILOGI("jsvm ends");
85         JsShortKeyContext *context = static_cast<JsShortKeyContext*>(data);
86         delete context;
87     }, nullptr, nullptr);
88     if (status != napi_ok) {
89         delete jsContext;
90         THROWERR(env, "Failed to wrap native instance");
91         return nullptr;
92     }
93     return thisVar;
94 }
95 
GetInstance(napi_env env)96 JsShortKeyContext* JsShortKeyContext::GetInstance(napi_env env)
97 {
98     CALL_DEBUG_ENTER;
99     napi_value global = nullptr;
100     CHKRP(napi_get_global(env, &global), GET_GLOBAL);
101 
102     bool result = false;
103     CHKRP(napi_has_named_property(env, global, SHORT_KEY_INSTANCE.c_str(), &result), HAS_NAMED_PROPERTY);
104     if (!result) {
105         THROWERR(env, "multimodal_short_key was not found");
106         return nullptr;
107     }
108 
109     napi_value object = nullptr;
110     CHKRP(napi_get_named_property(env, global, SHORT_KEY_INSTANCE.c_str(), &object), SET_NAMED_PROPERTY);
111     if (object == nullptr) {
112         THROWERR(env, "Object is nullptr");
113         return nullptr;
114     }
115 
116     JsShortKeyContext *instance = nullptr;
117     CHKRP(napi_unwrap(env, object, (void**)&instance), UNWRAP);
118     if (instance == nullptr) {
119         THROWERR(env, "Instance is nullptr");
120         return nullptr;
121     }
122     return instance;
123 }
124 
GetJsShortKeyMgr() const125 std::shared_ptr<JsShortKeyManager> JsShortKeyContext::GetJsShortKeyMgr() const
126 {
127     return mgr_;
128 }
129 
SetKeyDownDuration(napi_env env,napi_callback_info info)130 napi_value JsShortKeyContext::SetKeyDownDuration(napi_env env, napi_callback_info info)
131 {
132     CALL_DEBUG_ENTER;
133     size_t argc = 3;
134     napi_value argv[3];
135     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
136     size_t paramsNum = 2;
137     if (argc < paramsNum) {
138         MMI_HILOGE("At least 2 parameter is required");
139         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "businessId", "string");
140         return nullptr;
141     }
142     if (!JsCommon::TypeOf(env, argv[0], napi_string)) {
143         MMI_HILOGE("businessId parameter type is invalid");
144         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "businessId", "string");
145         return nullptr;
146     }
147 
148     char businessId[MAX_STRING_LEN] = { 0 };
149     size_t ret = 0;
150     CHKRP(napi_get_value_string_utf8(env, argv[0], businessId, MAX_STRING_LEN - 1, &ret), GET_VALUE_STRING_UTF8);
151     if (ret <= 0) {
152         MMI_HILOGE("Invalid businessId");
153         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "businessId is invalid");
154         return nullptr;
155     }
156 
157     int32_t delay = 0;
158     CHKRP(napi_get_value_int32(env, argv[1], &delay), GET_VALUE_INT32);
159     if (delay < MIN_DELAY || delay > MAX_DELAY) {
160         MMI_HILOGE("Invalid delay");
161         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Delay is invalid");
162         return nullptr;
163     }
164     if (!JsCommon::TypeOf(env, argv[1], napi_number)) {
165         MMI_HILOGE("Delay parameter type is invalid");
166         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "delay", "number");
167         return nullptr;
168     }
169     JsShortKeyContext *jsShortKey = JsShortKeyContext::GetInstance(env);
170     CHKPP(jsShortKey);
171     auto jsShortKeyMgr = jsShortKey->GetJsShortKeyMgr();
172     if (argc == paramsNum) {
173         return jsShortKeyMgr->SetKeyDownDuration(env, businessId, delay);
174     }
175     if (!JsCommon::TypeOf(env, argv[paramsNum], napi_function)) {
176         MMI_HILOGE("Callback parameter type is invalid");
177         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
178         return nullptr;
179     }
180     return jsShortKeyMgr->SetKeyDownDuration(env, businessId, delay, argv[paramsNum]);
181 }
182 
GetNapiInt32(napi_env env,int32_t code)183 napi_value JsShortKeyContext::GetNapiInt32(napi_env env, int32_t code)
184 {
185     CALL_DEBUG_ENTER;
186     napi_value ret = nullptr;
187     CHKRP(napi_create_int32(env, code, &ret), CREATE_INT32);
188     return ret;
189 }
190 
EnumClassConstructor(napi_env env,napi_callback_info info)191 napi_value JsShortKeyContext::EnumClassConstructor(napi_env env, napi_callback_info info)
192 {
193     CALL_DEBUG_ENTER;
194     size_t argc = 0;
195     napi_value args[1] = { 0 };
196     napi_value ret = nullptr;
197     void *data = nullptr;
198     CHKRP(napi_get_cb_info(env, info, &argc, args, &ret, &data), GET_CB_INFO);
199     return ret;
200 }
201 
Export(napi_env env,napi_value exports)202 napi_value JsShortKeyContext::Export(napi_env env, napi_value exports)
203 {
204     CALL_DEBUG_ENTER;
205     auto instance = CreateInstance(env);
206     if (instance == nullptr) {
207         THROWERR(env, "Failed to create instance");
208         return nullptr;
209     }
210     napi_property_descriptor desc[] = {
211         DECLARE_NAPI_STATIC_FUNCTION("setKeyDownDuration", SetKeyDownDuration),
212     };
213     CHKRP(napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc), DEFINE_PROPERTIES);
214 
215     napi_property_descriptor fingerprintActionArr[] = {
216         DECLARE_NAPI_STATIC_PROPERTY("DOWN", GetNapiInt32(env, static_cast<int32_t>(FingerprintAction::DOWN))),
217         DECLARE_NAPI_STATIC_PROPERTY("UP", GetNapiInt32(env, static_cast<int32_t>(FingerprintAction::UP))),
218         DECLARE_NAPI_STATIC_PROPERTY("SLIDE", GetNapiInt32(env, static_cast<int32_t>(FingerprintAction::SLIDE))),
219         DECLARE_NAPI_STATIC_PROPERTY("RETOUCH", GetNapiInt32(env, static_cast<int32_t>(FingerprintAction::RETOUCH))),
220         DECLARE_NAPI_STATIC_PROPERTY("CLICK", GetNapiInt32(env, static_cast<int32_t>(FingerprintAction::CLICK))),
221         DECLARE_NAPI_STATIC_PROPERTY("CANCEL", GetNapiInt32(env, static_cast<int32_t>(FingerprintAction::CANCEL))),
222     };
223     napi_value fingerprintAction = nullptr;
224     CHKRP(napi_define_class(env, "FingerprintAction", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
225         sizeof(fingerprintActionArr) / sizeof(*fingerprintActionArr), fingerprintActionArr, &fingerprintAction),
226         DEFINE_CLASS);
227     CHKRP(napi_set_named_property(env, exports, "FingerprintAction", fingerprintAction), SET_NAMED_PROPERTY);
228     return exports;
229 }
230 } // namespace MMI
231 } // namespace OHOS
232