Commit 9e73e976 authored by Andrey Kosyakov's avatar Andrey Kosyakov Committed by Chromium LUCI CQ

Discard pending commands once target is reloaded after crash

Bug: 1128206
Change-Id: I7bc10beb585f07b6f49e61faae9cd8ab35eaa5b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2587606Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Commit-Queue: Andrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836789}
parent 7e5c7199
...@@ -71,6 +71,7 @@ const char kSessionId[] = "sessionId"; ...@@ -71,6 +71,7 @@ const char kSessionId[] = "sessionId";
// Clients match against this error message verbatim (http://crbug.com/1001678). // Clients match against this error message verbatim (http://crbug.com/1001678).
const char kTargetClosedMessage[] = "Inspected target navigated or closed"; const char kTargetClosedMessage[] = "Inspected target navigated or closed";
const char kTargetCrashedMessage[] = "Target crashed";
} // namespace } // namespace
DevToolsSession::PendingMessage::PendingMessage(PendingMessage&&) = default; DevToolsSession::PendingMessage::PendingMessage(PendingMessage&&) = default;
...@@ -418,6 +419,24 @@ void DevToolsSession::ResumeSendingMessagesToAgent() { ...@@ -418,6 +419,24 @@ void DevToolsSession::ResumeSendingMessagesToAgent() {
} }
} }
void DevToolsSession::ClearPendingMessages() {
for (auto it = pending_messages_.begin(); it != pending_messages_.end();) {
const PendingMessage& message = *it;
if (SpanEquals(crdtp::SpanFrom("Page.reload"),
crdtp::SpanFrom(message.method))) {
++it;
continue;
}
// Send error to the client and remove the message from pending.
SendProtocolResponse(
message.call_id,
crdtp::CreateErrorResponse(
message.call_id,
crdtp::DispatchResponse::ServerError(kTargetCrashedMessage)));
it = pending_messages_.erase(it);
}
}
// The following methods handle responses or notifications coming from // The following methods handle responses or notifications coming from
// the browser to the client. // the browser to the client.
void DevToolsSession::SendProtocolResponse( void DevToolsSession::SendProtocolResponse(
......
...@@ -64,6 +64,7 @@ class DevToolsSession : public protocol::FrontendChannel, ...@@ -64,6 +64,7 @@ class DevToolsSession : public protocol::FrontendChannel,
void DispatchProtocolMessage(base::span<const uint8_t> message); void DispatchProtocolMessage(base::span<const uint8_t> message);
void SuspendSendingMessagesToAgent(); void SuspendSendingMessagesToAgent();
void ResumeSendingMessagesToAgent(); void ResumeSendingMessagesToAgent();
void ClearPendingMessages();
using HandlersMap = using HandlersMap =
base::flat_map<std::string, base::flat_map<std::string,
......
...@@ -1052,6 +1052,47 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, PageCrashInFrame) { ...@@ -1052,6 +1052,47 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, PageCrashInFrame) {
EXPECT_EQ(frame_target_id, crashed_target_id); EXPECT_EQ(frame_target_id, crashed_target_id);
} }
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, PageCrashClearsPendingCommands) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
Attach();
std::unique_ptr<base::DictionaryValue> command_params;
command_params = std::make_unique<base::DictionaryValue>();
command_params->SetBoolean("discover", true);
SendCommand("Target.setDiscoverTargets", std::move(command_params));
std::string target_id;
std::unique_ptr<base::DictionaryValue> params;
std::string type;
params = WaitForNotification("Target.targetCreated", true);
ASSERT_TRUE(params->GetString("targetInfo.type", &type));
ASSERT_EQ(type, "page");
ASSERT_TRUE(params->GetString("targetInfo.targetId", &target_id));
SendCommand("Debugger.enable", nullptr, true);
params = std::make_unique<base::DictionaryValue>();
params->SetString("expression", "console.log('first page'); debugger");
SendCommand("Runtime.evaluate", std::move(params), false);
WaitForNotification("Debugger.paused");
{
content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
shell()->LoadURL(GURL(content::kChromeUICrashURL));
params = WaitForNotification("Target.targetCrashed", true);
}
ClearNotifications();
SendCommand("Page.reload", std::move(params), false);
WaitForNotification("Inspector.targetReloadedAfterCrash", true);
params = std::make_unique<base::DictionaryValue>();
params->SetString("expression", "console.log('second page')");
SendCommand("Runtime.evaluate", std::move(params), true);
EXPECT_THAT(console_messages_, ElementsAre("first page", "second page"));
}
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigationPreservesMessages) { IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigationPreservesMessages) {
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html"); GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
......
...@@ -245,8 +245,8 @@ void DevToolsProtocolTest::DispatchProtocolMessage( ...@@ -245,8 +245,8 @@ void DevToolsProtocolTest::DispatchProtocolMessage(
if (root->GetInteger("id", &id)) { if (root->GetInteger("id", &id)) {
result_ids_.push_back(id); result_ids_.push_back(id);
base::DictionaryValue* result; base::DictionaryValue* result;
ASSERT_TRUE(root->GetDictionary("result", &result)); bool have_result = root->GetDictionary("result", &result);
result_.reset(result->DeepCopy()); result_.reset(have_result ? result->DeepCopy() : nullptr);
in_dispatch_ = false; in_dispatch_ = false;
if (id && id == waiting_for_command_result_id_) { if (id && id == waiting_for_command_result_id_) {
waiting_for_command_result_id_ = 0; waiting_for_command_result_id_ = 0;
......
...@@ -565,6 +565,8 @@ void RenderFrameDevToolsAgentHost::UpdateFrameAlive() { ...@@ -565,6 +565,8 @@ void RenderFrameDevToolsAgentHost::UpdateFrameAlive() {
render_frame_alive_ = frame_host_ && frame_host_->IsRenderFrameLive(); render_frame_alive_ = frame_host_ && frame_host_->IsRenderFrameLive();
if (render_frame_alive_ && render_frame_crashed_) { if (render_frame_alive_ && render_frame_crashed_) {
render_frame_crashed_ = false; render_frame_crashed_ = false;
for (DevToolsSession* session : sessions())
session->ClearPendingMessages();
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this)) for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetReloadedAfterCrash(); inspector->TargetReloadedAfterCrash();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment