1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci#include "js_window_register_manager.h"
16e0dac50fSopenharmony_ci#include "window_manager_hilog.h"
17e0dac50fSopenharmony_ci
18e0dac50fSopenharmony_cinamespace OHOS {
19e0dac50fSopenharmony_cinamespace Rosen {
20e0dac50fSopenharmony_cinamespace {
21e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsRegisterManager"};
22e0dac50fSopenharmony_ci
23e0dac50fSopenharmony_ciconst std::map<std::string, ListenerFunctionType> WindowListenerFunctionMap {
24e0dac50fSopenharmony_ci    {SYSTEM_AVOID_AREA_CHANGE_CB, ListenerFunctionType::SYSTEM_AVOID_AREA_CHANGE_CB},
25e0dac50fSopenharmony_ci    {AVOID_AREA_CHANGE_CB, ListenerFunctionType::AVOID_AREA_CHANGE_CB},
26e0dac50fSopenharmony_ci};
27e0dac50fSopenharmony_ci
28e0dac50fSopenharmony_ciconst std::map<CaseType, std::map<std::string, ListenerFunctionType>> ListenerFunctionMap {
29e0dac50fSopenharmony_ci    {CaseType::CASE_WINDOW, WindowListenerFunctionMap},
30e0dac50fSopenharmony_ci};
31e0dac50fSopenharmony_ci}
32e0dac50fSopenharmony_ci
33e0dac50fSopenharmony_ciJsWindowRegisterManager::JsWindowRegisterManager()
34e0dac50fSopenharmony_ci{
35e0dac50fSopenharmony_ci}
36e0dac50fSopenharmony_ci
37e0dac50fSopenharmony_ciJsWindowRegisterManager::~JsWindowRegisterManager()
38e0dac50fSopenharmony_ci{
39e0dac50fSopenharmony_ci}
40e0dac50fSopenharmony_ci
41e0dac50fSopenharmony_ciWmErrorCode JsWindowRegisterManager::ProcessSystemAvoidAreaChangeRegister(sptr<JsWindowListener> listener,
42e0dac50fSopenharmony_ci    sptr<Window> window, bool isRegister, napi_env env, napi_value parameter)
43e0dac50fSopenharmony_ci{
44e0dac50fSopenharmony_ci    if (window == nullptr) {
45e0dac50fSopenharmony_ci        WLOGFE("[NAPI]Window is nullptr");
46e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
47e0dac50fSopenharmony_ci    }
48e0dac50fSopenharmony_ci    if (listener == nullptr) {
49e0dac50fSopenharmony_ci        WLOGFE("[NAPI]listener is nullptr");
50e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
51e0dac50fSopenharmony_ci    }
52e0dac50fSopenharmony_ci    listener->SetIsDeprecatedInterface(true);
53e0dac50fSopenharmony_ci    sptr<IAvoidAreaChangedListener> thisListener(listener);
54e0dac50fSopenharmony_ci    WmErrorCode ret;
55e0dac50fSopenharmony_ci    if (isRegister) {
56e0dac50fSopenharmony_ci        ret = WM_JS_TO_ERROR_CODE_MAP.at(window->RegisterAvoidAreaChangeListener(thisListener));
57e0dac50fSopenharmony_ci    } else {
58e0dac50fSopenharmony_ci        ret = WM_JS_TO_ERROR_CODE_MAP.at(window->UnregisterAvoidAreaChangeListener(thisListener));
59e0dac50fSopenharmony_ci    }
60e0dac50fSopenharmony_ci    return ret;
61e0dac50fSopenharmony_ci}
62e0dac50fSopenharmony_ci
63e0dac50fSopenharmony_ciWmErrorCode JsWindowRegisterManager::ProcessAvoidAreaChangeRegister(sptr<JsWindowListener> listener,
64e0dac50fSopenharmony_ci    sptr<Window> window, bool isRegister, napi_env env, napi_value parameter)
65e0dac50fSopenharmony_ci{
66e0dac50fSopenharmony_ci    if (window == nullptr) {
67e0dac50fSopenharmony_ci        WLOGFE("[NAPI]Window is nullptr");
68e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
69e0dac50fSopenharmony_ci    }
70e0dac50fSopenharmony_ci    sptr<IAvoidAreaChangedListener> thisListener(listener);
71e0dac50fSopenharmony_ci    WmErrorCode ret;
72e0dac50fSopenharmony_ci    if (isRegister) {
73e0dac50fSopenharmony_ci        ret = WM_JS_TO_ERROR_CODE_MAP.at(window->RegisterAvoidAreaChangeListener(thisListener));
74e0dac50fSopenharmony_ci    } else {
75e0dac50fSopenharmony_ci        ret = WM_JS_TO_ERROR_CODE_MAP.at(window->UnregisterAvoidAreaChangeListener(thisListener));
76e0dac50fSopenharmony_ci    }
77e0dac50fSopenharmony_ci    return ret;
78e0dac50fSopenharmony_ci}
79e0dac50fSopenharmony_ci
80e0dac50fSopenharmony_ciWmErrorCode JsWindowRegisterManager::RegisterListener(sptr<Window> window, std::string type,
81e0dac50fSopenharmony_ci    CaseType caseType, napi_env env, napi_value callback, napi_value parameter)
82e0dac50fSopenharmony_ci{
83e0dac50fSopenharmony_ci    std::lock_guard<std::mutex> lock(mtx_);
84e0dac50fSopenharmony_ci    if (IsCallbackRegistered(env, type, callback)) {
85e0dac50fSopenharmony_ci        return WmErrorCode::WM_OK;
86e0dac50fSopenharmony_ci    }
87e0dac50fSopenharmony_ci    auto iterCaseType = ListenerFunctionMap.find(caseType);
88e0dac50fSopenharmony_ci    if (iterCaseType == ListenerFunctionMap.end()) {
89e0dac50fSopenharmony_ci        WLOGFE("[NAPI]CaseType %{public}u is not supported", static_cast<uint32_t>(caseType));
90e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
91e0dac50fSopenharmony_ci    }
92e0dac50fSopenharmony_ci    auto iterCallbackType = iterCaseType->second.find(type);
93e0dac50fSopenharmony_ci    if (iterCallbackType == iterCaseType->second.end()) {
94e0dac50fSopenharmony_ci        WLOGFE("[NAPI]Type %{public}s is not supported", type.c_str());
95e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
96e0dac50fSopenharmony_ci    }
97e0dac50fSopenharmony_ci    ListenerFunctionType listenerFunctionType = iterCallbackType->second;
98e0dac50fSopenharmony_ci    napi_ref result = nullptr;
99e0dac50fSopenharmony_ci    napi_create_reference(env, callback, 1, &result);
100e0dac50fSopenharmony_ci    std::shared_ptr<NativeReference> callbackRef(reinterpret_cast<NativeReference*>(result));
101e0dac50fSopenharmony_ci    sptr<JsWindowListener> windowManagerListener = new(std::nothrow) JsWindowListener(env, callbackRef);
102e0dac50fSopenharmony_ci    if (windowManagerListener == nullptr) {
103e0dac50fSopenharmony_ci        WLOGFE("[NAPI]New JsWindowListener failed");
104e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
105e0dac50fSopenharmony_ci    }
106e0dac50fSopenharmony_ci    windowManagerListener->SetMainEventHandler();
107e0dac50fSopenharmony_ci    WmErrorCode ret = ProcessRegisterCallback(listenerFunctionType, caseType, windowManagerListener, window,
108e0dac50fSopenharmony_ci        true, env, parameter);
109e0dac50fSopenharmony_ci    if (ret != WmErrorCode::WM_OK) {
110e0dac50fSopenharmony_ci        WLOGFE("[NAPI]Register type %{public}s failed", type.c_str());
111e0dac50fSopenharmony_ci        return ret;
112e0dac50fSopenharmony_ci    }
113e0dac50fSopenharmony_ci    jsCbMap_[type][callbackRef] = windowManagerListener;
114e0dac50fSopenharmony_ci    WLOGI("[NAPI]Register type %{public}s success! callback map size: %{public}zu",
115e0dac50fSopenharmony_ci        type.c_str(), jsCbMap_[type].size());
116e0dac50fSopenharmony_ci    return WmErrorCode::WM_OK;
117e0dac50fSopenharmony_ci}
118e0dac50fSopenharmony_ci
119e0dac50fSopenharmony_ciWmErrorCode JsWindowRegisterManager::ProcessRegisterCallback(ListenerFunctionType listenerFunctionType,
120e0dac50fSopenharmony_ci    CaseType caseType, const sptr<JsWindowListener>& listener, const sptr<Window>& window, bool isRegister,
121e0dac50fSopenharmony_ci    napi_env env, napi_value parameter)
122e0dac50fSopenharmony_ci{
123e0dac50fSopenharmony_ci    if (caseType == CaseType::CASE_WINDOW) {
124e0dac50fSopenharmony_ci        switch (listenerFunctionType) {
125e0dac50fSopenharmony_ci            case ListenerFunctionType::SYSTEM_AVOID_AREA_CHANGE_CB:
126e0dac50fSopenharmony_ci                return ProcessSystemAvoidAreaChangeRegister(listener, window, isRegister, env, parameter);
127e0dac50fSopenharmony_ci            case ListenerFunctionType::AVOID_AREA_CHANGE_CB:
128e0dac50fSopenharmony_ci                return ProcessAvoidAreaChangeRegister(listener, window, isRegister, env, parameter);
129e0dac50fSopenharmony_ci            default:
130e0dac50fSopenharmony_ci                return WmErrorCode::WM_ERROR_INVALID_PARAM;
131e0dac50fSopenharmony_ci        }
132e0dac50fSopenharmony_ci    }
133e0dac50fSopenharmony_ci    return WmErrorCode::WM_ERROR_INVALID_PARAM;
134e0dac50fSopenharmony_ci}
135e0dac50fSopenharmony_ci
136e0dac50fSopenharmony_ciWmErrorCode JsWindowRegisterManager::UnregisterListener(sptr<Window> window, std::string type,
137e0dac50fSopenharmony_ci    CaseType caseType, napi_env env, napi_value value)
138e0dac50fSopenharmony_ci{
139e0dac50fSopenharmony_ci    std::lock_guard<std::mutex> lock(mtx_);
140e0dac50fSopenharmony_ci    if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
141e0dac50fSopenharmony_ci        WLOGFE("[NAPI]Type %{public}s was not registerted", type.c_str());
142e0dac50fSopenharmony_ci        return WmErrorCode::WM_OK;
143e0dac50fSopenharmony_ci    }
144e0dac50fSopenharmony_ci    auto iterCaseType = ListenerFunctionMap.find(caseType);
145e0dac50fSopenharmony_ci    if (iterCaseType == ListenerFunctionMap.end()) {
146e0dac50fSopenharmony_ci        WLOGFE("[NAPI]CaseType %{public}u is not supported", static_cast<uint32_t>(caseType));
147e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
148e0dac50fSopenharmony_ci    }
149e0dac50fSopenharmony_ci    auto iterCallbackType = iterCaseType->second.find(type);
150e0dac50fSopenharmony_ci    if (iterCallbackType == iterCaseType->second.end()) {
151e0dac50fSopenharmony_ci        WLOGFE("[NAPI]Type %{public}s is not supported", type.c_str());
152e0dac50fSopenharmony_ci        return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
153e0dac50fSopenharmony_ci    }
154e0dac50fSopenharmony_ci    ListenerFunctionType listenerFunctionType = iterCallbackType->second;
155e0dac50fSopenharmony_ci    if (value == nullptr) {
156e0dac50fSopenharmony_ci        for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
157e0dac50fSopenharmony_ci            WmErrorCode ret = ProcessRegisterCallback(listenerFunctionType, caseType, it->second, window, false,
158e0dac50fSopenharmony_ci                env, nullptr);
159e0dac50fSopenharmony_ci            if (ret != WmErrorCode::WM_OK) {
160e0dac50fSopenharmony_ci                WLOGFE("[NAPI]Unregister type %{public}s failed, no value", type.c_str());
161e0dac50fSopenharmony_ci                return ret;
162e0dac50fSopenharmony_ci            }
163e0dac50fSopenharmony_ci            jsCbMap_[type].erase(it++);
164e0dac50fSopenharmony_ci        }
165e0dac50fSopenharmony_ci    } else {
166e0dac50fSopenharmony_ci        bool findFlag = false;
167e0dac50fSopenharmony_ci        for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end(); ++it) {
168e0dac50fSopenharmony_ci            bool isEquals = false;
169e0dac50fSopenharmony_ci            napi_strict_equals(env, value, it->first->GetNapiValue(), &isEquals);
170e0dac50fSopenharmony_ci            if (!isEquals) {
171e0dac50fSopenharmony_ci                continue;
172e0dac50fSopenharmony_ci            }
173e0dac50fSopenharmony_ci            findFlag = true;
174e0dac50fSopenharmony_ci            WmErrorCode ret = ProcessRegisterCallback(listenerFunctionType, caseType, it->second, window, false,
175e0dac50fSopenharmony_ci                env, nullptr);
176e0dac50fSopenharmony_ci            if (ret != WmErrorCode::WM_OK) {
177e0dac50fSopenharmony_ci                WLOGFE("[NAPI]Unregister type %{public}s failed", type.c_str());
178e0dac50fSopenharmony_ci                return ret;
179e0dac50fSopenharmony_ci            }
180e0dac50fSopenharmony_ci            jsCbMap_[type].erase(it);
181e0dac50fSopenharmony_ci            break;
182e0dac50fSopenharmony_ci        }
183e0dac50fSopenharmony_ci        if (!findFlag) {
184e0dac50fSopenharmony_ci            WLOGFE("[NAPI]Unregister type %{public}s failed because not found callback!", type.c_str());
185e0dac50fSopenharmony_ci            return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
186e0dac50fSopenharmony_ci        }
187e0dac50fSopenharmony_ci    }
188e0dac50fSopenharmony_ci    WLOGI("[NAPI]Unregister type %{public}s success! callback map size: %{public}zu",
189e0dac50fSopenharmony_ci        type.c_str(), jsCbMap_[type].size());
190e0dac50fSopenharmony_ci    // erase type when there is no callback in one type
191e0dac50fSopenharmony_ci    if (jsCbMap_[type].empty()) {
192e0dac50fSopenharmony_ci        jsCbMap_.erase(type);
193e0dac50fSopenharmony_ci    }
194e0dac50fSopenharmony_ci    return WmErrorCode::WM_OK;
195e0dac50fSopenharmony_ci}
196e0dac50fSopenharmony_ci
197e0dac50fSopenharmony_cibool JsWindowRegisterManager::IsCallbackRegistered(napi_env env, std::string& type, napi_value jsListenerObject)
198e0dac50fSopenharmony_ci{
199e0dac50fSopenharmony_ci    if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
200e0dac50fSopenharmony_ci        WLOGI("[NAPI]Method %{public}s has not been registerted", type.c_str());
201e0dac50fSopenharmony_ci        return false;
202e0dac50fSopenharmony_ci    }
203e0dac50fSopenharmony_ci
204e0dac50fSopenharmony_ci    for (auto iter = jsCbMap_[type].begin(); iter != jsCbMap_[type].end(); ++iter) {
205e0dac50fSopenharmony_ci        bool isEquals = false;
206e0dac50fSopenharmony_ci        napi_strict_equals(env, jsListenerObject, iter->first->GetNapiValue(), &isEquals);
207e0dac50fSopenharmony_ci        if (isEquals) {
208e0dac50fSopenharmony_ci            WLOGFE("[NAPI]Method %{public}s has already been registered", type.c_str());
209e0dac50fSopenharmony_ci            return true;
210e0dac50fSopenharmony_ci        }
211e0dac50fSopenharmony_ci    }
212e0dac50fSopenharmony_ci    return false;
213e0dac50fSopenharmony_ci}
214e0dac50fSopenharmony_ci
215e0dac50fSopenharmony_ci} // namespace Rosen
216e0dac50fSopenharmony_ci} // namespace OHOS
217