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_manager.h"
17
18 #include "napi_constants.h"
19
20 #undef MMI_LOG_TAG
21 #define MMI_LOG_TAG "JsShortKeyManager"
22
23 namespace OHOS {
24 namespace MMI {
25 namespace {
26 enum class ReturnType {
27 VOID,
28 BOOL,
29 NUMBER,
30 };
31 } // namespace
32
TypeOf(napi_env env,napi_value value,napi_valuetype type)33 bool JsCommon::TypeOf(napi_env env, napi_value value, napi_valuetype type)
34 {
35 napi_valuetype valueType = napi_undefined;
36 CHKRF(napi_typeof(env, value, &valueType), TYPEOF);
37 return valueType == type;
38 }
39
~AsyncContext()40 AsyncContext::~AsyncContext()
41 {
42 CALL_DEBUG_ENTER;
43 if (work != nullptr) {
44 CHKRV(napi_delete_async_work(env, work), DELETE_ASYNC_WORK);
45 }
46 if (callback != nullptr && env != nullptr) {
47 CHKRV(napi_delete_reference(env, callback), DELETE_REFERENCE);
48 env = nullptr;
49 }
50 }
51
GetResult(sptr<AsyncContext> asyncContext,napi_value * results,int32_t size)52 static bool GetResult(sptr<AsyncContext> asyncContext, napi_value * results, int32_t size)
53 {
54 CALL_DEBUG_ENTER;
55 const int32_t length = 2;
56 if (size < length) {
57 MMI_HILOGE("results size less than 2");
58 return false;
59 }
60 napi_env env = asyncContext->env;
61 if (asyncContext->errorCode != RET_OK) {
62 if (asyncContext->errorCode == RET_ERR) {
63 MMI_HILOGE("Other errors");
64 return false;
65 }
66 NapiError codeMsg;
67 if (!UtilNapiError::GetApiError(asyncContext->errorCode, codeMsg)) {
68 MMI_HILOGE("ErrorCode not found, errCode:%{public}d", asyncContext->errorCode);
69 return false;
70 }
71 napi_value errCode = nullptr;
72 napi_value errMsg = nullptr;
73 napi_value businessError = nullptr;
74 CHKRF(napi_create_int32(env, asyncContext->errorCode, &errCode), CREATE_INT32);
75 CHKRF(napi_create_string_utf8(env, codeMsg.msg.c_str(),
76 NAPI_AUTO_LENGTH, &errMsg), CREATE_STRING_UTF8);
77 CHKRF(napi_create_error(env, nullptr, errMsg, &businessError), CREATE_ERROR);
78 CHKRF(napi_set_named_property(env, businessError, ERR_CODE.c_str(), errCode), SET_NAMED_PROPERTY);
79 results[0] = businessError;
80 } else {
81 CHKRF(napi_get_undefined(env, &results[0]), GET_UNDEFINED);
82 }
83
84 ReturnType resultType;
85 asyncContext->reserve >> resultType;
86 if (resultType == ReturnType::BOOL) {
87 bool temp;
88 asyncContext->reserve >> temp;
89 CHKRF(napi_get_boolean(env, temp, &results[1]), GET_BOOLEAN);
90 } else if (resultType == ReturnType::NUMBER) {
91 int32_t temp;
92 asyncContext->reserve >> temp;
93 CHKRF(napi_create_int32(env, temp, &results[1]), CREATE_INT32);
94 } else {
95 CHKRF(napi_get_undefined(env, &results[1]), GET_UNDEFINED);
96 }
97 return true;
98 }
99
AsyncCallbackWork(sptr<AsyncContext> asyncContext)100 void AsyncCallbackWork(sptr<AsyncContext> asyncContext)
101 {
102 CALL_DEBUG_ENTER;
103 CHKPV(asyncContext);
104 CHKPV(asyncContext->env);
105 napi_env env = asyncContext->env;
106 napi_value resource = nullptr;
107 CHKRV(napi_create_string_utf8(env, "AsyncCallbackWork", NAPI_AUTO_LENGTH, &resource), CREATE_STRING_UTF8);
108 asyncContext->IncStrongRef(nullptr);
109 napi_status status = napi_create_async_work(
110 env, nullptr, resource,
111 [](napi_env env, void* data) {
112 MMI_HILOGD("async_work callback function is called");
113 },
114 [](napi_env env, napi_status status, void* data) {
115 sptr<AsyncContext> asyncContext(static_cast<AsyncContext *>(data));
116 /**
117 * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
118 * to 0 destruction, so you need to add 1 to the asyncCallbackInfo reference count when the
119 * asynchronous task is created, and subtract 1 from the reference count after the naked
120 * pointer is converted to a pointer when the asynchronous task is executed, the reference
121 * count of the smart pointer is guaranteed to be 1.
122 */
123 asyncContext->DecStrongRef(nullptr);
124 napi_value results[2] = { 0 };
125 int32_t size = 2;
126 if (!GetResult(asyncContext, results, size)) {
127 MMI_HILOGE("Failed to create napi data");
128 return;
129 }
130 if (asyncContext->deferred) {
131 if (asyncContext->errorCode == RET_OK) {
132 CHKRV(napi_resolve_deferred(env, asyncContext->deferred, results[1]), RESOLVE_DEFERRED);
133 } else {
134 CHKRV(napi_reject_deferred(env, asyncContext->deferred, results[0]), REJECT_DEFERRED);
135 }
136 } else {
137 napi_value callback = nullptr;
138 CHKRV(napi_get_reference_value(env, asyncContext->callback, &callback), GET_REFERENCE_VALUE);
139 napi_value callResult = nullptr;
140 CHKRV(napi_call_function(env, nullptr, callback, size, results, &callResult), CALL_FUNCTION);
141 }
142 },
143 asyncContext.GetRefPtr(), &asyncContext->work);
144 if (status != napi_ok ||
145 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_t::napi_qos_user_initiated) != napi_ok) {
146 MMI_HILOGE("Create async work failed");
147 asyncContext->DecStrongRef(nullptr);
148 }
149 }
150
SetKeyDownDuration(napi_env env,const std::string & businessId,int32_t delay,napi_value handle)151 napi_value JsShortKeyManager::SetKeyDownDuration(napi_env env, const std::string &businessId, int32_t delay,
152 napi_value handle)
153 {
154 CALL_DEBUG_ENTER;
155 int32_t ret = InputManager::GetInstance()->SetKeyDownDuration(businessId, delay);
156 if (ret == COMMON_USE_SYSAPI_ERROR) {
157 MMI_HILOGE("Non system applications use system API");
158 THROWERR_CUSTOM(env, COMMON_USE_SYSAPI_ERROR, "Non system applications use system API");
159 return nullptr;
160 } else if (ret == COMMON_PARAMETER_ERROR) {
161 MMI_HILOGE("Invalid param");
162 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "param is invalid");
163 return nullptr;
164 }
165 sptr<AsyncContext> asyncContext = new (std::nothrow) AsyncContext(env);
166 CHKPP(asyncContext);
167 asyncContext->errorCode = ret;
168 asyncContext->reserve << ReturnType::VOID;
169
170 napi_value promise = nullptr;
171 if (handle != nullptr) {
172 CHKRP(napi_create_reference(env, handle, 1, &asyncContext->callback), CREATE_REFERENCE);
173 if (napi_get_undefined(env, &promise) != napi_ok) {
174 CHKRP(napi_delete_reference(env, asyncContext->callback), DELETE_REFERENCE);
175 return nullptr;
176 }
177 } else {
178 CHKRP(napi_create_promise(env, &asyncContext->deferred, &promise), CREATE_PROMISE);
179 }
180 AsyncCallbackWork(asyncContext);
181 return promise;
182 }
183 } // namespace MMI
184 } // namespace OHOS