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"
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));
40 static void PostCommandCallback(
41 scoped_refptr<base::MessageLoopProxy> response_message_loop,
42 const AndroidDeviceManager::CommandCallback& callback,
44 const std::string& response) {
45 response_message_loop->PostTask(FROM_HERE,
46 base::Bind(callback, result, response));
49 static void PostSocketCallback(
50 scoped_refptr<base::MessageLoopProxy> response_message_loop,
51 const AndroidDeviceManager::SocketCallback& callback,
53 scoped_ptr<net::StreamSocket> socket) {
54 response_message_loop->PostTask(
55 FROM_HERE, base::Bind(callback, result, base::Passed(&socket)));
60 typedef AndroidDeviceManager::CommandCallback CommandCallback;
61 typedef AndroidDeviceManager::SocketCallback SocketCallback;
63 static void CommandRequest(const std::string& request,
64 const CommandCallback& callback,
66 scoped_ptr<net::StreamSocket> socket) {
67 if (result != net::OK) {
68 callback.Run(result, std::string());
71 new HttpRequest(socket.Pass(), request, callback);
74 static void SocketRequest(const std::string& request,
75 const SocketCallback& callback,
77 scoped_ptr<net::StreamSocket> socket) {
78 if (result != net::OK) {
79 callback.Run(result, make_scoped_ptr<net::StreamSocket>(NULL));
82 new HttpRequest(socket.Pass(), request, 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),
95 HttpRequest(scoped_ptr<net::StreamSocket> socket,
96 const std::string& request,
97 const SocketCallback& callback)
98 : socket_(socket.Pass()),
99 socket_callback_(callback),
101 SendRequest(request);
107 void SendRequest(const std::string& request) {
108 scoped_refptr<net::StringIOBuffer> request_buffer =
109 new net::StringIOBuffer(request);
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);
119 void ReadResponse(int result) {
120 if (!CheckNetResultOrDie(result))
122 scoped_refptr<net::IOBuffer> response_buffer =
123 new net::IOBuffer(kBufferSize);
125 result = socket_->Read(
126 response_buffer.get(),
128 base::Bind(&HttpRequest::OnResponseData, base::Unretained(this),
131 if (result != net::ERR_IO_PENDING)
132 OnResponseData(response_buffer, -1, result);
135 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
138 if (!CheckNetResultOrDie(result))
141 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
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);
163 body_pos_ = response_.find("\r\n\r\n");
164 if (body_pos_ != std::string::npos) {
166 bytes_total = body_pos_ + expected_length;
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_));
174 socket_callback_.Run(net::OK, socket_.Pass());
179 result = socket_->Read(
180 response_buffer.get(),
182 base::Bind(&HttpRequest::OnResponseData,
183 base::Unretained(this),
186 if (result != net::ERR_IO_PENDING)
187 OnResponseData(response_buffer, bytes_total, result);
190 bool CheckNetResultOrDie(int result) {
193 if (!command_callback_.is_null())
194 command_callback_.Run(result, std::string());
196 socket_callback_.Run(result, make_scoped_ptr<net::StreamSocket>(NULL));
201 scoped_ptr<net::StreamSocket> socket_;
202 std::string response_;
203 AndroidDeviceManager::CommandCallback command_callback_;
204 AndroidDeviceManager::SocketCallback socket_callback_;
208 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> {
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*)>
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
224 for (DeviceProviders::const_iterator it = providers.begin();
225 it != providers.end(); ++it) {
226 device_message_loop->PostTask(
229 &DeviceProvider::QueryDevices,
231 base::Bind(&DevicesRequest::ProcessSerials, request, *it)));
233 device_message_loop->ReleaseSoon(FROM_HERE, request);
237 explicit DevicesRequest(const DescriptorsCallback& callback)
238 : response_message_loop_(base::MessageLoopProxy::current()),
240 descriptors_(new DeviceDescriptors()) {
243 friend class base::RefCountedThreadSafe<DevicesRequest>;
245 response_message_loop_->PostTask(FROM_HERE,
246 base::Bind(callback_, descriptors_.release()));
249 typedef std::vector<std::string> Serials;
251 void ProcessSerials(scoped_refptr<DeviceProvider> provider,
252 const Serials& serials) {
253 for (Serials::const_iterator it = serials.begin(); it != serials.end();
255 descriptors_->resize(descriptors_->size() + 1);
256 descriptors_->back().provider = provider;
257 descriptors_->back().serial = *it;
261 scoped_refptr<base::MessageLoopProxy> response_message_loop_;
262 DescriptorsCallback callback_;
263 scoped_ptr<DeviceDescriptors> descriptors_;
266 void ReleaseDeviceAndProvider(
267 AndroidDeviceManager::DeviceProvider* provider,
268 const std::string& serial) {
269 provider->ReleaseDevice(serial);
275 AndroidDeviceManager::BrowserInfo::BrowserInfo()
279 AndroidDeviceManager::DeviceInfo::DeviceInfo()
280 : model(kModelOffline), connected(false) {
283 AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
286 AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
289 AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
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) {
299 base::Bind(&HttpRequest::CommandRequest,
300 base::StringPrintf(kHttpGetRequest, request.c_str()),
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) {
312 base::Bind(&HttpRequest::SocketRequest,
313 base::StringPrintf(kWebSocketUpgradeRequest, url.c_str()),
317 void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
318 const std::string& serial) {
321 AndroidDeviceManager::DeviceProvider::DeviceProvider() {
324 AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
327 void AndroidDeviceManager::Device::QueryDeviceInfo(
328 const DeviceInfoCallback& callback) {
329 device_message_loop_->PostTask(
331 base::Bind(&DeviceProvider::QueryDeviceInfo,
334 base::Bind(&PostDeviceInfoCallback,
335 base::MessageLoopProxy::current(),
339 void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name,
340 const SocketCallback& callback) {
341 device_message_loop_->PostTask(
343 base::Bind(&DeviceProvider::OpenSocket,
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(
356 base::Bind(&DeviceProvider::SendJsonRequest,
361 base::Bind(&PostCommandCallback,
362 base::MessageLoopProxy::current(),
366 void AndroidDeviceManager::Device::HttpUpgrade(const std::string& socket_name,
367 const std::string& url,
368 const SocketCallback& callback) {
369 device_message_loop_->PostTask(
371 base::Bind(&DeviceProvider::HttpUpgrade,
376 base::Bind(&PostSocketCallback,
377 base::MessageLoopProxy::current(),
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),
388 weak_factory_(this) {
391 AndroidDeviceManager::Device::~Device() {
393 DeviceProvider* raw_ptr = provider_.get();
395 device_message_loop_->PostTask(
397 base::Bind(&ReleaseDeviceAndProvider,
398 base::Unretained(raw_ptr),
402 AndroidDeviceManager::HandlerThread*
403 AndroidDeviceManager::HandlerThread::instance_ = NULL;
406 scoped_refptr<AndroidDeviceManager::HandlerThread>
407 AndroidDeviceManager::HandlerThread::GetInstance() {
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 AndroidDeviceManager::HandlerThread::HandlerThread() {
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
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)) {
426 scoped_refptr<base::MessageLoopProxy>
427 AndroidDeviceManager::HandlerThread::message_loop() {
428 return thread_ ? thread_->message_loop_proxy() : NULL;
432 void AndroidDeviceManager::HandlerThread::StopThread(
433 base::Thread* thread) {
437 AndroidDeviceManager::HandlerThread::~HandlerThread() {
438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
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_));
449 scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
450 return new AndroidDeviceManager();
453 void AndroidDeviceManager::SetDeviceProviders(
454 const DeviceProviders& providers) {
455 for (DeviceProviders::iterator it = providers_.begin();
456 it != providers_.end(); ++it) {
458 DeviceProvider* raw_ptr = it->get();
460 handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
462 providers_ = providers;
465 void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) {
466 DevicesRequest::Start(handler_thread_->message_loop(),
468 base::Bind(&AndroidDeviceManager::UpdateDevices,
473 AndroidDeviceManager::AndroidDeviceManager()
474 : handler_thread_(HandlerThread::GetInstance()) {
477 AndroidDeviceManager::~AndroidDeviceManager() {
478 SetDeviceProviders(DeviceProviders());
481 void AndroidDeviceManager::UpdateDevices(
482 const DevicesCallback& callback,
483 DeviceDescriptors* descriptors_raw) {
484 scoped_ptr<DeviceDescriptors> descriptors(descriptors_raw);
486 DeviceWeakMap new_devices;
487 for (DeviceDescriptors::const_iterator it = descriptors->begin();
488 it != descriptors->end();
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);
497 device = found->second.get();
499 response.push_back(device);
500 new_devices[it->serial] = device->weak_factory_.GetWeakPtr();
502 devices_.swap(new_devices);
503 callback.Run(response);