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