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