1 /*
2 * Copyright (c) 2025 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 "on_screen_napi.h"
17
18 #include <mutex>
19
20 #include "devicestatus_define.h"
21 #include "fi_log.h"
22 #include "napi_constants.h"
23 #include "on_screen_manager.h"
24 #include "on_screen_napi_error.h"
25 #include "util_napi.h"
26
27 #undef LOG_TAG
28 #define LOG_TAG "OnScreenNapi"
29
30 namespace OHOS {
31 namespace Msdp {
32 namespace DeviceStatus {
33 namespace OnScreen {
34 namespace {
35 constexpr uint8_t ARG_0 = 0;
36 constexpr uint8_t ARG_1 = 1;
37 constexpr int32_t DEFAULT_WINDOW_ID = -1;
38 OnScreenNapi *g_onScreenObj = nullptr;
39 std::mutex g_mtx;
40 } // namespace
41
OnScreenNapi(napi_env env,napi_value thisVar)42 OnScreenNapi::OnScreenNapi(napi_env env, napi_value thisVar)
43 {
44 env_ = env;
45 }
46
~OnScreenNapi()47 OnScreenNapi::~OnScreenNapi() {}
48
Init(napi_env env,napi_value exports)49 napi_value OnScreenNapi::Init(napi_env env, napi_value exports)
50 {
51 FI_HILOGD("Enter");
52 napi_property_descriptor desc[] = {
53 DECLARE_NAPI_STATIC_FUNCTION("sendControlEvent", SendControlEventNapi),
54 DECLARE_NAPI_STATIC_FUNCTION("getPageContent", GetPageContentNapi),
55 };
56 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc)/sizeof(desc[0]), desc));
57 // 声明枚举值Scenario
58 napi_value napiScenario;
59 napi_status status = napi_create_object(env, &napiScenario);
60 if (status != napi_ok) {
61 FI_HILOGE("Failed create object");
62 return nullptr;
63 }
64 bool ret = SetInt32Property(env, napiScenario, static_cast<int32_t>(Scenario::UNKNOWN), "UNKNOWN");
65 ret = ret && SetInt32Property(env, napiScenario, static_cast<int32_t>(Scenario::ARTICLE), "ARTICLE");
66 ret = ret && SetPropertyName(env, exports, "Scenario", napiScenario);
67 if (!ret) {
68 FI_HILOGE("Failed set enum scenario");
69 return nullptr;
70 }
71 // 声明枚举值EventType
72 napi_value napiEventType;
73 status = napi_create_object(env, &napiEventType);
74 if (status != napi_ok) {
75 FI_HILOGE("Failed create object");
76 return nullptr;
77 }
78 ret = SetInt32Property(env, napiEventType, static_cast<int32_t>(EventType::SCROLL_TO_HOOK), "SCROLL_TO_HOOK");
79 ret = ret && SetPropertyName(env, exports, "EventType", napiEventType);
80 if (!ret) {
81 FI_HILOGE("Failed set enum eventtype");
82 return nullptr;
83 }
84 FI_HILOGD("Exit");
85 return exports;
86 }
87
GetPageContentNapi(napi_env env,napi_callback_info info)88 napi_value OnScreenNapi::GetPageContentNapi(napi_env env, napi_callback_info info)
89 {
90 FI_HILOGD("Enter");
91 size_t argc = ARG_1;
92 napi_value args[ARG_1] = { nullptr };
93 napi_value jsThis = nullptr;
94 ContentOption option;
95 napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
96 if (status != napi_ok) {
97 ThrowOnScreenErr(env, RET_SERVICE_EXCEPTION, "napi_get_cb_info failed");
98 return nullptr;
99 }
100 if (!GetContentOption(env, args, argc, option)) {
101 ThrowOnScreenErr(env, RET_PARAM_ERR, "param is invalid");
102 return nullptr;
103 }
104 {
105 std::lock_guard lockGrd(g_mtx);
106 if (!ConstructOnScreen(env, jsThis)) {
107 ThrowOnScreenErr(env, RET_SERVICE_EXCEPTION, "failed to get g_onScreenObj");
108 return nullptr;
109 }
110 }
111 napi_value promise = nullptr;
112 napi_deferred deferred = nullptr;
113 status = napi_create_promise(env, &deferred, &promise);
114 if (status != napi_ok) {
115 ThrowOnScreenErr(env, RET_SERVICE_EXCEPTION, "Failed to create promise");
116 return nullptr;
117 }
118 GetPageContentAsyncContext* asyncContext = new (std::nothrow) GetPageContentAsyncContext();
119 CHKPP(asyncContext);
120 asyncContext->env = env;
121 asyncContext->deferred = deferred;
122 asyncContext->option = option;
123 FI_HILOGD("invoke get page content, windowid = %{public}d, contentUnderstand = %{public}d, pageLink = %{public}d,"
124 "textOnly = %{public}d, minParaLen = %{public}d, maxParaLen = %{public}d", asyncContext->option.windowId,
125 asyncContext->option.contentUnderstand, asyncContext->option.pageLink, asyncContext->option.textOnly,
126 asyncContext->option.paragraphSizeRange.minSize, asyncContext->option.paragraphSizeRange.maxSize);
127 if (!GetPageContentExec(asyncContext)) {
128 FI_HILOGE("get page content execution failed");
129 delete asyncContext;
130 return nullptr;
131 }
132 return promise;
133 }
134
SendControlEventNapi(napi_env env,napi_callback_info info)135 napi_value OnScreenNapi::SendControlEventNapi(napi_env env, napi_callback_info info)
136 {
137 FI_HILOGD("Enter");
138 size_t argc = ARG_1;
139 napi_value args[ARG_1] = { nullptr };
140 napi_value jsThis = nullptr;
141 napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
142 if (status != napi_ok) {
143 ThrowOnScreenErr(env, RET_SERVICE_EXCEPTION, "napi_get_cb_info failed");
144 return nullptr;
145 }
146 ControlEvent event;
147 if (!GetControlEvent(env, args, argc, event)) {
148 ThrowOnScreenErr(env, RET_PARAM_ERR, "param is invalid");
149 return nullptr;
150 }
151 {
152 std::lock_guard lockGrd(g_mtx);
153 if (!ConstructOnScreen(env, jsThis)) {
154 ThrowOnScreenErr(env, RET_SERVICE_EXCEPTION, "failed to get g_onScreenObj");
155 return nullptr;
156 }
157 }
158 napi_value promise = nullptr;
159 napi_deferred deferred = nullptr;
160 status = napi_create_promise(env, &deferred, &promise);
161 if (status != napi_ok) {
162 ThrowOnScreenErr(env, RET_SERVICE_EXCEPTION, "Failed to create promise");
163 return nullptr;
164 }
165 SendControlEventAsyncContext* asyncContext = new (std::nothrow) SendControlEventAsyncContext();
166 CHKPP(asyncContext);
167 asyncContext->env = env;
168 asyncContext->deferred = deferred;
169 asyncContext->event = event;
170 FI_HILOGD("invoke send control event, windowid = %{public}d, sessionId = %{public}" PRId64
171 ", eventType = %{public}d, hookid = %{public}" PRId64, asyncContext->event.windowId,
172 asyncContext->event.sessionId, asyncContext->event.eventType, asyncContext->event.hookId);
173 if (!SendControlEventExec(asyncContext)) {
174 FI_HILOGE("send control event execution failed");
175 delete asyncContext;
176 return nullptr;
177 }
178 return promise;
179 }
180
ConstructOnScreen(napi_env env,napi_value jsThis)181 bool OnScreenNapi::ConstructOnScreen(napi_env env, napi_value jsThis)
182 {
183 if (g_onScreenObj == nullptr) {
184 g_onScreenObj = new (std::nothrow) OnScreenNapi(env, jsThis);
185 if (g_onScreenObj == nullptr) {
186 FI_HILOGE("faild to get g_onScreenObj");
187 return false;
188 }
189 napi_status status = napi_wrap(env, jsThis, reinterpret_cast<void *>(g_onScreenObj),
190 [](napi_env env, void *data, void *hint) {
191 (void)env;
192 (void)hint;
193 if (data != nullptr) {
194 OnScreenNapi *onScreen = reinterpret_cast<OnScreenNapi *>(data);
195 delete onScreen;
196 }
197 }, nullptr, nullptr);
198 if (status != napi_ok) {
199 delete g_onScreenObj;
200 g_onScreenObj = nullptr;
201 FI_HILOGE("napi_wrap failed");
202 return false;
203 }
204 }
205 return true;
206 }
207
GetContentOption(napi_env env,napi_value * args,size_t argc,ContentOption & option)208 bool OnScreenNapi::GetContentOption(napi_env env, napi_value *args, size_t argc, ContentOption &option)
209 {
210 if (argc != ARG_1) {
211 return false;
212 }
213 napi_value contentOptionObj = args[ARG_0];
214 bool ret = GetInt32FromJs(env, contentOptionObj, "windowId", option.windowId, false);
215 ret = ret && GetBoolFromJs(env, contentOptionObj, "contentUnderstand", option.contentUnderstand, false);
216 ret = ret && GetBoolFromJs(env, contentOptionObj, "pageLink", option.pageLink, false);
217 ret = ret && GetBoolFromJs(env, contentOptionObj, "textOnly", option.textOnly, false);
218 ret = ret && GetParagraphSizeRange(env, contentOptionObj, "paragraphSizeRange", option.paragraphSizeRange, false);
219 if (!ret) {
220 FI_HILOGE("get content option failed");
221 }
222 if (option.windowId < DEFAULT_WINDOW_ID) {
223 FI_HILOGE("windowId is invalid");
224 return false;
225 }
226 return ret;
227 }
228
GetControlEvent(napi_env env,napi_value * args,size_t argc,ControlEvent & event)229 bool OnScreenNapi::GetControlEvent(napi_env env, napi_value *args, size_t argc, ControlEvent &event)
230 {
231 if (argc != ARG_1) {
232 return false;
233 }
234 napi_value eventObj = args[ARG_0];
235 int32_t eventType = 0;
236 bool ret = GetInt32FromJs(env, eventObj, "windowId", event.windowId, true);
237 ret = ret && GetInt64FromJs(env, eventObj, "sessionId", event.sessionId, true);
238 ret = ret && GetInt32FromJs(env, eventObj, "eventType", eventType, true);
239 ret = ret && GetInt64FromJs(env, eventObj, "hookId", event.hookId, false);
240 if (eventType <= static_cast<int32_t>(EventType::UNKNOWN) || eventType >= static_cast<int32_t>(EventType::END)) {
241 FI_HILOGE("event type is invalid");
242 return false;
243 } else {
244 event.eventType = static_cast<EventType>(eventType);
245 }
246 if (!ret) {
247 FI_HILOGE("get control event failed");
248 }
249 if (event.windowId < 0 || event.sessionId < 0 || event.hookId < 0) {
250 FI_HILOGE("windowId or sessionId or hookId is invalid");
251 return false;
252 }
253 return ret;
254 }
255
GetInt32FromJs(napi_env env,const napi_value & value,const std::string & field,int32_t & result,bool isNecessary)256 bool OnScreenNapi::GetInt32FromJs(napi_env env, const napi_value &value, const std::string &field,
257 int32_t &result, bool isNecessary)
258 {
259 bool hasProperty = false;
260 if (napi_has_named_property(env, value, field.c_str(), &hasProperty) != napi_ok) {
261 FI_HILOGE("napi_has_named_property failed");
262 return false;
263 }
264 if (!hasProperty) {
265 FI_HILOGW("napi dont have this property");
266 // 如果是必要的,则返回false,如果不必要,则返回true,使用默认值
267 return !isNecessary;
268 }
269 napi_value fieldValue = nullptr;
270 napi_valuetype valueType = napi_undefined;
271 if (napi_get_named_property(env, value, field.c_str(), &fieldValue) != napi_ok) {
272 FI_HILOGE("napi_get_named_property failed");
273 return false;
274 }
275 if (napi_typeof(env, fieldValue, &valueType) != napi_ok) {
276 FI_HILOGE("typeof failed");
277 return false;
278 }
279 if ((!isNecessary) && valueType == napi_undefined) {
280 FI_HILOGW("isNecessary is false and valueType is undefined");
281 return true;
282 }
283 if (valueType != napi_number) {
284 FI_HILOGE("valueType is not number");
285 return false;
286 }
287 if (napi_get_value_int32(env, fieldValue, &result) != napi_ok) {
288 FI_HILOGE("napi_get_value_int32 failed");
289 return false;
290 }
291 return true;
292 }
293
GetInt64FromJs(napi_env env,const napi_value & value,const std::string & field,int64_t & result,bool isNecessary)294 bool OnScreenNapi::GetInt64FromJs(napi_env env, const napi_value &value, const std::string &field,
295 int64_t &result, bool isNecessary)
296 {
297 bool hasProperty = false;
298 if (napi_has_named_property(env, value, field.c_str(), &hasProperty) != napi_ok) {
299 FI_HILOGE("napi_has_named_property failed");
300 return false;
301 }
302 if (!hasProperty) {
303 FI_HILOGW("napi dont have this property");
304 // 如果是必要的,则返回false,如果不必要,则返回true,使用默认值
305 return !isNecessary;
306 }
307 napi_value fieldValue = nullptr;
308 napi_valuetype valueType = napi_undefined;
309 if (napi_get_named_property(env, value, field.c_str(), &fieldValue) != napi_ok) {
310 FI_HILOGE("napi_get_named_property failed");
311 return false;
312 }
313 if (napi_typeof(env, fieldValue, &valueType) != napi_ok) {
314 FI_HILOGE("typeof failed");
315 return false;
316 }
317 if ((!isNecessary) && valueType == napi_undefined) {
318 FI_HILOGW("isNecessary is false and valueType is undefined");
319 return true;
320 }
321 if (valueType != napi_number) {
322 FI_HILOGE("valueType is not number");
323 return false;
324 }
325 if (napi_get_value_int64(env, fieldValue, &result) != napi_ok) {
326 FI_HILOGE("napi_get_value_int64 failed");
327 return false;
328 }
329 return true;
330 }
331
GetBoolFromJs(napi_env env,const napi_value & value,const std::string & field,bool & result,bool isNecessary)332 bool OnScreenNapi::GetBoolFromJs(napi_env env, const napi_value &value, const std::string &field,
333 bool &result, bool isNecessary)
334 {
335 bool hasProperty = false;
336 if (napi_has_named_property(env, value, field.c_str(), &hasProperty) != napi_ok) {
337 FI_HILOGE("napi_has_named_property failed");
338 return false;
339 }
340 if (!hasProperty) {
341 FI_HILOGW("napi dont have this property");
342 // 如果是必要的,则返回false,如果不必要,则返回true,使用默认值
343 return !isNecessary;
344 }
345 napi_value fieldValue = nullptr;
346 napi_valuetype valueType = napi_undefined;
347 if (napi_get_named_property(env, value, field.c_str(), &fieldValue) != napi_ok) {
348 FI_HILOGE("napi_get_named_property failed");
349 return false;
350 }
351 if (napi_typeof(env, fieldValue, &valueType) != napi_ok) {
352 FI_HILOGE("typeof failed");
353 return false;
354 }
355 if ((!isNecessary) && valueType == napi_undefined) {
356 FI_HILOGW("isNecessary is false and valueType is undefined");
357 return true;
358 }
359 if (valueType != napi_boolean) {
360 FI_HILOGE("valueType is not bool");
361 return false;
362 }
363 if (napi_get_value_bool(env, fieldValue, &result) != napi_ok) {
364 FI_HILOGE("napi_get_value_bool failed");
365 return false;
366 }
367 return true;
368 }
369
GetParagraphSizeRange(napi_env env,const napi_value & value,const std::string & field,ParagraphSizeRange & range,bool isNecessary)370 bool OnScreenNapi::GetParagraphSizeRange(napi_env env, const napi_value &value, const std::string &field,
371 ParagraphSizeRange &range, bool isNecessary)
372 {
373 bool hasProperty = false;
374 if (napi_has_named_property(env, value, field.c_str(), &hasProperty) != napi_ok) {
375 FI_HILOGE("napi_has_named_property failed");
376 return false;
377 }
378 if (!hasProperty) {
379 FI_HILOGW("napi dont have this property");
380 // 如果是必要的,则返回false,如果不必要,则返回true,使用默认值
381 return !isNecessary;
382 }
383 napi_value fieldValue = nullptr;
384 napi_valuetype valueType = napi_undefined;
385 if (napi_get_named_property(env, value, field.c_str(), &fieldValue) != napi_ok) {
386 FI_HILOGE("napi_get_named_property failed");
387 return false;
388 }
389 if (napi_typeof(env, fieldValue, &valueType) != napi_ok) {
390 FI_HILOGE("typeof failed");
391 return false;
392 }
393 if ((!isNecessary) && valueType == napi_undefined) {
394 FI_HILOGW("isNecessary is false and valueType is undefined");
395 return true;
396 }
397 if (valueType != napi_object) {
398 FI_HILOGE("valueType is not object");
399 return false;
400 }
401 bool ret = GetInt32FromJs(env, fieldValue, "minSize", range.minSize, true);
402 ret = ret && GetInt32FromJs(env, fieldValue, "maxSize", range.maxSize, true);
403 if (!ret) {
404 FI_HILOGE("para size range is not enough to parse");
405 return false;
406 }
407 if (!(range.minSize > 0 && range.maxSize > 0 && range.maxSize > range.minSize)) {
408 FI_HILOGE("para size range is invalid");
409 return false;
410 }
411 return true;
412 }
413
SetInt32Property(napi_env env,napi_value targetObj,int32_t value,const char * propName)414 bool OnScreenNapi::SetInt32Property(napi_env env, napi_value targetObj, int32_t value, const char *propName)
415 {
416 napi_value prop = nullptr;
417 napi_status ret = napi_create_int32(env, value, &prop);
418 if (ret != napi_ok) {
419 FI_HILOGE("napi_create_int32 failed");
420 return false;
421 }
422 return SetPropertyName(env, targetObj, propName, prop);
423 }
424
SetInt64Property(napi_env env,napi_value targetObj,int64_t value,const char * propName)425 bool OnScreenNapi::SetInt64Property(napi_env env, napi_value targetObj, int64_t value, const char *propName)
426 {
427 napi_value prop = nullptr;
428 napi_status ret = napi_create_int64(env, value, &prop);
429 if (ret != napi_ok) {
430 FI_HILOGE("napi_create_int64 failed");
431 return false;
432 }
433 return SetPropertyName(env, targetObj, propName, prop);
434 }
435
SetStringProperty(napi_env env,napi_value targetObj,const std::string & value,const char * propName)436 bool OnScreenNapi::SetStringProperty(napi_env env, napi_value targetObj, const std::string &value,
437 const char *propName)
438 {
439 napi_value prop = nullptr;
440 napi_status ret = napi_create_string_utf8(env, value.c_str(), value.size(), &prop);
441 if (ret != napi_ok) {
442 FI_HILOGE("napi_create_string_utf8 failed");
443 return false;
444 }
445 return SetPropertyName(env, targetObj, propName, prop);
446 }
447
ConstructParagraphObj(napi_env env,napi_value & retObj,const Paragraph & value)448 bool OnScreenNapi::ConstructParagraphObj(napi_env env, napi_value &retObj, const Paragraph &value)
449 {
450 retObj = nullptr;
451 if (napi_create_object(env, &retObj) != napi_ok) {
452 FI_HILOGE("create obj failed");
453 retObj = nullptr;
454 return false;
455 }
456 bool ret = SetInt64Property(env, retObj, value.hookId, "hookId");
457 ret = ret && SetInt32Property(env, retObj, value.chapterId, "chapterId");
458 ret = ret && SetStringProperty(env, retObj, value.title, "title");
459 ret = ret && SetStringProperty(env, retObj, value.content, "text");
460 if (!ret) {
461 FI_HILOGE("create paragrah obj failed");
462 return false;
463 }
464 return true;
465 }
466
SetParagraphVecProperty(napi_env env,napi_value targetObj,const std::vector<Paragraph> paragraphs,const char * propName)467 bool OnScreenNapi::SetParagraphVecProperty(napi_env env, napi_value targetObj, const std::vector<Paragraph> paragraphs,
468 const char *propName)
469 {
470 napi_value paraArray = nullptr;
471 if (napi_create_array(env, ¶Array) != napi_ok) {
472 FI_HILOGE("failed to create array");
473 return false;
474 }
475 for (size_t i = 0; i < paragraphs.size(); i++) {
476 napi_value element = nullptr;
477 if (!ConstructParagraphObj(env, element, paragraphs[i])) {
478 FI_HILOGE("failed to create para, i = %{public}zu", i);
479 return false;
480 }
481 if (napi_set_element(env, paraArray, i, element) != napi_ok) {
482 FI_HILOGE("failed to set element, i = %{public}zu", i);
483 return false;
484 }
485 }
486 return SetPropertyName(env, targetObj, propName, paraArray);
487 }
488
SetPropertyName(napi_env env,napi_value targetObj,const char * propName,napi_value propValue)489 bool OnScreenNapi::SetPropertyName(napi_env env, napi_value targetObj, const char *propName, napi_value propValue)
490 {
491 napi_status status = napi_set_named_property(env, targetObj, propName, propValue);
492 if (status != napi_ok) {
493 FI_HILOGE("Failed to set the name property");
494 return false;
495 }
496 return true;
497 }
498
ConstructPageContentObj(napi_env env,napi_value & pageContentObj,const GetPageContentAsyncContext * ctx)499 bool OnScreenNapi::ConstructPageContentObj(napi_env env, napi_value &pageContentObj,
500 const GetPageContentAsyncContext* ctx)
501 {
502 if (napi_create_object(env, &pageContentObj) != napi_ok) {
503 FI_HILOGE("create pageContent failed");
504 return false;
505 }
506 bool ret = SetInt32Property(env, pageContentObj, ctx->pageContent.windowId, "windowId");
507 ret = ret && SetInt64Property(env, pageContentObj, ctx->pageContent.sessionId, "sessionId");
508 ret = ret && SetStringProperty(env, pageContentObj, ctx->pageContent.bundleName, "bundleName");
509 if (ctx->option.contentUnderstand) {
510 ret = ret && SetInt32Property(env, pageContentObj, static_cast<int32_t>(ctx->pageContent.scenario), "scenario");
511 ret = ret && SetStringProperty(env, pageContentObj, ctx->pageContent.title, "title");
512 ret = ret && SetStringProperty(env, pageContentObj, ctx->pageContent.content, "content");
513 }
514 if (ctx->option.pageLink) {
515 ret = ret && SetStringProperty(env, pageContentObj, ctx->pageContent.pageLink, "pageLink");
516 }
517 if (ctx->option.textOnly) {
518 ret = ret && SetParagraphVecProperty(env, pageContentObj, ctx->pageContent.paragraphs, "paragraphs");
519 }
520 if (!ret) {
521 FI_HILOGE("construct page content failed");
522 return false;
523 }
524 return true;
525 }
526
GetPageContentExec(GetPageContentAsyncContext * asyncContext)527 bool OnScreenNapi::GetPageContentExec(GetPageContentAsyncContext *asyncContext)
528 {
529 CHKPF(asyncContext);
530 CHKPF(asyncContext->env);
531 CHKPF(asyncContext->deferred);
532 napi_value resource = nullptr;
533 std::string funcName = "getPageContentExec";
534 napi_create_string_utf8(asyncContext->env, "getPageContentExec", funcName.size(), &resource);
535 CHKRF(napi_create_async_work(asyncContext->env, nullptr, resource, GetPageContentExecCB,
536 GetPageContentCompCB, static_cast<void*>(asyncContext), &asyncContext->work), "CREATE_ASYNC_WORK");
537 CHKRF(napi_queue_async_work_with_qos(asyncContext->env, asyncContext->work, napi_qos_default), "QUEUE_ASYNC_WORK");
538 FI_HILOGI("exec get page content succ");
539 return true;
540 }
541
GetPageContentExecCB(napi_env env,void * data)542 void OnScreenNapi::GetPageContentExecCB(napi_env env, void *data)
543 {
544 CHKPV(data);
545 CHKPV(env);
546 std::lock_guard lockGuard(g_mtx);
547 GetPageContentAsyncContext* execAsyncContext = static_cast<GetPageContentAsyncContext*>(data);
548 execAsyncContext->result = OnScreenManager::GetInstance().GetPageContent(
549 execAsyncContext->option, execAsyncContext->pageContent);
550 }
551
GetPageContentCompCB(napi_env env,napi_status status,void * data)552 void OnScreenNapi::GetPageContentCompCB(napi_env env, napi_status status, void *data)
553 {
554 CHKPV(data);
555 CHKPV(env);
556 std::lock_guard lockGrd(g_mtx);
557 GetPageContentAsyncContext* ctx = static_cast<GetPageContentAsyncContext*>(data);
558 CHKPV(ctx->deferred);
559 napi_value errVal = nullptr;
560 napi_value pageContentObj = nullptr;
561 napi_status retStatus = napi_ok;
562 if (ctx->result != RET_OK) {
563 auto retMsg = GetOnScreenErrMsg(ctx->result);
564 if (retMsg != std::nullopt) {
565 ThrowOnScreenErrByPromise(env, ctx->result, retMsg.value(), errVal);
566 } else {
567 ThrowOnScreenErrByPromise(env, RET_SERVICE_EXCEPTION, "service exception", errVal);
568 }
569 retStatus = napi_reject_deferred(env, ctx->deferred, errVal);
570 } else {
571 if (!ConstructPageContentObj(env, pageContentObj, ctx)) {
572 ThrowOnScreenErrByPromise(env, RET_SERVICE_EXCEPTION, "service exception", errVal);
573 retStatus = napi_reject_deferred(env, ctx->deferred, errVal);
574 }
575 retStatus = napi_resolve_deferred(env, ctx->deferred, pageContentObj);
576 }
577 if (retStatus != napi_ok) {
578 FI_HILOGE("napi pack defer err, result = %{public}d, status = %{public}d", ctx->result, retStatus);
579 }
580 napi_delete_async_work(env, ctx->work);
581 delete ctx;
582 ctx = nullptr;
583 }
584
SendControlEventExec(SendControlEventAsyncContext * asyncContext)585 bool OnScreenNapi::SendControlEventExec(SendControlEventAsyncContext *asyncContext)
586 {
587 CHKPF(asyncContext);
588 CHKPF(asyncContext->env);
589 CHKPF(asyncContext->deferred);
590 napi_value resource = nullptr;
591 std::string funcName = "sendControlEventExec";
592 napi_create_string_utf8(asyncContext->env, "sendControlEventExec", funcName.size(), &resource);
593 CHKRF(napi_create_async_work(asyncContext->env, nullptr, resource, SendControlEventExecCB,
594 SendControlEventCompCB, static_cast<void*>(asyncContext), &asyncContext->work), "CREATE_ASYNC_WORK");
595 CHKRF(napi_queue_async_work_with_qos(asyncContext->env, asyncContext->work, napi_qos_default), "QUEUE_ASYNC_WORK");
596 FI_HILOGI("exec send control event succ");
597 return true;
598 }
599
SendControlEventExecCB(napi_env env,void * data)600 void OnScreenNapi::SendControlEventExecCB(napi_env env, void *data)
601 {
602 CHKPV(data);
603 CHKPV(env);
604 std::lock_guard lockGuard(g_mtx);
605 SendControlEventAsyncContext* execAsyncContext = static_cast<SendControlEventAsyncContext*>(data);
606 execAsyncContext->result = OnScreenManager::GetInstance().SendControlEvent(
607 execAsyncContext->event);
608 }
609
SendControlEventCompCB(napi_env env,napi_status status,void * data)610 void OnScreenNapi::SendControlEventCompCB(napi_env env, napi_status status, void *data)
611 {
612 CHKPV(data);
613 CHKPV(env);
614 std::lock_guard lockGrd(g_mtx);
615 SendControlEventAsyncContext* ctx = static_cast<SendControlEventAsyncContext*>(data);
616 CHKPV(ctx->deferred);
617 napi_value errVal = nullptr;
618 napi_status retStatus = napi_ok;
619 napi_value retVal = nullptr;
620 if (napi_create_object(env, &retVal) != napi_ok) {
621 FI_HILOGE("send control event create obj failed");
622 ThrowOnScreenErrByPromise(env, RET_SERVICE_EXCEPTION, "service exception", errVal);
623 napi_reject_deferred(env, ctx->deferred, errVal);
624 napi_delete_async_work(env, ctx->work);
625 delete ctx;
626 ctx = nullptr;
627 return;
628 }
629 if (ctx->result != RET_OK) {
630 auto retMsg = GetOnScreenErrMsg(ctx->result);
631 if (retMsg != std::nullopt) {
632 ThrowOnScreenErrByPromise(env, ctx->result, retMsg.value(), errVal);
633 } else {
634 ThrowOnScreenErrByPromise(env, RET_SERVICE_EXCEPTION, "service exception", errVal);
635 }
636 retStatus = napi_reject_deferred(env, ctx->deferred, errVal);
637 } else {
638 retStatus = napi_resolve_deferred(env, ctx->deferred, retVal);
639 }
640 if (retStatus != napi_ok) {
641 FI_HILOGE("napi pack defer err, result = %{public}d, status = %{public}d", ctx->result, retStatus);
642 }
643 napi_delete_async_work(env, ctx->work);
644 delete ctx;
645 ctx = nullptr;
646 }
647
648 EXTERN_C_START
649 /*
650 * function for module exports
651 */
OnScreenNapiInit(napi_env env,napi_value exports)652 static napi_value OnScreenNapiInit(napi_env env, napi_value exports)
653 {
654 FI_HILOGD("Enter");
655 napi_value ret = OnScreenNapi::Init(env, exports);
656 if (ret == nullptr) {
657 FI_HILOGE("Failed to init");
658 return ret;
659 }
660 FI_HILOGD("Exit");
661 return ret;
662 }
663 EXTERN_C_END
664
665 /*
666 * Module definition
667 */
668 static napi_module g_module = {
669 .nm_version = 1,
670 .nm_flags = 0,
671 .nm_filename = "multimodalAwareness.onScreen",
672 .nm_register_func = OnScreenNapiInit,
673 .nm_modname = "multimodalAwareness.onScreen",
674 .nm_priv = (static_cast<void *>(nullptr)),
675 .reserved = { nullptr }
676 };
677
678 /*
679 * Module registration
680 */
RegisterModule(void)681 extern "C" __attribute__((constructor)) void RegisterModule(void)
682 {
683 napi_module_register(&g_module);
684 }
685 } // namespace OnScreen
686 } // namespace DeviceStatus
687 } // namespace Msdp
688 } // namespace OHOS