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