Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / devtools / device / android_device_manager.cc
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
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
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
49 static 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
58 class 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
208 class 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
266 void ReleaseDeviceAndProvider(
267     AndroidDeviceManager::DeviceProvider* provider,
268     const std::string& serial) {
269   provider->ReleaseDevice(serial);
270   provider->Release();
271 }
272
273 } // namespace
274
275 AndroidDeviceManager::BrowserInfo::BrowserInfo()
276     : type(kTypeOther) {
277 }
278
279 AndroidDeviceManager::DeviceInfo::DeviceInfo()
280     : model(kModelOffline), connected(false) {
281 }
282
283 AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
284 }
285
286 AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
287 }
288
289 AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
290 }
291
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) {
297   OpenSocket(serial,
298              socket_name,
299              base::Bind(&HttpRequest::CommandRequest,
300                         base::StringPrintf(kHttpGetRequest, request.c_str()),
301                         callback));
302 }
303
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) {
309   OpenSocket(
310       serial,
311       socket_name,
312       base::Bind(&HttpRequest::SocketRequest,
313                  base::StringPrintf(kWebSocketUpgradeRequest, url.c_str()),
314                  callback));
315 }
316
317 void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
318     const std::string& serial) {
319 }
320
321 AndroidDeviceManager::DeviceProvider::DeviceProvider() {
322 }
323
324 AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
325 }
326
327 void 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
339 void 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
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(
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
366 void 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
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),
386       provider_(provider),
387       serial_(serial),
388       weak_factory_(this) {
389 }
390
391 AndroidDeviceManager::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
402 AndroidDeviceManager::HandlerThread*
403 AndroidDeviceManager::HandlerThread::instance_ = NULL;
404
405 // static
406 scoped_refptr<AndroidDeviceManager::HandlerThread>
407 AndroidDeviceManager::HandlerThread::GetInstance() {
408   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
409   if (!instance_)
410     new HandlerThread();
411   return instance_;
412 }
413
414 AndroidDeviceManager::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
426 scoped_refptr<base::MessageLoopProxy>
427 AndroidDeviceManager::HandlerThread::message_loop() {
428   return thread_ ? thread_->message_loop_proxy() : NULL;
429 }
430
431 // static
432 void AndroidDeviceManager::HandlerThread::StopThread(
433     base::Thread* thread) {
434   thread->Stop();
435 }
436
437 AndroidDeviceManager::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
449 scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
450   return new AndroidDeviceManager();
451 }
452
453 void 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
465 void 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
473 AndroidDeviceManager::AndroidDeviceManager()
474     : handler_thread_(HandlerThread::GetInstance()) {
475 }
476
477 AndroidDeviceManager::~AndroidDeviceManager() {
478   SetDeviceProviders(DeviceProviders());
479 }
480
481 void 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 }