1 /*
2  * Copyright (c) 2024 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 "interfaces/napi/kits/utils/napi_utils.h"
17 #include "napi/native_api.h"
18 #include "native_value.h"
19 #include "napi/native_node_api.h"
20 
21 #include "bridge/common/utils/engine_helper.h"
22 #include "bridge/js_frontend/engine/common/js_engine.h"
23 
24 namespace OHOS::Ace::Napi {
ParseFrameNode(napi_env env,napi_callback_info info)25 static NG::FrameNode* ParseFrameNode(napi_env env, napi_callback_info info)
26 {
27     size_t argc = 1;
28     napi_value argv[2] = { nullptr };
29     napi_value thisVar = nullptr;
30     void* data = nullptr;
31     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
32     NAPI_ASSERT(env, argc >= 1, "wrong number of argument\n");
33 
34     napi_value nodePtr = nullptr;
35     NAPI_CALL(env, napi_get_named_property(env, argv[0], "nodePtr_", &nodePtr));
36     napi_valuetype valueType = napi_undefined;
37     napi_typeof(env, nodePtr, &valueType);
38     NG::UINode* uiNode = nullptr;
39     if (valueType == napi_external) {
40         NAPI_CALL(env, napi_get_value_external(env, nodePtr, (void**)&uiNode));
41     }
42     CHECK_NULL_RETURN(uiNode, nullptr);
43     return reinterpret_cast<NG::FrameNode*>(uiNode);
44 }
45 
JSAddFrameNode(napi_env env,napi_callback_info info)46 static napi_value JSAddFrameNode(napi_env env, napi_callback_info info)
47 {
48     NG::FrameNode* frameNode = ParseFrameNode(env, info);
49     CHECK_NULL_RETURN(frameNode, nullptr);
50     size_t argc = 2;
51     napi_value argv[2] = { nullptr };
52     napi_value thisVar = nullptr;
53     void* data = nullptr;
54     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
55     auto delegate = EngineHelper::GetCurrentDelegateSafely();
56     if (!delegate) {
57         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
58         return nullptr;
59     }
60     if (argc == 1) {
61         delegate->AddFrameNodeToOverlay(AceType::Claim(frameNode));
62     } else {
63         napi_valuetype valueType = napi_undefined;
64         napi_typeof(env, argv[1], &valueType);
65         if (valueType == napi_number) {
66             int32_t index = 0;
67             napi_get_value_int32(env, argv[1], &index);
68             delegate->AddFrameNodeToOverlay(AceType::Claim(frameNode), index);
69         } else {
70             NapiThrow(env, "the second paramter is not number.", ERROR_CODE_PARAM_INVALID);
71             return nullptr;
72         }
73     }
74     return nullptr;
75 }
76 
JSRemoveFrameNode(napi_env env,napi_callback_info info)77 static napi_value JSRemoveFrameNode(napi_env env, napi_callback_info info)
78 {
79     NG::FrameNode* frameNode = ParseFrameNode(env, info);
80     CHECK_NULL_RETURN(frameNode, nullptr);
81     auto delegate = EngineHelper::GetCurrentDelegateSafely();
82     if (!delegate) {
83         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
84         return nullptr;
85     }
86     delegate->RemoveFrameNodeOnOverlay(AceType::Claim(frameNode));
87     return nullptr;
88 }
89 
JSShowNode(napi_env env,napi_callback_info info)90 static napi_value JSShowNode(napi_env env, napi_callback_info info)
91 {
92     NG::FrameNode* frameNode = ParseFrameNode(env, info);
93     CHECK_NULL_RETURN(frameNode, nullptr);
94     auto delegate = EngineHelper::GetCurrentDelegateSafely();
95     if (!delegate) {
96         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
97         return nullptr;
98     }
99     delegate->ShowNodeOnOverlay(AceType::Claim(frameNode));
100     return nullptr;
101 }
102 
JSHideNode(napi_env env,napi_callback_info info)103 static napi_value JSHideNode(napi_env env, napi_callback_info info)
104 {
105     NG::FrameNode* frameNode = ParseFrameNode(env, info);
106     CHECK_NULL_RETURN(frameNode, nullptr);
107     auto delegate = EngineHelper::GetCurrentDelegateSafely();
108     if (!delegate) {
109         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
110         return nullptr;
111     }
112     delegate->HideNodeOnOverlay(AceType::Claim(frameNode));
113     return nullptr;
114 }
115 
JSShowAllFrameNodes(napi_env env,napi_callback_info info)116 static napi_value JSShowAllFrameNodes(napi_env env, napi_callback_info info)
117 {
118     auto delegate = EngineHelper::GetCurrentDelegateSafely();
119     if (!delegate) {
120         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
121         return nullptr;
122     }
123     delegate->ShowAllNodesOnOverlay();
124     return nullptr;
125 }
126 
JSHideAllFrameNodes(napi_env env,napi_callback_info info)127 static napi_value JSHideAllFrameNodes(napi_env env, napi_callback_info info)
128 {
129     auto delegate = EngineHelper::GetCurrentDelegateSafely();
130     if (!delegate) {
131         NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
132         return nullptr;
133     }
134     delegate->HideAllNodesOnOverlay();
135     return nullptr;
136 }
137 
OverlayManagerExport(napi_env env,napi_value exports)138 static napi_value OverlayManagerExport(napi_env env, napi_value exports)
139 {
140     napi_property_descriptor overlayManagerDesc[] = {
141         DECLARE_NAPI_FUNCTION("addFrameNode", JSAddFrameNode),
142         DECLARE_NAPI_FUNCTION("removeFrameNode", JSRemoveFrameNode),
143         DECLARE_NAPI_FUNCTION("showNode", JSShowNode),
144         DECLARE_NAPI_FUNCTION("hideNode", JSHideNode),
145         DECLARE_NAPI_FUNCTION("showAllFrameNodes", JSShowAllFrameNodes),
146         DECLARE_NAPI_FUNCTION("hideAllFrameNodes", JSHideAllFrameNodes)
147     };
148     NAPI_CALL(env, napi_define_properties(
149         env, exports, sizeof(overlayManagerDesc) / sizeof(overlayManagerDesc[0]), overlayManagerDesc));
150     return exports;
151 }
152 
153 static napi_module overlayManagerModule = {
154     .nm_version = 1,
155     .nm_flags = 0,
156     .nm_filename = nullptr,
157     .nm_register_func = OverlayManagerExport,
158     .nm_modname = "overlay",
159     .nm_priv = ((void*)0),
160     .reserved = { 0 },
161 };
162 
OverlayRegister()163 extern "C" __attribute__((constructor)) void OverlayRegister()
164 {
165     napi_module_register(&overlayManagerModule);
166 }
167 } // namespace OHOS::Ace::Napi
168