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.
5 #include "chrome/browser/devtools/device/android_device_manager.h"
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"
14 using content::BrowserThread
;
18 const char kDevToolsAdbBridgeThreadName
[] = "Chrome_DevToolsADBThread";
20 const int kBufferSize
= 16 * 1024;
22 static const char kModelOffline
[] = "Offline";
24 static const char kHttpGetRequest
[] = "GET %s HTTP/1.1\r\n\r\n";
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"
34 static void PostDeviceInfoCallback(
35 scoped_refptr
<base::MessageLoopProxy
> response_message_loop
,
36 const AndroidDeviceManager::DeviceInfoCallback
& callback
,
37 const AndroidDeviceManager::DeviceInfo
& device_info
) {
38 response_message_loop
->PostTask(FROM_HERE
, base::Bind(callback
, device_info
));
41 static void PostCommandCallback(
42 scoped_refptr
<base::MessageLoopProxy
> response_message_loop
,
43 const AndroidDeviceManager::CommandCallback
& callback
,
45 const std::string
& response
) {
46 response_message_loop
->PostTask(FROM_HERE
,
47 base::Bind(callback
, result
, response
));
50 static void PostHttpUpgradeCallback(
51 scoped_refptr
<base::MessageLoopProxy
> response_message_loop
,
52 const AndroidDeviceManager::HttpUpgradeCallback
& callback
,
54 const std::string
& extensions
,
55 scoped_ptr
<net::StreamSocket
> socket
) {
56 response_message_loop
->PostTask(
58 base::Bind(callback
, result
, extensions
, base::Passed(&socket
)));
63 typedef AndroidDeviceManager::CommandCallback CommandCallback
;
64 typedef AndroidDeviceManager::HttpUpgradeCallback HttpUpgradeCallback
;
66 static void CommandRequest(const std::string
& request
,
67 const CommandCallback
& callback
,
69 scoped_ptr
<net::StreamSocket
> socket
) {
70 if (result
!= net::OK
) {
71 callback
.Run(result
, std::string());
74 new HttpRequest(socket
.Pass(), request
, callback
);
77 static void HttpUpgradeRequest(const std::string
& request
,
78 const HttpUpgradeCallback
& callback
,
80 scoped_ptr
<net::StreamSocket
> socket
) {
81 if (result
!= net::OK
) {
82 callback
.Run(result
, "", make_scoped_ptr
<net::StreamSocket
>(nullptr));
85 new HttpRequest(socket
.Pass(), request
, callback
);
89 HttpRequest(scoped_ptr
<net::StreamSocket
> socket
,
90 const std::string
& request
,
91 const CommandCallback
& callback
)
92 : socket_(socket
.Pass()),
93 command_callback_(callback
),
98 HttpRequest(scoped_ptr
<net::StreamSocket
> socket
,
99 const std::string
& request
,
100 const HttpUpgradeCallback
& callback
)
101 : socket_(socket
.Pass()),
102 http_upgrade_callback_(callback
),
104 SendRequest(request
);
110 void SendRequest(const std::string
& request
) {
111 scoped_refptr
<net::StringIOBuffer
> request_buffer
=
112 new net::StringIOBuffer(request
);
114 int result
= socket_
->Write(
115 request_buffer
.get(),
116 request_buffer
->size(),
117 base::Bind(&HttpRequest::ReadResponse
, base::Unretained(this)));
118 if (result
!= net::ERR_IO_PENDING
)
119 ReadResponse(result
);
122 void ReadResponse(int result
) {
123 if (!CheckNetResultOrDie(result
))
125 scoped_refptr
<net::IOBuffer
> response_buffer
=
126 new net::IOBuffer(kBufferSize
);
128 result
= socket_
->Read(
129 response_buffer
.get(),
131 base::Bind(&HttpRequest::OnResponseData
, base::Unretained(this),
134 if (result
!= net::ERR_IO_PENDING
)
135 OnResponseData(response_buffer
, -1, result
);
138 void OnResponseData(scoped_refptr
<net::IOBuffer
> response_buffer
,
141 if (!CheckNetResultOrDie(result
))
144 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED
);
148 response_
+= std::string(response_buffer
->data(), result
);
149 int expected_length
= 0;
150 if (bytes_total
< 0) {
151 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
152 std::string content_length
= ExtractHeader("Content-Length:");
153 if (!content_length
.empty()) {
154 if (!base::StringToInt(content_length
, &expected_length
)) {
155 CheckNetResultOrDie(net::ERR_FAILED
);
160 body_pos_
= response_
.find("\r\n\r\n");
161 if (body_pos_
!= std::string::npos
) {
163 bytes_total
= body_pos_
+ expected_length
;
167 if (bytes_total
== static_cast<int>(response_
.length())) {
168 if (!command_callback_
.is_null()) {
169 command_callback_
.Run(net::OK
, response_
.substr(body_pos_
));
171 http_upgrade_callback_
.Run(net::OK
,
172 ExtractHeader("Sec-WebSocket-Extensions:"), socket_
.Pass());
178 result
= socket_
->Read(
179 response_buffer
.get(),
181 base::Bind(&HttpRequest::OnResponseData
,
182 base::Unretained(this),
185 if (result
!= net::ERR_IO_PENDING
)
186 OnResponseData(response_buffer
, bytes_total
, result
);
189 std::string
ExtractHeader(const std::string
& header
) {
190 size_t start_pos
= response_
.find(header
);
191 if (start_pos
== std::string::npos
)
192 return std::string();
194 size_t endline_pos
= response_
.find("\n", start_pos
);
195 if (endline_pos
== std::string::npos
)
196 return std::string();
198 std::string value
= response_
.substr(
199 start_pos
+ header
.length(), endline_pos
- start_pos
- header
.length());
200 base::TrimWhitespace(value
, base::TRIM_ALL
, &value
);
204 bool CheckNetResultOrDie(int result
) {
207 if (!command_callback_
.is_null()) {
208 command_callback_
.Run(result
, std::string());
210 http_upgrade_callback_
.Run(
211 result
, "", make_scoped_ptr
<net::StreamSocket
>(nullptr));
217 scoped_ptr
<net::StreamSocket
> socket_
;
218 std::string response_
;
219 CommandCallback command_callback_
;
220 HttpUpgradeCallback http_upgrade_callback_
;
224 class DevicesRequest
: public base::RefCountedThreadSafe
<DevicesRequest
> {
226 typedef AndroidDeviceManager::DeviceInfo DeviceInfo
;
227 typedef AndroidDeviceManager::DeviceProvider DeviceProvider
;
228 typedef AndroidDeviceManager::DeviceProviders DeviceProviders
;
229 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors
;
230 typedef base::Callback
<void(scoped_ptr
<DeviceDescriptors
>)>
233 static void Start(scoped_refptr
<base::MessageLoopProxy
> device_message_loop
,
234 const DeviceProviders
& providers
,
235 const DescriptorsCallback
& callback
) {
236 // Don't keep counted reference on calling thread;
237 DevicesRequest
* request
= new DevicesRequest(callback
);
238 // Avoid destruction while sending requests
240 for (DeviceProviders::const_iterator it
= providers
.begin();
241 it
!= providers
.end(); ++it
) {
242 device_message_loop
->PostTask(
245 &DeviceProvider::QueryDevices
,
247 base::Bind(&DevicesRequest::ProcessSerials
, request
, *it
)));
249 device_message_loop
->ReleaseSoon(FROM_HERE
, request
);
253 explicit DevicesRequest(const DescriptorsCallback
& callback
)
254 : response_message_loop_(base::MessageLoopProxy::current()),
256 descriptors_(new DeviceDescriptors()) {
259 friend class base::RefCountedThreadSafe
<DevicesRequest
>;
261 response_message_loop_
->PostTask(FROM_HERE
,
262 base::Bind(callback_
, base::Passed(&descriptors_
)));
265 typedef std::vector
<std::string
> Serials
;
267 void ProcessSerials(scoped_refptr
<DeviceProvider
> provider
,
268 const Serials
& serials
) {
269 for (Serials::const_iterator it
= serials
.begin(); it
!= serials
.end();
271 descriptors_
->resize(descriptors_
->size() + 1);
272 descriptors_
->back().provider
= provider
;
273 descriptors_
->back().serial
= *it
;
277 scoped_refptr
<base::MessageLoopProxy
> response_message_loop_
;
278 DescriptorsCallback callback_
;
279 scoped_ptr
<DeviceDescriptors
> descriptors_
;
282 void ReleaseDeviceAndProvider(
283 AndroidDeviceManager::DeviceProvider
* provider
,
284 const std::string
& serial
) {
285 provider
->ReleaseDevice(serial
);
291 AndroidDeviceManager::BrowserInfo::BrowserInfo()
295 AndroidDeviceManager::DeviceInfo::DeviceInfo()
296 : model(kModelOffline
), connected(false) {
299 AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
302 AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
305 AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
308 void AndroidDeviceManager::DeviceProvider::SendJsonRequest(
309 const std::string
& serial
,
310 const std::string
& socket_name
,
311 const std::string
& request
,
312 const CommandCallback
& callback
) {
315 base::Bind(&HttpRequest::CommandRequest
,
316 base::StringPrintf(kHttpGetRequest
, request
.c_str()),
320 void AndroidDeviceManager::DeviceProvider::HttpUpgrade(
321 const std::string
& serial
,
322 const std::string
& socket_name
,
323 const std::string
& url
,
324 const std::string
& extensions
,
325 const HttpUpgradeCallback
& callback
) {
326 std::string extensions_with_new_line
=
327 extensions
.empty() ? std::string() : extensions
+ "\r\n";
331 base::Bind(&HttpRequest::HttpUpgradeRequest
,
332 base::StringPrintf(kWebSocketUpgradeRequest
,
334 extensions_with_new_line
.c_str()),
338 void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
339 const std::string
& serial
) {
342 AndroidDeviceManager::DeviceProvider::DeviceProvider() {
345 AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
348 void AndroidDeviceManager::Device::QueryDeviceInfo(
349 const DeviceInfoCallback
& callback
) {
350 message_loop_proxy_
->PostTask(
352 base::Bind(&DeviceProvider::QueryDeviceInfo
,
355 base::Bind(&PostDeviceInfoCallback
,
356 base::MessageLoopProxy::current(),
360 void AndroidDeviceManager::Device::OpenSocket(const std::string
& socket_name
,
361 const SocketCallback
& callback
) {
362 message_loop_proxy_
->PostTask(
364 base::Bind(&DeviceProvider::OpenSocket
,
371 void AndroidDeviceManager::Device::SendJsonRequest(
372 const std::string
& socket_name
,
373 const std::string
& request
,
374 const CommandCallback
& callback
) {
375 message_loop_proxy_
->PostTask(
377 base::Bind(&DeviceProvider::SendJsonRequest
,
382 base::Bind(&PostCommandCallback
,
383 base::MessageLoopProxy::current(),
387 void AndroidDeviceManager::Device::HttpUpgrade(
388 const std::string
& socket_name
,
389 const std::string
& url
,
390 const std::string
& extensions
,
391 const HttpUpgradeCallback
& callback
) {
392 message_loop_proxy_
->PostTask(
394 base::Bind(&DeviceProvider::HttpUpgrade
,
400 base::Bind(&PostHttpUpgradeCallback
,
401 base::MessageLoopProxy::current(),
405 AndroidDeviceManager::Device::Device(
406 scoped_refptr
<base::MessageLoopProxy
> device_message_loop
,
407 scoped_refptr
<DeviceProvider
> provider
,
408 const std::string
& serial
)
409 : message_loop_proxy_(device_message_loop
),
412 weak_factory_(this) {
415 AndroidDeviceManager::Device::~Device() {
416 std::set
<AndroidWebSocket
*> sockets_copy(sockets_
);
417 for (AndroidWebSocket
* socket
: sockets_copy
)
418 socket
->OnSocketClosed();
421 DeviceProvider
* raw_ptr
= provider_
.get();
423 message_loop_proxy_
->PostTask(
425 base::Bind(&ReleaseDeviceAndProvider
,
426 base::Unretained(raw_ptr
),
430 AndroidDeviceManager::HandlerThread
*
431 AndroidDeviceManager::HandlerThread::instance_
= NULL
;
434 scoped_refptr
<AndroidDeviceManager::HandlerThread
>
435 AndroidDeviceManager::HandlerThread::GetInstance() {
436 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
442 AndroidDeviceManager::HandlerThread::HandlerThread() {
443 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
445 thread_
= new base::Thread(kDevToolsAdbBridgeThreadName
);
446 base::Thread::Options options
;
447 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
448 if (!thread_
->StartWithOptions(options
)) {
454 scoped_refptr
<base::MessageLoopProxy
>
455 AndroidDeviceManager::HandlerThread::message_loop() {
456 return thread_
? thread_
->message_loop_proxy() : NULL
;
460 void AndroidDeviceManager::HandlerThread::StopThread(
461 base::Thread
* thread
) {
465 AndroidDeviceManager::HandlerThread::~HandlerThread() {
466 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
470 // Shut down thread on FILE thread to join into IO.
471 content::BrowserThread::PostTask(
472 content::BrowserThread::FILE, FROM_HERE
,
473 base::Bind(&HandlerThread::StopThread
, thread_
));
477 scoped_ptr
<AndroidDeviceManager
> AndroidDeviceManager::Create() {
478 return make_scoped_ptr(new AndroidDeviceManager());
481 void AndroidDeviceManager::SetDeviceProviders(
482 const DeviceProviders
& providers
) {
483 for (DeviceProviders::iterator it
= providers_
.begin();
484 it
!= providers_
.end(); ++it
) {
486 DeviceProvider
* raw_ptr
= it
->get();
488 handler_thread_
->message_loop()->ReleaseSoon(FROM_HERE
, raw_ptr
);
490 providers_
= providers
;
493 void AndroidDeviceManager::QueryDevices(const DevicesCallback
& callback
) {
494 DevicesRequest::Start(handler_thread_
->message_loop(),
496 base::Bind(&AndroidDeviceManager::UpdateDevices
,
497 weak_factory_
.GetWeakPtr(),
501 AndroidDeviceManager::AndroidDeviceManager()
502 : handler_thread_(HandlerThread::GetInstance()),
503 weak_factory_(this) {
506 AndroidDeviceManager::~AndroidDeviceManager() {
507 SetDeviceProviders(DeviceProviders());
510 void AndroidDeviceManager::UpdateDevices(
511 const DevicesCallback
& callback
,
512 scoped_ptr
<DeviceDescriptors
> descriptors
) {
514 DeviceWeakMap new_devices
;
515 for (DeviceDescriptors::const_iterator it
= descriptors
->begin();
516 it
!= descriptors
->end();
518 DeviceWeakMap::iterator found
= devices_
.find(it
->serial
);
519 scoped_refptr
<Device
> device
;
520 if (found
== devices_
.end() || !found
->second
||
521 found
->second
->provider_
.get() != it
->provider
.get()) {
522 device
= new Device(handler_thread_
->message_loop(),
523 it
->provider
, it
->serial
);
525 device
= found
->second
.get();
527 response
.push_back(device
);
528 new_devices
[it
->serial
] = device
->weak_factory_
.GetWeakPtr();
530 devices_
.swap(new_devices
);
531 callback
.Run(response
);