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"
9 #include "base/location.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16 #include "net/socket/stream_socket.h"
18 using content::BrowserThread
;
22 const char kDevToolsAdbBridgeThreadName
[] = "Chrome_DevToolsADBThread";
24 const int kBufferSize
= 16 * 1024;
26 static const char kModelOffline
[] = "Offline";
28 static const char kHttpGetRequest
[] = "GET %s HTTP/1.1\r\n\r\n";
30 static const char kWebSocketUpgradeRequest
[] = "GET %s HTTP/1.1\r\n"
31 "Upgrade: WebSocket\r\n"
32 "Connection: Upgrade\r\n"
33 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
34 "Sec-WebSocket-Version: 13\r\n"
38 static void PostDeviceInfoCallback(
39 scoped_refptr
<base::SingleThreadTaskRunner
> response_task_runner
,
40 const AndroidDeviceManager::DeviceInfoCallback
& callback
,
41 const AndroidDeviceManager::DeviceInfo
& device_info
) {
42 response_task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, device_info
));
45 static void PostCommandCallback(
46 scoped_refptr
<base::SingleThreadTaskRunner
> response_task_runner
,
47 const AndroidDeviceManager::CommandCallback
& callback
,
49 const std::string
& response
) {
50 response_task_runner
->PostTask(FROM_HERE
,
51 base::Bind(callback
, result
, response
));
54 static void PostHttpUpgradeCallback(
55 scoped_refptr
<base::SingleThreadTaskRunner
> response_task_runner
,
56 const AndroidDeviceManager::HttpUpgradeCallback
& callback
,
58 const std::string
& extensions
,
59 const std::string
& body_head
,
60 scoped_ptr
<net::StreamSocket
> socket
) {
61 response_task_runner
->PostTask(
62 FROM_HERE
, base::Bind(callback
, result
, extensions
, body_head
,
63 base::Passed(&socket
)));
68 typedef AndroidDeviceManager::CommandCallback CommandCallback
;
69 typedef AndroidDeviceManager::HttpUpgradeCallback HttpUpgradeCallback
;
71 static void CommandRequest(const std::string
& request
,
72 const CommandCallback
& callback
,
74 scoped_ptr
<net::StreamSocket
> socket
) {
75 if (result
!= net::OK
) {
76 callback
.Run(result
, std::string());
79 new HttpRequest(socket
.Pass(), request
, callback
);
82 static void HttpUpgradeRequest(const std::string
& request
,
83 const HttpUpgradeCallback
& callback
,
85 scoped_ptr
<net::StreamSocket
> socket
) {
86 if (result
!= net::OK
) {
88 result
, std::string(), std::string(),
89 make_scoped_ptr
<net::StreamSocket
>(nullptr));
92 new HttpRequest(socket
.Pass(), request
, callback
);
96 HttpRequest(scoped_ptr
<net::StreamSocket
> socket
,
97 const std::string
& request
,
98 const CommandCallback
& callback
)
99 : socket_(socket
.Pass()),
100 command_callback_(callback
),
103 SendRequest(request
);
106 HttpRequest(scoped_ptr
<net::StreamSocket
> socket
,
107 const std::string
& request
,
108 const HttpUpgradeCallback
& callback
)
109 : socket_(socket
.Pass()),
110 http_upgrade_callback_(callback
),
113 SendRequest(request
);
119 void DoSendRequest(int result
) {
120 while (result
!= net::ERR_IO_PENDING
) {
121 if (!CheckNetResultOrDie(result
))
125 request_
->DidConsume(result
);
127 if (request_
->BytesRemaining() == 0) {
129 ReadResponse(net::OK
);
133 result
= socket_
->Write(
135 request_
->BytesRemaining(),
136 base::Bind(&HttpRequest::DoSendRequest
, base::Unretained(this)));
140 void SendRequest(const std::string
& request
) {
141 scoped_refptr
<net::IOBuffer
> base_buffer
=
142 new net::IOBuffer(request
.size());
143 memcpy(base_buffer
->data(), request
.data(), request
.size());
144 request_
= new net::DrainableIOBuffer(base_buffer
.get(), request
.size());
146 DoSendRequest(net::OK
);
149 void ReadResponse(int result
) {
150 if (!CheckNetResultOrDie(result
))
153 response_buffer_
= new net::IOBuffer(kBufferSize
);
155 result
= socket_
->Read(
156 response_buffer_
.get(),
158 base::Bind(&HttpRequest::OnResponseData
, base::Unretained(this)));
159 if (result
!= net::ERR_IO_PENDING
)
160 OnResponseData(result
);
163 void OnResponseData(int result
) {
164 if (!CheckNetResultOrDie(result
))
167 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED
);
171 response_
.append(response_buffer_
->data(), result
);
172 if (expected_size_
< 0) {
173 int expected_length
= 0;
175 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
176 std::string content_length
= ExtractHeader("Content-Length:");
177 if (!content_length
.empty()) {
178 if (!base::StringToInt(content_length
, &expected_length
)) {
179 CheckNetResultOrDie(net::ERR_FAILED
);
184 header_size_
= response_
.find("\r\n\r\n");
185 if (header_size_
!= std::string::npos
) {
187 expected_size_
= header_size_
+ expected_length
;
191 // WebSocket handshake doesn't contain the Content-Length. For this case,
192 // |expected_size_| is set to the size of the header (handshake).
193 // Some WebSocket frames can be already received into |response_|.
194 if (static_cast<int>(response_
.length()) >= expected_size_
) {
195 const std::string
& body
= response_
.substr(header_size_
);
196 if (!command_callback_
.is_null()) {
197 command_callback_
.Run(net::OK
, body
);
199 // Pass the WebSocket frames (in |body|), too.
200 http_upgrade_callback_
.Run(net::OK
,
201 ExtractHeader("Sec-WebSocket-Extensions:"), body
, socket_
.Pass());
207 result
= socket_
->Read(
208 response_buffer_
.get(),
210 base::Bind(&HttpRequest::OnResponseData
, base::Unretained(this)));
211 if (result
!= net::ERR_IO_PENDING
)
212 OnResponseData(result
);
215 std::string
ExtractHeader(const std::string
& header
) {
216 size_t start_pos
= response_
.find(header
);
217 if (start_pos
== std::string::npos
)
218 return std::string();
220 size_t endline_pos
= response_
.find("\n", start_pos
);
221 if (endline_pos
== std::string::npos
)
222 return std::string();
224 std::string value
= response_
.substr(
225 start_pos
+ header
.length(), endline_pos
- start_pos
- header
.length());
226 base::TrimWhitespace(value
, base::TRIM_ALL
, &value
);
230 bool CheckNetResultOrDie(int result
) {
233 if (!command_callback_
.is_null()) {
234 command_callback_
.Run(result
, std::string());
236 http_upgrade_callback_
.Run(
237 result
, std::string(), std::string(),
238 make_scoped_ptr
<net::StreamSocket
>(nullptr));
244 scoped_ptr
<net::StreamSocket
> socket_
;
245 scoped_refptr
<net::DrainableIOBuffer
> request_
;
246 std::string response_
;
247 CommandCallback command_callback_
;
248 HttpUpgradeCallback http_upgrade_callback_
;
250 scoped_refptr
<net::IOBuffer
> response_buffer_
;
251 // Initially -1. Once the end of the header is seen:
252 // - If the Content-Length header is included, this variable is set to the
253 // sum of the header size (including the last two CRLFs) and the value of
255 // - Otherwise, this variable is set to the size of the header (including the
258 // Set to the size of the header part in |response_|.
262 class DevicesRequest
: public base::RefCountedThreadSafe
<DevicesRequest
> {
264 typedef AndroidDeviceManager::DeviceInfo DeviceInfo
;
265 typedef AndroidDeviceManager::DeviceProvider DeviceProvider
;
266 typedef AndroidDeviceManager::DeviceProviders DeviceProviders
;
267 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors
;
268 typedef base::Callback
<void(scoped_ptr
<DeviceDescriptors
>)>
272 scoped_refptr
<base::SingleThreadTaskRunner
> device_task_runner
,
273 const DeviceProviders
& providers
,
274 const DescriptorsCallback
& callback
) {
275 // Don't keep counted reference on calling thread;
276 DevicesRequest
* request
= new DevicesRequest(callback
);
277 // Avoid destruction while sending requests
279 for (DeviceProviders::const_iterator it
= providers
.begin();
280 it
!= providers
.end(); ++it
) {
281 device_task_runner
->PostTask(
282 FROM_HERE
, base::Bind(&DeviceProvider::QueryDevices
, *it
,
283 base::Bind(&DevicesRequest::ProcessSerials
,
286 device_task_runner
->ReleaseSoon(FROM_HERE
, request
);
290 explicit DevicesRequest(const DescriptorsCallback
& callback
)
291 : response_task_runner_(base::ThreadTaskRunnerHandle::Get()),
293 descriptors_(new DeviceDescriptors()) {}
295 friend class base::RefCountedThreadSafe
<DevicesRequest
>;
297 response_task_runner_
->PostTask(
298 FROM_HERE
, base::Bind(callback_
, base::Passed(&descriptors_
)));
301 typedef std::vector
<std::string
> Serials
;
303 void ProcessSerials(scoped_refptr
<DeviceProvider
> provider
,
304 const Serials
& serials
) {
305 for (Serials::const_iterator it
= serials
.begin(); it
!= serials
.end();
307 descriptors_
->resize(descriptors_
->size() + 1);
308 descriptors_
->back().provider
= provider
;
309 descriptors_
->back().serial
= *it
;
313 scoped_refptr
<base::SingleThreadTaskRunner
> response_task_runner_
;
314 DescriptorsCallback callback_
;
315 scoped_ptr
<DeviceDescriptors
> descriptors_
;
318 void ReleaseDeviceAndProvider(
319 AndroidDeviceManager::DeviceProvider
* provider
,
320 const std::string
& serial
) {
321 provider
->ReleaseDevice(serial
);
327 AndroidDeviceManager::BrowserInfo::BrowserInfo()
331 AndroidDeviceManager::DeviceInfo::DeviceInfo()
332 : model(kModelOffline
), connected(false) {
335 AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
338 AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
341 AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
344 void AndroidDeviceManager::DeviceProvider::SendJsonRequest(
345 const std::string
& serial
,
346 const std::string
& socket_name
,
347 const std::string
& request
,
348 const CommandCallback
& callback
) {
351 base::Bind(&HttpRequest::CommandRequest
,
352 base::StringPrintf(kHttpGetRequest
, request
.c_str()),
356 void AndroidDeviceManager::DeviceProvider::HttpUpgrade(
357 const std::string
& serial
,
358 const std::string
& socket_name
,
359 const std::string
& path
,
360 const std::string
& extensions
,
361 const HttpUpgradeCallback
& callback
) {
362 std::string extensions_with_new_line
=
363 extensions
.empty() ? std::string() : extensions
+ "\r\n";
367 base::Bind(&HttpRequest::HttpUpgradeRequest
,
368 base::StringPrintf(kWebSocketUpgradeRequest
,
370 extensions_with_new_line
.c_str()),
374 void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
375 const std::string
& serial
) {
378 AndroidDeviceManager::DeviceProvider::DeviceProvider() {
381 AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
384 void AndroidDeviceManager::Device::QueryDeviceInfo(
385 const DeviceInfoCallback
& callback
) {
386 task_runner_
->PostTask(
388 base::Bind(&DeviceProvider::QueryDeviceInfo
, provider_
, serial_
,
389 base::Bind(&PostDeviceInfoCallback
,
390 base::ThreadTaskRunnerHandle::Get(), callback
)));
393 void AndroidDeviceManager::Device::OpenSocket(const std::string
& socket_name
,
394 const SocketCallback
& callback
) {
395 task_runner_
->PostTask(
396 FROM_HERE
, base::Bind(&DeviceProvider::OpenSocket
, provider_
, serial_
,
397 socket_name
, callback
));
400 void AndroidDeviceManager::Device::SendJsonRequest(
401 const std::string
& socket_name
,
402 const std::string
& request
,
403 const CommandCallback
& callback
) {
404 task_runner_
->PostTask(
406 base::Bind(&DeviceProvider::SendJsonRequest
, provider_
, serial_
,
407 socket_name
, request
,
408 base::Bind(&PostCommandCallback
,
409 base::ThreadTaskRunnerHandle::Get(), callback
)));
412 void AndroidDeviceManager::Device::HttpUpgrade(
413 const std::string
& socket_name
,
414 const std::string
& path
,
415 const std::string
& extensions
,
416 const HttpUpgradeCallback
& callback
) {
417 task_runner_
->PostTask(
419 base::Bind(&DeviceProvider::HttpUpgrade
, provider_
, serial_
, socket_name
,
421 base::Bind(&PostHttpUpgradeCallback
,
422 base::ThreadTaskRunnerHandle::Get(), callback
)));
425 AndroidDeviceManager::Device::Device(
426 scoped_refptr
<base::SingleThreadTaskRunner
> device_task_runner
,
427 scoped_refptr
<DeviceProvider
> provider
,
428 const std::string
& serial
)
429 : task_runner_(device_task_runner
),
432 weak_factory_(this) {
435 AndroidDeviceManager::Device::~Device() {
436 std::set
<AndroidWebSocket
*> sockets_copy(sockets_
);
437 for (AndroidWebSocket
* socket
: sockets_copy
)
438 socket
->OnSocketClosed();
441 DeviceProvider
* raw_ptr
= provider_
.get();
443 task_runner_
->PostTask(FROM_HERE
,
444 base::Bind(&ReleaseDeviceAndProvider
,
445 base::Unretained(raw_ptr
), serial_
));
448 AndroidDeviceManager::HandlerThread
*
449 AndroidDeviceManager::HandlerThread::instance_
= NULL
;
452 scoped_refptr
<AndroidDeviceManager::HandlerThread
>
453 AndroidDeviceManager::HandlerThread::GetInstance() {
454 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
460 AndroidDeviceManager::HandlerThread::HandlerThread() {
461 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
463 thread_
= new base::Thread(kDevToolsAdbBridgeThreadName
);
464 base::Thread::Options options
;
465 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
466 if (!thread_
->StartWithOptions(options
)) {
472 scoped_refptr
<base::SingleThreadTaskRunner
>
473 AndroidDeviceManager::HandlerThread::message_loop() {
474 return thread_
? thread_
->task_runner() : NULL
;
478 void AndroidDeviceManager::HandlerThread::StopThread(
479 base::Thread
* thread
) {
483 AndroidDeviceManager::HandlerThread::~HandlerThread() {
484 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
488 // Shut down thread on FILE thread to join into IO.
489 content::BrowserThread::PostTask(
490 content::BrowserThread::FILE, FROM_HERE
,
491 base::Bind(&HandlerThread::StopThread
, thread_
));
495 scoped_ptr
<AndroidDeviceManager
> AndroidDeviceManager::Create() {
496 return make_scoped_ptr(new AndroidDeviceManager());
499 void AndroidDeviceManager::SetDeviceProviders(
500 const DeviceProviders
& providers
) {
501 for (DeviceProviders::iterator it
= providers_
.begin();
502 it
!= providers_
.end(); ++it
) {
504 DeviceProvider
* raw_ptr
= it
->get();
506 handler_thread_
->message_loop()->ReleaseSoon(FROM_HERE
, raw_ptr
);
508 providers_
= providers
;
511 void AndroidDeviceManager::QueryDevices(const DevicesCallback
& callback
) {
512 DevicesRequest::Start(handler_thread_
->message_loop(), providers_
,
513 base::Bind(&AndroidDeviceManager::UpdateDevices
,
514 weak_factory_
.GetWeakPtr(), callback
));
517 AndroidDeviceManager::AndroidDeviceManager()
518 : handler_thread_(HandlerThread::GetInstance()),
519 weak_factory_(this) {
522 AndroidDeviceManager::~AndroidDeviceManager() {
523 SetDeviceProviders(DeviceProviders());
526 void AndroidDeviceManager::UpdateDevices(
527 const DevicesCallback
& callback
,
528 scoped_ptr
<DeviceDescriptors
> descriptors
) {
530 DeviceWeakMap new_devices
;
531 for (DeviceDescriptors::const_iterator it
= descriptors
->begin();
532 it
!= descriptors
->end();
534 DeviceWeakMap::iterator found
= devices_
.find(it
->serial
);
535 scoped_refptr
<Device
> device
;
536 if (found
== devices_
.end() || !found
->second
||
537 found
->second
->provider_
.get() != it
->provider
.get()) {
539 new Device(handler_thread_
->message_loop(), it
->provider
, it
->serial
);
541 device
= found
->second
.get();
543 response
.push_back(device
);
544 new_devices
[it
->serial
] = device
->weak_factory_
.GetWeakPtr();
546 devices_
.swap(new_devices
);
547 callback
.Run(response
);