Home | History | Annotate | Download | only in devtools
      1 // Copyright (c) 2013 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/devtools/devtools_adb_bridge.h"
      6 
      7 #include <map>
      8 #include <vector>
      9 
     10 #include "base/base64.h"
     11 #include "base/bind.h"
     12 #include "base/command_line.h"
     13 #include "base/compiler_specific.h"
     14 #include "base/json/json_reader.h"
     15 #include "base/lazy_instance.h"
     16 #include "base/logging.h"
     17 #include "base/memory/singleton.h"
     18 #include "base/message_loop/message_loop.h"
     19 #include "base/strings/string_number_conversions.h"
     20 #include "base/strings/string_util.h"
     21 #include "base/strings/stringprintf.h"
     22 #include "base/threading/thread.h"
     23 #include "base/values.h"
     24 #include "chrome/browser/devtools/adb/android_rsa.h"
     25 #include "chrome/browser/devtools/adb_client_socket.h"
     26 #include "chrome/browser/devtools/adb_web_socket.h"
     27 #include "chrome/browser/devtools/devtools_protocol.h"
     28 #include "chrome/browser/devtools/devtools_window.h"
     29 #include "chrome/browser/devtools/tethering_adb_filter.h"
     30 #include "chrome/browser/profiles/profile.h"
     31 #include "chrome/common/chrome_switches.h"
     32 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
     33 #include "content/public/browser/devtools_agent_host.h"
     34 #include "content/public/browser/devtools_client_host.h"
     35 #include "content/public/browser/devtools_external_agent_proxy.h"
     36 #include "content/public/browser/devtools_external_agent_proxy_delegate.h"
     37 #include "content/public/browser/devtools_manager.h"
     38 #include "crypto/rsa_private_key.h"
     39 #include "net/base/net_errors.h"
     40 
     41 using content::BrowserThread;
     42 
     43 namespace {
     44 
     45 static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
     46 static const char kHostDevicesCommand[] = "host:devices";
     47 static const char kHostTransportCommand[] = "host:transport:%s|%s";
     48 static const char kLocalAbstractCommand[] = "localabstract:%s";
     49 static const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
     50 static const char kLocalChrome[] = "Local Chrome";
     51 static const char kChrome[] = "Chrome";
     52 static const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
     53 
     54 static const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n";
     55 static const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n";
     56 static const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n";
     57 static const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n";
     58 const int kAdbPort = 5037;
     59 const int kBufferSize = 16 * 1024;
     60 const int kAdbPollingIntervalMs = 1000;
     61 
     62 static const char kUrlParam[] = "url";
     63 static const char kPageReloadCommand[] = "Page.reload";
     64 static const char kPageNavigateCommand[] = "Page.navigate";
     65 
     66 typedef DevToolsAdbBridge::Callback Callback;
     67 typedef std::vector<scoped_refptr<DevToolsAdbBridge::AndroidDevice> >
     68     AndroidDevices;
     69 typedef base::Callback<void(const AndroidDevices&)> AndroidDevicesCallback;
     70 
     71 class AdbDeviceImpl : public DevToolsAdbBridge::AndroidDevice {
     72  public:
     73   explicit AdbDeviceImpl(const std::string& serial)
     74       : AndroidDevice(serial) {
     75   }
     76 
     77   virtual void RunCommand(const std::string& command,
     78                           const CommandCallback& callback) OVERRIDE {
     79     std::string query = base::StringPrintf(kHostTransportCommand,
     80                                            serial().c_str(), command.c_str());
     81     AdbClientSocket::AdbQuery(kAdbPort, query, callback);
     82   }
     83 
     84   virtual void OpenSocket(const std::string& name,
     85                           const SocketCallback& callback) OVERRIDE {
     86     std::string socket_name =
     87         base::StringPrintf(kLocalAbstractCommand, name.c_str());
     88     AdbClientSocket::TransportQuery(kAdbPort, serial(), socket_name, callback);
     89   }
     90  private:
     91   virtual ~AdbDeviceImpl() {}
     92 };
     93 
     94 class UsbDeviceImpl : public DevToolsAdbBridge::AndroidDevice {
     95  public:
     96   explicit UsbDeviceImpl(AndroidUsbDevice* device)
     97       : AndroidDevice(device->serial()),
     98         device_(device) {
     99   }
    100 
    101   virtual void RunCommand(const std::string& command,
    102                           const CommandCallback& callback) OVERRIDE {
    103     net::StreamSocket* socket = device_->CreateSocket(command);
    104     int result = socket->Connect(base::Bind(&UsbDeviceImpl::OpenedForCommand,
    105                                             this, callback, socket));
    106     if (result != net::ERR_IO_PENDING)
    107       callback.Run(result, std::string());
    108   }
    109 
    110   virtual void OpenSocket(const std::string& name,
    111                           const SocketCallback& callback) OVERRIDE {
    112     std::string socket_name =
    113         base::StringPrintf(kLocalAbstractCommand, name.c_str());
    114     net::StreamSocket* socket = device_->CreateSocket(socket_name);
    115     int result = socket->Connect(base::Bind(&UsbDeviceImpl::OnOpenSocket, this,
    116                                             callback, socket));
    117     if (result != net::ERR_IO_PENDING)
    118       callback.Run(result, NULL);
    119   }
    120 
    121  private:
    122   void OnOpenSocket(const SocketCallback& callback,
    123                     net::StreamSocket* socket,
    124                     int result) {
    125     callback.Run(result, result == net::OK ? socket : NULL);
    126   }
    127 
    128   void OpenedForCommand(const CommandCallback& callback,
    129                         net::StreamSocket* socket,
    130                         int result) {
    131     if (result != net::OK) {
    132       callback.Run(result, std::string());
    133       return;
    134     }
    135     scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
    136     result = socket->Read(buffer, kBufferSize,
    137                           base::Bind(&UsbDeviceImpl::OnRead, this,
    138                                      socket, buffer, std::string(), callback));
    139     if (result != net::ERR_IO_PENDING)
    140       OnRead(socket, buffer, std::string(), callback, result);
    141   }
    142 
    143   void OnRead(net::StreamSocket* socket,
    144               scoped_refptr<net::IOBuffer> buffer,
    145               const std::string& data,
    146               const CommandCallback& callback,
    147               int result) {
    148     if (result <= 0) {
    149       callback.Run(result, result == 0 ? data : std::string());
    150       delete socket;
    151       return;
    152     }
    153 
    154     std::string new_data = data + std::string(buffer->data(), result);
    155     result = socket->Read(buffer, kBufferSize,
    156                           base::Bind(&UsbDeviceImpl::OnRead, this,
    157                                      socket, buffer, new_data, callback));
    158     if (result != net::ERR_IO_PENDING)
    159       OnRead(socket, buffer, new_data, callback, result);
    160   }
    161 
    162   virtual ~UsbDeviceImpl() {}
    163   scoped_refptr<AndroidUsbDevice> device_;
    164 };
    165 
    166 class AdbPagesCommand : public base::RefCountedThreadSafe<
    167     AdbPagesCommand,
    168     content::BrowserThread::DeleteOnUIThread> {
    169  public:
    170   typedef base::Callback<void(DevToolsAdbBridge::RemoteDevices*)> Callback;
    171 
    172   AdbPagesCommand(DevToolsAdbBridge* bridge, const Callback& callback)
    173      : bridge_(bridge),
    174        callback_(callback) {
    175     remote_devices_.reset(new DevToolsAdbBridge::RemoteDevices());
    176     bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
    177         base::Bind(&DevToolsAdbBridge::EnumerateUsbDevices, bridge_,
    178                    base::Bind(&AdbPagesCommand::ReceivedUsbDevices, this)));
    179   }
    180 
    181  private:
    182   friend struct content::BrowserThread::DeleteOnThread<
    183       content::BrowserThread::UI>;
    184   friend class base::DeleteHelper<AdbPagesCommand>;
    185 
    186   virtual ~AdbPagesCommand() {
    187     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    188   }
    189 
    190   void ReceivedUsbDevices(const AndroidDevices& devices) {
    191     DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
    192     devices_ = devices;
    193     bridge_->EnumerateAdbDevices(
    194         base::Bind(&AdbPagesCommand::ReceivedAdbDevices, this));
    195   }
    196 
    197   void ReceivedAdbDevices(const AndroidDevices& devices) {
    198     devices_.insert(devices_.end(), devices.begin(), devices.end());
    199     ProcessSerials();
    200   }
    201 
    202   void ProcessSerials() {
    203     DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
    204     if (devices_.size() == 0) {
    205       BrowserThread::PostTask(
    206           BrowserThread::UI, FROM_HERE,
    207           base::Bind(&AdbPagesCommand::Respond, this));
    208       return;
    209     }
    210 
    211 #if defined(DEBUG_DEVTOOLS)
    212     // For desktop remote debugging.
    213     if (devices_.back()->serial().empty()) {
    214       scoped_refptr<DevToolsAdbBridge::AndroidDevice> device =
    215           devices_.back();
    216       device->set_model(kLocalChrome);
    217       remote_devices_->push_back(
    218           new DevToolsAdbBridge::RemoteDevice(bridge_, device));
    219       scoped_refptr<DevToolsAdbBridge::RemoteBrowser> remote_browser =
    220           new DevToolsAdbBridge::RemoteBrowser(bridge_, device, std::string());
    221       remote_browser->set_product(kChrome);
    222       remote_devices_->back()->AddBrowser(remote_browser);
    223       browsers_.push_back(remote_browser);
    224       device->HttpQuery(
    225           std::string(), kVersionRequest,
    226           base::Bind(&AdbPagesCommand::ReceivedVersion, this));
    227       return;
    228     }
    229 #endif  // defined(DEBUG_DEVTOOLS)
    230 
    231     scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
    232     device->RunCommand(kDeviceModelCommand,
    233                        base::Bind(&AdbPagesCommand::ReceivedModel, this));
    234   }
    235 
    236   void ReceivedModel(int result, const std::string& response) {
    237     DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
    238     if (result < 0) {
    239       devices_.pop_back();
    240       ProcessSerials();
    241       return;
    242     }
    243     scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
    244     device->set_model(response);
    245     remote_devices_->push_back(
    246         new DevToolsAdbBridge::RemoteDevice(bridge_, device));
    247     device->RunCommand(kOpenedUnixSocketsCommand,
    248                        base::Bind(&AdbPagesCommand::ReceivedSockets, this));
    249   }
    250 
    251   void ReceivedSockets(int result,
    252                        const std::string& response) {
    253     DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
    254     if (result < 0) {
    255       devices_.pop_back();
    256       ProcessSerials();
    257       return;
    258     }
    259 
    260     ParseSocketsList(response);
    261     if (browsers_.size() == 0) {
    262       devices_.pop_back();
    263       ProcessSerials();
    264     } else {
    265       ProcessSockets();
    266     }
    267   }
    268 
    269   void ProcessSockets() {
    270     DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
    271     if (browsers_.size() == 0) {
    272       devices_.pop_back();
    273       ProcessSerials();
    274     } else {
    275       scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
    276       device->HttpQuery(browsers_.back()->socket(), kVersionRequest,
    277                         base::Bind(&AdbPagesCommand::ReceivedVersion, this));
    278     }
    279   }
    280 
    281   void ReceivedVersion(int result,
    282                        const std::string& response) {
    283     DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
    284     if (result < 0) {
    285       browsers_.pop_back();
    286       ProcessSockets();
    287       return;
    288     }
    289 
    290     // Parse version, append to package name if available,
    291     scoped_ptr<base::Value> value(base::JSONReader::Read(response));
    292     base::DictionaryValue* dict;
    293     if (value && value->GetAsDictionary(&dict)) {
    294       std::string browser;
    295       if (dict->GetString("Browser", &browser)) {
    296         std::vector<std::string> parts;
    297         Tokenize(browser, "/", &parts);
    298         if (parts.size() == 2) {
    299           if (parts[0] != "Version")  // WebView has this for legacy reasons.
    300             browsers_.back()->set_product(parts[0]);
    301           browsers_.back()->set_version(parts[1]);
    302         } else {
    303           browsers_.back()->set_version(browser);
    304         }
    305       }
    306     }
    307 
    308     scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
    309     device->HttpQuery(browsers_.back()->socket(), kPageListRequest,
    310                       base::Bind(&AdbPagesCommand::ReceivedPages, this));
    311   }
    312 
    313   void ReceivedPages(int result,
    314                      const std::string& response) {
    315     DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
    316     scoped_refptr<DevToolsAdbBridge::RemoteBrowser> browser = browsers_.back();
    317     browsers_.pop_back();
    318     if (result < 0) {
    319       ProcessSockets();
    320       return;
    321     }
    322 
    323     scoped_ptr<base::Value> value(base::JSONReader::Read(response));
    324     base::ListValue* list_value;
    325     if (!value || !value->GetAsList(&list_value)) {
    326       ProcessSockets();
    327       return;
    328     }
    329 
    330     base::Value* item;
    331 
    332     for (size_t i = 0; i < list_value->GetSize(); ++i) {
    333       list_value->Get(i, &item);
    334       base::DictionaryValue* dict;
    335       if (!item || !item->GetAsDictionary(&dict))
    336         continue;
    337       browser->AddPage(new DevToolsAdbBridge::RemotePage(
    338           bridge_, browser->device(), browser->socket(), *dict));
    339     }
    340     ProcessSockets();
    341   }
    342 
    343   void Respond() {
    344     callback_.Run(remote_devices_.release());
    345   }
    346 
    347   void ParseSocketsList(const std::string& response) {
    348     // On Android, '/proc/net/unix' looks like this:
    349     //
    350     // Num       RefCount Protocol Flags    Type St Inode Path
    351     // 00000000: 00000002 00000000 00010000 0001 01 331813 /dev/socket/zygote
    352     // 00000000: 00000002 00000000 00010000 0001 01 358606 @xxx_devtools_remote
    353     // 00000000: 00000002 00000000 00010000 0001 01 347300 @yyy_devtools_remote
    354     //
    355     // We need to find records with paths starting from '@' (abstract socket)
    356     // and containing "devtools_remote". We have to extract the inode number
    357     // in order to find the owning process name.
    358 
    359     scoped_refptr<DevToolsAdbBridge::RemoteDevice> remote_device =
    360         remote_devices_->back();
    361 
    362     std::vector<std::string> entries;
    363     Tokenize(response, "\n", &entries);
    364     const std::string channel_pattern =
    365         base::StringPrintf(kDevToolsChannelNameFormat, "");
    366     for (size_t i = 1; i < entries.size(); ++i) {
    367       std::vector<std::string> fields;
    368       Tokenize(entries[i], " ", &fields);
    369       if (fields.size() < 8)
    370         continue;
    371       if (fields[3] != "00010000" || fields[5] != "01")
    372         continue;
    373       std::string path_field = fields[7];
    374       if (path_field.size() < 1 || path_field[0] != '@')
    375         continue;
    376       size_t socket_name_pos = path_field.find(channel_pattern);
    377       if (socket_name_pos == std::string::npos)
    378         continue;
    379       std::string socket = path_field.substr(1, path_field.size() - 2);
    380       std::string package = path_field.substr(1, socket_name_pos - 1);
    381       if (socket_name_pos + channel_pattern.size() < path_field.size() - 1) {
    382         package += path_field.substr(
    383             socket_name_pos + channel_pattern.size(), path_field.size() - 1);
    384       }
    385       package[0] = base::ToUpperASCII(package[0]);
    386       scoped_refptr<DevToolsAdbBridge::RemoteBrowser> remote_browser =
    387           new DevToolsAdbBridge::RemoteBrowser(
    388               bridge_, remote_device->device(), socket);
    389       remote_browser->set_product(package);
    390       remote_device->AddBrowser(remote_browser);
    391     }
    392     browsers_ = remote_device->browsers();
    393   }
    394 
    395   scoped_refptr<DevToolsAdbBridge> bridge_;
    396   Callback callback_;
    397   AndroidDevices devices_;
    398   DevToolsAdbBridge::RemoteBrowsers browsers_;
    399   scoped_ptr<DevToolsAdbBridge::RemoteDevices> remote_devices_;
    400 };
    401 
    402 // AdbProtocolCommand ---------------------------------------------------------
    403 
    404 class AdbProtocolCommand : public AdbWebSocket::Delegate {
    405  public:
    406   AdbProtocolCommand(
    407       scoped_refptr<DevToolsAdbBridge> bridge_,
    408       scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
    409       const std::string& socket_name,
    410       const std::string& debug_url,
    411       const std::string& command);
    412 
    413  private:
    414   virtual void OnSocketOpened() OVERRIDE;
    415   virtual void OnFrameRead(const std::string& message) OVERRIDE;
    416   virtual void OnSocketClosed(bool closed_by_device) OVERRIDE;
    417   virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE;
    418 
    419   scoped_refptr<DevToolsAdbBridge> bridge_;
    420   const std::string command_;
    421   scoped_refptr<AdbWebSocket> web_socket_;
    422 
    423   DISALLOW_COPY_AND_ASSIGN(AdbProtocolCommand);
    424 };
    425 
    426 AdbProtocolCommand::AdbProtocolCommand(
    427     scoped_refptr<DevToolsAdbBridge> bridge,
    428     scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
    429     const std::string& socket_name,
    430     const std::string& debug_url,
    431     const std::string& command)
    432     : bridge_(bridge),
    433       command_(command) {
    434   web_socket_ = new AdbWebSocket(
    435       device, socket_name, debug_url, bridge_->GetAdbMessageLoop(), this);
    436 }
    437 
    438 void AdbProtocolCommand::OnSocketOpened() {
    439   web_socket_->SendFrame(command_);
    440   web_socket_->Disconnect();
    441 }
    442 
    443 void AdbProtocolCommand::OnFrameRead(const std::string& message) {}
    444 
    445 void AdbProtocolCommand::OnSocketClosed(bool closed_by_device) {
    446   delete this;
    447 }
    448 
    449 bool AdbProtocolCommand::ProcessIncomingMessage(const std::string& message) {
    450   return false;
    451 }
    452 
    453 }  // namespace
    454 
    455 const char kDevToolsChannelNameFormat[] = "%s_devtools_remote";
    456 
    457 class AgentHostDelegate;
    458 
    459 typedef std::map<std::string, AgentHostDelegate*> AgentHostDelegates;
    460 
    461 base::LazyInstance<AgentHostDelegates>::Leaky g_host_delegates =
    462     LAZY_INSTANCE_INITIALIZER;
    463 
    464 DevToolsAdbBridge::Wrapper::Wrapper(Profile* profile)
    465     : bridge_(new DevToolsAdbBridge(profile)) {
    466 }
    467 
    468 DevToolsAdbBridge::Wrapper::~Wrapper() {
    469 }
    470 
    471 DevToolsAdbBridge* DevToolsAdbBridge::Wrapper::Get() {
    472   return bridge_.get();
    473 }
    474 
    475 // static
    476 DevToolsAdbBridge::Factory* DevToolsAdbBridge::Factory::GetInstance() {
    477   return Singleton<DevToolsAdbBridge::Factory>::get();
    478 }
    479 
    480 // static
    481 DevToolsAdbBridge* DevToolsAdbBridge::Factory::GetForProfile(
    482     Profile* profile) {
    483   DevToolsAdbBridge::Wrapper* wrapper =
    484       static_cast<DevToolsAdbBridge::Wrapper*>(GetInstance()->
    485           GetServiceForBrowserContext(profile, true));
    486   return wrapper ? wrapper->Get() : NULL;
    487 }
    488 
    489 DevToolsAdbBridge::Factory::Factory()
    490     : BrowserContextKeyedServiceFactory(
    491           "DevToolsAdbBridge",
    492           BrowserContextDependencyManager::GetInstance()) {}
    493 
    494 DevToolsAdbBridge::Factory::~Factory() {}
    495 
    496 BrowserContextKeyedService*
    497 DevToolsAdbBridge::Factory::BuildServiceInstanceFor(
    498     content::BrowserContext* context) const {
    499   return new DevToolsAdbBridge::Wrapper(Profile::FromBrowserContext(context));
    500 }
    501 
    502 DevToolsAdbBridge::AndroidDevice::AndroidDevice(const std::string& serial)
    503     : serial_(serial) {
    504 }
    505 
    506 void DevToolsAdbBridge::AndroidDevice::HttpQuery(
    507     const std::string& la_name,
    508     const std::string& request,
    509     const CommandCallback& callback) {
    510   OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened, this,
    511                                  request, callback));
    512 }
    513 
    514 void DevToolsAdbBridge::AndroidDevice::HttpUpgrade(
    515     const std::string& la_name,
    516     const std::string& request,
    517     const SocketCallback& callback) {
    518   OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened2, this,
    519                                  request, callback));
    520 }
    521 
    522 DevToolsAdbBridge::AndroidDevice::~AndroidDevice() {
    523 }
    524 
    525 void DevToolsAdbBridge::AndroidDevice::OnHttpSocketOpened(
    526     const std::string& request,
    527     const CommandCallback& callback,
    528     int result,
    529     net::StreamSocket* socket) {
    530   if (result != net::OK) {
    531     callback.Run(result, std::string());
    532     return;
    533   }
    534   AdbClientSocket::HttpQuery(socket, request, callback);
    535 }
    536 
    537 void DevToolsAdbBridge::AndroidDevice::OnHttpSocketOpened2(
    538     const std::string& request,
    539     const SocketCallback& callback,
    540     int result,
    541     net::StreamSocket* socket) {
    542   if (result != net::OK) {
    543     callback.Run(result, NULL);
    544     return;
    545   }
    546   AdbClientSocket::HttpQuery(socket, request, callback);
    547 }
    548 
    549 class AgentHostDelegate : public content::DevToolsExternalAgentProxyDelegate,
    550                           public AdbWebSocket::Delegate {
    551  public:
    552   AgentHostDelegate(
    553       const std::string& id,
    554       scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
    555       const std::string& socket_name,
    556       const std::string& debug_url,
    557       const std::string& frontend_url,
    558       base::MessageLoop* adb_message_loop,
    559       Profile* profile)
    560       : id_(id),
    561         serial_(device->serial()),
    562         frontend_url_(frontend_url),
    563         adb_message_loop_(adb_message_loop),
    564         profile_(profile) {
    565     web_socket_ = new AdbWebSocket(
    566         device, socket_name, debug_url, adb_message_loop, this);
    567     g_host_delegates.Get()[id] = this;
    568   }
    569 
    570   void OpenFrontend() {
    571     if (!proxy_)
    572       return;
    573     DevToolsWindow::OpenExternalFrontend(
    574         profile_, frontend_url_, proxy_->GetAgentHost().get());
    575   }
    576 
    577  private:
    578   virtual ~AgentHostDelegate() {
    579     g_host_delegates.Get().erase(id_);
    580   }
    581 
    582   virtual void Attach() OVERRIDE {}
    583 
    584   virtual void Detach() OVERRIDE {
    585     web_socket_->Disconnect();
    586   }
    587 
    588   virtual void SendMessageToBackend(const std::string& message) OVERRIDE {
    589     web_socket_->SendFrame(message);
    590   }
    591 
    592   virtual void OnSocketOpened() OVERRIDE {
    593     proxy_.reset(content::DevToolsExternalAgentProxy::Create(this));
    594     OpenFrontend();
    595   }
    596 
    597   virtual void OnFrameRead(const std::string& message) OVERRIDE {
    598     proxy_->DispatchOnClientHost(message);
    599   }
    600 
    601   virtual void OnSocketClosed(bool closed_by_device) OVERRIDE {
    602     if (proxy_ && closed_by_device)
    603       proxy_->ConnectionClosed();
    604     delete this;
    605   }
    606 
    607   virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE {
    608     return false;
    609   }
    610 
    611   const std::string id_;
    612   const std::string serial_;
    613   const std::string frontend_url_;
    614   base::MessageLoop* adb_message_loop_;
    615   Profile* profile_;
    616 
    617   scoped_ptr<content::DevToolsExternalAgentProxy> proxy_;
    618   scoped_refptr<AdbWebSocket> web_socket_;
    619   DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate);
    620 };
    621 
    622 DevToolsAdbBridge::RemotePage::RemotePage(
    623     scoped_refptr<DevToolsAdbBridge> bridge,
    624     scoped_refptr<AndroidDevice> device,
    625     const std::string& socket,
    626     const base::DictionaryValue& value)
    627     : bridge_(bridge),
    628       device_(device),
    629       socket_(socket) {
    630   value.GetString("id", &id_);
    631   value.GetString("url", &url_);
    632   value.GetString("title", &title_);
    633   value.GetString("descirption", &description_);
    634   value.GetString("faviconUrl", &favicon_url_);
    635   value.GetString("webSocketDebuggerUrl", &debug_url_);
    636   value.GetString("devtoolsFrontendUrl", &frontend_url_);
    637 
    638   if (debug_url_.find("ws://") == 0)
    639     debug_url_ = debug_url_.substr(5);
    640   else
    641     debug_url_ = "";
    642 
    643   size_t ws_param = frontend_url_.find("?ws");
    644   if (ws_param != std::string::npos)
    645     frontend_url_ = frontend_url_.substr(0, ws_param);
    646   if (frontend_url_.find("http:") == 0)
    647     frontend_url_ = "https:" + frontend_url_.substr(5);
    648 }
    649 
    650 void DevToolsAdbBridge::RemotePage::Inspect(Profile* profile) {
    651   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    652   std::string agent_id = base::StringPrintf("%s:%s:%s",
    653     device_->serial().c_str(), socket_.c_str(), id_.c_str());
    654   AgentHostDelegates::iterator it =
    655       g_host_delegates.Get().find(agent_id);
    656   if (it != g_host_delegates.Get().end())
    657     it->second->OpenFrontend();
    658   else if (!debug_url_.empty())
    659     new AgentHostDelegate(
    660         agent_id, device_, socket_, debug_url_,
    661         frontend_url_, bridge_->GetAdbMessageLoop(), profile);
    662 }
    663 
    664 static void Noop(int, const std::string&) {}
    665 
    666 void DevToolsAdbBridge::RemotePage::Close() {
    667   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    668   if (attached())
    669     return;
    670   std::string request = base::StringPrintf(kClosePageRequest, id_.c_str());
    671   bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
    672       base::Bind(&AndroidDevice::HttpQuery,
    673           device_, socket_, request, base::Bind(&Noop)));
    674 }
    675 
    676 void DevToolsAdbBridge::RemotePage::Reload() {
    677   SendProtocolCommand(kPageReloadCommand, NULL);
    678 }
    679 
    680 void DevToolsAdbBridge::RemotePage::SendProtocolCommand(
    681     const std::string& method,
    682     base::DictionaryValue* params) {
    683   if (attached())
    684     return;
    685   DevToolsProtocol::Command command(1, method, params);
    686   new AdbProtocolCommand(
    687       bridge_, device_, socket_, debug_url_, command.Serialize());
    688 }
    689 
    690 DevToolsAdbBridge::RemotePage::~RemotePage() {
    691 }
    692 
    693 DevToolsAdbBridge::RemoteBrowser::RemoteBrowser(
    694     scoped_refptr<DevToolsAdbBridge> bridge,
    695     scoped_refptr<AndroidDevice> device,
    696     const std::string& socket)
    697     : bridge_(bridge),
    698       device_(device),
    699       socket_(socket) {
    700 }
    701 
    702 void DevToolsAdbBridge::RemoteBrowser::Open(const std::string& url) {
    703   bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
    704       base::Bind(&AndroidDevice::HttpQuery,
    705           device_, socket_, kNewPageRequest,
    706           base::Bind(&RemoteBrowser::PageCreatedOnHandlerThread, this, url)));
    707 }
    708 
    709 void DevToolsAdbBridge::RemoteBrowser::PageCreatedOnHandlerThread(
    710     const std::string& url, int result, const std::string& response) {
    711   if (result < 0)
    712     return;
    713   BrowserThread::PostTask(
    714       BrowserThread::UI, FROM_HERE,
    715       base::Bind(&RemoteBrowser::PageCreatedOnUIThread, this, response, url));
    716 }
    717 
    718 void DevToolsAdbBridge::RemoteBrowser::PageCreatedOnUIThread(
    719     const std::string& response, const std::string& url) {
    720   scoped_ptr<base::Value> value(base::JSONReader::Read(response));
    721   base::DictionaryValue* dict;
    722   if (value && value->GetAsDictionary(&dict)) {
    723     scoped_refptr<RemotePage> new_page =
    724         new RemotePage(bridge_, device_, socket_, *dict);
    725     base::DictionaryValue params;
    726     params.SetString(kUrlParam, url);
    727     new_page->SendProtocolCommand(kPageNavigateCommand, &params);
    728   }
    729 }
    730 
    731 DevToolsAdbBridge::RemoteBrowser::~RemoteBrowser() {
    732 }
    733 
    734 DevToolsAdbBridge::RemoteDevice::RemoteDevice(
    735     scoped_refptr<DevToolsAdbBridge> bridge,
    736     scoped_refptr<AndroidDevice> device)
    737     : bridge_(bridge),
    738       device_(device) {
    739 }
    740 
    741 DevToolsAdbBridge::RemoteDevice::~RemoteDevice() {
    742 }
    743 
    744 
    745 DevToolsAdbBridge::RefCountedAdbThread*
    746 DevToolsAdbBridge::RefCountedAdbThread::instance_ = NULL;
    747 
    748 // static
    749 scoped_refptr<DevToolsAdbBridge::RefCountedAdbThread>
    750 DevToolsAdbBridge::RefCountedAdbThread::GetInstance() {
    751   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    752   if (!instance_)
    753     new RefCountedAdbThread();
    754   return instance_;
    755 }
    756 
    757 DevToolsAdbBridge::RefCountedAdbThread::RefCountedAdbThread() {
    758   instance_ = this;
    759   thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
    760   base::Thread::Options options;
    761   options.message_loop_type = base::MessageLoop::TYPE_IO;
    762   if (!thread_->StartWithOptions(options)) {
    763     delete thread_;
    764     thread_ = NULL;
    765   }
    766 }
    767 
    768 base::MessageLoop* DevToolsAdbBridge::RefCountedAdbThread::message_loop() {
    769   return thread_ ? thread_->message_loop() : NULL;
    770 }
    771 
    772 // static
    773 void DevToolsAdbBridge::RefCountedAdbThread::StopThread(base::Thread* thread) {
    774   thread->Stop();
    775 }
    776 
    777 DevToolsAdbBridge::RefCountedAdbThread::~RefCountedAdbThread() {
    778   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    779   instance_ = NULL;
    780   if (!thread_)
    781     return;
    782   // Shut down thread on FILE thread to join into IO.
    783   BrowserThread::PostTask(
    784       BrowserThread::FILE, FROM_HERE,
    785       base::Bind(&RefCountedAdbThread::StopThread, thread_));
    786 }
    787 
    788 DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile)
    789     : profile_(profile),
    790       adb_thread_(RefCountedAdbThread::GetInstance()),
    791       has_message_loop_(adb_thread_->message_loop() != NULL) {
    792   rsa_key_.reset(AndroidRSAPrivateKey(profile));
    793   port_forwarding_controller_.reset(
    794       new PortForwardingController(GetAdbMessageLoop(), profile->GetPrefs()));
    795 }
    796 
    797 void DevToolsAdbBridge::EnumerateUsbDevices(
    798     const AndroidDevicesCallback& callback) {
    799   DCHECK_EQ(base::MessageLoop::current(), adb_thread_->message_loop());
    800   if (CommandLine::ForCurrentProcess()->HasSwitch(
    801           switches::kRemoteDebuggingRawUSB)) {
    802     AndroidUsbDevice::Enumerate(rsa_key_.get(),
    803         base::Bind(&DevToolsAdbBridge::ReceivedUsbDevices, this, callback));
    804   } else {
    805     ReceivedUsbDevices(callback, AndroidUsbDevices());
    806   }
    807 }
    808 
    809 void DevToolsAdbBridge::EnumerateAdbDevices(
    810     const AndroidDevicesCallback& callback) {
    811   DCHECK_EQ(base::MessageLoop::current(), adb_thread_->message_loop());
    812 
    813   AdbClientSocket::AdbQuery(
    814       kAdbPort, kHostDevicesCommand,
    815       base::Bind(&DevToolsAdbBridge::ReceivedAdbDevices, this, callback));
    816 }
    817 
    818 void DevToolsAdbBridge::AddListener(Listener* listener) {
    819   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    820   if (listeners_.empty())
    821     RequestRemoteDevices();
    822   listeners_.push_back(listener);
    823 }
    824 
    825 void DevToolsAdbBridge::RemoveListener(Listener* listener) {
    826   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    827   Listeners::iterator it =
    828       std::find(listeners_.begin(), listeners_.end(), listener);
    829   DCHECK(it != listeners_.end());
    830   listeners_.erase(it);
    831 }
    832 
    833 base::MessageLoop* DevToolsAdbBridge::GetAdbMessageLoop() {
    834   return adb_thread_->message_loop();
    835 }
    836 
    837 DevToolsAdbBridge::~DevToolsAdbBridge() {
    838   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    839   DCHECK(listeners_.empty());
    840 }
    841 
    842 void DevToolsAdbBridge::ReceivedUsbDevices(
    843     const AndroidDevicesCallback& callback,
    844     const AndroidUsbDevices& usb_devices) {
    845   AndroidDevices devices;
    846 
    847 #if defined(DEBUG_DEVTOOLS)
    848   devices.push_back(new AdbDeviceImpl(""));  // For desktop remote debugging.
    849 #endif  // defined(DEBUG_DEVTOOLS)
    850 
    851   for (AndroidUsbDevices::const_iterator it = usb_devices.begin();
    852        it != usb_devices.end(); ++it) {
    853     devices.push_back(new UsbDeviceImpl(*it));
    854   }
    855 
    856   callback.Run(devices);
    857 }
    858 
    859 void DevToolsAdbBridge::ReceivedAdbDevices(
    860     const AndroidDevicesCallback& callback,
    861     int result,
    862     const std::string& response) {
    863   AndroidDevices devices;
    864   if (result != net::OK) {
    865     callback.Run(devices);
    866     return;
    867   }
    868 
    869   std::vector<std::string> serials;
    870   Tokenize(response, "\n", &serials);
    871   for (size_t i = 0; i < serials.size(); ++i) {
    872     std::vector<std::string> tokens;
    873     Tokenize(serials[i], "\t ", &tokens);
    874     devices.push_back(new AdbDeviceImpl(tokens[0]));
    875   }
    876   callback.Run(devices);
    877 }
    878 
    879 void DevToolsAdbBridge::RequestRemoteDevices() {
    880   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    881   if (!has_message_loop_)
    882     return;
    883 
    884   new AdbPagesCommand(
    885       this, base::Bind(&DevToolsAdbBridge::ReceivedRemoteDevices, this));
    886 }
    887 
    888 void DevToolsAdbBridge::ReceivedRemoteDevices(RemoteDevices* devices_ptr) {
    889   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    890 
    891   scoped_ptr<RemoteDevices> devices(devices_ptr);
    892   port_forwarding_controller_->UpdateDeviceList(*devices.get());
    893 
    894   Listeners copy(listeners_);
    895   for (Listeners::iterator it = copy.begin(); it != copy.end(); ++it)
    896     (*it)->RemoteDevicesChanged(devices.get());
    897 
    898   if (listeners_.empty())
    899     return;
    900 
    901   BrowserThread::PostDelayedTask(
    902       BrowserThread::UI,
    903       FROM_HERE,
    904       base::Bind(&DevToolsAdbBridge::RequestRemoteDevices, this),
    905       base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs));
    906 }
    907