• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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