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_browser_target.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/location.h"
      9 #include "base/logging.h"
     10 #include "base/message_loop/message_loop_proxy.h"
     11 #include "base/values.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "net/server/http_server.h"
     14 
     15 namespace content {
     16 
     17 DevToolsBrowserTarget::DevToolsBrowserTarget(
     18     base::MessageLoopProxy* message_loop_proxy,
     19     net::HttpServer* http_server,
     20     int connection_id)
     21     : message_loop_proxy_(message_loop_proxy),
     22       http_server_(http_server),
     23       connection_id_(connection_id),
     24       handlers_deleter_(&handlers_),
     25       weak_factory_(this) {
     26 }
     27 
     28 void DevToolsBrowserTarget::RegisterDomainHandler(
     29     const std::string& domain,
     30     DevToolsProtocol::Handler* handler,
     31     bool handle_on_ui_thread) {
     32   DCHECK(handlers_.find(domain) == handlers_.end());
     33   handlers_[domain] = handler;
     34   if (handle_on_ui_thread) {
     35     handle_on_ui_thread_.insert(domain);
     36     handler->SetNotifier(base::Bind(&DevToolsBrowserTarget::RespondFromUIThread,
     37                                     weak_factory_.GetWeakPtr()));
     38   } else {
     39     handler->SetNotifier(base::Bind(&DevToolsBrowserTarget::Respond,
     40                                     base::Unretained(this)));
     41   }
     42 }
     43 
     44 void DevToolsBrowserTarget::HandleMessage(const std::string& data) {
     45   std::string error_response;
     46   scoped_refptr<DevToolsProtocol::Command> command =
     47       DevToolsProtocol::ParseCommand(data, &error_response);
     48   if (!command) {
     49     Respond(error_response);
     50     return;
     51   }
     52 
     53   DomainHandlerMap::iterator it = handlers_.find(command->domain());
     54   if (it == handlers_.end()) {
     55     Respond(command->NoSuchMethodErrorResponse()->Serialize());
     56     return;
     57   }
     58 
     59   DevToolsProtocol::Handler* handler = it->second;
     60   bool handle_directly = handle_on_ui_thread_.find(command->domain()) ==
     61       handle_on_ui_thread_.end();
     62   if (handle_directly) {
     63     scoped_refptr<DevToolsProtocol::Response> response =
     64         handler->HandleCommand(command);
     65     if (response && response->is_async_promise())
     66       return;
     67     if (response)
     68       Respond(response->Serialize());
     69     else
     70       Respond(command->NoSuchMethodErrorResponse()->Serialize());
     71     return;
     72   }
     73 
     74   BrowserThread::PostTask(
     75       BrowserThread::UI,
     76       FROM_HERE,
     77       base::Bind(&DevToolsBrowserTarget::HandleCommandOnUIThread,
     78                  this,
     79                  handler,
     80                  command));
     81 }
     82 
     83 void DevToolsBrowserTarget::Detach() {
     84   message_loop_proxy_ = NULL;
     85   http_server_ = NULL;
     86 
     87   std::vector<DevToolsProtocol::Handler*> ui_handlers;
     88   for (std::set<std::string>::iterator domain_it = handle_on_ui_thread_.begin();
     89        domain_it != handle_on_ui_thread_.end();
     90        ++domain_it) {
     91     DomainHandlerMap::iterator handler_it = handlers_.find(*domain_it);
     92     CHECK(handler_it != handlers_.end());
     93     ui_handlers.push_back(handler_it->second);
     94     handlers_.erase(handler_it);
     95   }
     96 
     97   BrowserThread::PostTask(
     98       BrowserThread::UI,
     99       FROM_HERE,
    100       base::Bind(&DevToolsBrowserTarget::DeleteHandlersOnUIThread,
    101                  this,
    102                  ui_handlers));
    103 }
    104 
    105 DevToolsBrowserTarget::~DevToolsBrowserTarget() {
    106 }
    107 
    108 void DevToolsBrowserTarget::HandleCommandOnUIThread(
    109     DevToolsProtocol::Handler* handler,
    110     scoped_refptr<DevToolsProtocol::Command> command) {
    111   scoped_refptr<DevToolsProtocol::Response> response =
    112       handler->HandleCommand(command);
    113   if (response && response->is_async_promise())
    114     return;
    115 
    116   if (response)
    117     RespondFromUIThread(response->Serialize());
    118   else
    119     RespondFromUIThread(command->NoSuchMethodErrorResponse()->Serialize());
    120 }
    121 
    122 void DevToolsBrowserTarget::DeleteHandlersOnUIThread(
    123     std::vector<DevToolsProtocol::Handler*> handlers) {
    124   STLDeleteElements(&handlers);
    125 }
    126 
    127 void DevToolsBrowserTarget::Respond(const std::string& message) {
    128   if (!http_server_)
    129     return;
    130   http_server_->SendOverWebSocket(connection_id_, message);
    131 }
    132 
    133 void DevToolsBrowserTarget::RespondFromUIThread(const std::string& message) {
    134   if (!message_loop_proxy_)
    135     return;
    136   message_loop_proxy_->PostTask(
    137       FROM_HERE,
    138       base::Bind(&DevToolsBrowserTarget::Respond, this, message));
    139 }
    140 
    141 }  // namespace content
    142