blob: 2973fa266f732573079e73e283980ce3c66854ec [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01007#include <map>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008#include <vector>
9
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010010#include "base/base64.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011#include "base/bind.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010012#include "base/command_line.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000013#include "base/compiler_specific.h"
14#include "base/json/json_reader.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010015#include "base/lazy_instance.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000016#include "base/logging.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010017#include "base/memory/singleton.h"
Ben Murdoch558790d2013-07-30 15:19:42 +010018#include "base/message_loop/message_loop.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000019#include "base/strings/string_number_conversions.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010020#include "base/strings/string_util.h"
21#include "base/strings/stringprintf.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000022#include "base/threading/thread.h"
23#include "base/values.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010024#include "chrome/browser/devtools/adb/android_rsa.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000025#include "chrome/browser/devtools/adb_client_socket.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010026#include "chrome/browser/devtools/adb_web_socket.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010027#include "chrome/browser/devtools/devtools_protocol.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010028#include "chrome/browser/devtools/devtools_window.h"
29#include "chrome/browser/devtools/tethering_adb_filter.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000030#include "chrome/browser/profiles/profile.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010031#include "chrome/common/chrome_switches.h"
32#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000033#include "content/public/browser/devtools_agent_host.h"
34#include "content/public/browser/devtools_client_host.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010035#include "content/public/browser/devtools_external_agent_proxy.h"
36#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000037#include "content/public/browser/devtools_manager.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010038#include "crypto/rsa_private_key.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000039#include "net/base/net_errors.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000040
41using content::BrowserThread;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000042
43namespace {
44
45static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000046static const char kHostDevicesCommand[] = "host:devices";
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010047static const char kHostTransportCommand[] = "host:transport:%s|%s";
48static const char kLocalAbstractCommand[] = "localabstract:%s";
49static const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010050static const char kUnknownModel[] = "Unknown";
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010051static const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000052
53static const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n";
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010054static const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n";
Ben Murdochbb1529c2013-08-08 10:24:53 +010055static const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n";
56static const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000057const int kAdbPort = 5037;
58const int kBufferSize = 16 * 1024;
Ben Murdoch9ab55632013-07-18 11:57:30 +010059const int kAdbPollingIntervalMs = 1000;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000060
Ben Murdochbb1529c2013-08-08 10:24:53 +010061static const char kUrlParam[] = "url";
62static const char kPageReloadCommand[] = "Page.reload";
63static const char kPageNavigateCommand[] = "Page.navigate";
64
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000065typedef DevToolsAdbBridge::Callback Callback;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010066typedef std::vector<scoped_refptr<DevToolsAdbBridge::AndroidDevice> >
67 AndroidDevices;
68typedef base::Callback<void(const AndroidDevices&)> AndroidDevicesCallback;
69
70class AdbDeviceImpl : public DevToolsAdbBridge::AndroidDevice {
71 public:
72 explicit AdbDeviceImpl(const std::string& serial)
73 : AndroidDevice(serial) {
74 }
75
76 virtual void RunCommand(const std::string& command,
77 const CommandCallback& callback) OVERRIDE {
78 std::string query = base::StringPrintf(kHostTransportCommand,
79 serial().c_str(), command.c_str());
80 AdbClientSocket::AdbQuery(kAdbPort, query, callback);
81 }
82
83 virtual void OpenSocket(const std::string& name,
84 const SocketCallback& callback) OVERRIDE {
85 std::string socket_name =
86 base::StringPrintf(kLocalAbstractCommand, name.c_str());
87 AdbClientSocket::TransportQuery(kAdbPort, serial(), socket_name, callback);
88 }
89 private:
90 virtual ~AdbDeviceImpl() {}
91};
92
93class UsbDeviceImpl : public DevToolsAdbBridge::AndroidDevice {
94 public:
95 explicit UsbDeviceImpl(AndroidUsbDevice* device)
96 : AndroidDevice(device->serial()),
97 device_(device) {
98 }
99
100 virtual void RunCommand(const std::string& command,
101 const CommandCallback& callback) OVERRIDE {
102 net::StreamSocket* socket = device_->CreateSocket(command);
103 int result = socket->Connect(base::Bind(&UsbDeviceImpl::OpenedForCommand,
104 this, callback, socket));
105 if (result != net::ERR_IO_PENDING)
106 callback.Run(result, std::string());
107 }
108
109 virtual void OpenSocket(const std::string& name,
110 const SocketCallback& callback) OVERRIDE {
111 std::string socket_name =
112 base::StringPrintf(kLocalAbstractCommand, name.c_str());
113 net::StreamSocket* socket = device_->CreateSocket(socket_name);
114 int result = socket->Connect(base::Bind(&UsbDeviceImpl::OnOpenSocket, this,
115 callback, socket));
116 if (result != net::ERR_IO_PENDING)
117 callback.Run(result, NULL);
118 }
119
120 private:
121 void OnOpenSocket(const SocketCallback& callback,
122 net::StreamSocket* socket,
123 int result) {
124 callback.Run(result, result == net::OK ? socket : NULL);
125 }
126
127 void OpenedForCommand(const CommandCallback& callback,
128 net::StreamSocket* socket,
129 int result) {
130 if (result != net::OK) {
131 callback.Run(result, std::string());
132 return;
133 }
134 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
135 result = socket->Read(buffer, kBufferSize,
136 base::Bind(&UsbDeviceImpl::OnRead, this,
137 socket, buffer, std::string(), callback));
138 if (result != net::ERR_IO_PENDING)
139 OnRead(socket, buffer, std::string(), callback, result);
140 }
141
142 void OnRead(net::StreamSocket* socket,
143 scoped_refptr<net::IOBuffer> buffer,
144 const std::string& data,
145 const CommandCallback& callback,
146 int result) {
147 if (result <= 0) {
148 callback.Run(result, result == 0 ? data : std::string());
149 delete socket;
150 return;
151 }
152
153 std::string new_data = data + std::string(buffer->data(), result);
154 result = socket->Read(buffer, kBufferSize,
155 base::Bind(&UsbDeviceImpl::OnRead, this,
156 socket, buffer, new_data, callback));
157 if (result != net::ERR_IO_PENDING)
158 OnRead(socket, buffer, new_data, callback, result);
159 }
160
161 virtual ~UsbDeviceImpl() {}
162 scoped_refptr<AndroidUsbDevice> device_;
163};
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000164
Ben Murdoch558790d2013-07-30 15:19:42 +0100165class AdbPagesCommand : public base::RefCountedThreadSafe<
166 AdbPagesCommand,
167 content::BrowserThread::DeleteOnUIThread> {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000168 public:
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100169 typedef base::Callback<void(DevToolsAdbBridge::RemoteDevices*)> Callback;
170
171 AdbPagesCommand(DevToolsAdbBridge* bridge, const Callback& callback)
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100172 : bridge_(bridge),
173 callback_(callback) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100174 remote_devices_.reset(new DevToolsAdbBridge::RemoteDevices());
Ben Murdoch32409262013-08-07 11:04:47 +0100175 bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
176 base::Bind(&DevToolsAdbBridge::EnumerateUsbDevices, bridge_,
177 base::Bind(&AdbPagesCommand::ReceivedUsbDevices, this)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000178 }
179
180 private:
Ben Murdoch558790d2013-07-30 15:19:42 +0100181 friend struct content::BrowserThread::DeleteOnThread<
182 content::BrowserThread::UI>;
183 friend class base::DeleteHelper<AdbPagesCommand>;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000184
Ben Murdoch558790d2013-07-30 15:19:42 +0100185 virtual ~AdbPagesCommand() {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
187 }
188
Ben Murdoch2385ea32013-08-06 11:01:04 +0100189 void ReceivedUsbDevices(const AndroidDevices& devices) {
Ben Murdoch32409262013-08-07 11:04:47 +0100190 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100191 devices_ = devices;
Ben Murdoch32409262013-08-07 11:04:47 +0100192 bridge_->EnumerateAdbDevices(
193 base::Bind(&AdbPagesCommand::ReceivedAdbDevices, this));
Ben Murdoch2385ea32013-08-06 11:01:04 +0100194 }
195
196 void ReceivedAdbDevices(const AndroidDevices& devices) {
197 devices_.insert(devices_.end(), devices.begin(), devices.end());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000198 ProcessSerials();
199 }
200
201 void ProcessSerials() {
Ben Murdoch558790d2013-07-30 15:19:42 +0100202 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100203 if (devices_.size() == 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000204 BrowserThread::PostTask(
205 BrowserThread::UI, FROM_HERE,
206 base::Bind(&AdbPagesCommand::Respond, this));
207 return;
208 }
209
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100210#if defined(DEBUG_DEVTOOLS)
211 // For desktop remote debugging.
212 if (devices_.back()->serial().empty()) {
213 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device =
214 devices_.back();
215 sockets_.push_back(std::string());
216 device->set_model(kUnknownModel);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100217 remote_devices_->push_back(
218 new DevToolsAdbBridge::RemoteDevice(bridge_, device));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100219 device->HttpQuery(
220 std::string(), kVersionRequest,
221 base::Bind(&AdbPagesCommand::ReceivedVersion, this));
222 return;
223 }
224#endif // defined(DEBUG_DEVTOOLS)
225
226 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
227 device->RunCommand(kDeviceModelCommand,
228 base::Bind(&AdbPagesCommand::ReceivedModel, this));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000229 }
230
231 void ReceivedModel(int result, const std::string& response) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100232 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100233 if (result < 0) {
234 devices_.pop_back();
235 ProcessSerials();
236 return;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100237 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100238 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
239 device->set_model(response);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100240 remote_devices_->push_back(
241 new DevToolsAdbBridge::RemoteDevice(bridge_, device));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100242 device->RunCommand(kOpenedUnixSocketsCommand,
243 base::Bind(&AdbPagesCommand::ReceivedSockets, this));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100244 }
245
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100246 void ReceivedSockets(int result,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100247 const std::string& response) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100248 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100249 if (result < 0) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100250 devices_.pop_back();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000251 ProcessSerials();
252 return;
253 }
254
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100255 ParseSocketsList(response);
256 if (sockets_.size() == 0) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100257 devices_.pop_back();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100258 ProcessSerials();
259 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100260 ProcessSockets();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100261 }
262 }
263
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100264 void ProcessSockets() {
Ben Murdoch558790d2013-07-30 15:19:42 +0100265 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100266 if (sockets_.size() == 0) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100267 devices_.pop_back();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100268 ProcessSerials();
269 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100270 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
271 device->HttpQuery(sockets_.back(), kVersionRequest,
272 base::Bind(&AdbPagesCommand::ReceivedVersion, this));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100273 }
274 }
275
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100276 void ReceivedVersion(int result,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100277 const std::string& response) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100278 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100279 if (result < 0) {
280 sockets_.pop_back();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100281 ProcessSockets();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100282 return;
283 }
284
285 // Parse version, append to package name if available,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100286 scoped_ptr<base::Value> value(base::JSONReader::Read(response));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100287 base::DictionaryValue* dict;
288 if (value && value->GetAsDictionary(&dict)) {
289 std::string browser;
290 if (dict->GetString("Browser", &browser)) {
291 socket_to_package_[sockets_.back()] = base::StringPrintf(
292 "%s (%s)", socket_to_package_[sockets_.back()].c_str(),
293 browser.c_str());
294 }
295 }
296
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100297 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
298 device->HttpQuery(sockets_.back(), kPageListRequest,
299 base::Bind(&AdbPagesCommand::ReceivedPages, this));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000300 }
301
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100302 void ReceivedPages(int result,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000303 const std::string& response) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100304 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100305 std::string socket = sockets_.back();
306 sockets_.pop_back();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000307 if (result < 0) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100308 ProcessSockets();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000309 return;
310 }
311
Ben Murdochbb1529c2013-08-08 10:24:53 +0100312 scoped_ptr<base::Value> value(base::JSONReader::Read(response));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000313 base::ListValue* list_value;
314 if (!value || !value->GetAsList(&list_value)) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100315 ProcessSockets();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000316 return;
317 }
318
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100319 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000320 base::Value* item;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100321
322 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> remote_browser =
323 new DevToolsAdbBridge::RemoteBrowser(
324 bridge_, device, socket, socket_to_package_[socket]);
325 remote_devices_->back()->AddBrowser(remote_browser);
326
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000327 for (size_t i = 0; i < list_value->GetSize(); ++i) {
328 list_value->Get(i, &item);
329 base::DictionaryValue* dict;
330 if (!item || !item->GetAsDictionary(&dict))
331 continue;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100332 remote_browser->AddPage(new DevToolsAdbBridge::RemotePage(
333 bridge_, device, remote_browser->socket(), *dict));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000334 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100335 ProcessSockets();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000336 }
337
338 void Respond() {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100339 callback_.Run(remote_devices_.release());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000340 }
341
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100342 void ParseSocketsList(const std::string& response) {
343 // On Android, '/proc/net/unix' looks like this:
344 //
345 // Num RefCount Protocol Flags Type St Inode Path
346 // 00000000: 00000002 00000000 00010000 0001 01 331813 /dev/socket/zygote
347 // 00000000: 00000002 00000000 00010000 0001 01 358606 @xxx_devtools_remote
348 // 00000000: 00000002 00000000 00010000 0001 01 347300 @yyy_devtools_remote
349 //
350 // We need to find records with paths starting from '@' (abstract socket)
351 // and containing "devtools_remote". We have to extract the inode number
352 // in order to find the owning process name.
353
354 socket_to_package_.clear();
355 std::vector<std::string> entries;
356 Tokenize(response, "\n", &entries);
Ben Murdocheb525c52013-07-10 11:40:50 +0100357 const std::string channel_pattern =
358 base::StringPrintf(kDevToolsChannelNameFormat, "");
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100359 for (size_t i = 1; i < entries.size(); ++i) {
360 std::vector<std::string> fields;
361 Tokenize(entries[i], " ", &fields);
362 if (fields.size() < 8)
363 continue;
364 if (fields[3] != "00010000" || fields[5] != "01")
365 continue;
366 std::string path_field = fields[7];
367 if (path_field.size() < 1 || path_field[0] != '@')
368 continue;
369 size_t socket_name_pos = path_field.find(channel_pattern);
370 if (socket_name_pos == std::string::npos)
371 continue;
372 std::string socket = path_field.substr(1, path_field.size() - 2);
373 sockets_.push_back(socket);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100374 std::string package = path_field.substr(1, socket_name_pos - 1);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100375 if (socket_name_pos + channel_pattern.size() < path_field.size() - 1) {
376 package += path_field.substr(
377 socket_name_pos + channel_pattern.size(), path_field.size() - 1);
378 }
379 package[0] = base::ToUpperASCII(package[0]);
380 socket_to_package_[socket] = package;
381 }
382 }
383
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100384 scoped_refptr<DevToolsAdbBridge> bridge_;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100385 Callback callback_;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100386 AndroidDevices devices_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100387 std::vector<std::string> sockets_;
388 std::map<std::string, std::string> socket_to_package_;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100389 scoped_ptr<DevToolsAdbBridge::RemoteDevices> remote_devices_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000390};
391
Ben Murdochbb1529c2013-08-08 10:24:53 +0100392// AdbProtocolCommand ---------------------------------------------------------
393
394class AdbProtocolCommand : public AdbWebSocket::Delegate {
395 public:
396 AdbProtocolCommand(
397 scoped_refptr<DevToolsAdbBridge> bridge_,
398 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
399 const std::string& socket_name,
400 const std::string& debug_url,
401 const std::string& command);
402
403 private:
404 virtual void OnSocketOpened() OVERRIDE;
405 virtual void OnFrameRead(const std::string& message) OVERRIDE;
406 virtual void OnSocketClosed(bool closed_by_device) OVERRIDE;
407 virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE;
408
409 scoped_refptr<DevToolsAdbBridge> bridge_;
410 const std::string command_;
411 scoped_refptr<AdbWebSocket> web_socket_;
412
413 DISALLOW_COPY_AND_ASSIGN(AdbProtocolCommand);
414};
415
416AdbProtocolCommand::AdbProtocolCommand(
417 scoped_refptr<DevToolsAdbBridge> bridge,
418 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
419 const std::string& socket_name,
420 const std::string& debug_url,
421 const std::string& command)
422 : bridge_(bridge),
423 command_(command) {
424 web_socket_ = new AdbWebSocket(
425 device, socket_name, debug_url, bridge_->GetAdbMessageLoop(), this);
426}
427
428void AdbProtocolCommand::OnSocketOpened() {
429 web_socket_->SendFrame(command_);
430 web_socket_->Disconnect();
431}
432
433void AdbProtocolCommand::OnFrameRead(const std::string& message) {}
434
435void AdbProtocolCommand::OnSocketClosed(bool closed_by_device) {
436 delete this;
437}
438
439bool AdbProtocolCommand::ProcessIncomingMessage(const std::string& message) {
440 return false;
441}
442
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100443} // namespace
444
Ben Murdocheb525c52013-07-10 11:40:50 +0100445const char kDevToolsChannelNameFormat[] = "%s_devtools_remote";
446
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100447class AgentHostDelegate;
448
449typedef std::map<std::string, AgentHostDelegate*> AgentHostDelegates;
450
451base::LazyInstance<AgentHostDelegates>::Leaky g_host_delegates =
452 LAZY_INSTANCE_INITIALIZER;
453
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100454DevToolsAdbBridge::Wrapper::Wrapper(Profile* profile)
455 : bridge_(new DevToolsAdbBridge(profile)) {
456}
457
458DevToolsAdbBridge::Wrapper::~Wrapper() {
459}
460
461DevToolsAdbBridge* DevToolsAdbBridge::Wrapper::Get() {
462 return bridge_.get();
463}
464
465// static
466DevToolsAdbBridge::Factory* DevToolsAdbBridge::Factory::GetInstance() {
467 return Singleton<DevToolsAdbBridge::Factory>::get();
468}
469
470// static
471DevToolsAdbBridge* DevToolsAdbBridge::Factory::GetForProfile(
472 Profile* profile) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100473 DevToolsAdbBridge::Wrapper* wrapper =
474 static_cast<DevToolsAdbBridge::Wrapper*>(GetInstance()->
475 GetServiceForBrowserContext(profile, true));
476 return wrapper ? wrapper->Get() : NULL;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100477}
478
479DevToolsAdbBridge::Factory::Factory()
480 : BrowserContextKeyedServiceFactory(
481 "DevToolsAdbBridge",
482 BrowserContextDependencyManager::GetInstance()) {}
483
484DevToolsAdbBridge::Factory::~Factory() {}
485
486BrowserContextKeyedService*
487DevToolsAdbBridge::Factory::BuildServiceInstanceFor(
488 content::BrowserContext* context) const {
489 return new DevToolsAdbBridge::Wrapper(Profile::FromBrowserContext(context));
490}
491
492DevToolsAdbBridge::AndroidDevice::AndroidDevice(const std::string& serial)
493 : serial_(serial) {
494}
495
496void DevToolsAdbBridge::AndroidDevice::HttpQuery(
497 const std::string& la_name,
498 const std::string& request,
499 const CommandCallback& callback) {
500 OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened, this,
501 request, callback));
502}
503
Ben Murdochbb1529c2013-08-08 10:24:53 +0100504void DevToolsAdbBridge::AndroidDevice::HttpUpgrade(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100505 const std::string& la_name,
506 const std::string& request,
507 const SocketCallback& callback) {
508 OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened2, this,
509 request, callback));
510}
511
512DevToolsAdbBridge::AndroidDevice::~AndroidDevice() {
513}
514
515void DevToolsAdbBridge::AndroidDevice::OnHttpSocketOpened(
516 const std::string& request,
517 const CommandCallback& callback,
518 int result,
519 net::StreamSocket* socket) {
520 if (result != net::OK) {
521 callback.Run(result, std::string());
522 return;
523 }
524 AdbClientSocket::HttpQuery(socket, request, callback);
525}
526
527void DevToolsAdbBridge::AndroidDevice::OnHttpSocketOpened2(
528 const std::string& request,
529 const SocketCallback& callback,
530 int result,
531 net::StreamSocket* socket) {
532 if (result != net::OK) {
533 callback.Run(result, NULL);
534 return;
535 }
536 AdbClientSocket::HttpQuery(socket, request, callback);
537}
538
Ben Murdoch9ab55632013-07-18 11:57:30 +0100539class AgentHostDelegate : public content::DevToolsExternalAgentProxyDelegate,
540 public AdbWebSocket::Delegate {
541 public:
542 AgentHostDelegate(
543 const std::string& id,
Ben Murdoch558790d2013-07-30 15:19:42 +0100544 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
545 const std::string& socket_name,
546 const std::string& debug_url,
547 const std::string& frontend_url,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100548 base::MessageLoop* adb_message_loop,
Ben Murdoch558790d2013-07-30 15:19:42 +0100549 Profile* profile)
Ben Murdoch9ab55632013-07-18 11:57:30 +0100550 : id_(id),
Ben Murdoch2385ea32013-08-06 11:01:04 +0100551 serial_(device->serial()),
Ben Murdoch558790d2013-07-30 15:19:42 +0100552 frontend_url_(frontend_url),
Ben Murdoch2385ea32013-08-06 11:01:04 +0100553 adb_message_loop_(adb_message_loop),
554 profile_(profile) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100555 web_socket_ = new AdbWebSocket(
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100556 device, socket_name, debug_url, adb_message_loop, this);
Ben Murdoch9ab55632013-07-18 11:57:30 +0100557 g_host_delegates.Get()[id] = this;
558 }
559
Ben Murdoch558790d2013-07-30 15:19:42 +0100560 void OpenFrontend() {
561 if (!proxy_)
562 return;
563 DevToolsWindow::OpenExternalFrontend(
564 profile_, frontend_url_, proxy_->GetAgentHost().get());
Ben Murdoch9ab55632013-07-18 11:57:30 +0100565 }
566
567 private:
568 virtual ~AgentHostDelegate() {
569 g_host_delegates.Get().erase(id_);
570 }
571
Ben Murdoch558790d2013-07-30 15:19:42 +0100572 virtual void Attach() OVERRIDE {}
Ben Murdoch9ab55632013-07-18 11:57:30 +0100573
574 virtual void Detach() OVERRIDE {
575 web_socket_->Disconnect();
576 }
577
578 virtual void SendMessageToBackend(const std::string& message) OVERRIDE {
579 web_socket_->SendFrame(message);
580 }
581
Ben Murdoch558790d2013-07-30 15:19:42 +0100582 virtual void OnSocketOpened() OVERRIDE {
583 proxy_.reset(content::DevToolsExternalAgentProxy::Create(this));
Ben Murdoch2385ea32013-08-06 11:01:04 +0100584 tethering_adb_filter_.reset(new TetheringAdbFilter(
585 kAdbPort, serial_, adb_message_loop_, profile_->GetPrefs(),
586 web_socket_));
Ben Murdoch558790d2013-07-30 15:19:42 +0100587 OpenFrontend();
588 }
589
Ben Murdoch9ab55632013-07-18 11:57:30 +0100590 virtual void OnFrameRead(const std::string& message) OVERRIDE {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100591 proxy_->DispatchOnClientHost(message);
592 }
593
Ben Murdoch9ab55632013-07-18 11:57:30 +0100594 virtual void OnSocketClosed(bool closed_by_device) OVERRIDE {
Ben Murdoch558790d2013-07-30 15:19:42 +0100595 if (proxy_ && closed_by_device)
Ben Murdoch9ab55632013-07-18 11:57:30 +0100596 proxy_->ConnectionClosed();
597 delete this;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100598 }
599
Ben Murdoch9ab55632013-07-18 11:57:30 +0100600 virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE {
Ben Murdoch2385ea32013-08-06 11:01:04 +0100601 return tethering_adb_filter_->ProcessIncomingMessage(message);
Ben Murdoch9ab55632013-07-18 11:57:30 +0100602 }
603
604 const std::string id_;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100605 const std::string serial_;
Ben Murdoch558790d2013-07-30 15:19:42 +0100606 const std::string frontend_url_;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100607 base::MessageLoop* adb_message_loop_;
Ben Murdoch558790d2013-07-30 15:19:42 +0100608 Profile* profile_;
609
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100610 scoped_ptr<content::DevToolsExternalAgentProxy> proxy_;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100611 scoped_ptr<TetheringAdbFilter> tethering_adb_filter_;
Ben Murdoch9ab55632013-07-18 11:57:30 +0100612 scoped_refptr<AdbWebSocket> web_socket_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100613 DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate);
614};
615
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100616DevToolsAdbBridge::RemotePage::RemotePage(
617 scoped_refptr<DevToolsAdbBridge> bridge,
618 scoped_refptr<AndroidDevice> device,
619 const std::string& socket,
620 const base::DictionaryValue& value)
621 : bridge_(bridge),
622 device_(device),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100623 socket_(socket) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000624 value.GetString("id", &id_);
625 value.GetString("url", &url_);
626 value.GetString("title", &title_);
627 value.GetString("descirption", &description_);
628 value.GetString("faviconUrl", &favicon_url_);
629 value.GetString("webSocketDebuggerUrl", &debug_url_);
630 value.GetString("devtoolsFrontendUrl", &frontend_url_);
631
632 if (debug_url_.find("ws://") == 0)
633 debug_url_ = debug_url_.substr(5);
634 else
635 debug_url_ = "";
636
637 size_t ws_param = frontend_url_.find("?ws");
638 if (ws_param != std::string::npos)
639 frontend_url_ = frontend_url_.substr(0, ws_param);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100640 if (frontend_url_.find("http:") == 0)
641 frontend_url_ = "https:" + frontend_url_.substr(5);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100642}
643
644void DevToolsAdbBridge::RemotePage::Inspect(Profile* profile) {
645 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Ben Murdochbb1529c2013-08-08 10:24:53 +0100646 std::string agent_id = base::StringPrintf("%s:%s:%s",
647 device_->serial().c_str(), socket_.c_str(), id_.c_str());
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100648 AgentHostDelegates::iterator it =
Ben Murdochbb1529c2013-08-08 10:24:53 +0100649 g_host_delegates.Get().find(agent_id);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100650 if (it != g_host_delegates.Get().end())
651 it->second->OpenFrontend();
652 else if (!debug_url_.empty())
653 new AgentHostDelegate(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100654 agent_id, device_, socket_, debug_url_,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100655 frontend_url_, bridge_->GetAdbMessageLoop(), profile);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000656}
657
Ben Murdochbb1529c2013-08-08 10:24:53 +0100658static void Noop(int, const std::string&) {}
659
660void DevToolsAdbBridge::RemotePage::Close() {
661 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
662 if (attached())
663 return;
664 std::string request = base::StringPrintf(kClosePageRequest, id_.c_str());
665 bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
666 base::Bind(&AndroidDevice::HttpQuery,
667 device_, socket_, request, base::Bind(&Noop)));
668}
669
670void DevToolsAdbBridge::RemotePage::Reload() {
671 SendProtocolCommand(kPageReloadCommand, NULL);
672}
673
674void DevToolsAdbBridge::RemotePage::SendProtocolCommand(
675 const std::string& method,
676 base::DictionaryValue* params) {
677 if (attached())
678 return;
679 DevToolsProtocol::Command command(1, method, params);
680 new AdbProtocolCommand(
681 bridge_, device_, socket_, debug_url_, command.Serialize());
682}
683
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000684DevToolsAdbBridge::RemotePage::~RemotePage() {
685}
686
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100687DevToolsAdbBridge::RemoteBrowser::RemoteBrowser(
688 scoped_refptr<DevToolsAdbBridge> bridge,
689 scoped_refptr<AndroidDevice> device,
690 const std::string& socket,
691 const std::string& name)
692 : bridge_(bridge),
693 device_(device),
694 socket_(socket),
695 name_(name) {
696}
697
Ben Murdochbb1529c2013-08-08 10:24:53 +0100698void DevToolsAdbBridge::RemoteBrowser::Open(const std::string& url) {
699 bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
700 base::Bind(&AndroidDevice::HttpQuery,
701 device_, socket_, kNewPageRequest,
702 base::Bind(&RemoteBrowser::PageCreatedOnHandlerThread, this, url)));
703}
704
705void DevToolsAdbBridge::RemoteBrowser::PageCreatedOnHandlerThread(
706 const std::string& url, int result, const std::string& response) {
707 if (result < 0)
708 return;
709 BrowserThread::PostTask(
710 BrowserThread::UI, FROM_HERE,
711 base::Bind(&RemoteBrowser::PageCreatedOnUIThread, this, response, url));
712}
713
714void DevToolsAdbBridge::RemoteBrowser::PageCreatedOnUIThread(
715 const std::string& response, const std::string& url) {
716 scoped_ptr<base::Value> value(base::JSONReader::Read(response));
717 base::DictionaryValue* dict;
718 if (value && value->GetAsDictionary(&dict)) {
719 scoped_refptr<RemotePage> new_page =
720 new RemotePage(bridge_, device_, socket_, *dict);
721 base::DictionaryValue params;
722 params.SetString(kUrlParam, url);
723 new_page->SendProtocolCommand(kPageNavigateCommand, &params);
724 }
725}
726
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100727DevToolsAdbBridge::RemoteBrowser::~RemoteBrowser() {
728}
729
730DevToolsAdbBridge::RemoteDevice::RemoteDevice(
731 scoped_refptr<DevToolsAdbBridge> bridge,
732 scoped_refptr<AndroidDevice> device)
733 : bridge_(bridge),
734 device_(device) {
735}
736
737DevToolsAdbBridge::RemoteDevice::~RemoteDevice() {
738}
739
740
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000741DevToolsAdbBridge::RefCountedAdbThread*
742DevToolsAdbBridge::RefCountedAdbThread::instance_ = NULL;
743
744// static
745scoped_refptr<DevToolsAdbBridge::RefCountedAdbThread>
746DevToolsAdbBridge::RefCountedAdbThread::GetInstance() {
747 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
748 if (!instance_)
749 new RefCountedAdbThread();
750 return instance_;
751}
752
753DevToolsAdbBridge::RefCountedAdbThread::RefCountedAdbThread() {
754 instance_ = this;
755 thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
756 base::Thread::Options options;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100757 options.message_loop_type = base::MessageLoop::TYPE_IO;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000758 if (!thread_->StartWithOptions(options)) {
759 delete thread_;
760 thread_ = NULL;
761 }
762}
763
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100764base::MessageLoop* DevToolsAdbBridge::RefCountedAdbThread::message_loop() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000765 return thread_ ? thread_->message_loop() : NULL;
766}
767
768// static
769void DevToolsAdbBridge::RefCountedAdbThread::StopThread(base::Thread* thread) {
770 thread->Stop();
771}
772
773DevToolsAdbBridge::RefCountedAdbThread::~RefCountedAdbThread() {
774 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
775 instance_ = NULL;
776 if (!thread_)
777 return;
778 // Shut down thread on FILE thread to join into IO.
779 BrowserThread::PostTask(
780 BrowserThread::FILE, FROM_HERE,
781 base::Bind(&RefCountedAdbThread::StopThread, thread_));
782}
783
784DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile)
785 : profile_(profile),
786 adb_thread_(RefCountedAdbThread::GetInstance()),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000787 has_message_loop_(adb_thread_->message_loop() != NULL) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100788 rsa_key_.reset(AndroidRSAPrivateKey(profile));
Ben Murdoch2385ea32013-08-06 11:01:04 +0100789 port_forwarding_controller_.reset(
790 new PortForwardingController(GetAdbMessageLoop(), profile->GetPrefs()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000791}
792
Ben Murdoch558790d2013-07-30 15:19:42 +0100793void DevToolsAdbBridge::EnumerateUsbDevices(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100794 const AndroidDevicesCallback& callback) {
Ben Murdoch32409262013-08-07 11:04:47 +0100795 DCHECK_EQ(base::MessageLoop::current(), adb_thread_->message_loop());
Ben Murdochca12bfa2013-07-23 11:17:05 +0100796 if (CommandLine::ForCurrentProcess()->HasSwitch(
797 switches::kRemoteDebuggingRawUSB)) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100798 AndroidUsbDevice::Enumerate(rsa_key_.get(),
Ben Murdochca12bfa2013-07-23 11:17:05 +0100799 base::Bind(&DevToolsAdbBridge::ReceivedUsbDevices, this, callback));
800 } else {
801 ReceivedUsbDevices(callback, AndroidUsbDevices());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000802 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000803}
804
Ben Murdoch558790d2013-07-30 15:19:42 +0100805void DevToolsAdbBridge::EnumerateAdbDevices(
806 const AndroidDevicesCallback& callback) {
807 DCHECK_EQ(base::MessageLoop::current(), adb_thread_->message_loop());
808
809 AdbClientSocket::AdbQuery(
810 kAdbPort, kHostDevicesCommand,
811 base::Bind(&DevToolsAdbBridge::ReceivedAdbDevices, this, callback));
812}
813
Ben Murdoch9ab55632013-07-18 11:57:30 +0100814void DevToolsAdbBridge::AddListener(Listener* listener) {
Ben Murdochca12bfa2013-07-23 11:17:05 +0100815 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Ben Murdoch9ab55632013-07-18 11:57:30 +0100816 if (listeners_.empty())
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100817 RequestRemoteDevices();
Ben Murdoch9ab55632013-07-18 11:57:30 +0100818 listeners_.push_back(listener);
819}
820
821void DevToolsAdbBridge::RemoveListener(Listener* listener) {
Ben Murdochca12bfa2013-07-23 11:17:05 +0100822 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Ben Murdoch9ab55632013-07-18 11:57:30 +0100823 Listeners::iterator it =
824 std::find(listeners_.begin(), listeners_.end(), listener);
825 DCHECK(it != listeners_.end());
826 listeners_.erase(it);
827}
828
Ben Murdoch558790d2013-07-30 15:19:42 +0100829base::MessageLoop* DevToolsAdbBridge::GetAdbMessageLoop() {
830 return adb_thread_->message_loop();
831}
832
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100833DevToolsAdbBridge::~DevToolsAdbBridge() {
834 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Ben Murdochca12bfa2013-07-23 11:17:05 +0100835 DCHECK(listeners_.empty());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100836}
837
Ben Murdochca12bfa2013-07-23 11:17:05 +0100838void DevToolsAdbBridge::ReceivedUsbDevices(
839 const AndroidDevicesCallback& callback,
840 const AndroidUsbDevices& usb_devices) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100841 AndroidDevices devices;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100842
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100843#if defined(DEBUG_DEVTOOLS)
844 devices.push_back(new AdbDeviceImpl("")); // For desktop remote debugging.
845#endif // defined(DEBUG_DEVTOOLS)
846
Ben Murdochca12bfa2013-07-23 11:17:05 +0100847 for (AndroidUsbDevices::const_iterator it = usb_devices.begin();
848 it != usb_devices.end(); ++it) {
849 devices.push_back(new UsbDeviceImpl(*it));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100850 }
851
Ben Murdoch558790d2013-07-30 15:19:42 +0100852 callback.Run(devices);
Ben Murdochca12bfa2013-07-23 11:17:05 +0100853}
854
855void DevToolsAdbBridge::ReceivedAdbDevices(
856 const AndroidDevicesCallback& callback,
Ben Murdochca12bfa2013-07-23 11:17:05 +0100857 int result,
858 const std::string& response) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100859 AndroidDevices devices;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100860 if (result != net::OK) {
861 callback.Run(devices);
862 return;
863 }
864
865 std::vector<std::string> serials;
866 Tokenize(response, "\n", &serials);
867 for (size_t i = 0; i < serials.size(); ++i) {
868 std::vector<std::string> tokens;
869 Tokenize(serials[i], "\t ", &tokens);
870 devices.push_back(new AdbDeviceImpl(tokens[0]));
871 }
872 callback.Run(devices);
873}
Ben Murdoch9ab55632013-07-18 11:57:30 +0100874
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100875void DevToolsAdbBridge::RequestRemoteDevices() {
Ben Murdoch9ab55632013-07-18 11:57:30 +0100876 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
877 if (!has_message_loop_)
878 return;
879
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100880 new AdbPagesCommand(
881 this, base::Bind(&DevToolsAdbBridge::ReceivedRemoteDevices, this));
Ben Murdoch9ab55632013-07-18 11:57:30 +0100882}
883
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100884void DevToolsAdbBridge::ReceivedRemoteDevices(RemoteDevices* devices_ptr) {
Ben Murdoch9ab55632013-07-18 11:57:30 +0100885 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Ben Murdoch9ab55632013-07-18 11:57:30 +0100886
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100887 scoped_ptr<RemoteDevices> devices(devices_ptr);
Ben Murdoch2385ea32013-08-06 11:01:04 +0100888 port_forwarding_controller_->UpdateDeviceList(*devices.get());
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100889
890 Listeners copy(listeners_);
891 for (Listeners::iterator it = copy.begin(); it != copy.end(); ++it)
892 (*it)->RemoteDevicesChanged(devices.get());
Ben Murdoch9ab55632013-07-18 11:57:30 +0100893
894 if (listeners_.empty())
895 return;
896
897 BrowserThread::PostDelayedTask(
898 BrowserThread::UI,
899 FROM_HERE,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100900 base::Bind(&DevToolsAdbBridge::RequestRemoteDevices, this),
Ben Murdoch9ab55632013-07-18 11:57:30 +0100901 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs));
902}