Skip to content

Commit

Permalink
[headless/m109] Improved Simple CDP Client callback handling.
Browse files Browse the repository at this point in the history
Previous implementation of the asynchronous callbacks posted a task
for each result and event which is suboptimal. This CL changes logic
so that all the result and event callbacks are called from a single
task posted on the browser UI thread.

Drive by: fixed occasional use-after-move in event handler.

(cherry picked from commit 3acd45e)

Bug: 1382993
Change-Id: I031044a5bfdaab2b88455d1649f53e4adf053140
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4026625
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
Commit-Queue: Peter Kvitek <kvitekp@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1071300}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4035384
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/branch-heads/5414@{#142}
Cr-Branched-From: 4417ee5-refs/heads/main@{#1070088}
  • Loading branch information
Peter Kvitek authored and Chromium LUCI CQ committed Nov 18, 2022
1 parent 30eccb5 commit c2d40e2
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ source_set("unit_tests") {
":simple_devtools_protocol_client",
"//base",
"//content/public/browser",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
]
Expand Down
1 change: 1 addition & 0 deletions components/devtools/simple_devtools_protocol_client/DEPS
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
include_rules = [
"+content/public/browser",
"+content/public/test",
]
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ int g_next_message_id = 0;
} // namespace

SimpleDevToolsProtocolClient::SimpleDevToolsProtocolClient() = default;

SimpleDevToolsProtocolClient::SimpleDevToolsProtocolClient(
const std::string& session_id)
: session_id_(session_id) {}
Expand All @@ -44,10 +45,6 @@ SimpleDevToolsProtocolClient::~SimpleDevToolsProtocolClient() {
parent_client_->sessions_.erase(session_id_);
}

void SimpleDevToolsProtocolClient::InitBrowserMainThread() {
browser_main_thread_ = content::GetUIThreadTaskRunner({});
}

void SimpleDevToolsProtocolClient::AttachClient(
scoped_refptr<content::DevToolsAgentHost> agent_host) {
DCHECK(!agent_host_);
Expand Down Expand Up @@ -94,12 +91,19 @@ void SimpleDevToolsProtocolClient::DispatchProtocolMessage(
if (const std::string* session_id = message.FindString("sessionId")) {
auto it = sessions_.find(*session_id);
if (it != sessions_.cend()) {
it->second->DispatchProtocolMessage(std::move(message));
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&SimpleDevToolsProtocolClient::DispatchProtocolMessageTask,
base::Unretained(it->second), std::move(message)));
return;
}
}

DispatchProtocolMessage(std::move(message));
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&SimpleDevToolsProtocolClient::DispatchProtocolMessageTask,
base::Unretained(this), std::move(message)));
}

void SimpleDevToolsProtocolClient::AgentHostClosed(
Expand All @@ -110,7 +114,7 @@ void SimpleDevToolsProtocolClient::AgentHostClosed(
}
}

void SimpleDevToolsProtocolClient::DispatchProtocolMessage(
void SimpleDevToolsProtocolClient::DispatchProtocolMessageTask(
base::Value::Dict message) {
// Handle response message shutting down the host if it's unexpected.
if (absl::optional<int> id = message.FindInt(kId)) {
Expand All @@ -127,12 +131,7 @@ void SimpleDevToolsProtocolClient::DispatchProtocolMessage(
ResponseCallback callback(std::move(it->second));
pending_response_map_.erase(it);

if (browser_main_thread_) {
browser_main_thread_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), std::move(message)));
} else {
std::move(callback).Run(std::move(message));
}
std::move(callback).Run(std::move(message));
return;
}

Expand All @@ -154,12 +153,7 @@ void SimpleDevToolsProtocolClient::DispatchProtocolMessage(
for (auto& callback : handlers) {
if (first_callback || HasEventHandler(*event_name, callback)) {
first_callback = false;
if (browser_main_thread_) {
browser_main_thread_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), std::move(message)));
} else {
callback.Run(std::move(message));
}
callback.Run(message);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host.h"

Expand All @@ -33,8 +32,6 @@ class SimpleDevToolsProtocolClient : public content::DevToolsAgentHostClient {

~SimpleDevToolsProtocolClient() override;

void InitBrowserMainThread();

void AttachClient(scoped_refptr<content::DevToolsAgentHost> agent_host);
void DetachClient();

Expand Down Expand Up @@ -66,15 +63,14 @@ class SimpleDevToolsProtocolClient : public content::DevToolsAgentHostClient {
base::span<const uint8_t> json_message) override;
void AgentHostClosed(content::DevToolsAgentHost* agent_host) override;

void DispatchProtocolMessage(base::Value::Dict message);
void DispatchProtocolMessageTask(base::Value::Dict message);

void SendProtocolMessage(base::Value::Dict message);

bool HasEventHandler(const std::string& event_name,
const EventCallback& event_callback);

const std::string session_id_;
scoped_refptr<base::SequencedTaskRunner> browser_main_thread_;
base::raw_ptr<SimpleDevToolsProtocolClient> parent_client_ = nullptr;
base::flat_map<std::string, SimpleDevToolsProtocolClient*> sessions_;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

Expand Down Expand Up @@ -86,6 +87,11 @@ class SimpleDevToolsProtocolClientTest : public SimpleDevToolsProtocolClient,
SimpleDevToolsProtocolClientTest() {
AttachClient(new MockDevToolsAgentHost);
}

void RunUntilIdle() { task_environment_.RunUntilIdle(); }

private:
content::BrowserTaskEnvironment task_environment_;
};

class SimpleDevToolsProtocolClientSendCommandTest
Expand All @@ -99,6 +105,7 @@ class SimpleDevToolsProtocolClientSendCommandTest
base::BindOnce(&SimpleDevToolsProtocolClientSendCommandTest::
OnSendCommand1Response,
base::Unretained(this)));
RunUntilIdle();
}

void OnSendCommand1Response(base::Value::Dict params) {
Expand All @@ -108,6 +115,7 @@ class SimpleDevToolsProtocolClientSendCommandTest
base::BindOnce(&SimpleDevToolsProtocolClientSendCommandTest::
OnSendCommand2Response,
base::Unretained(this)));
RunUntilIdle();
}

void OnSendCommand2Response(base::Value::Dict params) {
Expand All @@ -120,6 +128,7 @@ class SimpleDevToolsProtocolClientSendCommandTest
self->OnSendCommand3Response(std::move(params));
},
base::Unretained(this)));
RunUntilIdle();
}

void OnSendCommand3Response(base::Value::Dict params) {
Expand Down Expand Up @@ -147,6 +156,7 @@ class SimpleDevToolsProtocolClientEventHandlerTest
base::JSONWriter::Write(base::Value(std::move(params)), &json);
DispatchProtocolMessage(agent_host_.get(),
base::as_bytes(base::make_span(json)));
RunUntilIdle();
}
};

Expand Down
2 changes: 0 additions & 2 deletions headless/app/headless_shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,6 @@ void HeadlessShell::OnBrowserStart(HeadlessBrowser* browser) {
}
#endif

devtools_client_.InitBrowserMainThread();

file_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT});

Expand Down

0 comments on commit c2d40e2

Please sign in to comment.