diff --git a/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.cpp b/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.cpp index d6ed4b169c24f00e061b4ef7708b750c422f46d5..474924a4461814469bff1ea8c9137690a9981830 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.cpp @@ -130,7 +130,6 @@ void JSUIExtensionProxy::SendSync(const JSCallbackInfo& info) JSException::Throw(reErrorCode, errMsg.c_str()); return; } - JSRef obj = JSRef::New(); auto execCtx = info.GetExecutionContext(); JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); auto reNativeWantParams = @@ -140,13 +139,111 @@ void JSUIExtensionProxy::SendSync(const JSCallbackInfo& info) } } +CallbackFuncPairList::const_iterator JSUIExtensionProxy::FindCbList(napi_env env, napi_value cb, + CallbackFuncPairList& callbackFuncPairList) +{ + return std::find_if(callbackFuncPairList.begin(), callbackFuncPairList.end(), + [env, cb](const auto& item) -> bool { + bool result = false; + napi_value refItem; + napi_get_reference_value(env, item.first, &refItem); + napi_strict_equals(env, refItem, cb, &result); + return result; + }); +} + +void JSUIExtensionProxy::AddCallbackToList(napi_env env, napi_value cb, + napi_handle_scope scope, RegisterType type, + const std::function&)>&& onFunc) +{ + if (type == RegisterType::SYNC) { + auto iter = FindCbList(env, cb, onSyncOnCallbackList_); + if (iter == onSyncOnCallbackList_.end()) { + napi_ref ref = nullptr; + napi_create_reference(env, cb, 1, &ref); + onSyncOnCallbackList_.emplace_back(ref, onFunc); + } + } else if (type == RegisterType::ASYNC) { + auto iter = FindCbList(env, cb, onAsyncOnCallbackList_); + if (iter == onAsyncOnCallbackList_.end()) { + napi_ref ref = nullptr; + napi_create_reference(env, cb, 1, &ref); + onAsyncOnCallbackList_.emplace_back(ref, onFunc); + } + } + napi_close_handle_scope(env, scope); +} + +void JSUIExtensionProxy::DeleteCallbackFromList(int argc, napi_env env, napi_value cb, RegisterType type) +{ + if (argc == 1) { + if (type == RegisterType::SYNC) { + for (const auto& item : onSyncOnCallbackList_) { + napi_delete_reference(env, item.first); + } + onSyncOnCallbackList_.clear(); + } else if (type == RegisterType::ASYNC) { + for (const auto& item : onAsyncOnCallbackList_) { + napi_delete_reference(env, item.first); + } + onAsyncOnCallbackList_.clear(); + } + } else if (argc == 2) { + if (type == RegisterType::SYNC) { + auto iter = FindCbList(env, cb, onSyncOnCallbackList_); + if (iter != onSyncOnCallbackList_.end()) { + napi_delete_reference(env, iter->first); + onSyncOnCallbackList_.erase(iter); + } + } else if (type == RegisterType::ASYNC) { + auto iter = FindCbList(env, cb, onAsyncOnCallbackList_); + if (iter != onAsyncOnCallbackList_.end()) { + napi_delete_reference(env, iter->first); + onAsyncOnCallbackList_.erase(iter); + } + } + } +} + +std::list&)>> JSUIExtensionProxy::GetOnFuncList( + RegisterType type) +{ + std::list&)>> reList; + if (type == RegisterType::SYNC) { + for (const auto& item : onSyncOnCallbackList_) { + reList.emplace_back(item.second); + } + } else if (type == RegisterType::ASYNC) { + for (const auto& item : onAsyncOnCallbackList_) { + reList.emplace_back(item.second); + } + } + return reList; +} + +RegisterType JSUIExtensionProxy::GetRegisterType(const std::string& strType) +{ + RegisterType type = RegisterType::UNKNOWN; + static constexpr char syncType[] = "syncReceiverRegister"; + static constexpr char asyncType[] = "asyncReceiverRegister"; + if (strType.compare(syncType) == 0) { + type = RegisterType::SYNC; + } else if (strType.compare(asyncType) == 0) { + type = RegisterType::ASYNC; + } + return type; +} + void JSUIExtensionProxy::On(const JSCallbackInfo& info) { - const int argCount = 2; - if (info.Length() != argCount || !info[0]->IsString() || !info[1]->IsFunction()) { + if (!info[0]->IsString() || !info[1]->IsFunction()) { + return; + } + const RegisterType registerType = GetRegisterType(info[0]->ToString()); + if (registerType == RegisterType::UNKNOWN) { return; } - const std::string registerType = info[0]->ToString(); + auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(info[1])); auto instanceId = ContainerScope::CurrentId(); auto onOnFunc = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId] @@ -161,46 +258,65 @@ void JSUIExtensionProxy::On(const JSCallbackInfo& info) func->ExecuteJS(1, ¶m); }; + ContainerScope scope(instanceId_); + auto engine = EngineHelper::GetCurrentEngine(); + CHECK_NULL_VOID(engine); + NativeEngine* nativeEngine = engine->GetNativeEngine(); + CHECK_NULL_VOID(nativeEngine); + auto env = reinterpret_cast(nativeEngine); + ScopeRAII scopeNapi(env); + panda::Local value = info[1].Get().GetLocalHandle(); + JSValueWrapper valueWrapper = value; + napi_value cb = nativeEngine->ValueToNapiValue(valueWrapper); + napi_handle_scope napiScope = nullptr; + napi_open_handle_scope(env, &napiScope); + CHECK_NULL_VOID(napiScope); + + std::lock_guard lock(callbackLisLock_); + AddCallbackToList(env, cb, napiScope, registerType, std::move(onOnFunc)); auto pattern = proxy_->GetPattern(); CHECK_NULL_VOID(pattern); - const std::string syncType = "syncReceiverRegister"; - const std::string asyncType = "asyncReceiverRegister"; - if (registerType == syncType) { - pattern->SetOnSyncOnCallback(std::move(onOnFunc)); - } else if (registerType == asyncType) { - pattern->SetOnAsyncOnCallback(std::move(onOnFunc)); + auto onFuncList = GetOnFuncList(registerType); + if (registerType == RegisterType::SYNC) { + pattern->SetOnSyncOnCallbackList(std::move(onFuncList)); + } else if (registerType == RegisterType::ASYNC) { + pattern->SetOnAsyncOnCallbackList(std::move(onFuncList)); } } void JSUIExtensionProxy::Off(const JSCallbackInfo& info) { - const int argCount = 2; - if (info.Length() != argCount || !info[0]->IsString() || !info[1]->IsFunction()) { + if (!info[0]->IsString()) { return; } - const std::string registerType = info[0]->ToString(); - auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(info[1])); - auto instanceId = ContainerScope::CurrentId(); - auto onOffFunc = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId] - (const RefPtr& session) { - ContainerScope scope(instanceId); - JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); - JSRef contextObj = JSClass::NewInstance(); - RefPtr proxy = Referenced::Claim(contextObj->Unwrap()); - proxy->SetInstanceId(instanceId); - proxy->SetProxy(session); - auto param = JSRef::Cast(contextObj); - func->ExecuteJS(1, ¶m); - }; + const RegisterType registerType = GetRegisterType(info[0]->ToString()); + if (registerType == RegisterType::UNKNOWN) { + return; + } + + ContainerScope scope(instanceId_); + auto engine = EngineHelper::GetCurrentEngine(); + CHECK_NULL_VOID(engine); + NativeEngine* nativeEngine = engine->GetNativeEngine(); + CHECK_NULL_VOID(nativeEngine); + auto env = reinterpret_cast(nativeEngine); + ScopeRAII scopeNapi(env); + napi_value cb = nullptr; + if (info[1]->IsFunction()) { + panda::Local value = info[1].Get().GetLocalHandle(); + JSValueWrapper valueWrapper = value; + cb = nativeEngine->ValueToNapiValue(valueWrapper); + } + std::lock_guard lock(callbackLisLock_); + DeleteCallbackFromList(info.Length(), env, cb, registerType); auto pattern = proxy_->GetPattern(); CHECK_NULL_VOID(pattern); - const std::string syncType = "syncReceiverRegister"; - const std::string asyncType = "asyncReceiverRegister"; - if (registerType == syncType) { - pattern->SetOnSyncOffCallback(std::move(onOffFunc)); - } else if (registerType == asyncType) { - pattern->SetOnAsyncOffCallback(std::move(onOffFunc)); + auto onFuncList = GetOnFuncList(registerType); + if (registerType == RegisterType::SYNC) { + pattern->SetOnSyncOffCallbackList(std::move(onFuncList)); + } else if (registerType == RegisterType::ASYNC) { + pattern->SetOnAsyncOffCallbackList(std::move(onFuncList)); } } diff --git a/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.h b/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.h index e6dc8932245f023bb175d38eb8ea20a99b8f5c23..4cb0de9273ea24eaa191447cb5cb1400c42f8424 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_ui_extension.h @@ -32,6 +32,14 @@ public: static void OnError(const JSCallbackInfo& info); }; +enum class RegisterType { + SYNC = 0, + ASYNC, + UNKNOWN +}; + +using CallbackFuncPairList = std::list&)>>>; + class JSUIExtensionProxy : public Referenced { public: JSUIExtensionProxy() = default; @@ -47,8 +55,19 @@ private: static void Constructor(const JSCallbackInfo& info); static void Destructor(JSUIExtensionProxy* uiExtensionProxy); + CallbackFuncPairList::const_iterator FindCbList(napi_env env, napi_value cb, + CallbackFuncPairList& callbackFuncPairList); + void AddCallbackToList(napi_env env, napi_value cb, napi_handle_scope scope, RegisterType type, + const std::function&)>&& onFunc); + void DeleteCallbackFromList(int argc, napi_env env, napi_value cb, RegisterType type); + std::list&)>> GetOnFuncList(RegisterType type); + RegisterType GetRegisterType(const std::string& strType); + RefPtr proxy_; int32_t instanceId_ = -1; + CallbackFuncPairList onSyncOnCallbackList_; + CallbackFuncPairList onAsyncOnCallbackList_; + std::mutex callbackLisLock_; }; } // namespace OHOS::Ace::Framework #endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_UI_EXTENSION_H diff --git a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.cpp b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.cpp index a553ac652bf92d7eb7328fccd9524eda3e068d1f..5d659c92f18b9bc0895c7c62ad40da5a540694f0 100755 --- a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.cpp +++ b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.cpp @@ -653,9 +653,10 @@ void UIExtensionPattern::SetOnRemoteReadyCallback(const std::function&)>&& callback) +void UIExtensionPattern::SetOnSyncOnCallbackList( + const std::list&)>>&& callbackList) { - onSyncOnCallback_ = std::move(callback); + onSyncOnCallbackList_ = std::move(callbackList); auto pipeline = PipelineBase::GetCurrentContext(); CHECK_NULL_VOID(pipeline); @@ -668,16 +669,22 @@ void UIExtensionPattern::SetOnSyncOnCallback(const std::functionPostTask([weak, instanceId]() { ContainerScope scope(instanceId); auto pattern = weak.Upgrade(); - if (pattern && pattern->onSyncOnCallback_) { - pattern->onSyncOnCallback_(MakeRefPtr(pattern->session_, pattern)); + if (!pattern) { + return; + } + for (const auto& callback : pattern->onSyncOnCallbackList_) { + if (callback) { + callback(MakeRefPtr(pattern->session_, pattern)); + } } }, TaskExecutor::TaskType::UI); }; } -void UIExtensionPattern::SetOnAsyncOnCallback(const std::function&)>&& callback) +void UIExtensionPattern::SetOnAsyncOnCallbackList( + const std::list&)>>&& callbackList) { - onAsyncOnCallback_ = std::move(callback); + onAsyncOnCallbackList_ = std::move(callbackList); auto pipeline = PipelineBase::GetCurrentContext(); CHECK_NULL_VOID(pipeline); @@ -690,37 +697,28 @@ void UIExtensionPattern::SetOnAsyncOnCallback(const std::functionPostTask([weak, instanceId]() { ContainerScope scope(instanceId); auto pattern = weak.Upgrade(); - if (pattern && pattern->onAsyncOnCallback_) { - pattern->onAsyncOnCallback_(MakeRefPtr(pattern->session_, pattern)); + if (!pattern) { + return; + } + for (const auto& callback : pattern->onAsyncOnCallbackList_) { + if (callback) { + callback(MakeRefPtr(pattern->session_, pattern)); + } } }, TaskExecutor::TaskType::UI); }; } -void UIExtensionPattern::SetOnSyncOffCallback(const std::function&)>&& callback) +void UIExtensionPattern::SetOnSyncOffCallbackList( + const std::list&)>>&& callbackList) { - onSyncOnCallback_ = std::move(callback); - - auto pipeline = PipelineBase::GetCurrentContext(); - CHECK_NULL_VOID(pipeline); - auto taskExecutor = pipeline->GetTaskExecutor(); - CHECK_NULL_VOID(taskExecutor); - sptr extensionSession(static_cast(session_.GetRefPtr())); - auto extSessionEventCallback = extensionSession->GetExtensionSessionEventCallback(); - extSessionEventCallback->notifySyncOnFunc_ = nullptr; + onSyncOnCallbackList_ = std::move(callbackList); } -void UIExtensionPattern::SetOnAsyncOffCallback(const std::function&)>&& callback) +void UIExtensionPattern::SetOnAsyncOffCallbackList( + const std::list&)>>&& callbackList) { - onAsyncOnCallback_ = std::move(callback); - - auto pipeline = PipelineBase::GetCurrentContext(); - CHECK_NULL_VOID(pipeline); - auto taskExecutor = pipeline->GetTaskExecutor(); - CHECK_NULL_VOID(taskExecutor); - sptr extensionSession(static_cast(session_.GetRefPtr())); - auto extSessionEventCallback = extensionSession->GetExtensionSessionEventCallback(); - extSessionEventCallback->notifyAsyncOnFunc_ = nullptr; + onAsyncOnCallbackList_ = std::move(callbackList); } void UIExtensionPattern::SetModalOnRemoteReadyCallback( diff --git a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.h b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.h index 2711473667dd902a928f9ffa4a28f1d121306a00..ccae173fa7acfd624f634179f45a19eb9a97d9a8 100644 --- a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.h +++ b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_pattern.h @@ -75,10 +75,14 @@ public: void SetModalOnRemoteReadyCallback( const std::function&)>&& callback); void SetOnRemoteReadyCallback(const std::function&)>&& callback); - void SetOnSyncOnCallback(const std::function&)>&& callback); - void SetOnAsyncOnCallback(const std::function&)>&& callback); - void SetOnSyncOffCallback(const std::function&)>&& callback); - void SetOnAsyncOffCallback(const std::function&)>&& callback); + void SetOnSyncOnCallbackList( + const std::list&)>>&& callbackList); + void SetOnAsyncOnCallbackList( + const std::list&)>>&& callbackList); + void SetOnSyncOffCallbackList( + const std::list&)>>&& callbackList); + void SetOnAsyncOffCallbackList( + const std::list&)>>&& callbackList); void SetOnReleaseCallback(const std::function&& callback); void SetOnResultCallback(const std::function&& callback); void SetOnReceiveCallback(const std::function&& callback); @@ -183,8 +187,8 @@ private: std::function onModalDestroy_; std::function&)> onModalRemoteReadyCallback_; std::function&)> onRemoteReadyCallback_; - std::function&)> onSyncOnCallback_; - std::function&)> onAsyncOnCallback_; + std::list&)>> onSyncOnCallbackList_; + std::list&)>> onAsyncOnCallbackList_; std::function onReleaseCallback_; std::function onResultCallback_; std::function onReceiveCallback_;