12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/devtools/devtools_agent_host_impl.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map> 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <vector> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/guid.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/devtools/devtools_manager.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/devtools/embedded_worker_devtools_manager.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/browser/devtools/forwarding_agent_host.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/devtools_manager_delegate.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::map<std::string, DevToolsAgentHostImpl*> Instances; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER; 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)typedef std::vector<const DevToolsAgentHost::AgentStateCallback*> 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AgentStateCallbacks; 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)base::LazyInstance<AgentStateCallbacks>::Leaky g_callbacks = 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciDevToolsAgentHost::List DevToolsAgentHost::GetOrCreateAll() { 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci List result = EmbeddedWorkerDevToolsManager::GetInstance() 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->GetOrCreateAllAgentHosts(); 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<WebContents*> wc_list = 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsAgentHostImpl::GetInspectableWebContents(); 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::vector<WebContents*>::iterator it = wc_list.begin(); 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it != wc_list.end(); ++it) { 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result.push_back(GetOrCreateFor(*it)); 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsAgentHostImpl::DevToolsAgentHostImpl() 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : id_(base::GenerateGUID()), 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_(NULL) { 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_instances.Get()[id_] = this; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsAgentHostImpl::~DevToolsAgentHostImpl() { 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_instances.Get().erase(g_instances.Get().find(id_)); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForId( 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& id) { 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (g_instances == NULL) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instances::iterator it = g_instances.Get().find(id); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it == g_instances.Get().end()) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return it->second; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//static 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::Create( 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DevToolsExternalAgentProxyDelegate* delegate) { 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return new ForwardingAgentHost(delegate); 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) { 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<DevToolsAgentHostImpl> protect(this); 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (client_) { 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_->AgentHostClosed(this, true); 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Detach(); 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->OnClientAttached(); 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_ = client; 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Attach(); 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHostImpl::DetachClient() { 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!client_) 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<DevToolsAgentHostImpl> protect(this); 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_ = NULL; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->OnClientDetached(); 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Detach(); 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DevToolsAgentHostImpl::IsAttached() { 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return !!client_; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsAgentHostImpl::InspectElement(int x, int y) { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string DevToolsAgentHostImpl::GetId() { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id_; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)WebContents* DevToolsAgentHostImpl::GetWebContents() { 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DevToolsAgentHostImpl::DisconnectWebContents() { 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DevToolsAgentHostImpl::ConnectWebContents(WebContents* wc) { 1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DevToolsAgentHostImpl::IsWorker() const { 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHostImpl::HostClosed() { 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!client_) 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<DevToolsAgentHostImpl> protect(this); 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Clear |client_| before notifying it. 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHostClient* client = client_; 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_ = NULL; 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->OnClientDetached(); 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client->AgentHostClosed(this, false); 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHostImpl::SendMessageToClient(const std::string& message) { 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!client_) 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client_->DispatchProtocolMessage(this, message); 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHost::DetachAllClients() { 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (g_instances == NULL) 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Make a copy, since detaching may lead to agent destruction, which 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // removes it from the instances. 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Instances copy = g_instances.Get(); 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (Instances::iterator it(copy.begin()); it != copy.end(); ++it) { 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHostImpl* agent_host = it->second; 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (agent_host->client_) { 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<DevToolsAgentHostImpl> protect(agent_host); 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Clear |client_| before notifying it. 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHostClient* client = agent_host->client_; 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) agent_host->client_ = NULL; 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->OnClientDetached(); 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client->AgentHostClosed(agent_host, true); 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) agent_host->Detach(); 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHost::AddAgentStateCallback( 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const AgentStateCallback& callback) { 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) g_callbacks.Get().push_back(&callback); 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHost::RemoveAgentStateCallback( 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const AgentStateCallback& callback) { 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (g_callbacks == NULL) 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AgentStateCallbacks* callbacks_ = g_callbacks.Pointer(); 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AgentStateCallbacks::iterator it = 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::find(callbacks_->begin(), callbacks_->end(), &callback); 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(it != callbacks_->end()); 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) callbacks_->erase(it); 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static 18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHostImpl::NotifyCallbacks( 18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHostImpl* agent_host, bool attached) { 18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AgentStateCallbacks copy(g_callbacks.Get()); 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager* manager = DevToolsManager::GetInstance(); 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (manager->delegate()) 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) manager->delegate()->DevToolsAgentStateChanged(agent_host, attached); 18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (AgentStateCallbacks::iterator it = copy.begin(); it != copy.end(); ++it) 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*it)->Run(agent_host, attached); 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DevToolsAgentHostImpl::Inspect(BrowserContext* browser_context) { 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager* manager = DevToolsManager::GetInstance(); 19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (manager->delegate()) 19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) manager->delegate()->Inspect(browser_context, this); 19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 197