From 897b51109adad73376539df223a1b22d85c9e880 Mon Sep 17 00:00:00 2001 From: liuxiao_310 Date: Fri, 12 Sep 2025 01:49:40 +0800 Subject: [PATCH] web connectNative deal mutilThread . Signed-off-by: liuxiao_310 --- .../declarative_frontend/jsview/js_web.cpp | 12 +-- .../components/web/resource/web_delegate.cpp | 92 +++++++++++++------ 2 files changed, 66 insertions(+), 38 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_web.cpp b/frameworks/bridge/declarative_frontend/jsview/js_web.cpp index 6c89810db3d..e4b7ddaf056 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_web.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_web.cpp @@ -2046,13 +2046,11 @@ public: void OnConnect(const JSCallbackInfo &args) { - int connectid; - if ((args.Length() <= 0) || !(args[0]->IsNumber())) { TAG_LOGW(AceLogTag::ACE_WEB, "JSWebNativeMessageCallback OnConnect type error"); return; } - connectid = args[0]->ToNumber(); + int connectid = args[0]->ToNumber(); TAG_LOGI(AceLogTag::ACE_WEB, "JSWebNativeMessageCallback OnConnect, connectid=%{public}d", connectid); if (callback_) { @@ -2062,13 +2060,11 @@ public: void OnDisconnect(const JSCallbackInfo &args) { - int connectid; - if ((args.Length() <= 0) || !(args[0]->IsNumber())) { TAG_LOGW(AceLogTag::ACE_WEB, "JSWebNativeMessageCallback OnDisconnect type error"); return; } - connectid = args[0]->ToNumber(); + int connectid = args[0]->ToNumber(); if (callback_) { callback_->OnDisconnect(connectid); } @@ -2076,13 +2072,11 @@ public: void OnFailed(const JSCallbackInfo &args) { - int failedCode; - if ((args.Length() <= 0) || !(args[0]->IsNumber())) { TAG_LOGW(AceLogTag::ACE_WEB, "JSWebNativeMessageCallback failedCode type error"); return; } - failedCode = args[0]->ToNumber(); + int failedCode = args[0]->ToNumber(); TAG_LOGW(AceLogTag::ACE_WEB, "JSWebNativeMessageCallback OnFailed, failedCode is %{public}d", failedCode); if (callback_) { diff --git a/frameworks/core/components/web/resource/web_delegate.cpp b/frameworks/core/components/web/resource/web_delegate.cpp index 5e2d8c8350e..8ed02cde8ec 100644 --- a/frameworks/core/components/web/resource/web_delegate.cpp +++ b/frameworks/core/components/web/resource/web_delegate.cpp @@ -9195,53 +9195,87 @@ std::string WebDelegate::OnWebNativeMessage(std::shared_ptr callback) { if (!callback) { - return std::string("error:-1"); + return "error:4201"; } auto context = context_.Upgrade(); - CHECK_NULL_RETURN(context, std::string("error:-1")); - auto pipelineContext = DynamicCast(context); - CHECK_NULL_RETURN(pipelineContext, std::string("error:-1")); + if (!context) { + return "error:4202"; + } auto pipeline = NG::PipelineContext::GetCurrentContextSafely(); - std::mutex mtx; - std::condition_variable cv; - bool isCallbackDone = false; - std::string callbackResult; - bool isTimeout = false; - constexpr auto timeout = std::chrono::seconds(TIMEOUT_SECONDS); + if (pipeline && pipeline->CheckThreadSafe()) { + TAG_LOGE(AceLogTag::ACE_WEB, "OnWebNativeMessage doesn't run on UI thread"); + return "error:4203"; + } + struct SharedState { + std::mutex mtx; + std::condition_variable cv; + bool isCallbackDone = false; + bool isTimeout = false; + std::string callbackResult; + std::atomic hasBeenCalled{false}; + }; + auto sharedState = std::make_shared(); auto jsTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::JS); jsTaskExecutor.PostSyncTask( - [weak = WeakClaim(this), info, callback, &mtx, &cv, &isCallbackDone, &callbackResult, &isTimeout]() { - auto setResultAndNotify = [&](const std::string& result = "") { - std::unique_lock lock(mtx); - if (!isTimeout) { - callbackResult = result; - isCallbackDone = true; + [weak = WeakClaim(this), info, callback, sharedState]() { + { + std::lock_guard lock(sharedState->mtx); + if (sharedState->isTimeout) { + return; } - cv.notify_one(); - }; + } auto delegate = weak.Upgrade(); - if (!delegate) return setResultAndNotify(); + if (!delegate) { + return; + } auto webPattern = delegate->webPattern_.Upgrade(); - if (!webPattern) return setResultAndNotify(); + if (!webPattern) { + return; + } auto webNativeMessageCallback = webPattern->GetWebNativeMessageConnectCallback(); - if (!webNativeMessageCallback) return setResultAndNotify(); + if (!webNativeMessageCallback) { + return; + } auto wrappedCallback = AceType::MakeRefPtr(callback); - wrappedCallback->SetCompletionHandler([&](const std::string &result) { setResultAndNotify(result); }); + wrappedCallback->SetCompletionHandler([sharedState](const std::string &result) { + bool expected = false; + if (!sharedState->hasBeenCalled.compare_exchange_strong(expected, true)) { + TAG_LOGW(AceLogTag::ACE_WEB, "OnWebNativeMessage callback called multiple times, ignoring"); + return; + } + std::unique_lock lock(sharedState->mtx); + if (sharedState->isTimeout) { + TAG_LOGW(AceLogTag::ACE_WEB, "OnWebNativeMessage callback after timeout"); + return; + } + sharedState->callbackResult = result; + sharedState->isCallbackDone = true; + sharedState->cv.notify_one(); + }); webNativeMessageCallback(std::make_shared(info->GetBundleName(), info->GetExtensionOrigin(), info->GetMessageReadPipe(), info->GetMessageWritePipe(), wrappedCallback)); - }, "ArkUIWebNativeMessage"); + }, + "ArkUIWebNativeMessage"); + TAG_LOGI(AceLogTag::ACE_WEB, "OnWebNativeMessage waiting start"); { - std::unique_lock lock(mtx); - if (!cv.wait_for(lock, timeout, [&]() { return isCallbackDone; })) { - isTimeout = true; - callbackResult = "error:4201"; - return callbackResult; + std::unique_lock lock(sharedState->mtx); + if (!sharedState->cv.wait_for( + lock, std::chrono::seconds(TIMEOUT_SECONDS), [sharedState]() { return sharedState->isCallbackDone; })) { + bool expected = false; + if (sharedState->hasBeenCalled.compare_exchange_strong(expected, true)) { + sharedState->isTimeout = true; + sharedState->callbackResult = "error:4204"; + TAG_LOGW(AceLogTag::ACE_WEB, "OnWebNativeMessage return by timeout"); + } else { + sharedState->cv.wait(lock, [sharedState]() { return sharedState->isCallbackDone; }); + } } } - return callbackResult; + TAG_LOGI(AceLogTag::ACE_WEB, "OnWebNativeMessage return result"); + return sharedState->callbackResult; } void WebDelegate::SetImeShow(bool visible) -- Gitee