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