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.
5 #include "content/browser/devtools/devtools_manager_impl.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"
23 DevToolsManager
* DevToolsManager::GetInstance() {
24 return DevToolsManagerImpl::GetInstance();
28 DevToolsManagerImpl
* DevToolsManagerImpl::GetInstance() {
29 return Singleton
<DevToolsManagerImpl
>::get();
32 DevToolsManagerImpl::DevToolsManagerImpl()
33 : delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()) {
36 DevToolsManagerImpl::~DevToolsManagerImpl() {
37 DCHECK(agent_to_client_host_
.empty());
38 DCHECK(client_to_agent_host_
.empty());
41 void DevToolsManagerImpl::Inspect(BrowserContext
* browser_context
,
42 DevToolsAgentHost
* agent_host
) {
44 delegate_
->Inspect(browser_context
, agent_host
);
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())
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();
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
);
75 BindClientHost(agent_host_impl
, client_host
);
76 agent_host_impl
->Attach();
79 bool DevToolsManagerImpl::DispatchOnInspectorBackend(
80 DevToolsClientHost
* from
,
81 const std::string
& message
) {
82 DevToolsAgentHost
* agent_host
= GetDevToolsAgentHostFor(from
);
85 DevToolsAgentHostImpl
* agent_host_impl
=
86 static_cast<DevToolsAgentHostImpl
*>(agent_host
);
87 agent_host_impl
->DispatchOnInspectorBackend(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
);
98 // Client window was closed while there were messages
102 client_host
->DispatchOnInspectorFrontend(message
);
105 void DevToolsManagerImpl::ClientHostClosing(DevToolsClientHost
* client_host
) {
106 DevToolsAgentHost
* agent_host
= GetDevToolsAgentHostFor(client_host
);
109 DevToolsAgentHostImpl
* agent_host_impl
=
110 static_cast<DevToolsAgentHostImpl
*>(agent_host
);
111 UnbindClientHost(agent_host_impl
, client_host
);
114 void DevToolsManagerImpl::AgentHostClosing(DevToolsAgentHostImpl
* agent_host
) {
115 UnregisterDevToolsClientHostFor(agent_host
);
118 void DevToolsManagerImpl::UnregisterDevToolsClientHostFor(
119 DevToolsAgentHostImpl
* agent_host_impl
) {
120 DevToolsClientHost
* client_host
= GetDevToolsClientHostFor(agent_host_impl
);
123 UnbindClientHost(agent_host_impl
, client_host
);
124 client_host
->InspectedContentsClosing();
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());
135 if (client_to_agent_host_
.empty()) {
136 BrowserThread::PostTask(
139 base::Bind(&DevToolsNetLogObserver::Attach
));
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);
146 void DevToolsManagerImpl::UnbindClientHost(DevToolsAgentHostImpl
* agent_host
,
147 DevToolsClientHost
* client_host
) {
149 scoped_refptr
<DevToolsAgentHostImpl
> protect(agent_host
);
150 DCHECK(agent_to_client_host_
.find(agent_host
)->second
==
152 DCHECK(client_to_agent_host_
.find(client_host
)->second
.get() == agent_host
);
153 agent_host
->set_close_listener(NULL
);
155 agent_to_client_host_
.erase(agent_host
);
156 client_to_agent_host_
.erase(client_host
);
158 if (client_to_agent_host_
.empty()) {
159 BrowserThread::PostTask(
162 base::Bind(&DevToolsNetLogObserver::Detach
));
164 // Lazy agent hosts can be deleted from within detach.
165 // Do not access agent_host below this line.
166 agent_host
->Detach();
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
);
176 for (std::vector
<DevToolsAgentHostImpl
*>::iterator it
= agents
.begin();
177 it
!= agents
.end(); ++it
) {
178 UnregisterDevToolsClientHostFor(*it
);
182 void DevToolsManagerImpl::AddAgentStateCallback(const Callback
& callback
) {
183 callbacks_
.push_back(&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
);
193 void DevToolsManagerImpl::NotifyObservers(DevToolsAgentHost
* agent_host
,
195 CallbackContainer
copy(callbacks_
);
197 delegate_
->DevToolsAgentStateChanged(agent_host
, attached
);
198 for (CallbackContainer::iterator it
= copy
.begin(); it
!= copy
.end(); ++it
)
199 (*it
)->Run(agent_host
, attached
);
202 } // namespace content