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