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 14using content::BrowserThread; 15 16namespace { 17 18const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread"; 19 20const int kBufferSize = 16 * 1024; 21 22static const char kModelOffline[] = "Offline"; 23 24static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n"; 25 26static 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 33static 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 40static 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 49static 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 58class HttpRequest { 59 public: 60 typedef AndroidDeviceManager::CommandCallback CommandCallback; 61 typedef AndroidDeviceManager::SocketCallback SocketCallback; 62 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 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: 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 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 104 ~HttpRequest() { 105 } 106 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 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 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 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 208class 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 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: 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>; 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 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 266void ReleaseDeviceAndProvider( 267 AndroidDeviceManager::DeviceProvider* provider, 268 const std::string& serial) { 269 provider->ReleaseDevice(serial); 270 provider->Release(); 271} 272 273} // namespace 274 275AndroidDeviceManager::BrowserInfo::BrowserInfo() 276 : type(kTypeOther) { 277} 278 279AndroidDeviceManager::DeviceInfo::DeviceInfo() 280 : model(kModelOffline), connected(false) { 281} 282 283AndroidDeviceManager::DeviceInfo::~DeviceInfo() { 284} 285 286AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() { 287} 288 289AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() { 290} 291 292void 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 304void 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 317void AndroidDeviceManager::DeviceProvider::ReleaseDevice( 318 const std::string& serial) { 319} 320 321AndroidDeviceManager::DeviceProvider::DeviceProvider() { 322} 323 324AndroidDeviceManager::DeviceProvider::~DeviceProvider() { 325} 326 327void 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 339void 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 350void 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 366void 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 381AndroidDeviceManager::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 391AndroidDeviceManager::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 402AndroidDeviceManager::HandlerThread* 403AndroidDeviceManager::HandlerThread::instance_ = NULL; 404 405// static 406scoped_refptr<AndroidDeviceManager::HandlerThread> 407AndroidDeviceManager::HandlerThread::GetInstance() { 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 409 if (!instance_) 410 new HandlerThread(); 411 return instance_; 412} 413 414AndroidDeviceManager::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 426scoped_refptr<base::MessageLoopProxy> 427AndroidDeviceManager::HandlerThread::message_loop() { 428 return thread_ ? thread_->message_loop_proxy() : NULL; 429} 430 431// static 432void AndroidDeviceManager::HandlerThread::StopThread( 433 base::Thread* thread) { 434 thread->Stop(); 435} 436 437AndroidDeviceManager::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 449scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() { 450 return new AndroidDeviceManager(); 451} 452 453void 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 465void 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 473AndroidDeviceManager::AndroidDeviceManager() 474 : handler_thread_(HandlerThread::GetInstance()) { 475} 476 477AndroidDeviceManager::~AndroidDeviceManager() { 478 SetDeviceProviders(DeviceProviders()); 479} 480 481void 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