1 /*
2 * Copyright (c) 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_pointer_manager.h"
17
18 #include "napi_constants.h"
19
20 namespace OHOS {
21 namespace MMI {
22 namespace {
23 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "JsPointerManager" };
24
25 enum class ReturnType {
26 VOID,
27 BOOL,
28 NUMBER,
29 };
30 }
31
TypeOf(napi_env env,napi_value value,napi_valuetype type)32 bool JsCommon::TypeOf(napi_env env, napi_value value, napi_valuetype type)
33 {
34 napi_valuetype valueType = napi_undefined;
35 CHKRF(env, napi_typeof(env, value, &valueType), TYPEOF);
36 if (valueType != type) {
37 return false;
38 }
39 return true;
40 }
41
~AsyncContext()42 AsyncContext::~AsyncContext()
43 {
44 CALL_DEBUG_ENTER;
45 if (work != nullptr) {
46 CHKRV(env, napi_delete_async_work(env, work), DELETE_ASYNC_WORK);
47 }
48 if (callback != nullptr && env != nullptr) {
49 CHKRV(env, napi_delete_reference(env, callback), DELETE_REFERENCE);
50 env = nullptr;
51 }
52 }
53
getResult(sptr<AsyncContext> asyncContext,napi_value * results)54 bool getResult(sptr<AsyncContext> asyncContext, napi_value * results)
55 {
56 CALL_DEBUG_ENTER;
57 napi_env env = asyncContext->env;
58 if (asyncContext->errorCode != RET_OK) {
59 if (asyncContext->errorCode == RET_ERR) {
60 MMI_HILOGE("Other errors");
61 return false;
62 }
63 NapiError codeMsg;
64 if (!UtilNapiError::GetApiError(asyncContext->errorCode, codeMsg)) {
65 MMI_HILOGE("ErrorCode not found, errCode:%{public}d", asyncContext->errorCode);
66 return false;
67 }
68 napi_value errCode = nullptr;
69 napi_value errMsg = nullptr;
70 napi_value businessError = nullptr;
71 CHKRF(env, napi_create_int32(env, asyncContext->errorCode, &errCode), CREATE_INT32);
72 CHKRF(env, napi_create_string_utf8(env, codeMsg.msg.c_str(),
73 NAPI_AUTO_LENGTH, &errMsg), CREATE_STRING_UTF8);
74 CHKRF(env, napi_create_error(env, nullptr, errMsg, &businessError), CREATE_ERROR);
75 CHKRF(env, napi_set_named_property(env, businessError, ERR_CODE.c_str(), errCode), SET_NAMED_PROPERTY);
76 results[0] = businessError;
77 } else {
78 CHKRF(env, napi_get_undefined(env, &results[0]), GET_UNDEFINED);
79 }
80
81 ReturnType resultType;
82 asyncContext->reserve >> resultType;
83 if (resultType == ReturnType::BOOL) {
84 bool temp;
85 asyncContext->reserve >> temp;
86 CHKRF(env, napi_get_boolean(env, temp, &results[1]), CREATE_BOOL);
87 } else if (resultType == ReturnType::NUMBER) {
88 int32_t temp;
89 asyncContext->reserve >> temp;
90 CHKRF(env, napi_create_int32(env, temp, &results[1]), CREATE_INT32);
91 } else {
92 CHKRF(env, napi_get_undefined(env, &results[1]), GET_UNDEFINED);
93 }
94 return true;
95 }
96
AsyncCallbackWork(sptr<AsyncContext> asyncContext)97 void AsyncCallbackWork(sptr<AsyncContext> asyncContext)
98 {
99 CALL_DEBUG_ENTER;
100 CHKPV(asyncContext);
101 CHKPV(asyncContext->env);
102 napi_env env = asyncContext->env;
103 napi_value resource = nullptr;
104 CHKRV(env, napi_create_string_utf8(env, "AsyncCallbackWork", NAPI_AUTO_LENGTH, &resource), CREATE_STRING_UTF8);
105 asyncContext->IncStrongRef(nullptr);
106 napi_status status = napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
107 [](napi_env env, napi_status status, void* data) {
108 sptr<AsyncContext> asyncContext(static_cast<AsyncContext *>(data));
109 /**
110 * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
111 * to 0 destructions, so you need to add 1 to the asyncCallbackInfo reference count when the
112 * asynchronous task is created, and subtract 1 from the reference count after the naked
113 * pointer is converted to a pointer when the asynchronous task is executed, the reference
114 * count of the smart pointer is guaranteed to be 1.
115 */
116 asyncContext->DecStrongRef(nullptr);
117 napi_value results[2] = { 0 };
118 if (!getResult(asyncContext, results)) {
119 MMI_HILOGE("Failed to create napi data");
120 return;
121 }
122 if (asyncContext->deferred) {
123 if (asyncContext->errorCode == RET_OK) {
124 CHKRV(env, napi_resolve_deferred(env, asyncContext->deferred, results[1]), RESOLVE_DEFERRED);
125 } else {
126 CHKRV(env, napi_reject_deferred(env, asyncContext->deferred, results[0]), REJECT_DEFERRED);
127 }
128 } else {
129 napi_value callback = nullptr;
130 CHKRV(env, napi_get_reference_value(env, asyncContext->callback, &callback), GET_REFERENCE);
131 napi_value callResult = nullptr;
132 CHKRV(env, napi_call_function(env, nullptr, callback, 2, results, &callResult), CALL_FUNCTION);
133 }
134 },
135 asyncContext.GetRefPtr(), &asyncContext->work);
136 if (status != napi_ok || napi_queue_async_work(env, asyncContext->work) != napi_ok) {
137 MMI_HILOGE("Create async work failed");
138 asyncContext->DecStrongRef(nullptr);
139 }
140 }
141
SetPointerVisible(napi_env env,bool visible,napi_value handle)142 napi_value JsPointerManager::SetPointerVisible(napi_env env, bool visible, napi_value handle)
143 {
144 CALL_DEBUG_ENTER;
145 sptr<AsyncContext> asyncContext = new (std::nothrow) AsyncContext(env);
146 CHKPP(asyncContext);
147
148 asyncContext->errorCode = InputManager::GetInstance()->SetPointerVisible(visible);
149 asyncContext->reserve << ReturnType::VOID;
150
151 napi_value promise = nullptr;
152 if (handle != nullptr) {
153 CHKRP(env, napi_create_reference(env, handle, 1, &asyncContext->callback), CREATE_REFERENCE);
154 CHKRP(env, napi_get_undefined(env, &promise), GET_UNDEFINED);
155 } else {
156 CHKRP(env, napi_create_promise(env, &asyncContext->deferred, &promise), CREATE_PROMISE);
157 }
158 AsyncCallbackWork(asyncContext);
159 return promise;
160 }
161
IsPointerVisible(napi_env env,napi_value handle)162 napi_value JsPointerManager::IsPointerVisible(napi_env env, napi_value handle)
163 {
164 CALL_DEBUG_ENTER;
165 sptr<AsyncContext> asyncContext = new (std::nothrow) AsyncContext(env);
166 CHKPP(asyncContext);
167
168 bool visible = InputManager::GetInstance()->IsPointerVisible();
169 asyncContext->errorCode = ERR_OK;
170 asyncContext->reserve << ReturnType::BOOL << visible;
171
172 napi_value promise = nullptr;
173 if (handle != nullptr) {
174 CHKRP(env, napi_create_reference(env, handle, 1, &asyncContext->callback), CREATE_REFERENCE);
175 CHKRP(env, napi_get_undefined(env, &promise), GET_UNDEFINED);
176 } else {
177 CHKRP(env, napi_create_promise(env, &asyncContext->deferred, &promise), CREATE_PROMISE);
178 }
179 AsyncCallbackWork(asyncContext);
180 return promise;
181 }
182
SetPointerSpeed(napi_env env,int32_t pointerSpeed,napi_value handle)183 napi_value JsPointerManager::SetPointerSpeed(napi_env env, int32_t pointerSpeed, napi_value handle)
184 {
185 CALL_DEBUG_ENTER;
186 sptr<AsyncContext> asyncContext = new (std::nothrow) AsyncContext(env);
187 CHKPP(asyncContext);
188 asyncContext->errorCode = InputManager::GetInstance()->SetPointerSpeed(pointerSpeed);
189 asyncContext->reserve << ReturnType::VOID;
190 napi_value promise = nullptr;
191 if (handle != nullptr) {
192 CHKRP(env, napi_create_reference(env, handle, 1, &asyncContext->callback), CREATE_REFERENCE);
193 CHKRP(env, napi_get_undefined(env, &promise), GET_UNDEFINED);
194 } else {
195 CHKRP(env, napi_create_promise(env, &asyncContext->deferred, &promise), CREATE_PROMISE);
196 }
197 AsyncCallbackWork(asyncContext);
198 return promise;
199 }
200
GetPointerSpeed(napi_env env,napi_value handle)201 napi_value JsPointerManager::GetPointerSpeed(napi_env env, napi_value handle)
202 {
203 CALL_DEBUG_ENTER;
204 sptr<AsyncContext> asyncContext = new (std::nothrow) AsyncContext(env);
205 CHKPP(asyncContext);
206 int32_t pointerSpeed = 0;
207 asyncContext->errorCode = InputManager::GetInstance()->GetPointerSpeed(pointerSpeed);
208 asyncContext->reserve << ReturnType::NUMBER << pointerSpeed;
209 napi_value promise = nullptr;
210 uint32_t initial_refcount = 1;
211 if (handle != nullptr) {
212 CHKRP(env, napi_create_reference(env, handle, initial_refcount, &asyncContext->callback), CREATE_REFERENCE);
213 CHKRP(env, napi_get_undefined(env, &promise), GET_UNDEFINED);
214 } else {
215 CHKRP(env, napi_create_promise(env, &asyncContext->deferred, &promise), CREATE_PROMISE);
216 }
217 AsyncCallbackWork(asyncContext);
218 return promise;
219 }
220
SetPointerStyle(napi_env env,int32_t windowid,int32_t pointerStyle,napi_value handle)221 napi_value JsPointerManager::SetPointerStyle(napi_env env, int32_t windowid, int32_t pointerStyle, napi_value handle)
222 {
223 CALL_DEBUG_ENTER;
224 sptr<AsyncContext> asyncContext = new (std::nothrow) AsyncContext(env);
225 CHKPP(asyncContext);
226 asyncContext->errorCode = InputManager::GetInstance()->SetPointerStyle(windowid, pointerStyle);
227 asyncContext->reserve << ReturnType::VOID;
228
229 napi_value promise = nullptr;
230 if (handle != nullptr) {
231 CHKRP(env, napi_create_reference(env, handle, 1, &asyncContext->callback), CREATE_REFERENCE);
232 CHKRP(env, napi_get_undefined(env, &promise), GET_UNDEFINED);
233 } else {
234 CHKRP(env, napi_create_promise(env, &asyncContext->deferred, &promise), CREATE_PROMISE);
235 }
236 AsyncCallbackWork(asyncContext);
237 return promise;
238 }
239
GetPointerStyle(napi_env env,int32_t windowid,napi_value handle)240 napi_value JsPointerManager::GetPointerStyle(napi_env env, int32_t windowid, napi_value handle)
241 {
242 CALL_DEBUG_ENTER;
243 sptr<AsyncContext> asyncContext = new (std::nothrow) AsyncContext(env);
244 CHKPP(asyncContext);
245 int32_t pointerStyle = 0;
246 asyncContext->errorCode = InputManager::GetInstance()->GetPointerStyle(windowid, pointerStyle);
247 asyncContext->reserve << ReturnType::NUMBER << pointerStyle;
248 napi_value promise = nullptr;
249 if (handle != nullptr) {
250 CHKRP(env, napi_create_reference(env, handle, 1, &asyncContext->callback), CREATE_REFERENCE);
251 CHKRP(env, napi_get_undefined(env, &promise), GET_UNDEFINED);
252 } else {
253 CHKRP(env, napi_create_promise(env, &asyncContext->deferred, &promise), CREATE_PROMISE);
254 }
255 AsyncCallbackWork(asyncContext);
256 return promise;
257 }
258 } // namespace MMI
259 } // namespace OHOS