• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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