• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/devtools/devtools_manager_impl.h"
6 
7 #include <vector>
8 
9 #include "base/bind.h"
10 #include "base/message_loop/message_loop.h"
11 #include "content/browser/devtools/devtools_netlog_observer.h"
12 #include "content/browser/devtools/render_view_devtools_agent_host.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/devtools_client_host.h"
17 
18 namespace content {
19 
20 // static
GetInstance()21 DevToolsManager* DevToolsManager::GetInstance() {
22   return DevToolsManagerImpl::GetInstance();
23 }
24 
25 // static
GetInstance()26 DevToolsManagerImpl* DevToolsManagerImpl::GetInstance() {
27   return Singleton<DevToolsManagerImpl>::get();
28 }
29 
DevToolsManagerImpl()30 DevToolsManagerImpl::DevToolsManagerImpl() {
31 }
32 
~DevToolsManagerImpl()33 DevToolsManagerImpl::~DevToolsManagerImpl() {
34   DCHECK(agent_to_client_host_.empty());
35   DCHECK(client_to_agent_host_.empty());
36 }
37 
GetDevToolsClientHostFor(DevToolsAgentHostImpl * agent_host_impl)38 DevToolsClientHost* DevToolsManagerImpl::GetDevToolsClientHostFor(
39     DevToolsAgentHostImpl* agent_host_impl) {
40   AgentToClientHostMap::iterator it =
41       agent_to_client_host_.find(agent_host_impl);
42   if (it != agent_to_client_host_.end())
43     return it->second;
44   return NULL;
45 }
46 
GetDevToolsAgentHostFor(DevToolsClientHost * client_host)47 DevToolsAgentHost* DevToolsManagerImpl::GetDevToolsAgentHostFor(
48     DevToolsClientHost* client_host) {
49   ClientToAgentHostMap::iterator it = client_to_agent_host_.find(client_host);
50   if (it != client_to_agent_host_.end())
51     return it->second.get();
52   return NULL;
53 }
54 
RegisterDevToolsClientHostFor(DevToolsAgentHost * agent_host,DevToolsClientHost * client_host)55 void DevToolsManagerImpl::RegisterDevToolsClientHostFor(
56     DevToolsAgentHost* agent_host,
57     DevToolsClientHost* client_host) {
58   DevToolsAgentHostImpl* agent_host_impl =
59       static_cast<DevToolsAgentHostImpl*>(agent_host);
60   DevToolsClientHost* old_client_host =
61       GetDevToolsClientHostFor(agent_host_impl);
62   if (old_client_host) {
63     old_client_host->ReplacedWithAnotherClient();
64     UnregisterDevToolsClientHostFor(agent_host_impl);
65   }
66   BindClientHost(agent_host_impl, client_host);
67   agent_host_impl->Attach();
68 }
69 
DispatchOnInspectorBackend(DevToolsClientHost * from,const std::string & message)70 bool DevToolsManagerImpl::DispatchOnInspectorBackend(
71     DevToolsClientHost* from,
72     const std::string& message) {
73   DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(from);
74   if (!agent_host)
75     return false;
76   DevToolsAgentHostImpl* agent_host_impl =
77       static_cast<DevToolsAgentHostImpl*>(agent_host);
78   agent_host_impl->DispatchOnInspectorBackend(message);
79   return true;
80 }
81 
DispatchOnInspectorFrontend(DevToolsAgentHost * agent_host,const std::string & message)82 void DevToolsManagerImpl::DispatchOnInspectorFrontend(
83     DevToolsAgentHost* agent_host,
84     const std::string& message) {
85   DevToolsAgentHostImpl* agent_host_impl =
86       static_cast<DevToolsAgentHostImpl*>(agent_host);
87   DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
88   if (!client_host) {
89     // Client window was closed while there were messages
90     // being sent to it.
91     return;
92   }
93   client_host->DispatchOnInspectorFrontend(message);
94 }
95 
ClientHostClosing(DevToolsClientHost * client_host)96 void DevToolsManagerImpl::ClientHostClosing(DevToolsClientHost* client_host) {
97   DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(client_host);
98   if (!agent_host)
99     return;
100   DevToolsAgentHostImpl* agent_host_impl =
101       static_cast<DevToolsAgentHostImpl*>(agent_host);
102   UnbindClientHost(agent_host_impl, client_host);
103 }
104 
AgentHostClosing(DevToolsAgentHostImpl * agent_host)105 void DevToolsManagerImpl::AgentHostClosing(DevToolsAgentHostImpl* agent_host) {
106   UnregisterDevToolsClientHostFor(agent_host);
107 }
108 
UnregisterDevToolsClientHostFor(DevToolsAgentHostImpl * agent_host_impl)109 void DevToolsManagerImpl::UnregisterDevToolsClientHostFor(
110     DevToolsAgentHostImpl* agent_host_impl) {
111   DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
112   if (!client_host)
113     return;
114   UnbindClientHost(agent_host_impl, client_host);
115   client_host->InspectedContentsClosing();
116 }
117 
BindClientHost(DevToolsAgentHostImpl * agent_host,DevToolsClientHost * client_host)118 void DevToolsManagerImpl::BindClientHost(
119     DevToolsAgentHostImpl* agent_host,
120     DevToolsClientHost* client_host) {
121   DCHECK(agent_to_client_host_.find(agent_host) ==
122       agent_to_client_host_.end());
123   DCHECK(client_to_agent_host_.find(client_host) ==
124       client_to_agent_host_.end());
125 
126   if (client_to_agent_host_.empty()) {
127     BrowserThread::PostTask(
128         BrowserThread::IO,
129         FROM_HERE,
130         base::Bind(&DevToolsNetLogObserver::Attach));
131   }
132   agent_to_client_host_[agent_host] = client_host;
133   client_to_agent_host_[client_host] = agent_host;
134   agent_host->set_close_listener(this);
135 }
136 
UnbindClientHost(DevToolsAgentHostImpl * agent_host,DevToolsClientHost * client_host)137 void DevToolsManagerImpl::UnbindClientHost(DevToolsAgentHostImpl* agent_host,
138                                            DevToolsClientHost* client_host) {
139   DCHECK(agent_host);
140   scoped_refptr<DevToolsAgentHostImpl> protect(agent_host);
141   DCHECK(agent_to_client_host_.find(agent_host)->second ==
142       client_host);
143   DCHECK(client_to_agent_host_.find(client_host)->second.get() == agent_host);
144   agent_host->set_close_listener(NULL);
145 
146   agent_to_client_host_.erase(agent_host);
147   client_to_agent_host_.erase(client_host);
148 
149   if (client_to_agent_host_.empty()) {
150     BrowserThread::PostTask(
151         BrowserThread::IO,
152         FROM_HERE,
153         base::Bind(&DevToolsNetLogObserver::Detach));
154   }
155   // Lazy agent hosts can be deleted from within detach.
156   // Do not access agent_host below this line.
157   agent_host->Detach();
158 }
159 
CloseAllClientHosts()160 void DevToolsManagerImpl::CloseAllClientHosts() {
161   std::vector<DevToolsAgentHostImpl*> agents;
162   for (AgentToClientHostMap::iterator it =
163            agent_to_client_host_.begin();
164        it != agent_to_client_host_.end(); ++it) {
165     agents.push_back(it->first);
166   }
167   for (std::vector<DevToolsAgentHostImpl*>::iterator it = agents.begin();
168        it != agents.end(); ++it) {
169     UnregisterDevToolsClientHostFor(*it);
170   }
171 }
172 
AddAgentStateCallback(const Callback & callback)173 void DevToolsManagerImpl::AddAgentStateCallback(const Callback& callback) {
174   callbacks_.push_back(&callback);
175 }
176 
RemoveAgentStateCallback(const Callback & callback)177 void DevToolsManagerImpl::RemoveAgentStateCallback(const Callback& callback) {
178   CallbackContainer::iterator it =
179       std::find(callbacks_.begin(), callbacks_.end(), &callback);
180   DCHECK(it != callbacks_.end());
181   callbacks_.erase(it);
182 }
183 
NotifyObservers(DevToolsAgentHost * agent_host,bool attached)184 void DevToolsManagerImpl::NotifyObservers(DevToolsAgentHost* agent_host,
185                                           bool attached) {
186   CallbackContainer copy(callbacks_);
187   for (CallbackContainer::iterator it = copy.begin(); it != copy.end(); ++it)
188      (*it)->Run(agent_host, attached);
189 }
190 
191 }  // namespace content
192