• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paraArray) != 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