Home | History | Annotate | Download | only in devtools
      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_agent_host_impl.h"
      6 
      7 #include <map>
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/guid.h"
     12 #include "base/lazy_instance.h"
     13 #include "content/browser/devtools/devtools_manager.h"
     14 #include "content/browser/devtools/embedded_worker_devtools_manager.h"
     15 #include "content/browser/devtools/forwarding_agent_host.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "content/public/browser/devtools_manager_delegate.h"
     18 
     19 namespace content {
     20 
     21 namespace {
     22 typedef std::map<std::string, DevToolsAgentHostImpl*> Instances;
     23 base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
     24 
     25 typedef std::vector<const DevToolsAgentHost::AgentStateCallback*>
     26     AgentStateCallbacks;
     27 base::LazyInstance<AgentStateCallbacks>::Leaky g_callbacks =
     28     LAZY_INSTANCE_INITIALIZER;
     29 }  // namespace
     30 
     31 // static
     32 DevToolsAgentHost::List DevToolsAgentHost::GetOrCreateAll() {
     33   List result = EmbeddedWorkerDevToolsManager::GetInstance()
     34       ->GetOrCreateAllAgentHosts();
     35   std::vector<WebContents*> wc_list =
     36       DevToolsAgentHostImpl::GetInspectableWebContents();
     37   for (std::vector<WebContents*>::iterator it = wc_list.begin();
     38       it != wc_list.end(); ++it) {
     39     result.push_back(GetOrCreateFor(*it));
     40   }
     41   return result;
     42 }
     43 
     44 DevToolsAgentHostImpl::DevToolsAgentHostImpl()
     45     : id_(base::GenerateGUID()),
     46       client_(NULL) {
     47   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     48   g_instances.Get()[id_] = this;
     49 }
     50 
     51 DevToolsAgentHostImpl::~DevToolsAgentHostImpl() {
     52   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     53   g_instances.Get().erase(g_instances.Get().find(id_));
     54 }
     55 
     56 // static
     57 scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForId(
     58     const std::string& id) {
     59   if (g_instances == NULL)
     60     return NULL;
     61   Instances::iterator it = g_instances.Get().find(id);
     62   if (it == g_instances.Get().end())
     63     return NULL;
     64   return it->second;
     65 }
     66 
     67 //static
     68 scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::Create(
     69     DevToolsExternalAgentProxyDelegate* delegate) {
     70   return new ForwardingAgentHost(delegate);
     71 }
     72 
     73 void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
     74   scoped_refptr<DevToolsAgentHostImpl> protect(this);
     75   if (client_) {
     76     client_->AgentHostClosed(this, true);
     77     Detach();
     78   } else {
     79     DevToolsManager::GetInstance()->OnClientAttached();
     80   }
     81   client_ = client;
     82   Attach();
     83 }
     84 
     85 void DevToolsAgentHostImpl::DetachClient() {
     86   if (!client_)
     87     return;
     88 
     89   scoped_refptr<DevToolsAgentHostImpl> protect(this);
     90   client_ = NULL;
     91   DevToolsManager::GetInstance()->OnClientDetached();
     92   Detach();
     93 }
     94 
     95 bool DevToolsAgentHostImpl::IsAttached() {
     96   return !!client_;
     97 }
     98 
     99 void DevToolsAgentHostImpl::InspectElement(int x, int y) {
    100 }
    101 
    102 std::string DevToolsAgentHostImpl::GetId() {
    103   return id_;
    104 }
    105 
    106 WebContents* DevToolsAgentHostImpl::GetWebContents() {
    107   return NULL;
    108 }
    109 
    110 void DevToolsAgentHostImpl::DisconnectWebContents() {
    111 }
    112 
    113 void DevToolsAgentHostImpl::ConnectWebContents(WebContents* wc) {
    114 }
    115 
    116 bool DevToolsAgentHostImpl::IsWorker() const {
    117   return false;
    118 }
    119 
    120 void DevToolsAgentHostImpl::HostClosed() {
    121   if (!client_)
    122     return;
    123 
    124   scoped_refptr<DevToolsAgentHostImpl> protect(this);
    125   // Clear |client_| before notifying it.
    126   DevToolsAgentHostClient* client = client_;
    127   client_ = NULL;
    128   DevToolsManager::GetInstance()->OnClientDetached();
    129   client->AgentHostClosed(this, false);
    130 }
    131 
    132 void DevToolsAgentHostImpl::SendMessageToClient(const std::string& message) {
    133   if (!client_)
    134     return;
    135   client_->DispatchProtocolMessage(this, message);
    136 }
    137 
    138 // static
    139 void DevToolsAgentHost::DetachAllClients() {
    140   if (g_instances == NULL)
    141     return;
    142 
    143   // Make a copy, since detaching may lead to agent destruction, which
    144   // removes it from the instances.
    145   Instances copy = g_instances.Get();
    146   for (Instances::iterator it(copy.begin()); it != copy.end(); ++it) {
    147     DevToolsAgentHostImpl* agent_host = it->second;
    148     if (agent_host->client_) {
    149       scoped_refptr<DevToolsAgentHostImpl> protect(agent_host);
    150       // Clear |client_| before notifying it.
    151       DevToolsAgentHostClient* client = agent_host->client_;
    152       agent_host->client_ = NULL;
    153       DevToolsManager::GetInstance()->OnClientDetached();
    154       client->AgentHostClosed(agent_host, true);
    155       agent_host->Detach();
    156     }
    157   }
    158 }
    159 
    160 // static
    161 void DevToolsAgentHost::AddAgentStateCallback(
    162     const AgentStateCallback& callback) {
    163   g_callbacks.Get().push_back(&callback);
    164 }
    165 
    166 // static
    167 void DevToolsAgentHost::RemoveAgentStateCallback(
    168     const AgentStateCallback& callback) {
    169   if (g_callbacks == NULL)
    170     return;
    171 
    172   AgentStateCallbacks* callbacks_ = g_callbacks.Pointer();
    173   AgentStateCallbacks::iterator it =
    174       std::find(callbacks_->begin(), callbacks_->end(), &callback);
    175   DCHECK(it != callbacks_->end());
    176   callbacks_->erase(it);
    177 }
    178 
    179 // static
    180 void DevToolsAgentHostImpl::NotifyCallbacks(
    181     DevToolsAgentHostImpl* agent_host, bool attached) {
    182   AgentStateCallbacks copy(g_callbacks.Get());
    183   DevToolsManager* manager = DevToolsManager::GetInstance();
    184   if (manager->delegate())
    185     manager->delegate()->DevToolsAgentStateChanged(agent_host, attached);
    186   for (AgentStateCallbacks::iterator it = copy.begin(); it != copy.end(); ++it)
    187      (*it)->Run(agent_host, attached);
    188 }
    189 
    190 void DevToolsAgentHostImpl::Inspect(BrowserContext* browser_context) {
    191   DevToolsManager* manager = DevToolsManager::GetInstance();
    192   if (manager->delegate())
    193     manager->delegate()->Inspect(browser_context, this);
    194 }
    195 
    196 }  // namespace content
    197