| 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 d572f3a01ce58545eedcd97df0338556273a8d8d..ef1161ecc86426a0cf778303d82e07e98ed9717f 100644
|
| --- a/content/browser/devtools/render_frame_devtools_agent_host.cc
|
| +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
|
| @@ -7,6 +7,7 @@
|
| #include <tuple>
|
| #include <utility>
|
|
|
| +#include "base/containers/flat_map.h"
|
| #include "base/guid.h"
|
| #include "base/json/json_reader.h"
|
| #include "base/lazy_instance.h"
|
| @@ -118,6 +119,7 @@ class RenderFrameDevToolsAgentHost::FrameHostHolder {
|
| void Attach(DevToolsSession* session);
|
| void Reattach(FrameHostHolder* old);
|
| void Detach(int session_id);
|
| + void Disconnect();
|
| void DispatchProtocolMessage(int session_id,
|
| int call_id,
|
| const std::string& method,
|
| @@ -130,36 +132,40 @@ class RenderFrameDevToolsAgentHost::FrameHostHolder {
|
| private:
|
| void GrantPolicy();
|
| void RevokePolicy();
|
| - void SendMessageToClient(int session_id, const std::string& message);
|
| + void SendChunkedMessage(int session_id, const std::string& message);
|
| +
|
| + struct MethodAndMessage {
|
| + std::string method;
|
| + std::string message;
|
| + };
|
| +
|
| + struct SessionInfo {
|
| + std::unique_ptr<DevToolsMessageChunkProcessor> chunk_processor;
|
| + std::vector<std::string> pending_messages;
|
| + // <call_id> -> MethodAndMessage
|
| + std::map<int, MethodAndMessage> sent_messages;
|
| + // These are sent messages for which we got a reply while suspended.
|
| + std::map<int, MethodAndMessage>
|
| + sent_messages_whose_reply_came_while_suspended;
|
| + };
|
|
|
| RenderFrameDevToolsAgentHost* agent_;
|
| RenderFrameHostImpl* host_;
|
| - bool attached_;
|
| bool suspended_;
|
| - DevToolsMessageChunkProcessor chunk_processor_;
|
| - // <session_id, message>
|
| - std::vector<std::pair<int, std::string>> pending_messages_;
|
| - // <call_id> -> PendingMessage
|
| - std::map<int, PendingMessage> sent_messages_;
|
| - // These are sent messages for which we got a reply while suspended.
|
| - std::map<int, PendingMessage> sent_messages_whose_reply_came_while_suspended_;
|
| + bool disconnected_;
|
| + base::flat_map<int, SessionInfo> session_infos_;
|
| };
|
|
|
| RenderFrameDevToolsAgentHost::FrameHostHolder::FrameHostHolder(
|
| - RenderFrameDevToolsAgentHost* agent, RenderFrameHostImpl* host)
|
| - : agent_(agent),
|
| - host_(host),
|
| - attached_(false),
|
| - suspended_(false),
|
| - chunk_processor_(base::Bind(
|
| - &RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient,
|
| - base::Unretained(this))) {
|
| + RenderFrameDevToolsAgentHost* agent,
|
| + RenderFrameHostImpl* host)
|
| + : agent_(agent), host_(host), suspended_(false), disconnected_(false) {
|
| DCHECK(agent_);
|
| DCHECK(host_);
|
| }
|
|
|
| RenderFrameDevToolsAgentHost::FrameHostHolder::~FrameHostHolder() {
|
| - if (attached_)
|
| + if (!disconnected_ && !session_infos_.empty())
|
| RevokePolicy();
|
| }
|
|
|
| @@ -168,37 +174,57 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Attach(
|
| host_->Send(new DevToolsAgentMsg_Attach(
|
| host_->GetRoutingID(), agent_->GetId(), session->session_id()));
|
| GrantPolicy();
|
| - attached_ = true;
|
| + SessionInfo& info = session_infos_[session->session_id()];
|
| + info.chunk_processor.reset(new DevToolsMessageChunkProcessor(base::Bind(
|
| + &RenderFrameDevToolsAgentHost::FrameHostHolder::SendChunkedMessage,
|
| + base::Unretained(this))));
|
| }
|
|
|
| void RenderFrameDevToolsAgentHost::FrameHostHolder::Reattach(
|
| FrameHostHolder* old) {
|
| - if (old)
|
| - chunk_processor_.set_state_cookie(old->chunk_processor_.state_cookie());
|
| - host_->Send(new DevToolsAgentMsg_Reattach(
|
| - host_->GetRoutingID(), agent_->GetId(), agent_->session()->session_id(),
|
| - chunk_processor_.state_cookie()));
|
| + int session_id = agent_->session()->session_id();
|
| + SessionInfo& info = session_infos_[session_id];
|
| + info.chunk_processor.reset(new DevToolsMessageChunkProcessor(base::Bind(
|
| + &RenderFrameDevToolsAgentHost::FrameHostHolder::SendChunkedMessage,
|
| + base::Unretained(this))));
|
| + SessionInfo* old_info = nullptr;
|
| if (old) {
|
| + auto it = old->session_infos_.find(session_id);
|
| + old_info = it != old->session_infos_.end() ? &(it->second) : nullptr;
|
| + }
|
| + if (old_info)
|
| + info.chunk_processor->set_state_cookie(
|
| + old_info->chunk_processor->state_cookie());
|
| + host_->Send(new DevToolsAgentMsg_Reattach(
|
| + host_->GetRoutingID(), agent_->GetId(), session_id,
|
| + info.chunk_processor->state_cookie()));
|
| + if (old_info) {
|
| if (IsBrowserSideNavigationEnabled()) {
|
| for (const auto& pair :
|
| - old->sent_messages_whose_reply_came_while_suspended_) {
|
| - DispatchProtocolMessage(pair.second.session_id, pair.first,
|
| - pair.second.method, pair.second.message);
|
| + old_info->sent_messages_whose_reply_came_while_suspended) {
|
| + DispatchProtocolMessage(session_id, pair.first, pair.second.method,
|
| + pair.second.message);
|
| }
|
| }
|
| - for (const auto& pair : old->sent_messages_) {
|
| - DispatchProtocolMessage(pair.second.session_id, pair.first,
|
| - pair.second.method, pair.second.message);
|
| + for (const auto& pair : old_info->sent_messages) {
|
| + DispatchProtocolMessage(session_id, pair.first, pair.second.method,
|
| + pair.second.message);
|
| }
|
| }
|
| GrantPolicy();
|
| - attached_ = true;
|
| }
|
|
|
| void RenderFrameDevToolsAgentHost::FrameHostHolder::Detach(int session_id) {
|
| host_->Send(new DevToolsAgentMsg_Detach(host_->GetRoutingID(), session_id));
|
| RevokePolicy();
|
| - attached_ = false;
|
| + session_infos_.erase(session_id);
|
| +}
|
| +
|
| +void RenderFrameDevToolsAgentHost::FrameHostHolder::Disconnect() {
|
| + for (auto& it : session_infos_)
|
| + host_->Send(new DevToolsAgentMsg_Detach(host_->GetRoutingID(), it.first));
|
| + RevokePolicy();
|
| + disconnected_ = true;
|
| }
|
|
|
| void RenderFrameDevToolsAgentHost::FrameHostHolder::GrantPolicy() {
|
| @@ -235,12 +261,12 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::DispatchProtocolMessage(
|
| const std::string& message) {
|
| host_->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(
|
| host_->GetRoutingID(), session_id, call_id, method, message));
|
| - sent_messages_[call_id] = { session_id, method, message };
|
| + session_infos_[session_id].sent_messages[call_id] = {method, message};
|
| }
|
|
|
| void RenderFrameDevToolsAgentHost::FrameHostHolder::InspectElement(
|
| int session_id, int x, int y) {
|
| - DCHECK(attached_);
|
| + DCHECK(session_infos_.find(session_id) != session_infos_.end());
|
| host_->Send(new DevToolsAgentMsg_InspectElement(
|
| host_->GetRoutingID(), session_id, x, y));
|
| }
|
| @@ -248,20 +274,29 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::InspectElement(
|
| bool
|
| RenderFrameDevToolsAgentHost::FrameHostHolder::ProcessChunkedMessageFromAgent(
|
| const DevToolsMessageChunk& chunk) {
|
| - return chunk_processor_.ProcessChunkedMessageFromAgent(chunk);
|
| + auto it = session_infos_.find(chunk.session_id);
|
| + if (it != session_infos_.end())
|
| + return it->second.chunk_processor->ProcessChunkedMessageFromAgent(chunk);
|
| + return false;
|
| }
|
|
|
| -void RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient(
|
| +void RenderFrameDevToolsAgentHost::FrameHostHolder::SendChunkedMessage(
|
| int session_id,
|
| const std::string& message) {
|
| - int id = chunk_processor_.last_call_id();
|
| - PendingMessage sent_message = sent_messages_[id];
|
| - sent_messages_.erase(id);
|
| + auto it = session_infos_.find(session_id);
|
| + if (it == session_infos_.end())
|
| + return;
|
| + SessionInfo& info = it->second;
|
| + int id = info.chunk_processor->last_call_id();
|
| + MethodAndMessage sent_message = info.sent_messages[id];
|
| + info.sent_messages.erase(id);
|
| if (suspended_) {
|
| - sent_messages_whose_reply_came_while_suspended_[id] = sent_message;
|
| - pending_messages_.push_back(std::make_pair(session_id, message));
|
| + info.sent_messages_whose_reply_came_while_suspended[id] = sent_message;
|
| + info.pending_messages.push_back(message);
|
| } else {
|
| - agent_->SendMessageToClient(session_id, message);
|
| + // Filter any messages from previous sessions.
|
| + if (agent_->session() && agent_->session()->session_id() == session_id)
|
| + agent_->session()->SendMessageToClient(message);
|
| // |this| may be deleted at this point.
|
| }
|
| }
|
| @@ -272,11 +307,16 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {
|
|
|
| void RenderFrameDevToolsAgentHost::FrameHostHolder::Resume() {
|
| suspended_ = false;
|
| - for (const auto& pair : pending_messages_)
|
| - agent_->SendMessageToClient(pair.first, pair.second);
|
| - std::vector<std::pair<int, std::string>> empty;
|
| - pending_messages_.swap(empty);
|
| - sent_messages_whose_reply_came_while_suspended_.clear();
|
| + for (auto& it : session_infos_) {
|
| + SessionInfo& info = it.second;
|
| + if (agent_->session() && agent_->session()->session_id() == it.first) {
|
| + for (const std::string& message : info.pending_messages)
|
| + agent_->session()->SendMessageToClient(message);
|
| + }
|
| + std::vector<std::string> empty;
|
| + info.pending_messages.swap(empty);
|
| + info.sent_messages_whose_reply_came_while_suspended.clear();
|
| + }
|
| }
|
|
|
| // RenderFrameDevToolsAgentHost ------------------------------------------------
|
| @@ -976,8 +1016,7 @@ void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
|
| DiscardPending();
|
| UpdateProtocolHandlers(nullptr);
|
| disconnected_ = std::move(current_);
|
| - if (session())
|
| - disconnected_->Detach(session()->session_id());
|
| + disconnected_->Disconnect();
|
| frame_tree_node_ = nullptr;
|
| in_navigation_protocol_message_buffer_.clear();
|
| navigating_handles_.clear();
|
|
|