Home | History | Annotate | Download | only in debugger
      1 // Copyright (c) 2009 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 "chrome/browser/debugger/devtools_protocol_handler.h"
      6 
      7 #include "base/logging.h"
      8 #include "chrome/browser/debugger/inspectable_tab_proxy.h"
      9 #include "chrome/browser/debugger/debugger_remote_service.h"
     10 #include "chrome/browser/debugger/devtools_remote_message.h"
     11 #include "chrome/browser/debugger/devtools_remote_listen_socket.h"
     12 #include "chrome/browser/debugger/devtools_remote_service.h"
     13 #include "chrome/browser/debugger/extension_ports_remote_service.h"
     14 #include "content/browser/browser_thread.h"
     15 
     16 // static
     17 scoped_refptr<DevToolsProtocolHandler> DevToolsProtocolHandler::Start(
     18     int port) {
     19   scoped_refptr<DevToolsProtocolHandler> proto_handler =
     20       new DevToolsProtocolHandler(port);
     21   proto_handler->RegisterDestination(
     22       new DevToolsRemoteService(proto_handler),
     23       DevToolsRemoteService::kToolName);
     24   proto_handler->RegisterDestination(
     25       new DebuggerRemoteService(proto_handler),
     26       DebuggerRemoteService::kToolName);
     27   proto_handler->RegisterDestination(
     28       new ExtensionPortsRemoteService(proto_handler),
     29       ExtensionPortsRemoteService::kToolName);
     30   proto_handler->Start();
     31   return proto_handler;
     32 }
     33 
     34 DevToolsProtocolHandler::DevToolsProtocolHandler(int port)
     35     : port_(port),
     36       connection_(NULL),
     37       server_(NULL) {
     38   inspectable_tab_proxy_.reset(new InspectableTabProxy);
     39 }
     40 
     41 DevToolsProtocolHandler::~DevToolsProtocolHandler() {
     42   // Stop() must be called prior to this being called
     43   DCHECK(server_.get() == NULL);
     44   DCHECK(connection_.get() == NULL);
     45 }
     46 
     47 void DevToolsProtocolHandler::Start() {
     48   BrowserThread::PostTask(
     49       BrowserThread::IO, FROM_HERE,
     50       NewRunnableMethod(this, &DevToolsProtocolHandler::Init));
     51 }
     52 
     53 void DevToolsProtocolHandler::Init() {
     54   server_ = DevToolsRemoteListenSocket::Listen(
     55       "127.0.0.1", port_, this);
     56 }
     57 
     58 void DevToolsProtocolHandler::Stop() {
     59   BrowserThread::PostTask(
     60       BrowserThread::IO, FROM_HERE,
     61       NewRunnableMethod(this, &DevToolsProtocolHandler::Teardown));
     62   tool_to_listener_map_.clear();  // Releases all scoped_refptr's to listeners
     63 }
     64 
     65 // Run in I/O thread
     66 void DevToolsProtocolHandler::Teardown() {
     67   connection_ = NULL;
     68   server_ = NULL;
     69 }
     70 
     71 void DevToolsProtocolHandler::RegisterDestination(
     72     DevToolsRemoteListener* listener,
     73     const std::string& tool_name) {
     74   DCHECK(tool_to_listener_map_.find(tool_name) == tool_to_listener_map_.end());
     75   tool_to_listener_map_.insert(std::make_pair(tool_name, listener));
     76 }
     77 
     78 void DevToolsProtocolHandler::UnregisterDestination(
     79     DevToolsRemoteListener* listener,
     80     const std::string& tool_name) {
     81   DCHECK(tool_to_listener_map_.find(tool_name) != tool_to_listener_map_.end());
     82   DCHECK(tool_to_listener_map_.find(tool_name)->second == listener);
     83   tool_to_listener_map_.erase(tool_name);
     84 }
     85 
     86 void DevToolsProtocolHandler::HandleMessage(
     87     const DevToolsRemoteMessage& message) {
     88   std::string tool = message.GetHeaderWithEmptyDefault(
     89       DevToolsRemoteMessageHeaders::kTool);
     90   ToolToListenerMap::const_iterator it = tool_to_listener_map_.find(tool);
     91   if (it == tool_to_listener_map_.end()) {
     92     NOTREACHED();  // an unsupported tool, bail out
     93     return;
     94   }
     95   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     96   BrowserThread::PostTask(
     97       BrowserThread::UI, FROM_HERE,
     98       NewRunnableMethod(
     99           it->second.get(), &DevToolsRemoteListener::HandleMessage, message));
    100 }
    101 
    102 void DevToolsProtocolHandler::Send(const DevToolsRemoteMessage& message) {
    103   if (connection_ != NULL) {
    104     connection_->Send(message.ToString());
    105   }
    106 }
    107 
    108 void DevToolsProtocolHandler::OnAcceptConnection(ListenSocket *connection) {
    109   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    110   connection_ = connection;
    111 }
    112 
    113 void DevToolsProtocolHandler::OnConnectionLost() {
    114   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    115   connection_ = NULL;
    116   for (ToolToListenerMap::const_iterator it = tool_to_listener_map_.begin(),
    117        end = tool_to_listener_map_.end();
    118        it != end;
    119        ++it) {
    120     BrowserThread::PostTask(
    121       BrowserThread::UI, FROM_HERE,
    122       NewRunnableMethod(
    123           it->second.get(), &DevToolsRemoteListener::OnConnectionLost));
    124   }
    125 }
    126