• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #include "js_err_utils.h"
16 #include "js_window_manager.h"
17 #include <ability.h>
18 #include <cinttypes>
19 #include <hitrace_meter.h>
20 #include <new>
21 #include <transaction/rs_interfaces.h>
22 #include "ability_context.h"
23 #include "display_manager.h"
24 #include "dm_common.h"
25 #include "wm_common.h"
26 #include "js_window.h"
27 #include "js_window_utils.h"
28 #include "window_helper.h"
29 #include "window_manager_hilog.h"
30 #include "window_option.h"
31 #include "pixel_map_napi.h"
32 #include "permission.h"
33 #include "singleton_container.h"
34 
35 namespace OHOS {
36 namespace Rosen {
37 using namespace AbilityRuntime;
38 namespace {
39 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindowManager"};
40 const std::string PIP_WINDOW = "pip_window";
41 constexpr size_t ARGC_ONE = 1;
42 constexpr size_t ARGC_TWO = 2;
43 constexpr size_t ARGC_THREE = 3;
44 constexpr size_t ARGC_FOUR = 4;
45 constexpr int32_t INVALID_COORDINATE = -1;
46 }
47 
JsWindowManager()48 JsWindowManager::JsWindowManager() : registerManager_(std::make_unique<JsWindowRegisterManager>())
49 {
50 }
51 
~JsWindowManager()52 JsWindowManager::~JsWindowManager()
53 {
54 }
55 
Finalizer(napi_env env,void * data,void * hint)56 void JsWindowManager::Finalizer(napi_env env, void* data, void* hint)
57 {
58     WLOGI("Finalizer");
59     std::unique_ptr<JsWindowManager>(static_cast<JsWindowManager*>(data));
60 }
61 
Create(napi_env env,napi_callback_info info)62 napi_value JsWindowManager::Create(napi_env env, napi_callback_info info)
63 {
64     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
65     return (me != nullptr) ? me->OnCreate(env, info) : nullptr;
66 }
67 
CreateWindow(napi_env env,napi_callback_info info)68 napi_value JsWindowManager::CreateWindow(napi_env env, napi_callback_info info)
69 {
70     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
71     return (me != nullptr) ? me->OnCreateWindow(env, info) : nullptr;
72 }
73 
FindWindow(napi_env env,napi_callback_info info)74 napi_value JsWindowManager::FindWindow(napi_env env, napi_callback_info info)
75 {
76     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
77     return (me != nullptr) ? me->OnFindWindow(env, info) : nullptr;
78 }
79 
FindWindowSync(napi_env env,napi_callback_info info)80 napi_value JsWindowManager::FindWindowSync(napi_env env, napi_callback_info info)
81 {
82     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
83     return (me != nullptr) ? me->OnFindWindowSync(env, info) : nullptr;
84 }
85 
MinimizeAll(napi_env env,napi_callback_info info)86 napi_value JsWindowManager::MinimizeAll(napi_env env, napi_callback_info info)
87 {
88     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
89     return (me != nullptr) ? me->OnMinimizeAll(env, info) : nullptr;
90 }
91 
ToggleShownStateForAllAppWindows(napi_env env,napi_callback_info info)92 napi_value JsWindowManager::ToggleShownStateForAllAppWindows(napi_env env, napi_callback_info info)
93 {
94     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
95     return (me != nullptr) ? me->OnToggleShownStateForAllAppWindows(env, info) : nullptr;
96 }
97 
RegisterWindowManagerCallback(napi_env env,napi_callback_info info)98 napi_value JsWindowManager::RegisterWindowManagerCallback(napi_env env, napi_callback_info info)
99 {
100     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
101     return (me != nullptr) ? me->OnRegisterWindowManagerCallback(env, info) : nullptr;
102 }
103 
UnregisterWindowMangerCallback(napi_env env,napi_callback_info info)104 napi_value JsWindowManager::UnregisterWindowMangerCallback(napi_env env, napi_callback_info info)
105 {
106     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
107     return (me != nullptr) ? me->OnUnregisterWindowManagerCallback(env, info) : nullptr;
108 }
109 
GetTopWindow(napi_env env,napi_callback_info info)110 napi_value JsWindowManager::GetTopWindow(napi_env env, napi_callback_info info)
111 {
112     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
113     return (me != nullptr) ? me->OnGetTopWindow(env, info) : nullptr;
114 }
115 
116 /** @note @window.hierarchy */
GetLastWindow(napi_env env,napi_callback_info info)117 napi_value JsWindowManager::GetLastWindow(napi_env env, napi_callback_info info)
118 {
119     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
120     return (me != nullptr) ? me->OnGetLastWindow(env, info) : nullptr;
121 }
122 
GetSnapshot(napi_env env,napi_callback_info info)123 napi_value JsWindowManager::GetSnapshot(napi_env env, napi_callback_info info)
124 {
125     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
126     return (me != nullptr) ? me->OnGetSnapshot(env, info) : nullptr;
127 }
128 
SetWindowLayoutMode(napi_env env,napi_callback_info info)129 napi_value JsWindowManager::SetWindowLayoutMode(napi_env env, napi_callback_info info)
130 {
131     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
132     return (me != nullptr) ? me->OnSetWindowLayoutMode(env, info) : nullptr;
133 }
134 
SetGestureNavigationEnabled(napi_env env,napi_callback_info info)135 napi_value JsWindowManager::SetGestureNavigationEnabled(napi_env env, napi_callback_info info)
136 {
137     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
138     return (me != nullptr) ? me->OnSetGestureNavigationEnabled(env, info) : nullptr;
139 }
140 
SetWaterMarkImage(napi_env env,napi_callback_info info)141 napi_value JsWindowManager::SetWaterMarkImage(napi_env env, napi_callback_info info)
142 {
143     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
144     return (me != nullptr) ? me->OnSetWaterMarkImage(env, info) : nullptr;
145 }
146 
ShiftAppWindowFocus(napi_env env,napi_callback_info info)147 napi_value JsWindowManager::ShiftAppWindowFocus(napi_env env, napi_callback_info info)
148 {
149     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
150     return (me != nullptr) ? me->OnShiftAppWindowFocus(env, info) : nullptr;
151 }
152 
GetVisibleWindowInfo(napi_env env,napi_callback_info info)153 napi_value JsWindowManager::GetVisibleWindowInfo(napi_env env, napi_callback_info info)
154 {
155     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
156     return (me != nullptr) ? me->OnGetVisibleWindowInfo(env, info) : nullptr;
157 }
158 
GetWindowsByCoordinate(napi_env env,napi_callback_info info)159 napi_value JsWindowManager::GetWindowsByCoordinate(napi_env env, napi_callback_info info)
160 {
161     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
162     return (me != nullptr) ? me->OnGetWindowsByCoordinate(env, info) : nullptr;
163 }
164 
GetNativeContext(napi_env env,napi_value nativeContext,void * & contextPtr,WMError & errCode)165 static void GetNativeContext(napi_env env, napi_value nativeContext, void*& contextPtr, WMError& errCode)
166 {
167     AppExecFwk::Ability* ability = nullptr;
168     bool isOldApi = GetAPI7Ability(env, ability);
169     WLOGFD("FA mode:%{public}u", isOldApi);
170     if (isOldApi) {
171         return;
172     }
173     if (nativeContext != nullptr) {
174         napi_unwrap(env, nativeContext, &contextPtr);
175     }
176 }
177 
GetParentId(napi_env env)178 static uint32_t GetParentId(napi_env env)
179 {
180     AppExecFwk::Ability* ability = nullptr;
181     uint32_t parentId = 0;
182     bool isOldApi = GetAPI7Ability(env, ability);
183     if (isOldApi) {
184         if (ability == nullptr) {
185             WLOGE("FA mode GetAPI7Ability failed");
186             return parentId;
187         }
188         auto window = ability->GetWindow();
189         if (window == nullptr) {
190             WLOGE("Get mainWindow failed");
191             return parentId;
192         }
193         parentId = window->GetWindowId();
194     }
195     return parentId;
196 }
197 
GetWindowTypeAndParentId(napi_env env,uint32_t & parentId,WindowType & winType,napi_value nativeString,napi_value nativeType)198 static bool GetWindowTypeAndParentId(napi_env env, uint32_t& parentId, WindowType& winType,
199     napi_value nativeString, napi_value nativeType)
200 {
201     napi_value type = nativeType;
202     if (type == nullptr) {
203         WLOGFE("Failed to convert parameter to windowType");
204         return false;
205     }
206     uint32_t resultValue = 0;
207     napi_get_value_uint32(env, type, &resultValue);
208     if (resultValue >= static_cast<uint32_t>(ApiWindowType::TYPE_BASE) &&
209         resultValue < static_cast<uint32_t>(ApiWindowType::TYPE_END)) {
210         winType = JS_TO_NATIVE_WINDOW_TYPE_MAP.at(static_cast<ApiWindowType>(resultValue));
211     } else {
212         WLOGFE("Type %{public}u is not supported", resultValue);
213         return false;
214     }
215 
216     AppExecFwk::Ability* ability = nullptr;
217     bool isOldApi = GetAPI7Ability(env, ability);
218     if (isOldApi) {
219         if (ability == nullptr || !WindowHelper::IsSubWindow(winType)) {
220             WLOGE("FA mode GetAPI7Ability failed or type %{public}u is not subWinodw", winType);
221             return false;
222         }
223         auto window = ability->GetWindow();
224         if (window == nullptr) {
225             WLOGE("Get mainWindow failed");
226             return false;
227         }
228         parentId = window->GetWindowId();
229     } else {
230         if (!WindowHelper::IsSystemWindow(winType)) {
231             WLOGFE("Only SystemWindow support create in stage mode, type is %{public}u", winType);
232             return false;
233         }
234     }
235     return true;
236 }
237 
CreateNewSystemWindowTask(void * contextPtr,sptr<WindowOption> windowOption,napi_env env,NapiAsyncTask & task)238 static void CreateNewSystemWindowTask(void* contextPtr, sptr<WindowOption> windowOption,
239     napi_env env, NapiAsyncTask& task)
240 {
241     WLOGI("CreateSystemWindowTask");
242     if (windowOption == nullptr) {
243         task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY,
244             "New window option failed"));
245         WLOGFE("New window option failed");
246         return;
247     }
248     auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(contextPtr);
249     if (contextPtr == nullptr || context == nullptr) {
250         task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_CONTEXT_ABNORMALLY,
251             "Context is nullptr"));
252         WLOGFE("Context is nullptr");
253         return;
254     }
255     if (windowOption->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT ||
256         windowOption->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) {
257         auto abilityContext = Context::ConvertTo<AbilityRuntime::AbilityContext>(context->lock());
258         if (abilityContext != nullptr) {
259             if (!CheckCallingPermission("ohos.permission.SYSTEM_FLOAT_WINDOW")) {
260                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_NO_PERMISSION,
261                     "TYPE_FLOAT CheckCallingPermission failed"));
262                 return;
263             }
264         }
265     }
266     WMError wmError = WMError::WM_OK;
267     sptr<Window> window = Window::Create(windowOption->GetWindowName(), windowOption, context->lock(), wmError);
268     WmErrorCode wmErrorCode = WM_JS_TO_ERROR_CODE_MAP.at(wmError);
269     if (window != nullptr && wmErrorCode == WmErrorCode::WM_OK) {
270         task.Resolve(env, CreateJsWindowObject(env, window));
271     } else {
272         WLOGFE("Create window failed");
273         task.Reject(env, JsErrUtils::CreateJsError(env, wmErrorCode, "Create window failed"));
274     }
275 }
276 
CreateSystemWindowTask(void * contextPtr,std::string windowName,WindowType winType,napi_env env,NapiAsyncTask & task)277 static void CreateSystemWindowTask(void* contextPtr, std::string windowName, WindowType winType,
278     napi_env env, NapiAsyncTask& task)
279 {
280     WLOGFD("CreateSystemWindowTask");
281     auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(contextPtr);
282     if (contextPtr == nullptr || context == nullptr) {
283         task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "Context is nullptr"));
284         WLOGFE("Context is nullptr");
285         return;
286     }
287     if (winType == WindowType::WINDOW_TYPE_FLOAT || winType == WindowType::WINDOW_TYPE_FLOAT_CAMERA) {
288         auto abilityContext = Context::ConvertTo<AbilityRuntime::AbilityContext>(context->lock());
289         if (abilityContext != nullptr) {
290             if (!CheckCallingPermission("ohos.permission.SYSTEM_FLOAT_WINDOW")) {
291                 task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_INVALID_PERMISSION,
292                     "TYPE_FLOAT CheckCallingPermission failed"));
293                 return;
294             }
295         }
296     }
297     sptr<WindowOption> windowOption = new(std::nothrow) WindowOption();
298     if (windowOption == nullptr) {
299         task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "New window option failed"));
300         WLOGFE("New window option failed");
301         return;
302     }
303     windowOption->SetWindowType(winType);
304     WMError wmError = WMError::WM_OK;
305     sptr<Window> window = Window::Create(windowName, windowOption, context->lock(), wmError);
306     WmErrorCode wmErrorCode = WM_JS_TO_ERROR_CODE_MAP.at(wmError);
307     if (window != nullptr && wmErrorCode == WmErrorCode::WM_OK) {
308         task.Resolve(env, CreateJsWindowObject(env, window));
309     } else {
310         WLOGFE("Create window failed");
311         task.Reject(env, JsErrUtils::CreateJsError(env, wmErrorCode, "Create window failed"));
312     }
313 }
314 
CreateNewSubWindowTask(sptr<WindowOption> windowOption,napi_env env,NapiAsyncTask & task)315 static void CreateNewSubWindowTask(sptr<WindowOption> windowOption, napi_env env, NapiAsyncTask& task)
316 {
317     if (windowOption == nullptr) {
318         task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY,
319             "New window option failed"));
320         WLOGFE("New window option failed");
321         return;
322     }
323     windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING);
324     if (windowOption->GetParentId() == INVALID_WINDOW_ID) {
325         uint32_t parentId = GetParentId(env);
326         if (!parentId) {
327             task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
328                 "parent window missed"));
329             WLOGFE("can not find parent window");
330             return;
331         }
332         windowOption->SetParentId(parentId);
333     }
334     sptr<Window> window = Window::Create(windowOption->GetWindowName(), windowOption);
335     if (window != nullptr) {
336         task.Resolve(env, CreateJsWindowObject(env, window));
337     } else {
338         WLOGFE("Create window failed");
339         task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
340             "Create window failed"));
341     }
342 }
343 
CreateSubWindowTask(uint32_t parentWinId,std::string windowName,WindowType winType,napi_env env,NapiAsyncTask & task,bool newErrorCode=false)344 static void CreateSubWindowTask(uint32_t parentWinId, std::string windowName, WindowType winType,
345     napi_env env, NapiAsyncTask& task, bool newErrorCode = false)
346 {
347     WLOGI("CreateSubWindowTask, parent id = %{public}u", parentWinId);
348     sptr<WindowOption> windowOption = new(std::nothrow) WindowOption();
349     if (windowOption == nullptr) {
350         if (newErrorCode) {
351             task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY,
352                 "New window option failed"));
353         } else {
354             task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "New window option failed"));
355         }
356         WLOGFE("New window option failed");
357         return;
358     }
359     windowOption->SetWindowType(winType);
360     windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING);
361     windowOption->SetParentId(parentWinId);
362     sptr<Window> window = Window::Create(windowName, windowOption);
363     if (window != nullptr) {
364         task.Resolve(env, CreateJsWindowObject(env, window));
365     } else {
366         WLOGFE("Create window failed");
367         if (newErrorCode) {
368             task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
369                 "Create window failed"));
370         } else {
371             task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "Create window failed"));
372         }
373     }
374 }
375 
isConfigOptionWindowTypeValid(napi_env env,WindowOption & option)376 static bool isConfigOptionWindowTypeValid(napi_env env, WindowOption& option)
377 {
378     WindowType type = option.GetWindowType();
379     AppExecFwk::Ability* ability = nullptr;
380     bool isOldApi = GetAPI7Ability(env, ability);
381     if (isOldApi) {
382         if (ability == nullptr || !WindowHelper::IsSubWindow(type)) {
383             WLOGE("FA mode GetAPI7Ability failed or convert parameter to invalid winType %{public}u", type);
384             return false;
385         }
386     } else {
387         if (!WindowHelper::IsSystemWindow(type)) {
388             WLOGFE("Stage mode convert parameter to invalid winType %{public}u", type);
389             return false;
390         }
391     }
392 
393     return true;
394 }
395 
OnCreate(napi_env env,napi_callback_info info)396 napi_value JsWindowManager::OnCreate(napi_env env, napi_callback_info info)
397 {
398     WLOGFD("OnCreate");
399     napi_value nativeString = nullptr, nativeContext = nullptr, nativeType = nullptr, callback = nullptr;
400     size_t argc = 4;
401     napi_value argv[4] = {nullptr};
402     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
403     if (argc >= 2 && GetType(env, argv[0]) == napi_string) { // 2: minimum params num
404         nativeString = argv[0];
405         nativeType = argv[1];
406         callback = (argc == 2) ? nullptr : (GetType(env, argv[2]) == napi_function ? argv[2] : nullptr); // 2: index
407     } else if (argc >= 3) { // 3: minimum params num
408         nativeContext = GetType(env, argv[0]) == napi_object ? argv[0] : nullptr;
409         nativeString = argv[1];
410         nativeType = argv[2]; // 2: index of type
411         callback = (argc == 3) ? nullptr : (GetType(env, argv[3]) == napi_function ? argv[3] : nullptr); // 3: index
412     }
413     std::string windowName;
414     WMError errCode = WMError::WM_OK;
415     if (!ConvertFromJsValue(env, nativeString, windowName)) {
416         WLOGFE("Failed to convert parameter to windowName");
417         errCode = WMError::WM_ERROR_INVALID_PARAM;
418     }
419     uint32_t parentId = INVALID_WINDOW_ID;
420     WindowType winType = WindowType::SYSTEM_WINDOW_BASE;
421     if (errCode == WMError::WM_OK &&
422         !GetWindowTypeAndParentId(env, parentId, winType, nativeString, nativeType)) {
423         errCode = WMError::WM_ERROR_INVALID_PARAM;
424     }
425     void* contextPtr = nullptr;
426     GetNativeContext(env, nativeContext, contextPtr, errCode);
427 
428     WLOGFD("Window name = %{public}s, type = %{public}u, err = %{public}d", windowName.c_str(), winType, errCode);
429     NapiAsyncTask::CompleteCallback complete =
430         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
431             if (errCode != WMError::WM_OK) {
432                 task.Reject(env, JsErrUtils::CreateJsError(env, errCode, "Invalidate params"));
433                 return;
434             }
435             if (parentId == INVALID_WINDOW_ID) {
436                 return CreateSystemWindowTask(contextPtr, windowName, winType, env, task);
437             } else {
438                 return CreateSubWindowTask(parentId, windowName, winType, env, task);
439             }
440         };
441     napi_value result = nullptr;
442     NapiAsyncTask::Schedule("JsWindowManager::OnCreate", env,
443         CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
444     return result;
445 }
446 
ParseRequiredConfigOption(napi_env env,napi_value jsObject,WindowOption & option)447 bool JsWindowManager::ParseRequiredConfigOption(napi_env env, napi_value jsObject,
448     WindowOption& option)
449 {
450     std::string windowName;
451     if (ParseJsValue(jsObject, env, "name", windowName)) {
452         option.SetWindowName(windowName);
453     } else {
454         WLOGFE("Failed to convert parameter to windowName");
455         return false;
456     }
457 
458     uint32_t winType;
459     if (ParseJsValue(jsObject, env, "windowType", winType)) {
460         if (winType >= static_cast<uint32_t>(ApiWindowType::TYPE_BASE) &&
461             winType < static_cast<uint32_t>(ApiWindowType::TYPE_END)) {
462             option.SetWindowType(JS_TO_NATIVE_WINDOW_TYPE_MAP.at(static_cast<ApiWindowType>(winType)));
463         } else {
464             TLOGE(WmsLogTag::DEFAULT, "Invalid winType");
465             return false;
466         }
467     } else {
468         WLOGFE("Failed to convert parameter to winType");
469         return false;
470     }
471     return true;
472 }
473 
ParseConfigOption(napi_env env,napi_value jsObject,WindowOption & option,void * & contextPtr)474 bool JsWindowManager::ParseConfigOption(napi_env env, napi_value jsObject,
475     WindowOption& option, void*& contextPtr)
476 {
477     if (!ParseRequiredConfigOption(env, jsObject, option)) {
478         return false;
479     }
480     if (!isConfigOptionWindowTypeValid(env, option)) {
481         return false;
482     }
483     napi_value value = nullptr;
484     napi_get_named_property(env, jsObject, "ctx", &value);
485     if (GetType(env, value) == napi_undefined) {
486         return true;
487     }
488     WMError errCode = WMError::WM_OK;
489     GetNativeContext(env, value, contextPtr, errCode);
490     if (errCode != WMError::WM_OK) {
491         return false;
492     }
493 
494     bool dialogDecorEnable = false;
495     if (ParseJsValue(jsObject, env, "decorEnabled", dialogDecorEnable)) {
496         option.SetDialogDecorEnable(dialogDecorEnable);
497     }
498 
499     std::string dialogTitle;
500     if (ParseJsValue(jsObject, env, "title", dialogTitle)) {
501         option.SetDialogTitle(dialogTitle);
502     }
503 
504     int64_t displayId = static_cast<int64_t>(DISPLAY_ID_INVALID);
505     if (ParseJsValue(jsObject, env, "displayId", displayId)) {
506         if (displayId < 0 ||
507             SingletonContainer::Get<DisplayManager>().GetDisplayById(static_cast<uint64_t>(displayId)) == nullptr) {
508             return false;
509         }
510         option.SetDisplayId(displayId);
511     } else {
512         return true;
513     }
514 
515     int64_t parentId = -1;
516     if (ParseJsValue(jsObject, env, "parentId", parentId)) {
517         option.SetParentId(parentId);
518     }
519 
520     return true;
521 }
522 
OnCreateWindow(napi_env env,napi_callback_info info)523 napi_value JsWindowManager::OnCreateWindow(napi_env env, napi_callback_info info)
524 {
525     WLOGFD("Called");
526     size_t argc = 4;
527     napi_value argv[4] = {nullptr};
528     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
529     if (argc < 1) {
530         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
531         return NapiGetUndefined(env);
532     }
533     napi_value nativeObj = argv[0];
534     if (nativeObj == nullptr) {
535         WLOGFE("Failed to convert object to CreateWindow");
536         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
537         return NapiGetUndefined(env);
538     }
539     WindowOption option;
540     void* contextPtr = nullptr;
541     if (!ParseConfigOption(env, nativeObj, option, contextPtr)) {
542         WLOGFE("Failed to parse config");
543         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
544         return NapiGetUndefined(env);
545     }
546     napi_value callback = nullptr;
547     if (argc > 1) {
548         callback = GetType(env, argv[1]) == napi_function ? argv[1] : nullptr; // 1: index of callback
549     }
550     NapiAsyncTask::CompleteCallback complete =
551         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
552             sptr<WindowOption> windowOption = new WindowOption(option);
553             if (WindowHelper::IsSystemWindow(option.GetWindowType())) {
554                 return CreateNewSystemWindowTask(contextPtr, windowOption, env, task);
555             }
556             if (WindowHelper::IsSubWindow(option.GetWindowType())) {
557                 return CreateNewSubWindowTask(windowOption, env, task);
558             }
559         };
560 
561     napi_value result = nullptr;
562     NapiAsyncTask::Schedule("JsWindowManager::OnCreateWindow", env,
563         CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
564     return result;
565 }
566 
OnGetSnapshot(napi_env env,napi_callback_info info)567 napi_value JsWindowManager::OnGetSnapshot(napi_env env, napi_callback_info info)
568 {
569     constexpr int maxArgumentsNum = 4;
570     size_t argc = maxArgumentsNum;
571     napi_value argv[maxArgumentsNum] = {nullptr};
572     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
573     if (argc != 1) {
574         TLOGE(WmsLogTag::WMS_SYSTEM, "[NAPI]Argc is invalid:%{public}zu", argc);
575         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
576         return NapiGetUndefined(env);
577     }
578     int32_t windowId = 0;
579     if (!ConvertFromJsValue(env, argv[0], windowId)) {
580         TLOGE(WmsLogTag::WMS_SYSTEM, "[NAPI]Failed to convert parameter to integer");
581         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
582         return NapiGetUndefined(env);
583     }
584     std::shared_ptr<WindowSnapshotDataPack> dataPack = std::make_shared<WindowSnapshotDataPack>();
585     NapiAsyncTask::ExecuteCallback execute = [dataPack, windowId]() {
586         dataPack->result = SingletonContainer::Get<WindowManager>()
587             .GetSnapshotByWindowId(windowId, dataPack->pixelMap);
588     };
589     NapiAsyncTask::CompleteCallback complete =
590         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
591             if (dataPack->result != WMError::WM_OK) {
592                 task.Reject(env, JsErrUtils::CreateJsError(env, WM_JS_TO_ERROR_CODE_MAP.at(dataPack->result)));
593                 TLOGW(WmsLogTag::WMS_SYSTEM, "[NAPI]Get snapshot not ok!");
594                 return;
595             }
596             if (dataPack->pixelMap == nullptr) {
597                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY));
598                 TLOGE(WmsLogTag::WMS_SYSTEM, "[NAPI]Get snapshot is nullptr!");
599                 return;
600             }
601             auto nativePixelMap = Media::PixelMapNapi::CreatePixelMap(env, dataPack->pixelMap);
602             if (nativePixelMap == nullptr) {
603                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY));
604                 TLOGE(WmsLogTag::WMS_SYSTEM, "[NAPI]Create native pixelmap is nullptr!");
605                 return;
606             }
607             task.Resolve(env, nativePixelMap);
608         };
609     napi_value lastParam = (argc <= 1) ? nullptr : argv[0];
610     napi_value result = nullptr;
611     NapiAsyncTask::Schedule("JsWindowManager::OnGetSnapshot",
612         env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
613     return result;
614 }
615 
OnFindWindow(napi_env env,napi_callback_info info)616 napi_value JsWindowManager::OnFindWindow(napi_env env, napi_callback_info info)
617 {
618     WLOGFD("OnFindWindow");
619     std::string windowName;
620     WMError errCode = WMError::WM_OK;
621     size_t argc = 4;
622     napi_value argv[4] = {nullptr};
623     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
624     if (argc < 1 || argc > 2) { // 2: maximum params num
625         WLOGFE("Argc is invalid: %{public}zu", argc);
626         errCode = WMError::WM_ERROR_INVALID_PARAM;
627     } else {
628         if (!ConvertFromJsValue(env, argv[0], windowName)) {
629             WLOGFE("Failed to convert parameter to windowName");
630             errCode = WMError::WM_ERROR_INVALID_PARAM;
631         }
632     }
633     if (windowName.compare(PIP_WINDOW) == 0) {
634         errCode = WMError::WM_ERROR_INVALID_PARAM;
635     }
636     WLOGI("Window name = %{public}s, err = %{public}d", windowName.c_str(), errCode);
637     NapiAsyncTask::CompleteCallback complete =
638         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
639             if (errCode != WMError::WM_OK) {
640                 task.Reject(env, JsErrUtils::CreateJsError(env, errCode, "Invalidate params"));
641                 return;
642             }
643             HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WM:Find %s", windowName.c_str());
644             std::shared_ptr<NativeReference> jsWindowObj = FindJsWindowObject(windowName);
645             if (jsWindowObj != nullptr && jsWindowObj->GetNapiValue() != nullptr) {
646                 WLOGI("Find window: %{public}s, use exist js window", windowName.c_str());
647                 task.Resolve(env, jsWindowObj->GetNapiValue());
648             } else {
649                 sptr<Window> window = Window::Find(windowName);
650                 if (window == nullptr) {
651                     WLOGFE("Cannot find window: %{public}s", windowName.c_str());
652                     task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "Cannot find window"));
653                 } else {
654                     task.Resolve(env, CreateJsWindowObject(env, window));
655                     WLOGI("Find window: %{public}s, create js window", windowName.c_str());
656                 }
657             }
658         };
659 
660     napi_value lastParam = (argc <= 1) ? nullptr :
661         (GetType(env, argv[1]) == napi_function ? argv[1] : nullptr);
662     napi_value result = nullptr;
663     NapiAsyncTask::Schedule("JsWindowManager::OnFindWindow",
664         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
665     return result;
666 }
667 
OnFindWindowSync(napi_env env,napi_callback_info info)668 napi_value JsWindowManager::OnFindWindowSync(napi_env env, napi_callback_info info)
669 {
670     WLOGFD("OnFindWindowSync");
671     std::string windowName;
672     WmErrorCode errCode = WmErrorCode::WM_OK;
673     size_t argc = 4;
674     napi_value argv[4] = {nullptr};
675     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
676     if (argc < 1) { // 1: params num
677         WLOGFE("Argc is invalid: %{public}zu", argc);
678         errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
679     } else {
680         if (!ConvertFromJsValue(env, argv[0], windowName)) {
681             WLOGFE("Failed to convert parameter to windowName");
682             errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
683         }
684     }
685     if (windowName.compare(PIP_WINDOW) == 0) {
686         errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
687     }
688     if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) {
689         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
690         return NapiGetUndefined(env);
691     }
692 
693     WLOGD("Window name = %{public}s, err = %{public}d", windowName.c_str(), errCode);
694     std::shared_ptr<NativeReference> jsWindowObj = FindJsWindowObject(windowName);
695     if (jsWindowObj != nullptr && jsWindowObj->GetNapiValue() != nullptr) {
696         WLOGD("Find window: %{public}s, use exist js window", windowName.c_str());
697         return jsWindowObj->GetNapiValue();
698     } else {
699         sptr<Window> window = Window::Find(windowName);
700         if (window == nullptr) {
701             napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY));
702             return NapiGetUndefined(env);
703         } else {
704             return CreateJsWindowObject(env, window);
705         }
706     }
707 }
708 
OnMinimizeAll(napi_env env,napi_callback_info info)709 napi_value JsWindowManager::OnMinimizeAll(napi_env env, napi_callback_info info)
710 {
711     WLOGI("OnMinimizeAll");
712     WmErrorCode errCode = WmErrorCode::WM_OK;
713     size_t argc = 4;
714     napi_value argv[4] = {nullptr};
715     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
716     if (argc < 1) {
717         WLOGFE("Argc is invalid: %{public}zu", argc);
718         errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
719     }
720     int64_t displayId = static_cast<int64_t>(DISPLAY_ID_INVALID);
721     if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(env, argv[0], displayId)) {
722         WLOGFE("Failed to convert parameter to displayId");
723         errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
724     }
725     if (displayId < 0 ||
726         SingletonContainer::Get<DisplayManager>().GetDisplayById(static_cast<uint64_t>(displayId)) == nullptr) {
727         errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
728     }
729     if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) {
730         WLOGFE("JsWindowManager::OnMinimizeAll failed, Invalidate params.");
731         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
732         return NapiGetUndefined(env);
733     }
734 
735     WLOGI("Display id = %{public}" PRIu64", err = %{public}d", static_cast<uint64_t>(displayId), errCode);
736     NapiAsyncTask::CompleteCallback complete =
737         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
738             HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WM:MinimizeAll: " PRIu64"",
739                 static_cast<uint64_t>(displayId));
740             WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(
741                 SingletonContainer::Get<WindowManager>().MinimizeAllAppWindows(static_cast<uint64_t>(displayId)));
742             if (ret == WmErrorCode::WM_OK) {
743                 task.Resolve(env, NapiGetUndefined(env));
744                 WLOGFI("OnMinimizeAll success");
745             } else {
746                 task.Reject(env, JsErrUtils::CreateJsError(env, ret, "OnMinimizeAll failed"));
747             }
748         };
749     napi_value lastParam = (argc <= 1) ? nullptr :
750         ((argv[1] != nullptr && GetType(env, argv[1]) == napi_function) ? argv[1] : nullptr);
751     napi_value result = nullptr;
752     NapiAsyncTask::Schedule("JsWindowManager::OnMinimizeAll",
753         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
754     return result;
755 }
756 
OnToggleShownStateForAllAppWindows(napi_env env,napi_callback_info info)757 napi_value JsWindowManager::OnToggleShownStateForAllAppWindows(napi_env env, napi_callback_info info)
758 {
759     WLOGI("OnToggleShownStateForAllAppWindows");
760     NapiAsyncTask::CompleteCallback complete =
761         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
762             WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(
763                 SingletonContainer::Get<WindowManager>().ToggleShownStateForAllAppWindows());
764             if (ret == WmErrorCode::WM_OK) {
765                 task.Resolve(env, NapiGetUndefined(env));
766                 WLOGI("OnToggleShownStateForAllAppWindows success");
767             } else {
768                 task.Reject(env, JsErrUtils::CreateJsError(env, ret, "OnToggleShownStateForAllAppWindows failed"));
769             }
770         };
771     size_t argc = 4;
772     napi_value argv[4] = {nullptr};
773     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
774     napi_value lastParam = (argc == 0) ? nullptr :
775         (GetType(env, argv[0]) == napi_function ? argv[0] : nullptr);
776     napi_value result = nullptr;
777     NapiAsyncTask::Schedule("JsWindowManager::OnToggleShownStateForAllAppWindows",
778         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
779     return result;
780 }
781 
OnRegisterWindowManagerCallback(napi_env env,napi_callback_info info)782 napi_value JsWindowManager::OnRegisterWindowManagerCallback(napi_env env, napi_callback_info info)
783 {
784     WLOGFD("OnRegisterWindowManagerCallback");
785     size_t argc = 4;
786     napi_value argv[4] = {nullptr};
787     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
788     if (argc < 2) { // 2: params num
789         WLOGFE("Argc is invalid: %{public}zu", argc);
790         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
791         return NapiGetUndefined(env);
792     }
793     std::string cbType;
794     if (!ConvertFromJsValue(env, argv[0], cbType)) {
795         WLOGFE("Failed to convert parameter to callbackType");
796         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
797         return NapiGetUndefined(env);
798     }
799     napi_value value = argv[1];
800     if (!NapiIsCallable(env, value)) {
801         WLOGI("Callback(argv[1]) is not callable");
802         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
803         return NapiGetUndefined(env);
804     }
805 
806     WmErrorCode ret = registerManager_->RegisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, env, value);
807     if (ret != WmErrorCode::WM_OK) {
808         napi_throw(env, JsErrUtils::CreateJsError(env, ret));
809         return NapiGetUndefined(env);
810     }
811     WLOGI("Register end, type = %{public}s", cbType.c_str());
812     return NapiGetUndefined(env);
813 }
814 
OnUnregisterWindowManagerCallback(napi_env env,napi_callback_info info)815 napi_value JsWindowManager::OnUnregisterWindowManagerCallback(napi_env env, napi_callback_info info)
816 {
817     WLOGFD("OnUnregisterWindowManagerCallback");
818     size_t argc = 4;
819     napi_value argv[4] = {nullptr};
820     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
821     if (argc < 1) {
822         WLOGFE("Argc is invalid: %{public}zu", argc);
823         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
824         return NapiGetUndefined(env);
825     }
826     std::string cbType;
827     if (!ConvertFromJsValue(env, argv[0], cbType)) {
828         WLOGFE("Failed to convert parameter to callbackType");
829         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
830         return NapiGetUndefined(env);
831     }
832 
833     napi_value value = nullptr;
834     WmErrorCode ret = WmErrorCode::WM_OK;
835     if (argc == 1) {
836         ret = registerManager_->UnregisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, env, value);
837     } else {
838         value = argv[1];
839         if ((value == nullptr) || (!NapiIsCallable(env, value))) {
840             ret = registerManager_->UnregisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, env, nullptr);
841         } else {
842             ret = registerManager_->UnregisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, env, value);
843         }
844     }
845     if (ret != WmErrorCode::WM_OK) {
846         napi_throw(env, JsErrUtils::CreateJsError(env, ret));
847         return NapiGetUndefined(env);
848     }
849     WLOGI("Unregister end, type = %{public}s", cbType.c_str());
850     return NapiGetUndefined(env);
851 }
852 
GetTopWindowTask(void * contextPtr,napi_env env,napi_value callback,bool newApi)853 static napi_value GetTopWindowTask(void* contextPtr, napi_env env, napi_value callback, bool newApi)
854 {
855     struct TopWindowInfoList {
856         sptr<Window> window = nullptr;
857         AppExecFwk::Ability* ability = nullptr;
858         int32_t errorCode = 0;
859         std::string errMsg = "";
860     };
861     std::shared_ptr<TopWindowInfoList> lists = std::make_shared<TopWindowInfoList>();
862     bool isOldApi = GetAPI7Ability(env, lists->ability);
863     NapiAsyncTask::ExecuteCallback execute = [lists, isOldApi, newApi, contextPtr]() {
864         if (lists == nullptr) {
865             return;
866         }
867         if (isOldApi) {
868             if (lists->ability->GetWindow() == nullptr) {
869                 lists->errorCode = newApi ? static_cast<int32_t>(WmErrorCode::WM_ERROR_STATE_ABNORMALLY) :
870                     static_cast<int32_t>(WMError::WM_ERROR_NULLPTR);
871                 lists->errMsg = "FA mode can not get ability window";
872                 return;
873             }
874             lists->window = Window::GetTopWindowWithId(lists->ability->GetWindow()->GetWindowId());
875         } else {
876             auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(contextPtr);
877             if (contextPtr == nullptr || context == nullptr) {
878                 lists->errorCode = newApi ? static_cast<int32_t>(WmErrorCode::WM_ERROR_STATE_ABNORMALLY) :
879                     static_cast<int32_t>(WMError::WM_ERROR_NULLPTR);
880                 lists->errMsg = "Stage mode without context";
881                 return;
882             }
883             lists->window = Window::GetTopWindowWithContext(context->lock());
884         }
885     };
886     NapiAsyncTask::CompleteCallback complete = [lists, newApi](napi_env env, NapiAsyncTask& task, int32_t status) {
887         if (lists == nullptr) {
888             if (newApi) {
889                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
890                     "napi abnormal"));
891             } else {
892                 task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "napi abnormal"));
893             }
894             return;
895         }
896         if (lists->errorCode != 0) {
897             if (newApi) {
898                 task.Reject(env, JsErrUtils::CreateJsError(env, static_cast<WmErrorCode>(lists->errorCode),
899                     lists->errMsg));
900             } else {
901                 task.Reject(env, JsErrUtils::CreateJsError(env, static_cast<WMError>(lists->errorCode),
902                     lists->errMsg));
903             }
904             WLOGFE("%{public}s", lists->errMsg.c_str());
905             return;
906         }
907         if (lists->window == nullptr || lists->window->GetWindowState() == WindowState::STATE_DESTROYED) {
908             if (newApi) {
909                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
910                     "Get top window failed"));
911             } else {
912                 task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR,
913                     "Get top window failed"));
914             }
915             return;
916         }
917         task.Resolve(env, CreateJsWindowObject(env, lists->window));
918         WLOGD("Get top window success");
919     };
920     napi_value result = nullptr;
921     NapiAsyncTask::Schedule("JsWindowManager::OnGetTopWindow",
922         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
923     return result;
924 }
925 
OnGetTopWindow(napi_env env,napi_callback_info info)926 napi_value JsWindowManager::OnGetTopWindow(napi_env env, napi_callback_info info)
927 {
928     WLOGFD("OnGetTopWindow");
929     WMError errCode = WMError::WM_OK;
930     napi_value nativeContext = nullptr;
931     napi_value nativeCallback = nullptr;
932     void* contextPtr = nullptr;
933     size_t argc = 4;
934     napi_value argv[4] = {nullptr};
935     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
936     if (argc > 2) { // 2: maximum params num
937         WLOGFE("Argc is invalid: %{public}zu", argc);
938         errCode = WMError::WM_ERROR_INVALID_PARAM;
939     } else {
940         if (argc > 0 && GetType(env, argv[0]) == napi_object) { // (context, callback?)
941             nativeContext = argv[0];
942             nativeCallback = (argc == 1) ? nullptr :
943                 (GetType(env, argv[1]) == napi_function ? argv[1] : nullptr);
944         } else { // (callback?)
945             nativeCallback = (argc == 0) ? nullptr :
946                 (GetType(env, argv[0]) == napi_function ? argv[0] : nullptr);
947         }
948         GetNativeContext(env, nativeContext, contextPtr, errCode);
949     }
950     return GetTopWindowTask(contextPtr, env, nativeCallback, false);
951 }
952 
OnGetLastWindow(napi_env env,napi_callback_info info)953 napi_value JsWindowManager::OnGetLastWindow(napi_env env, napi_callback_info info)
954 {
955     WLOGFD("OnGetLastWindow");
956     WMError errCode = WMError::WM_OK;
957     napi_value nativeContext = nullptr;
958     napi_value nativeCallback = nullptr;
959     void* contextPtr = nullptr;
960     size_t argc = 4;
961     napi_value argv[4] = {nullptr};
962     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
963     if (argc < 1) {
964         WLOGFE("Argc is invalid: %{public}zu", argc);
965         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
966         return NapiGetUndefined(env);
967     } else {
968         nativeContext = argv[0];
969         nativeCallback = (argc == 1) ? nullptr : argv[1];
970         GetNativeContext(env, nativeContext, contextPtr, errCode);
971     }
972     if (errCode != WMError::WM_OK) {
973         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
974         return NapiGetUndefined(env);
975     }
976 
977     return GetTopWindowTask(contextPtr, env, nativeCallback, true);
978 }
979 
OnSetWindowLayoutMode(napi_env env,napi_callback_info info)980 napi_value JsWindowManager::OnSetWindowLayoutMode(napi_env env, napi_callback_info info)
981 {
982     WLOGFD("OnSetWindowLayoutMode");
983     WmErrorCode errCode = WmErrorCode::WM_OK;
984     size_t argc = 4;
985     napi_value argv[4] = {nullptr};
986     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
987     if (argc < 1) { // 1: minimum params num
988         TLOGE(WmsLogTag::WMS_LAYOUT, "Argc is invalid: %{public}zu", argc);
989         errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
990     }
991     WindowLayoutMode winLayoutMode = WindowLayoutMode::CASCADE;
992     if (!Permission::IsSystemCalling() && !Permission::IsStartByHdcd()) {
993         TLOGE(WmsLogTag::WMS_LAYOUT, "set window layout mode permission denied!");
994         return NapiThrowError(env, WmErrorCode::WM_ERROR_NOT_SYSTEM_APP);
995     }
996     if (errCode == WmErrorCode::WM_OK) {
997         napi_value nativeMode = argv[0];
998         if (nativeMode == nullptr) {
999             TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to convert parameter to windowLayoutMode");
1000             errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
1001         } else {
1002             uint32_t resultValue = 0;
1003             napi_get_value_uint32(env, nativeMode, &resultValue);
1004             winLayoutMode = static_cast<WindowLayoutMode>(resultValue);
1005         }
1006     }
1007     if (winLayoutMode != WindowLayoutMode::CASCADE && winLayoutMode != WindowLayoutMode::TILE) {
1008         errCode = WmErrorCode::WM_ERROR_INVALID_PARAM;
1009     }
1010     if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) {
1011         TLOGE(WmsLogTag::WMS_LAYOUT, "JsWindowManager::OnSetWindowLayoutMode failed, Invalidate params.");
1012         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
1013         return NapiGetUndefined(env);
1014     }
1015 
1016     WLOGI("LayoutMode = %{public}u, err = %{public}d", winLayoutMode, errCode);
1017     NapiAsyncTask::CompleteCallback complete =
1018         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
1019             WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(
1020                 SingletonContainer::Get<WindowManager>().SetWindowLayoutMode(winLayoutMode));
1021             if (ret == WmErrorCode::WM_OK) {
1022                 task.Resolve(env, NapiGetUndefined(env));
1023                 WLOGD("SetWindowLayoutMode success");
1024             } else {
1025                 task.Reject(env, JsErrUtils::CreateJsError(env, ret, "SetWindowLayoutMode failed"));
1026             }
1027         };
1028     // 1: maximum params num; 1: index of callback
1029     napi_value lastParam = (argc <= 1) ? nullptr :
1030         ((argv[1] != nullptr && GetType(env, argv[1]) == napi_function) ? argv[1] : nullptr);
1031     napi_value result = nullptr;
1032     NapiAsyncTask::Schedule("JsWindowManager::OnSetWindowLayoutMode",
1033         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1034     return result;
1035 }
1036 
OnSetGestureNavigationEnabled(napi_env env,napi_callback_info info)1037 napi_value JsWindowManager::OnSetGestureNavigationEnabled(napi_env env, napi_callback_info info)
1038 {
1039     WLOGFD("OnSetGestureNavigationEnabled");
1040     size_t argc = 4;
1041     napi_value argv[4] = {nullptr};
1042     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1043     if (argc < 1) { // 1: minimum params num
1044         WLOGFE("Argc is invalid: %{public}zu", argc);
1045         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
1046         return NapiGetUndefined(env);
1047     }
1048 
1049     napi_value nativeBool = argv[0];
1050     if (nativeBool == nullptr) {
1051         WLOGFE("Failed to convert parameter to bool");
1052         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
1053         return NapiGetUndefined(env);
1054     }
1055     bool gestureNavigationEnable = false;
1056     napi_get_value_bool(env, nativeBool, &gestureNavigationEnable);
1057 
1058     WLOGI("Set gesture navigation enable as %{public}d", gestureNavigationEnable);
1059     NapiAsyncTask::CompleteCallback complete =
1060         [gestureNavigationEnable](napi_env env, NapiAsyncTask& task, int32_t status) {
1061             WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(
1062                 SingletonContainer::Get<WindowManager>().SetGestureNavigaionEnabled(gestureNavigationEnable));
1063             if (ret == WmErrorCode::WM_OK) {
1064                 task.Resolve(env, NapiGetUndefined(env));
1065                 WLOGD("SetGestureNavigationEnabled success");
1066             } else {
1067                 task.Reject(env, JsErrUtils::CreateJsError(env, ret, "SetGestureNavigationEnabled failed"));
1068             }
1069         };
1070     // 1: maximum params num; 1: index of callback
1071     napi_value lastParam = (argc <= 1) ? nullptr :
1072         ((argv[1] != nullptr && GetType(env, argv[1]) == napi_function) ? argv[1] : nullptr);
1073     napi_value result = nullptr;
1074     NapiAsyncTask::Schedule("JsWindowManager::OnSetGestureNavigationEnabled",
1075         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1076     return result;
1077 }
1078 
OnSetWaterMarkImage(napi_env env,napi_callback_info info)1079 napi_value JsWindowManager::OnSetWaterMarkImage(napi_env env, napi_callback_info info)
1080 {
1081     WLOGFD("OnSetWaterMarkImage");
1082     napi_value nativeObject = nullptr;
1083     napi_value nativeBoolean = nullptr;
1084     size_t argc = 4;
1085     napi_value argv[4] = {nullptr};
1086     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1087     if (argc < 2) { // 2: params num
1088         WLOGFE("Argc is invalid: %{public}zu", argc);
1089         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
1090         return NapiGetUndefined(env);
1091     } else {
1092         if (argc > 0 && GetType(env, argv[0]) == napi_object) {
1093             nativeObject = argv[0];
1094             nativeBoolean = (GetType(env, argv[1]) == napi_boolean ? argv[1] : nullptr);
1095         }
1096     }
1097 
1098     std::shared_ptr<Media::PixelMap> pixelMap;
1099     pixelMap = OHOS::Media::PixelMapNapi::GetPixelMap(env, nativeObject);
1100     if (pixelMap == nullptr) {
1101         WLOGFE("Failed to convert parameter to PixelMap");
1102         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
1103         return NapiGetUndefined(env);
1104     }
1105 
1106     if (nativeBoolean == nullptr) {
1107         WLOGFE("Failed to convert parameter to bool");
1108         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
1109         return NapiGetUndefined(env);
1110     }
1111     bool isShow = false;
1112     napi_get_value_bool(env, nativeBoolean, &isShow);
1113     if (!Permission::IsSystemCalling()) {
1114         WLOGFE("set watermark image permission denied!");
1115         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_NOT_SYSTEM_APP));
1116         return NapiGetUndefined(env);
1117     }
1118 
1119     NapiAsyncTask::CompleteCallback complete =
1120         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
1121             RSInterfaces::GetInstance().ShowWatermark(pixelMap, isShow);
1122             task.Resolve(env, NapiGetUndefined(env));
1123             WLOGD("OnSetWaterMarkImage success");
1124         };
1125     // 2: maximum params num; 2: index of callback
1126     napi_value lastParam = (argc <= 2) ? nullptr :
1127         (GetType(env, argv[2]) == napi_function ? argv[2] : nullptr);
1128     napi_value result = nullptr;
1129     NapiAsyncTask::Schedule("JsWindowManager::OnSetWaterMarkImage",
1130         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1131     return result;
1132 }
1133 
OnShiftAppWindowFocus(napi_env env,napi_callback_info info)1134 napi_value JsWindowManager::OnShiftAppWindowFocus(napi_env env, napi_callback_info info)
1135 {
1136     WLOGFD("OnShiftAppWindowFocus");
1137     WMError errCode = WMError::WM_OK;
1138     size_t argc = 4;
1139     napi_value argv[4] = {nullptr};
1140     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1141     if (argc != 2) { // 2: params num
1142         WLOGFE("Argc is invalid: %{public}zu", argc);
1143         errCode = WMError::WM_ERROR_INVALID_PARAM;
1144     }
1145     int32_t sourcePersistentId = static_cast<int32_t>(INVALID_WINDOW_ID);
1146     int32_t targetPersistentId = static_cast<int32_t>(INVALID_WINDOW_ID);
1147     if (errCode == WMError::WM_OK && !ConvertFromJsValue(env, argv[0], sourcePersistentId)) {
1148         WLOGFE("Failed to convert parameter to source window Id");
1149         errCode = WMError::WM_ERROR_INVALID_PARAM;
1150     }
1151     if (errCode == WMError::WM_OK && !ConvertFromJsValue(env, argv[1], targetPersistentId)) {
1152         WLOGFE("Failed to convert parameter to target window Id");
1153         errCode = WMError::WM_ERROR_INVALID_PARAM;
1154     }
1155     if (errCode == WMError::WM_ERROR_INVALID_PARAM) {
1156         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
1157         return NapiGetUndefined(env);
1158     }
1159     NapiAsyncTask::CompleteCallback complete =
1160         [=](napi_env env, NapiAsyncTask& task, int32_t status) {
1161             WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(
1162                 SingletonContainer::Get<WindowManager>().ShiftAppWindowFocus(sourcePersistentId, targetPersistentId));
1163             if (ret == WmErrorCode::WM_OK) {
1164                 task.Resolve(env, NapiGetUndefined(env));
1165                 WLOGD("OnShiftAppWindowFocus success");
1166             } else {
1167                 task.Reject(env, JsErrUtils::CreateJsError(env, ret, "ShiftAppWindowFocus failed"));
1168             }
1169         };
1170     // only return promiss<void>
1171     napi_value lastParam = nullptr;
1172     napi_value result = nullptr;
1173     NapiAsyncTask::Schedule("JsWindowManager::OnShiftAppWindowFocus",
1174         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1175     return result;
1176 }
1177 
OnGetVisibleWindowInfo(napi_env env,napi_callback_info info)1178 napi_value JsWindowManager::OnGetVisibleWindowInfo(napi_env env, napi_callback_info info)
1179 {
1180     size_t argc = 4;
1181     napi_value argv[4] = {nullptr};
1182     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1183     napi_value lastParam = argc <= 0 || GetType(env, argv[0]) != napi_function ? nullptr : argv[0];
1184     napi_value result = nullptr;
1185     NapiAsyncTask::CompleteCallback complete =
1186         [](napi_env env, NapiAsyncTask& task, int32_t status) {
1187             std::vector<sptr<WindowVisibilityInfo>> infos;
1188             WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(
1189                 SingletonContainer::Get<WindowManager>().GetVisibilityWindowInfo(infos));
1190             if (ret == WmErrorCode::WM_OK) {
1191                 task.Resolve(env, CreateJsWindowInfoArrayObject(env, infos));
1192                 TLOGD(WmsLogTag::DEFAULT, "OnGetVisibleWindowInfo success");
1193             } else {
1194                 TLOGE(WmsLogTag::DEFAULT, "OnGetVisibleWindowInfo failed");
1195                 task.Reject(env, JsErrUtils::CreateJsError(env, ret, "OnGetVisibleWindowInfo failed"));
1196             }
1197         };
1198     NapiAsyncTask::Schedule("JsWindowManager::OnGetVisibleWindowInfo",
1199                             env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1200     return result;
1201 }
1202 
OnGetWindowsByCoordinate(napi_env env,napi_callback_info info)1203 napi_value JsWindowManager::OnGetWindowsByCoordinate(napi_env env, napi_callback_info info)
1204 {
1205     size_t argc = ARGC_FOUR;
1206     napi_value argv[ARGC_FOUR] = {nullptr};
1207     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1208     if (argc < ARGC_ONE || argc > ARGC_FOUR) { // min param num 1, max param num 4
1209         return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
1210     }
1211     int64_t displayId = static_cast<int64_t>(DISPLAY_ID_INVALID);
1212     if (!ConvertFromJsValue(env, argv[0], displayId)) {
1213         TLOGE(WmsLogTag::DEFAULT, "Failed to convert parameter to displayId");
1214         return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
1215     }
1216     if (displayId < 0 ||
1217         SingletonContainer::Get<DisplayManager>().GetDisplayById(static_cast<uint64_t>(displayId)) == nullptr) {
1218         TLOGE(WmsLogTag::DEFAULT, "invalid displayId");
1219         return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
1220     }
1221     int32_t windowNumber = 0;
1222     if (argc > ARGC_ONE && !ConvertFromJsValue(env, argv[ARGC_ONE], windowNumber)) {
1223         windowNumber = 0;
1224     }
1225     int32_t x = INVALID_COORDINATE;
1226     if (argc > ARGC_TWO && !ConvertFromJsValue(env, argv[ARGC_TWO], x)) {
1227         x = INVALID_COORDINATE;
1228     }
1229     int32_t y = INVALID_COORDINATE;
1230     if (argc > ARGC_THREE && !ConvertFromJsValue(env, argv[ARGC_THREE], y)) {
1231         y = INVALID_COORDINATE;
1232     }
1233     napi_value result = nullptr;
1234     NapiAsyncTask::CompleteCallback complete =
1235         [displayId, windowNumber, x, y](napi_env env, NapiAsyncTask& task, int32_t status) {
1236             std::vector<int32_t> windowIds;
1237             WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(SingletonContainer::Get<WindowManager>().
1238                 GetWindowIdsByCoordinate(static_cast<uint64_t>(displayId), windowNumber, x, y, windowIds));
1239             if (ret == WmErrorCode::WM_OK) {
1240                 std::vector<sptr<Window>> windows(windowIds.size());
1241                 for (size_t i = 0; i < windowIds.size(); i++) {
1242                     sptr<Window> window = Window::GetWindowWithId(windowIds[i]);
1243                     windows[i] = window;
1244                 }
1245                 task.Resolve(env, CreateJsWindowArrayObject(env, windows));
1246             } else {
1247                 task.Reject(env, JsErrUtils::CreateJsError(env, ret, "OnGetWindowsByCoordinate failed"));
1248             }
1249         };
1250     NapiAsyncTask::Schedule("JsWindowManager::OnGetWindowsByCoordinate",
1251         env, CreateAsyncTaskWithLastParam(env, nullptr, nullptr, std::move(complete), &result));
1252     return result;
1253 }
1254 
JsWindowManagerInit(napi_env env,napi_value exportObj)1255 napi_value JsWindowManagerInit(napi_env env, napi_value exportObj)
1256 {
1257     WLOGFD("JsWindowManagerInit");
1258 
1259     if (env == nullptr || exportObj == nullptr) {
1260         WLOGFE("JsWindowManagerInit env or exportObj is nullptr");
1261         return nullptr;
1262     }
1263 
1264     std::unique_ptr<JsWindowManager> jsWinManager = std::make_unique<JsWindowManager>();
1265     napi_wrap(env, exportObj, jsWinManager.release(), JsWindowManager::Finalizer, nullptr, nullptr);
1266     napi_set_named_property(env, exportObj, "WindowType", WindowTypeInit(env));
1267     napi_set_named_property(env, exportObj, "AvoidAreaType", AvoidAreaTypeInit(env));
1268     napi_set_named_property(env, exportObj, "WindowMode", WindowModeInit(env));
1269     napi_set_named_property(env, exportObj, "ColorSpace", ColorSpaceInit(env));
1270     napi_set_named_property(env, exportObj, "WindowStageEventType", WindowStageEventTypeInit(env));
1271     napi_set_named_property(env, exportObj, "WindowEventType", WindowEventTypeInit(env));
1272     napi_set_named_property(env, exportObj, "WindowLayoutMode", WindowLayoutModeInit(env));
1273     napi_set_named_property(env, exportObj, "Orientation", OrientationInit(env));
1274     napi_set_named_property(env, exportObj, "BlurStyle", BlurStyleInit(env));
1275     napi_set_named_property(env, exportObj, "WmErrorCode", WindowErrorCodeInit(env));
1276     napi_set_named_property(env, exportObj, "WMError", WindowErrorInit(env));
1277     napi_set_named_property(env, exportObj, "WindowStatusType", WindowStatusTypeInit(env));
1278     napi_set_named_property(env, exportObj, "RectChangeReason", RectChangeReasonInit(env));
1279     napi_set_named_property(env, exportObj, "MaximizePresentation", MaximizePresentationInit(env));
1280     napi_set_named_property(env, exportObj, "ModalityType", ModalityTypeInit(env));
1281     napi_set_named_property(env, exportObj, "ExtensionWindowAttribute", ExtensionWindowAttributeInit(env));
1282     const char *moduleName = "JsWindowManager";
1283     BindNativeFunction(env, exportObj, "create", moduleName, JsWindowManager::Create);
1284     BindNativeFunction(env, exportObj, "createWindow", moduleName, JsWindowManager::CreateWindow);
1285     BindNativeFunction(env, exportObj, "find", moduleName, JsWindowManager::FindWindow);
1286     BindNativeFunction(env, exportObj, "findWindow", moduleName, JsWindowManager::FindWindowSync);
1287     BindNativeFunction(env, exportObj, "on", moduleName, JsWindowManager::RegisterWindowManagerCallback);
1288     BindNativeFunction(env, exportObj, "off", moduleName, JsWindowManager::UnregisterWindowMangerCallback);
1289     BindNativeFunction(env, exportObj, "getTopWindow", moduleName, JsWindowManager::GetTopWindow);
1290     BindNativeFunction(env, exportObj, "getLastWindow", moduleName, JsWindowManager::GetLastWindow);
1291     BindNativeFunction(env, exportObj, "getSnapshot", moduleName, JsWindowManager::GetSnapshot);
1292     BindNativeFunction(env, exportObj, "minimizeAll", moduleName, JsWindowManager::MinimizeAll);
1293     BindNativeFunction(env, exportObj, "toggleShownStateForAllAppWindows", moduleName,
1294         JsWindowManager::ToggleShownStateForAllAppWindows);
1295     BindNativeFunction(env, exportObj, "setWindowLayoutMode", moduleName, JsWindowManager::SetWindowLayoutMode);
1296     BindNativeFunction(env, exportObj, "setGestureNavigationEnabled", moduleName,
1297         JsWindowManager::SetGestureNavigationEnabled);
1298     BindNativeFunction(env, exportObj, "setWaterMarkImage", moduleName, JsWindowManager::SetWaterMarkImage);
1299     BindNativeFunction(env, exportObj, "shiftAppWindowFocus", moduleName, JsWindowManager::ShiftAppWindowFocus);
1300     BindNativeFunction(env, exportObj, "getVisibleWindowInfo", moduleName, JsWindowManager::GetVisibleWindowInfo);
1301     BindNativeFunction(env, exportObj, "getWindowsByCoordinate", moduleName, JsWindowManager::GetWindowsByCoordinate);
1302     return NapiGetUndefined(env);
1303 }
1304 }  // namespace Rosen
1305 }  // namespace OHOS
1306