• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_register_manager.h"
17 #include "singleton_container.h"
18 #include "window_manager.h"
19 #include "window_manager_hilog.h"
20 
21 namespace OHOS {
22 namespace Rosen {
23 namespace {
24 const std::string WINDOW_SIZE_CHANGE_CB = "windowSizeChange";
25 const std::string WINDOW_RECT_CHANGE_CB = "rectChange";
26 const std::string AVOID_AREA_CHANGE_CB = "avoidAreaChange";
27 const std::string WINDOW_STAGE_EVENT_CB = "windowStageEvent";
28 const std::string WINDOW_EVENT_CB = "windowEvent";
29 }
30 
JsExtensionWindowRegisterManager()31 JsExtensionWindowRegisterManager::JsExtensionWindowRegisterManager()
32 {
33     // white register list for window
34     listenerCodeMap_[CaseType::CASE_WINDOW] = {
35         {WINDOW_SIZE_CHANGE_CB, ListenerType::WINDOW_SIZE_CHANGE_CB},
36         {WINDOW_RECT_CHANGE_CB, ListenerType::WINDOW_RECT_CHANGE_CB},
37         {AVOID_AREA_CHANGE_CB, ListenerType::AVOID_AREA_CHANGE_CB},
38         {WINDOW_EVENT_CB, ListenerType::WINDOW_EVENT_CB},
39     };
40     // white register list for window stage
41     listenerCodeMap_[CaseType::CASE_STAGE] = {
42         {WINDOW_STAGE_EVENT_CB, ListenerType::WINDOW_STAGE_EVENT_CB}
43     };
44 }
45 
~JsExtensionWindowRegisterManager()46 JsExtensionWindowRegisterManager::~JsExtensionWindowRegisterManager()
47 {
48 }
49 
ProcessWindowChangeRegister(sptr<JsExtensionWindowListener> listener,sptr<Window> window,bool isRegister)50 WmErrorCode JsExtensionWindowRegisterManager::ProcessWindowChangeRegister(sptr<JsExtensionWindowListener> listener,
51     sptr<Window> window, bool isRegister)
52 {
53     if (window == nullptr) {
54         TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Window is nullptr");
55         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
56     }
57     sptr<IWindowChangeListener> thisListener(listener);
58     WmErrorCode ret = WmErrorCode::WM_OK;
59     if (isRegister) {
60         ret = WM_JS_TO_ERROR_CODE_MAP.at(window->RegisterWindowChangeListener(thisListener));
61     } else {
62         ret = WM_JS_TO_ERROR_CODE_MAP.at(window->UnregisterWindowChangeListener(thisListener));
63     }
64     return ret;
65 }
66 
ProcessWindowRectChangeRegister(const sptr<JsExtensionWindowListener> & listener,const sptr<Window> & window,bool isRegister)67 WmErrorCode JsExtensionWindowRegisterManager::ProcessWindowRectChangeRegister(
68     const sptr<JsExtensionWindowListener>& listener, const sptr<Window>& window, bool isRegister)
69 {
70     if (window == nullptr) {
71         TLOGE(WmsLogTag::WMS_UIEXT, "Window is nullptr");
72         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
73     }
74     return isRegister ?
75         WM_JS_TO_ERROR_CODE_MAP.at(window->RegisterWindowRectChangeListener(listener)) :
76         WM_JS_TO_ERROR_CODE_MAP.at(window->UnregisterWindowRectChangeListener(listener));
77 }
78 
ProcessAvoidAreaChangeRegister(sptr<JsExtensionWindowListener> listener,sptr<Window> window,bool isRegister)79 WmErrorCode JsExtensionWindowRegisterManager::ProcessAvoidAreaChangeRegister(sptr<JsExtensionWindowListener> listener,
80     sptr<Window> window, bool isRegister)
81 {
82     if (window == nullptr) {
83         TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Window is nullptr");
84         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
85     }
86     sptr<IAvoidAreaChangedListener> thisListener(listener);
87     WmErrorCode ret = WmErrorCode::WM_OK;
88     if (isRegister) {
89         ret = WM_JS_TO_ERROR_CODE_MAP.at(window->RegisterAvoidAreaChangeListener(thisListener));
90     } else {
91         ret = WM_JS_TO_ERROR_CODE_MAP.at(window->UnregisterAvoidAreaChangeListener(thisListener));
92     }
93     return ret;
94 }
95 
ProcessLifeCycleEventRegister(sptr<JsExtensionWindowListener> listener,sptr<Window> window,bool isRegister)96 WmErrorCode JsExtensionWindowRegisterManager::ProcessLifeCycleEventRegister(sptr<JsExtensionWindowListener> listener,
97     sptr<Window> window, bool isRegister)
98 {
99     if (window == nullptr) {
100         TLOGE(WmsLogTag::WMS_UIEXT, "Window is nullptr");
101         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
102     }
103     sptr<IWindowLifeCycle> thisListener(listener);
104     WmErrorCode ret = WmErrorCode::WM_OK;
105     if (isRegister) {
106         ret = WM_JS_TO_ERROR_CODE_MAP.at(window->RegisterLifeCycleListener(thisListener));
107     } else {
108         ret = WM_JS_TO_ERROR_CODE_MAP.at(window->UnregisterLifeCycleListener(thisListener));
109     }
110     return ret;
111 }
112 
IsCallbackRegistered(napi_env env,std::string type,napi_value jsListenerObject)113 bool JsExtensionWindowRegisterManager::IsCallbackRegistered(napi_env env, std::string type, napi_value jsListenerObject)
114 {
115     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
116         TLOGI(WmsLogTag::WMS_UIEXT, "[NAPI]Method %{public}s has not been registered", type.c_str());
117         return false;
118     }
119 
120     for (auto iter = jsCbMap_[type].begin(); iter != jsCbMap_[type].end(); ++iter) {
121         bool isEquals = false;
122         napi_strict_equals(env, jsListenerObject, iter->first->GetNapiValue(), &isEquals);
123         if (isEquals) {
124             TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Method %{public}s has already been registered", type.c_str());
125             return true;
126         }
127     }
128     return false;
129 }
130 
RegisterListener(sptr<Window> window,std::string type,CaseType caseType,napi_env env,napi_value value)131 WmErrorCode JsExtensionWindowRegisterManager::RegisterListener(sptr<Window> window, std::string type,
132     CaseType caseType, napi_env env, napi_value value)
133 {
134     std::lock_guard<std::mutex> lock(mtx_);
135     if (IsCallbackRegistered(env, type, value)) {
136         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
137     }
138     if (listenerCodeMap_[caseType].count(type) == 0) {
139         TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Type %{public}s is not supported", type.c_str());
140         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
141     }
142     napi_ref result = nullptr;
143     napi_create_reference(env, value, 1, &result);
144     std::shared_ptr<NativeReference> callbackRef(reinterpret_cast<NativeReference*>(result));
145     sptr<JsExtensionWindowListener> extensionWindowListener =
146         new(std::nothrow) JsExtensionWindowListener(env, callbackRef);
147     if (extensionWindowListener == nullptr) {
148         TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]New JsExtensionWindowListener failed");
149         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
150     }
151     extensionWindowListener->SetMainEventHandler();
152     WmErrorCode ret = ProcessRegister(caseType, extensionWindowListener, window, type, true);
153     if (ret != WmErrorCode::WM_OK) {
154         TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Register type %{public}s failed", type.c_str());
155         return ret;
156     }
157     jsCbMap_[type][callbackRef] = extensionWindowListener;
158     TLOGI(WmsLogTag::WMS_UIEXT, "[NAPI]Register type %{public}s success! callback map size: %{public}zu", type.c_str(),
159           jsCbMap_[type].size());
160     return WmErrorCode::WM_OK;
161 }
162 
UnregisterListener(sptr<Window> window,std::string type,CaseType caseType,napi_env env,napi_value value)163 WmErrorCode JsExtensionWindowRegisterManager::UnregisterListener(sptr<Window> window, std::string type,
164     CaseType caseType, napi_env env, napi_value value)
165 {
166     std::lock_guard<std::mutex> lock(mtx_);
167     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
168         TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Type %{public}s was not registered", type.c_str());
169         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
170     }
171     if (listenerCodeMap_[caseType].count(type) == 0) {
172         TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Type %{public}s is not supported", type.c_str());
173         return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
174     }
175     if (value == nullptr) {
176         for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
177             WmErrorCode ret = ProcessRegister(caseType, it->second, window, type, false);
178             if (ret != WmErrorCode::WM_OK) {
179                 TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Unregister type %{public}s failed, no value", type.c_str());
180                 return ret;
181             }
182             jsCbMap_[type].erase(it++);
183         }
184     } else {
185         bool findFlag = false;
186         for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end(); ++it) {
187             bool isEquals = false;
188             napi_strict_equals(env, value, it->first->GetNapiValue(), &isEquals);
189             if (!isEquals) {
190                 continue;
191             }
192             findFlag = true;
193             WmErrorCode ret = ProcessRegister(caseType, it->second, window, type, false);
194             if (ret != WmErrorCode::WM_OK) {
195                 TLOGE(WmsLogTag::WMS_UIEXT, "[NAPI]Unregister type %{public}s failed", type.c_str());
196                 return ret;
197             }
198             jsCbMap_[type].erase(it);
199             break;
200         }
201         if (!findFlag) {
202             TLOGE(WmsLogTag::WMS_UIEXT,
203                 "[NAPI]Unregister type %{public}s failed because not found callback!", type.c_str());
204             return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
205         }
206     }
207     TLOGI(WmsLogTag::WMS_UIEXT, "[NAPI]Unregister type %{public}s success! callback map size: %{public}zu",
208         type.c_str(), jsCbMap_[type].size());
209     // erase type when there is no callback in one type
210     if (jsCbMap_[type].empty()) {
211         jsCbMap_.erase(type);
212     }
213     return WmErrorCode::WM_OK;
214 }
215 
ProcessRegister(CaseType caseType,const sptr<JsExtensionWindowListener> & listener,const sptr<Window> & window,const std::string & type,bool isRegister)216 WmErrorCode JsExtensionWindowRegisterManager::ProcessRegister(CaseType caseType,
217     const sptr<JsExtensionWindowListener>& listener, const sptr<Window>& window, const std::string& type,
218     bool isRegister)
219 {
220     WmErrorCode ret = WmErrorCode::WM_OK;
221     if (caseType == CaseType::CASE_WINDOW) {
222         switch (listenerCodeMap_[caseType][type]) {
223             case ListenerType::WINDOW_SIZE_CHANGE_CB:
224                 ret = ProcessWindowChangeRegister(listener, window, isRegister);
225                 break;
226             case ListenerType::WINDOW_RECT_CHANGE_CB:
227                 ret = ProcessWindowRectChangeRegister(listener, window, isRegister);
228                 break;
229             case ListenerType::AVOID_AREA_CHANGE_CB:
230                 ret = ProcessAvoidAreaChangeRegister(listener, window, isRegister);
231                 break;
232             case ListenerType::WINDOW_EVENT_CB:
233                 ret = ProcessLifeCycleEventRegister(listener, window, isRegister);
234                 break;
235             default:
236                 break;
237         }
238     } else if (caseType == CaseType::CASE_STAGE) {
239         if (type == WINDOW_STAGE_EVENT_CB) {
240             ret = ProcessLifeCycleEventRegister(listener, window, isRegister);
241         }
242     }
243     return ret;
244 }
245 
246 } // namespace Rosen
247 } // namespace OHOS