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