1 // Copyright 2014 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/device/android_device_manager.h"
6
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12 #include "net/socket/stream_socket.h"
13
14 using content::BrowserThread;
15
16 namespace {
17
18 const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
19
20 const int kBufferSize = 16 * 1024;
21
22 static const char kModelOffline[] = "Offline";
23
24 static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n";
25
26 static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n"
27 "Upgrade: WebSocket\r\n"
28 "Connection: Upgrade\r\n"
29 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
30 "Sec-WebSocket-Version: 13\r\n"
31 "\r\n";
32
PostDeviceInfoCallback(scoped_refptr<base::MessageLoopProxy> response_message_loop,const AndroidDeviceManager::DeviceInfoCallback & callback,const AndroidDeviceManager::DeviceInfo & device_info)33 static void PostDeviceInfoCallback(
34 scoped_refptr<base::MessageLoopProxy> response_message_loop,
35 const AndroidDeviceManager::DeviceInfoCallback& callback,
36 const AndroidDeviceManager::DeviceInfo& device_info) {
37 response_message_loop->PostTask(FROM_HERE, base::Bind(callback, device_info));
38 }
39
PostCommandCallback(scoped_refptr<base::MessageLoopProxy> response_message_loop,const AndroidDeviceManager::CommandCallback & callback,int result,const std::string & response)40 static void PostCommandCallback(
41 scoped_refptr<base::MessageLoopProxy> response_message_loop,
42 const AndroidDeviceManager::CommandCallback& callback,
43 int result,
44 const std::string& response) {
45 response_message_loop->PostTask(FROM_HERE,
46 base::Bind(callback, result, response));
47 }
48
PostSocketCallback(scoped_refptr<base::MessageLoopProxy> response_message_loop,const AndroidDeviceManager::SocketCallback & callback,int result,scoped_ptr<net::StreamSocket> socket)49 static void PostSocketCallback(
50 scoped_refptr<base::MessageLoopProxy> response_message_loop,
51 const AndroidDeviceManager::SocketCallback& callback,
52 int result,
53 scoped_ptr<net::StreamSocket> socket) {
54 response_message_loop->PostTask(
55 FROM_HERE, base::Bind(callback, result, base::Passed(&socket)));
56 }
57
58 class HttpRequest {
59 public:
60 typedef AndroidDeviceManager::CommandCallback CommandCallback;
61 typedef AndroidDeviceManager::SocketCallback SocketCallback;
62
CommandRequest(const std::string & request,const CommandCallback & callback,int result,scoped_ptr<net::StreamSocket> socket)63 static void CommandRequest(const std::string& request,
64 const CommandCallback& callback,
65 int result,
66 scoped_ptr<net::StreamSocket> socket) {
67 if (result != net::OK) {
68 callback.Run(result, std::string());
69 return;
70 }
71 new HttpRequest(socket.Pass(), request, callback);
72 }
73
SocketRequest(const std::string & request,const SocketCallback & callback,int result,scoped_ptr<net::StreamSocket> socket)74 static void SocketRequest(const std::string& request,
75 const SocketCallback& callback,
76 int result,
77 scoped_ptr<net::StreamSocket> socket) {
78 if (result != net::OK) {
79 callback.Run(result, make_scoped_ptr<net::StreamSocket>(NULL));
80 return;
81 }
82 new HttpRequest(socket.Pass(), request, callback);
83 }
84
85 private:
HttpRequest(scoped_ptr<net::StreamSocket> socket,const std::string & request,const CommandCallback & callback)86 HttpRequest(scoped_ptr<net::StreamSocket> socket,
87 const std::string& request,
88 const CommandCallback& callback)
89 : socket_(socket.Pass()),
90 command_callback_(callback),
91 body_pos_(0) {
92 SendRequest(request);
93 }
94
HttpRequest(scoped_ptr<net::StreamSocket> socket,const std::string & request,const SocketCallback & callback)95 HttpRequest(scoped_ptr<net::StreamSocket> socket,
96 const std::string& request,
97 const SocketCallback& callback)
98 : socket_(socket.Pass()),
99 socket_callback_(callback),
100 body_pos_(0) {
101 SendRequest(request);
102 }
103
~HttpRequest()104 ~HttpRequest() {
105 }
106
SendRequest(const std::string & request)107 void SendRequest(const std::string& request) {
108 scoped_refptr<net::StringIOBuffer> request_buffer =
109 new net::StringIOBuffer(request);
110
111 int result = socket_->Write(
112 request_buffer.get(),
113 request_buffer->size(),
114 base::Bind(&HttpRequest::ReadResponse, base::Unretained(this)));
115 if (result != net::ERR_IO_PENDING)
116 ReadResponse(result);
117 }
118
ReadResponse(int result)119 void ReadResponse(int result) {
120 if (!CheckNetResultOrDie(result))
121 return;
122 scoped_refptr<net::IOBuffer> response_buffer =
123 new net::IOBuffer(kBufferSize);
124
125 result = socket_->Read(
126 response_buffer.get(),
127 kBufferSize,
128 base::Bind(&HttpRequest::OnResponseData, base::Unretained(this),
129 response_buffer,
130 -1));
131 if (result != net::ERR_IO_PENDING)
132 OnResponseData(response_buffer, -1, result);
133 }
134
OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,int bytes_total,int result)135 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
136 int bytes_total,
137 int result) {
138 if (!CheckNetResultOrDie(result))
139 return;
140 if (result == 0) {
141 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
142 return;
143 }
144
145 response_ += std::string(response_buffer->data(), result);
146 int expected_length = 0;
147 if (bytes_total < 0) {
148 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
149 size_t content_pos = response_.find("Content-Length:");
150 if (content_pos != std::string::npos) {
151 size_t endline_pos = response_.find("\n", content_pos);
152 if (endline_pos != std::string::npos) {
153 std::string len = response_.substr(content_pos + 15,
154 endline_pos - content_pos - 15);
155 base::TrimWhitespace(len, base::TRIM_ALL, &len);
156 if (!base::StringToInt(len, &expected_length)) {
157 CheckNetResultOrDie(net::ERR_FAILED);
158 return;
159 }
160 }
161 }
162
163 body_pos_ = response_.find("\r\n\r\n");
164 if (body_pos_ != std::string::npos) {
165 body_pos_ += 4;
166 bytes_total = body_pos_ + expected_length;
167 }
168 }
169
170 if (bytes_total == static_cast<int>(response_.length())) {
171 if (!command_callback_.is_null())
172 command_callback_.Run(net::OK, response_.substr(body_pos_));
173 else
174 socket_callback_.Run(net::OK, socket_.Pass());
175 delete this;
176 return;
177 }
178
179 result = socket_->Read(
180 response_buffer.get(),
181 kBufferSize,
182 base::Bind(&HttpRequest::OnResponseData,
183 base::Unretained(this),
184 response_buffer,
185 bytes_total));
186 if (result != net::ERR_IO_PENDING)
187 OnResponseData(response_buffer, bytes_total, result);
188 }
189
CheckNetResultOrDie(int result)190 bool CheckNetResultOrDie(int result) {
191 if (result >= 0)
192 return true;
193 if (!command_callback_.is_null())
194 command_callback_.Run(result, std::string());
195 else
196 socket_callback_.Run(result, make_scoped_ptr<net::StreamSocket>(NULL));
197 delete this;
198 return false;
199 }
200
201 scoped_ptr<net::StreamSocket> socket_;
202 std::string response_;
203 AndroidDeviceManager::CommandCallback command_callback_;
204 AndroidDeviceManager::SocketCallback socket_callback_;
205 size_t body_pos_;
206 };
207
208 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> {
209 public:
210 typedef AndroidDeviceManager::DeviceInfo DeviceInfo;
211 typedef AndroidDeviceManager::DeviceProvider DeviceProvider;
212 typedef AndroidDeviceManager::DeviceProviders DeviceProviders;
213 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors;
214 typedef base::Callback<void(DeviceDescriptors*)>
215 DescriptorsCallback;
216
Start(scoped_refptr<base::MessageLoopProxy> device_message_loop,const DeviceProviders & providers,const DescriptorsCallback & callback)217 static void Start(scoped_refptr<base::MessageLoopProxy> device_message_loop,
218 const DeviceProviders& providers,
219 const DescriptorsCallback& callback) {
220 // Don't keep counted reference on calling thread;
221 DevicesRequest* request = new DevicesRequest(callback);
222 // Avoid destruction while sending requests
223 request->AddRef();
224 for (DeviceProviders::const_iterator it = providers.begin();
225 it != providers.end(); ++it) {
226 device_message_loop->PostTask(
227 FROM_HERE,
228 base::Bind(
229 &DeviceProvider::QueryDevices,
230 *it,
231 base::Bind(&DevicesRequest::ProcessSerials, request, *it)));
232 }
233 device_message_loop->ReleaseSoon(FROM_HERE, request);
234 }
235
236 private:
DevicesRequest(const DescriptorsCallback & callback)237 explicit DevicesRequest(const DescriptorsCallback& callback)
238 : response_message_loop_(base::MessageLoopProxy::current()),
239 callback_(callback),
240 descriptors_(new DeviceDescriptors()) {
241 }
242
243 friend class base::RefCountedThreadSafe<DevicesRequest>;
~DevicesRequest()244 ~DevicesRequest() {
245 response_message_loop_->PostTask(FROM_HERE,
246 base::Bind(callback_, descriptors_.release()));
247 }
248
249 typedef std::vector<std::string> Serials;
250
ProcessSerials(scoped_refptr<DeviceProvider> provider,const Serials & serials)251 void ProcessSerials(scoped_refptr<DeviceProvider> provider,
252 const Serials& serials) {
253 for (Serials::const_iterator it = serials.begin(); it != serials.end();
254 ++it) {
255 descriptors_->resize(descriptors_->size() + 1);
256 descriptors_->back().provider = provider;
257 descriptors_->back().serial = *it;
258 }
259 }
260
261 scoped_refptr<base::MessageLoopProxy> response_message_loop_;
262 DescriptorsCallback callback_;
263 scoped_ptr<DeviceDescriptors> descriptors_;
264 };
265
ReleaseDeviceAndProvider(AndroidDeviceManager::DeviceProvider * provider,const std::string & serial)266 void ReleaseDeviceAndProvider(
267 AndroidDeviceManager::DeviceProvider* provider,
268 const std::string& serial) {
269 provider->ReleaseDevice(serial);
270 provider->Release();
271 }
272
273 } // namespace
274
BrowserInfo()275 AndroidDeviceManager::BrowserInfo::BrowserInfo()
276 : type(kTypeOther) {
277 }
278
DeviceInfo()279 AndroidDeviceManager::DeviceInfo::DeviceInfo()
280 : model(kModelOffline), connected(false) {
281 }
282
~DeviceInfo()283 AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
284 }
285
DeviceDescriptor()286 AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
287 }
288
~DeviceDescriptor()289 AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
290 }
291
SendJsonRequest(const std::string & serial,const std::string & socket_name,const std::string & request,const CommandCallback & callback)292 void AndroidDeviceManager::DeviceProvider::SendJsonRequest(
293 const std::string& serial,
294 const std::string& socket_name,
295 const std::string& request,
296 const CommandCallback& callback) {
297 OpenSocket(serial,
298 socket_name,
299 base::Bind(&HttpRequest::CommandRequest,
300 base::StringPrintf(kHttpGetRequest, request.c_str()),
301 callback));
302 }
303
HttpUpgrade(const std::string & serial,const std::string & socket_name,const std::string & url,const SocketCallback & callback)304 void AndroidDeviceManager::DeviceProvider::HttpUpgrade(
305 const std::string& serial,
306 const std::string& socket_name,
307 const std::string& url,
308 const SocketCallback& callback) {
309 OpenSocket(
310 serial,
311 socket_name,
312 base::Bind(&HttpRequest::SocketRequest,
313 base::StringPrintf(kWebSocketUpgradeRequest, url.c_str()),
314 callback));
315 }
316
ReleaseDevice(const std::string & serial)317 void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
318 const std::string& serial) {
319 }
320
DeviceProvider()321 AndroidDeviceManager::DeviceProvider::DeviceProvider() {
322 }
323
~DeviceProvider()324 AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
325 }
326
QueryDeviceInfo(const DeviceInfoCallback & callback)327 void AndroidDeviceManager::Device::QueryDeviceInfo(
328 const DeviceInfoCallback& callback) {
329 device_message_loop_->PostTask(
330 FROM_HERE,
331 base::Bind(&DeviceProvider::QueryDeviceInfo,
332 provider_,
333 serial_,
334 base::Bind(&PostDeviceInfoCallback,
335 base::MessageLoopProxy::current(),
336 callback)));
337 }
338
OpenSocket(const std::string & socket_name,const SocketCallback & callback)339 void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name,
340 const SocketCallback& callback) {
341 device_message_loop_->PostTask(
342 FROM_HERE,
343 base::Bind(&DeviceProvider::OpenSocket,
344 provider_,
345 serial_,
346 socket_name,
347 callback));
348 }
349
SendJsonRequest(const std::string & socket_name,const std::string & request,const CommandCallback & callback)350 void AndroidDeviceManager::Device::SendJsonRequest(
351 const std::string& socket_name,
352 const std::string& request,
353 const CommandCallback& callback) {
354 device_message_loop_->PostTask(
355 FROM_HERE,
356 base::Bind(&DeviceProvider::SendJsonRequest,
357 provider_,
358 serial_,
359 socket_name,
360 request,
361 base::Bind(&PostCommandCallback,
362 base::MessageLoopProxy::current(),
363 callback)));
364 }
365
HttpUpgrade(const std::string & socket_name,const std::string & url,const SocketCallback & callback)366 void AndroidDeviceManager::Device::HttpUpgrade(const std::string& socket_name,
367 const std::string& url,
368 const SocketCallback& callback) {
369 device_message_loop_->PostTask(
370 FROM_HERE,
371 base::Bind(&DeviceProvider::HttpUpgrade,
372 provider_,
373 serial_,
374 socket_name,
375 url,
376 base::Bind(&PostSocketCallback,
377 base::MessageLoopProxy::current(),
378 callback)));
379 }
380
Device(scoped_refptr<base::MessageLoopProxy> device_message_loop,scoped_refptr<DeviceProvider> provider,const std::string & serial)381 AndroidDeviceManager::Device::Device(
382 scoped_refptr<base::MessageLoopProxy> device_message_loop,
383 scoped_refptr<DeviceProvider> provider,
384 const std::string& serial)
385 : device_message_loop_(device_message_loop),
386 provider_(provider),
387 serial_(serial),
388 weak_factory_(this) {
389 }
390
~Device()391 AndroidDeviceManager::Device::~Device() {
392 provider_->AddRef();
393 DeviceProvider* raw_ptr = provider_.get();
394 provider_ = NULL;
395 device_message_loop_->PostTask(
396 FROM_HERE,
397 base::Bind(&ReleaseDeviceAndProvider,
398 base::Unretained(raw_ptr),
399 serial_));
400 }
401
402 AndroidDeviceManager::HandlerThread*
403 AndroidDeviceManager::HandlerThread::instance_ = NULL;
404
405 // static
406 scoped_refptr<AndroidDeviceManager::HandlerThread>
GetInstance()407 AndroidDeviceManager::HandlerThread::GetInstance() {
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
409 if (!instance_)
410 new HandlerThread();
411 return instance_;
412 }
413
HandlerThread()414 AndroidDeviceManager::HandlerThread::HandlerThread() {
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
416 instance_ = this;
417 thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
418 base::Thread::Options options;
419 options.message_loop_type = base::MessageLoop::TYPE_IO;
420 if (!thread_->StartWithOptions(options)) {
421 delete thread_;
422 thread_ = NULL;
423 }
424 }
425
426 scoped_refptr<base::MessageLoopProxy>
message_loop()427 AndroidDeviceManager::HandlerThread::message_loop() {
428 return thread_ ? thread_->message_loop_proxy() : NULL;
429 }
430
431 // static
StopThread(base::Thread * thread)432 void AndroidDeviceManager::HandlerThread::StopThread(
433 base::Thread* thread) {
434 thread->Stop();
435 }
436
~HandlerThread()437 AndroidDeviceManager::HandlerThread::~HandlerThread() {
438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
439 instance_ = NULL;
440 if (!thread_)
441 return;
442 // Shut down thread on FILE thread to join into IO.
443 content::BrowserThread::PostTask(
444 content::BrowserThread::FILE, FROM_HERE,
445 base::Bind(&HandlerThread::StopThread, thread_));
446 }
447
448 // static
Create()449 scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
450 return new AndroidDeviceManager();
451 }
452
SetDeviceProviders(const DeviceProviders & providers)453 void AndroidDeviceManager::SetDeviceProviders(
454 const DeviceProviders& providers) {
455 for (DeviceProviders::iterator it = providers_.begin();
456 it != providers_.end(); ++it) {
457 (*it)->AddRef();
458 DeviceProvider* raw_ptr = it->get();
459 *it = NULL;
460 handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
461 }
462 providers_ = providers;
463 }
464
QueryDevices(const DevicesCallback & callback)465 void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) {
466 DevicesRequest::Start(handler_thread_->message_loop(),
467 providers_,
468 base::Bind(&AndroidDeviceManager::UpdateDevices,
469 this,
470 callback));
471 }
472
AndroidDeviceManager()473 AndroidDeviceManager::AndroidDeviceManager()
474 : handler_thread_(HandlerThread::GetInstance()) {
475 }
476
~AndroidDeviceManager()477 AndroidDeviceManager::~AndroidDeviceManager() {
478 SetDeviceProviders(DeviceProviders());
479 }
480
UpdateDevices(const DevicesCallback & callback,DeviceDescriptors * descriptors_raw)481 void AndroidDeviceManager::UpdateDevices(
482 const DevicesCallback& callback,
483 DeviceDescriptors* descriptors_raw) {
484 scoped_ptr<DeviceDescriptors> descriptors(descriptors_raw);
485 Devices response;
486 DeviceWeakMap new_devices;
487 for (DeviceDescriptors::const_iterator it = descriptors->begin();
488 it != descriptors->end();
489 ++it) {
490 DeviceWeakMap::iterator found = devices_.find(it->serial);
491 scoped_refptr<Device> device;
492 if (found == devices_.end() || !found->second ||
493 found->second->provider_.get() != it->provider.get()) {
494 device = new Device(handler_thread_->message_loop(),
495 it->provider, it->serial);
496 } else {
497 device = found->second.get();
498 }
499 response.push_back(device);
500 new_devices[it->serial] = device->weak_factory_.GetWeakPtr();
501 }
502 devices_.swap(new_devices);
503 callback.Run(response);
504 }
505