| Index: content/browser/devtools/render_frame_devtools_agent_host.cc
|
| diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
|
| index 2ac257fbc3b88d5d9e58b8c98377a0c6bc066a28..b4223fffd7eb821e0ceaed60bab620ab4798fa79 100644
|
| --- a/content/browser/devtools/render_frame_devtools_agent_host.cc
|
| +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
|
| @@ -6,8 +6,10 @@
|
|
|
| #include "base/basictypes.h"
|
| #include "base/command_line.h"
|
| +#include "base/json/json_reader.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| +#include "base/values.h"
|
| #include "content/browser/child_process_security_policy_impl.h"
|
| #include "content/browser/devtools/devtools_frame_trace_recorder.h"
|
| #include "content/browser/devtools/devtools_protocol_handler.h"
|
| @@ -99,6 +101,11 @@ class RenderFrameDevToolsAgentHost::FrameHostHolder {
|
| void Suspend();
|
| void Resume();
|
|
|
| + bool suspended() const { return suspended_; }
|
| + const std::string& last_loading_frame_id() const {
|
| + return last_loading_frame_id_;
|
| + }
|
| +
|
| private:
|
| void GrantPolicy();
|
| void RevokePolicy();
|
| @@ -113,6 +120,7 @@ class RenderFrameDevToolsAgentHost::FrameHostHolder {
|
| std::vector<std::pair<int, std::string>> pending_messages_;
|
| // <call_id> -> <session_id, message>
|
| std::map<int, std::pair<int, std::string>> sent_messages_;
|
| + std::string last_loading_frame_id_;
|
| };
|
|
|
| RenderFrameDevToolsAgentHost::FrameHostHolder::FrameHostHolder(
|
| @@ -220,6 +228,19 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient(
|
| pending_messages_.push_back(std::make_pair(session_id, message));
|
| else
|
| agent_->SendMessageToClient(session_id, message);
|
| +
|
| + // Store frameId when the frame starts loading to use it in case if the
|
| + // pending frame host is discarded.
|
| + if (last_loading_frame_id_.empty() &&
|
| + message.find("Page.frameStartedLoading") != std::string::npos) {
|
| + scoped_ptr<base::Value> message_content = base::JSONReader::Read(message);
|
| + base::DictionaryValue* message_dict;
|
| + if (message_content && message_content->GetAsDictionary(&message_dict)) {
|
| + base::DictionaryValue* params;
|
| + if (message_dict->GetDictionary("params", ¶ms))
|
| + params->GetString("frameId", &last_loading_frame_id_);
|
| + }
|
| + }
|
| }
|
|
|
| void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {
|
| @@ -390,7 +411,7 @@ void RenderFrameDevToolsAgentHost::SetPending(RenderFrameHostImpl* host) {
|
| // Can only be null in constructor.
|
| if (current_)
|
| current_->Suspend();
|
| - pending_->Suspend();
|
| + // Don't suspend pending_ as it may break clients.
|
|
|
| UpdateProtocolHandlers(host);
|
| }
|
| @@ -724,8 +745,19 @@ void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
|
| bool was_ignored_by_handler) {
|
| if (browser_side_navigation)
|
| return;
|
| - if (pending_ && pending_->host() == render_frame_host)
|
| + if (pending_ && pending_->host() == render_frame_host) {
|
| + // When a pending cross-process navigation gets cancelled, the client does
|
| + // not receive frameStoppedLoading event, which can cause problems with
|
| + // further operation. Forge the event to avoid that.
|
| + if (!pending_->suspended() && !pending_->last_loading_frame_id().empty()) {
|
| + SendMessageToClient(
|
| + session_id(),
|
| + "{\"method\":\"Page.frameStoppedLoading\",\"params\":"
|
| + "{\"frameId\":\"" + pending_->last_loading_frame_id() + "\"}}");
|
| + }
|
| +
|
| DiscardPending();
|
| + }
|
| }
|
|
|
| void RenderFrameDevToolsAgentHost::
|
|
|