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:: |