• 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/content_browser_client.h"
17 #include "content/public/browser/devtools_client_host.h"
18 #include "content/public/browser/devtools_manager_delegate.h"
19 
20 namespace content {
21 
22 // static
GetInstance()23 DevToolsManager* DevToolsManager::GetInstance() {
24   return DevToolsManagerImpl::GetInstance();
25 }
26 
27 // static
GetInstance()28 DevToolsManagerImpl* DevToolsManagerImpl::GetInstance() {
29   return Singleton<DevToolsManagerImpl>::get();
30 }
31 
DevToolsManagerImpl()32 DevToolsManagerImpl::DevToolsManagerImpl()
33     : delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()) {
34 }
35 
~DevToolsManagerImpl()36 DevToolsManagerImpl::~DevToolsManagerImpl() {
37   DCHECK(agent_to_client_host_.empty());
38   DCHECK(client_to_agent_host_.empty());
39 }
40 
Inspect(BrowserContext * browser_context,DevToolsAgentHost * agent_host)41 void DevToolsManagerImpl::Inspect(BrowserContext* browser_context,
42                                   DevToolsAgentHost* agent_host) {
43   if (delegate_)
44     delegate_->Inspect(browser_context, agent_host);
45 }
46 
GetDevToolsClientHostFor(DevToolsAgentHostImpl * agent_host_impl)47 DevToolsClientHost* DevToolsManagerImpl::GetDevToolsClientHostFor(
48     DevToolsAgentHostImpl* agent_host_impl) {
49   AgentToClientHostMap::iterator it =
50       agent_to_client_host_.find(agent_host_impl);
51   if (it != agent_to_client_host_.end())
52     return it->second;
53   return NULL;
54 }
55 
GetDevToolsAgentHostFor(DevToolsClientHost * client_host)56 DevToolsAgentHost* DevToolsManagerImpl::GetDevToolsAgentHostFor(
57     DevToolsClientHost* client_host) {
58   ClientToAgentHostMap::iterator it = client_to_agent_host_.find(client_host);
59   if (it != client_to_agent_host_.end())
60     return it->second.get();
61   return NULL;
62 }
63 
RegisterDevToolsClientHostFor(DevToolsAgentHost * agent_host,DevToolsClientHost * client_host)64 void DevToolsManagerImpl::RegisterDevToolsClientHostFor(
65     DevToolsAgentHost* agent_host,
66     DevToolsClientHost* client_host) {
67   DevToolsAgentHostImpl* agent_host_impl =
68       static_cast<DevToolsAgentHostImpl*>(agent_host);
69   DevToolsClientHost* old_client_host =
70       GetDevToolsClientHostFor(agent_host_impl);
71   if (old_client_host) {
72     old_client_host->ReplacedWithAnotherClient();
73     UnregisterDevToolsClientHostFor(agent_host_impl);
74   }
75   BindClientHost(agent_host_impl, client_host);
76   agent_host_impl->Attach();
77 }
78 
DispatchOnInspectorBackend(DevToolsClientHost * from,const std::string & message)79 bool DevToolsManagerImpl::DispatchOnInspectorBackend(
80     DevToolsClientHost* from,
81     const std::string& message) {
82   DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(from);
83   if (!agent_host)
84     return false;
85   DevToolsAgentHostImpl* agent_host_impl =
86       static_cast<DevToolsAgentHostImpl*>(agent_host);
87   agent_host_impl->DispatchOnInspectorBackend(message);
88   return true;
89 }
90 
DispatchOnInspectorFrontend(DevToolsAgentHost * agent_host,const std::string & message)91 void DevToolsManagerImpl::DispatchOnInspectorFrontend(
92     DevToolsAgentHost* agent_host,
93     const std::string& message) {
94   DevToolsAgentHostImpl* agent_host_impl =
95       static_cast<DevToolsAgentHostImpl*>(agent_host);
96   DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
97   if (!client_host) {
98     // Client window was closed while there were messages
99     // being sent to it.
100     return;
101   }
102   client_host->DispatchOnInspectorFrontend(message);
103 }
104 
ClientHostClosing(DevToolsClientHost * client_host)105 void DevToolsManagerImpl::ClientHostClosing(DevToolsClientHost* client_host) {
106   DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(client_host);
107   if (!agent_host)
108     return;
109   DevToolsAgentHostImpl* agent_host_impl =
110       static_cast<DevToolsAgentHostImpl*>(agent_host);
111   UnbindClientHost(agent_host_impl, client_host);
112 }
113 
AgentHostClosing(DevToolsAgentHostImpl * agent_host)114 void DevToolsManagerImpl::AgentHostClosing(DevToolsAgentHostImpl* agent_host) {
115   UnregisterDevToolsClientHostFor(agent_host);
116 }
117 
UnregisterDevToolsClientHostFor(DevToolsAgentHostImpl * agent_host_impl)118 void DevToolsManagerImpl::UnregisterDevToolsClientHostFor(
119     DevToolsAgentHostImpl* agent_host_impl) {
120   DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
121   if (!client_host)
122     return;
123   UnbindClientHost(agent_host_impl, client_host);
124   client_host->InspectedContentsClosing();
125 }
126 
BindClientHost(DevToolsAgentHostImpl * agent_host,DevToolsClientHost * client_host)127 void DevToolsManagerImpl::BindClientHost(
128     DevToolsAgentHostImpl* agent_host,
129     DevToolsClientHost* client_host) {
130   DCHECK(agent_to_client_host_.find(agent_host) ==
131       agent_to_client_host_.end());
132   DCHECK(client_to_agent_host_.find(client_host) ==
133       client_to_agent_host_.end());
134 
135   if (client_to_agent_host_.empty()) {
136     BrowserThread::PostTask(
137         BrowserThread::IO,
138         FROM_HERE,
139         base::Bind(&DevToolsNetLogObserver::Attach));
140   }
141   agent_to_client_host_[agent_host] = client_host;
142   client_to_agent_host_[client_host] = agent_host;
143   agent_host->set_close_listener(this);
144 }
145 
UnbindClientHost(DevToolsAgentHostImpl * agent_host,DevToolsClientHost * client_host)146 void DevToolsManagerImpl::UnbindClientHost(DevToolsAgentHostImpl* agent_host,
147                                            DevToolsClientHost* client_host) {
148   DCHECK(agent_host);
149   scoped_refptr<DevToolsAgentHostImpl> protect(agent_host);
150   DCHECK(agent_to_client_host_.find(agent_host)->second ==
151       client_host);
152   DCHECK(client_to_agent_host_.find(client_host)->second.get() == agent_host);
153   agent_host->set_close_listener(NULL);
154 
155   agent_to_client_host_.erase(agent_host);
156   client_to_agent_host_.erase(client_host);
157 
158   if (client_to_agent_host_.empty()) {
159     BrowserThread::PostTask(
160         BrowserThread::IO,
161         FROM_HERE,
162         base::Bind(&DevToolsNetLogObserver::Detach));
163   }
164   // Lazy agent hosts can be deleted from within detach.
165   // Do not access agent_host below this line.
166   agent_host->Detach();
167 }
168 
CloseAllClientHosts()169 void DevToolsManagerImpl::CloseAllClientHosts() {
170   std::vector<DevToolsAgentHostImpl*> agents;
171   for (AgentToClientHostMap::iterator it =
172            agent_to_client_host_.begin();
173        it != agent_to_client_host_.end(); ++it) {
174     agents.push_back(it->first);
175   }
176   for (std::vector<DevToolsAgentHostImpl*>::iterator it = agents.begin();
177        it != agents.end(); ++it) {
178     UnregisterDevToolsClientHostFor(*it);
179   }
180 }
181 
AddAgentStateCallback(const Callback & callback)182 void DevToolsManagerImpl::AddAgentStateCallback(const Callback& callback) {
183   callbacks_.push_back(&callback);
184 }
185 
RemoveAgentStateCallback(const Callback & callback)186 void DevToolsManagerImpl::RemoveAgentStateCallback(const Callback& callback) {
187   CallbackContainer::iterator it =
188       std::find(callbacks_.begin(), callbacks_.end(), &callback);
189   DCHECK(it != callbacks_.end());
190   callbacks_.erase(it);
191 }
192 
NotifyObservers(DevToolsAgentHost * agent_host,bool attached)193 void DevToolsManagerImpl::NotifyObservers(DevToolsAgentHost* agent_host,
194                                           bool attached) {
195   CallbackContainer copy(callbacks_);
196   if (delegate_)
197     delegate_->DevToolsAgentStateChanged(agent_host, attached);
198   for (CallbackContainer::iterator it = copy.begin(); it != copy.end(); ++it)
199      (*it)->Run(agent_host, attached);
200 }
201 
202 }  // namespace content
203