1 /*
2 * Copyright (c) 2023-2023 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_extension_window.h"
17
18 #include "js_extension_window_utils.h"
19 #include "js_runtime_utils.h"
20 #include "js_window_utils.h"
21 #include "window_manager_hilog.h"
22 #include "wm_common.h"
23 #include "extension_window.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 using namespace AbilityRuntime;
28 namespace {
29 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsExtensionWindow"};
30 constexpr Rect g_emptyRect = {0, 0, 0, 0};
31 } // namespace
32
JsExtensionWindow(const std::shared_ptr<Rosen::ExtensionWindow> extensionWindow)33 JsExtensionWindow::JsExtensionWindow(const std::shared_ptr<Rosen::ExtensionWindow> extensionWindow)
34 : extensionWindow_(extensionWindow),
35 extensionRegisterManager_(std::make_unique<JsExtensionWindowRegisterManager>()) {
36 }
37
~JsExtensionWindow()38 JsExtensionWindow::~JsExtensionWindow() {}
39
CreateJsExtensionWindow(napi_env env,sptr<Rosen::Window> window)40 napi_value JsExtensionWindow::CreateJsExtensionWindow(napi_env env, sptr<Rosen::Window> window)
41 {
42 WLOGI("JsExtensionWindow CreateJsExtensionWindow");
43 napi_value objValue = nullptr;
44 napi_create_object(env, &objValue);
45
46 if (env == nullptr || window == nullptr) {
47 WLOGFE("JsExtensionWindow env or window is nullptr");
48 return nullptr;
49 }
50
51 std::shared_ptr<ExtensionWindow> extensionWindow = std::make_shared<ExtensionWindowImpl>(window);
52 std::unique_ptr<JsExtensionWindow> jsExtensionWindow = std::make_unique<JsExtensionWindow>(extensionWindow);
53 napi_wrap(env, objValue, jsExtensionWindow.release(), JsExtensionWindow::Finalizer, nullptr, nullptr);
54
55 napi_property_descriptor desc[] = {
56 DECLARE_NAPI_GETTER("properties", JsExtensionWindow::GetProperties)
57 };
58 NAPI_CALL(env, napi_define_properties(env, objValue, sizeof(desc) / sizeof(desc[0]), desc));
59
60 const char *moduleName = "JsExtensionWindow";
61 BindNativeFunction(env, objValue, "getWindowAvoidArea", moduleName, JsExtensionWindow::GetWindowAvoidArea);
62 BindNativeFunction(env, objValue, "on", moduleName, JsExtensionWindow::RegisterExtensionWindowCallback);
63 BindNativeFunction(env, objValue, "off", moduleName, JsExtensionWindow::UnRegisterExtensionWindowCallback);
64 BindNativeFunction(env, objValue, "hideNonSecureWindows", moduleName, JsExtensionWindow::HideNonSecureWindows);
65
66 return objValue;
67 }
68
Finalizer(napi_env env,void * data,void * hint)69 void JsExtensionWindow::Finalizer(napi_env env, void* data, void* hint)
70 {
71 WLOGI("Finalizer is called");
72 std::unique_ptr<JsExtensionWindow>(static_cast<JsExtensionWindow*>(data));
73 }
74
GetWindowAvoidArea(napi_env env,napi_callback_info info)75 napi_value JsExtensionWindow::GetWindowAvoidArea(napi_env env, napi_callback_info info)
76 {
77 WLOGI("GetWindowAvoidArea is called");
78 JsExtensionWindow* me = CheckParamsAndGetThis<JsExtensionWindow>(env, info);
79 return (me != nullptr) ? me->OnGetWindowAvoidArea(env, info) : nullptr;
80 }
81
RegisterExtensionWindowCallback(napi_env env,napi_callback_info info)82 napi_value JsExtensionWindow::RegisterExtensionWindowCallback(napi_env env, napi_callback_info info)
83 {
84 WLOGI("RegisterExtensionWindowCallback is called");
85 JsExtensionWindow* me = CheckParamsAndGetThis<JsExtensionWindow>(env, info);
86 return (me != nullptr) ? me->OnRegisterExtensionWindowCallback(env, info) : nullptr;
87 }
88
UnRegisterExtensionWindowCallback(napi_env env,napi_callback_info info)89 napi_value JsExtensionWindow::UnRegisterExtensionWindowCallback(napi_env env, napi_callback_info info)
90 {
91 WLOGI("UnRegisterExtensionWindowCallback is called");
92 JsExtensionWindow* me = CheckParamsAndGetThis<JsExtensionWindow>(env, info);
93 return (me != nullptr) ? me->OnUnRegisterExtensionWindowCallback(env, info) : nullptr;
94 }
95
HideNonSecureWindows(napi_env env,napi_callback_info info)96 napi_value JsExtensionWindow::HideNonSecureWindows(napi_env env, napi_callback_info info)
97 {
98 WLOGI("HideNonSecureWindows is called");
99 JsExtensionWindow* me = CheckParamsAndGetThis<JsExtensionWindow>(env, info);
100 return (me != nullptr) ? me->OnHideNonSecureWindows(env, info) : nullptr;
101 }
102
OnGetWindowAvoidArea(napi_env env,napi_callback_info info)103 napi_value JsExtensionWindow::OnGetWindowAvoidArea(napi_env env, napi_callback_info info)
104 {
105 WLOGI("OnGetWindowAvoidArea is called");
106
107 WmErrorCode errCode = WmErrorCode::WM_OK;
108 size_t argc = 4;
109 napi_value argv[4] = {nullptr};
110 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
111 if (argc < 1) { // 1: params num
112 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
113 }
114 AvoidAreaType avoidAreaType = AvoidAreaType::TYPE_SYSTEM;
115 napi_value nativeMode = argv[0];
116 if (nativeMode == nullptr) {
117 errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
118 } else {
119 uint32_t resultValue = 0;
120 napi_get_value_uint32(env, nativeMode, &resultValue);
121 avoidAreaType = static_cast<AvoidAreaType>(resultValue);
122 errCode = ((avoidAreaType > AvoidAreaType::TYPE_NAVIGATION_INDICATOR) ||
123 (avoidAreaType < AvoidAreaType::TYPE_SYSTEM)) ?
124 WmErrorCode::WM_ERROR_INVALID_PARAM : WmErrorCode::WM_OK;
125 }
126 if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) {
127 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
128 }
129
130 if (extensionWindow_ == nullptr) {
131 WLOGFE("extensionWindow_ is nullptr");
132 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WmErrorCode::WM_ERROR_STAGE_ABNORMALLY)));
133 return CreateJsValue(env, static_cast<int32_t>(WmErrorCode::WM_ERROR_STAGE_ABNORMALLY));
134 }
135 // getAvoidRect by avoidAreaType
136 AvoidArea avoidArea;
137 WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(extensionWindow_->GetAvoidAreaByType(avoidAreaType, avoidArea));
138 if (ret != WmErrorCode::WM_OK) {
139 WLOGFE("OnGetAvoidAreaByType failed");
140 avoidArea.topRect_ = g_emptyRect;
141 avoidArea.leftRect_ = g_emptyRect;
142 avoidArea.rightRect_ = g_emptyRect;
143 avoidArea.bottomRect_ = g_emptyRect;
144 }
145 napi_value avoidAreaObj = ConvertAvoidAreaToJsValue(env, avoidArea, avoidAreaType);
146 if (avoidAreaObj != nullptr) {
147 WLOGI("avoidAreaObj is finish");
148 return avoidAreaObj;
149 } else {
150 WLOGFE("avoidAreaObj is nullptr");
151 return NapiThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY);
152 }
153 }
154
OnRegisterExtensionWindowCallback(napi_env env,napi_callback_info info)155 napi_value JsExtensionWindow::OnRegisterExtensionWindowCallback(napi_env env, napi_callback_info info)
156 {
157 sptr<Window> windowImpl = extensionWindow_->GetWindow();
158 if (windowImpl == nullptr) {
159 WLOGFE("WindowImpl is nullptr");
160 return NapiThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY);
161 }
162 size_t argc = 4;
163 napi_value argv[4] = {nullptr};
164 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
165 if (argc < 2) { // 2: params num
166 WLOGFE("Argc is invalid: %{public}zu", argc);
167 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
168 }
169 std::string cbType;
170 if (!ConvertFromJsValue(env, argv[0], cbType)) {
171 WLOGFE("Failed to convert parameter to callbackType");
172 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
173 }
174 napi_value value = argv[1];
175 if (!NapiIsCallable(env, value)) {
176 WLOGFE("Callback(info->argv[1]) is not callable");
177 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
178 }
179 WmErrorCode ret = extensionRegisterManager_->RegisterListener(windowImpl, cbType, CaseType::CASE_WINDOW,
180 env, value);
181 if (ret != WmErrorCode::WM_OK) {
182 WLOGFE("Callback(info->argv[1]) is not callable");
183 return NapiThrowError(env, ret);
184 }
185 WLOGI("Register end, window [%{public}u, %{public}s], type = %{public}s",
186 windowImpl->GetWindowId(), windowImpl->GetWindowName().c_str(), cbType.c_str());
187 return NapiGetUndefined(env);
188 }
189
OnUnRegisterExtensionWindowCallback(napi_env env,napi_callback_info info)190 napi_value JsExtensionWindow::OnUnRegisterExtensionWindowCallback(napi_env env, napi_callback_info info)
191 {
192 sptr<Window> windowImpl = extensionWindow_->GetWindow();
193 if (windowImpl == nullptr) {
194 WLOGFE("windowImpl is nullptr");
195 return NapiThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY);
196 }
197 size_t argc = 4;
198 napi_value argv[4] = {nullptr};
199 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
200 if (argc < 1) {
201 WLOGFE("Argc is invalid: %{public}zu", argc);
202 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
203 }
204 std::string cbType;
205 if (!ConvertFromJsValue(env, argv[0], cbType)) {
206 WLOGFE("Failed to convert parameter to callbackType");
207 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
208 }
209
210 napi_value value = nullptr;
211 WmErrorCode ret = WmErrorCode::WM_OK;
212 if (argc == 1) {
213 ret = extensionRegisterManager_->UnregisterListener(windowImpl, cbType, CaseType::CASE_WINDOW, env, value);
214 } else {
215 value = argv[1];
216 if (value == nullptr || !NapiIsCallable(env, value)) {
217 ret = extensionRegisterManager_->UnregisterListener(windowImpl, cbType, CaseType::CASE_WINDOW,
218 env, nullptr);
219 } else {
220 ret = extensionRegisterManager_->UnregisterListener(windowImpl, cbType, CaseType::CASE_WINDOW, env, value);
221 }
222 }
223
224 if (ret != WmErrorCode::WM_OK) {
225 return NapiThrowError(env, ret);
226 }
227 WLOGI("UnRegister end, window [%{public}u, %{public}s], type = %{public}s",
228 windowImpl->GetWindowId(), windowImpl->GetWindowName().c_str(), cbType.c_str());
229 return NapiGetUndefined(env);
230 }
231
OnHideNonSecureWindows(napi_env env,napi_callback_info info)232 napi_value JsExtensionWindow::OnHideNonSecureWindows(napi_env env, napi_callback_info info)
233 {
234 if (extensionWindow_ == nullptr) {
235 WLOGFE("extensionWindow_ is nullptr");
236 return NapiThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY);
237 }
238 sptr<Window> windowImpl = extensionWindow_->GetWindow();
239 if (windowImpl == nullptr) {
240 WLOGFE("windowImpl is nullptr");
241 return NapiThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY);
242 }
243 size_t argc = 4;
244 napi_value argv[4] = {nullptr};
245 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
246 if (argc < 1) {
247 WLOGFE("Argc is invalid: %{public}zu", argc);
248 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
249 }
250 bool shouldHide = false;
251 if (!ConvertFromJsValue(env, argv[0], shouldHide)) {
252 WLOGFE("Failed to convert parameter to bool");
253 return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
254 }
255
256 WmErrorCode ret = WmErrorCode::WM_OK;
257 ret = WM_JS_TO_ERROR_CODE_MAP.at(extensionWindow_->HideNonSecureWindows(shouldHide));
258 if (ret != WmErrorCode::WM_OK) {
259 return NapiThrowError(env, ret);
260 }
261 WLOGI("OnHideNonSecureWindows end, window [%{public}u, %{public}s], shouldHide:%{public}u",
262 windowImpl->GetWindowId(), windowImpl->GetWindowName().c_str(), shouldHide);
263 return NapiGetUndefined(env);
264 }
265
GetProperties(napi_env env,napi_callback_info info)266 napi_value JsExtensionWindow::GetProperties(napi_env env, napi_callback_info info)
267 {
268 WLOGI("GetProperties is called");
269 napi_value jsThis;
270 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr));
271
272 JsExtensionWindow* jsExtensionWindow = nullptr;
273 NAPI_CALL(env, napi_unwrap(env, jsThis, reinterpret_cast<void**>(&jsExtensionWindow)));
274 if (!jsExtensionWindow || !jsExtensionWindow->extensionWindow_) {
275 WLOGFE("window is nullptr");
276 return nullptr;
277 }
278 sptr<Rosen::Window> window = jsExtensionWindow->extensionWindow_->GetWindow();
279 return CreateJsExtensionWindowPropertiesObject(env, window);
280 }
281 } // namespace Rosen
282 } // namespace OHOS
283