10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/devtools/device/android_device_manager.h"
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/strings/string_util.h"
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/strings/stringprintf.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/base/io_buffer.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/net_errors.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/socket/stream_socket.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using content::BrowserThread;
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace {
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kBufferSize = 16 * 1024;
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static const char kModelOffline[] = "Offline";
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n";
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n"
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    "Upgrade: WebSocket\r\n"
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    "Connection: Upgrade\r\n"
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    "Sec-WebSocket-Version: 13\r\n"
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    "\r\n";
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static void PostDeviceInfoCallback(
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> response_message_loop,
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AndroidDeviceManager::DeviceInfoCallback& callback,
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AndroidDeviceManager::DeviceInfo& device_info) {
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  response_message_loop->PostTask(FROM_HERE, base::Bind(callback, device_info));
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static void PostCommandCallback(
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> response_message_loop,
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AndroidDeviceManager::CommandCallback& callback,
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int result,
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& response) {
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  response_message_loop->PostTask(FROM_HERE,
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  base::Bind(callback, result, response));
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static void PostSocketCallback(
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> response_message_loop,
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AndroidDeviceManager::SocketCallback& callback,
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int result,
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<net::StreamSocket> socket) {
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  response_message_loop->PostTask(
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FROM_HERE, base::Bind(callback, result, base::Passed(&socket)));
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class HttpRequest {
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public:
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  typedef AndroidDeviceManager::CommandCallback CommandCallback;
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  typedef AndroidDeviceManager::SocketCallback SocketCallback;
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  static void CommandRequest(const std::string& request,
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             const CommandCallback& callback,
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             int result,
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             scoped_ptr<net::StreamSocket> socket) {
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result != net::OK) {
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      callback.Run(result, std::string());
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    new HttpRequest(socket.Pass(), request, callback);
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  static void SocketRequest(const std::string& request,
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            const SocketCallback& callback,
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            int result,
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            scoped_ptr<net::StreamSocket> socket) {
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result != net::OK) {
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      callback.Run(result, make_scoped_ptr<net::StreamSocket>(NULL));
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    new HttpRequest(socket.Pass(), request, callback);
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private:
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  HttpRequest(scoped_ptr<net::StreamSocket> socket,
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              const std::string& request,
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              const CommandCallback& callback)
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      : socket_(socket.Pass()),
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        command_callback_(callback),
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        body_pos_(0) {
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendRequest(request);
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  HttpRequest(scoped_ptr<net::StreamSocket> socket,
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              const std::string& request,
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              const SocketCallback& callback)
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : socket_(socket.Pass()),
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      socket_callback_(callback),
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      body_pos_(0) {
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendRequest(request);
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ~HttpRequest() {
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void SendRequest(const std::string& request) {
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<net::StringIOBuffer> request_buffer =
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        new net::StringIOBuffer(request);
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int result = socket_->Write(
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        request_buffer.get(),
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        request_buffer->size(),
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HttpRequest::ReadResponse, base::Unretained(this)));
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result != net::ERR_IO_PENDING)
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ReadResponse(result);
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void ReadResponse(int result) {
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!CheckNetResultOrDie(result))
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<net::IOBuffer> response_buffer =
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        new net::IOBuffer(kBufferSize);
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    result = socket_->Read(
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        response_buffer.get(),
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kBufferSize,
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HttpRequest::OnResponseData, base::Unretained(this),
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                  response_buffer,
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                  -1));
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result != net::ERR_IO_PENDING)
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      OnResponseData(response_buffer, -1, result);
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                      int bytes_total,
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                      int result) {
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!CheckNetResultOrDie(result))
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result == 0) {
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    response_ += std::string(response_buffer->data(), result);
146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int expected_length = 0;
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (bytes_total < 0) {
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      size_t content_pos = response_.find("Content-Length:");
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (content_pos != std::string::npos) {
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        size_t endline_pos = response_.find("\n", content_pos);
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (endline_pos != std::string::npos) {
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          std::string len = response_.substr(content_pos + 15,
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             endline_pos - content_pos - 15);
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          base::TrimWhitespace(len, base::TRIM_ALL, &len);
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          if (!base::StringToInt(len, &expected_length)) {
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            CheckNetResultOrDie(net::ERR_FAILED);
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            return;
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          }
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      body_pos_ = response_.find("\r\n\r\n");
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (body_pos_ != std::string::npos) {
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        body_pos_ += 4;
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        bytes_total = body_pos_ + expected_length;
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (bytes_total == static_cast<int>(response_.length())) {
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (!command_callback_.is_null())
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        command_callback_.Run(net::OK, response_.substr(body_pos_));
173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      else
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        socket_callback_.Run(net::OK, socket_.Pass());
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      delete this;
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    result = socket_->Read(
180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        response_buffer.get(),
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kBufferSize,
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HttpRequest::OnResponseData,
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   base::Unretained(this),
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   response_buffer,
185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   bytes_total));
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result != net::ERR_IO_PENDING)
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      OnResponseData(response_buffer, bytes_total, result);
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool CheckNetResultOrDie(int result) {
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result >= 0)
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return true;
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!command_callback_.is_null())
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      command_callback_.Run(result, std::string());
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    else
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      socket_callback_.Run(result, make_scoped_ptr<net::StreamSocket>(NULL));
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    delete this;
198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<net::StreamSocket> socket_;
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string response_;
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  AndroidDeviceManager::CommandCallback command_callback_;
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  AndroidDeviceManager::SocketCallback socket_callback_;
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  size_t body_pos_;
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)};
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> {
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef AndroidDeviceManager::DeviceInfo DeviceInfo;
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef AndroidDeviceManager::DeviceProvider DeviceProvider;
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef AndroidDeviceManager::DeviceProviders DeviceProviders;
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors;
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef base::Callback<void(DeviceDescriptors*)>
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      DescriptorsCallback;
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  static void Start(scoped_refptr<base::MessageLoopProxy> device_message_loop,
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                    const DeviceProviders& providers,
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                    const DescriptorsCallback& callback) {
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Don't keep counted reference on calling thread;
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DevicesRequest* request = new DevicesRequest(callback);
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Avoid destruction while sending requests
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    request->AddRef();
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (DeviceProviders::const_iterator it = providers.begin();
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         it != providers.end(); ++it) {
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      device_message_loop->PostTask(
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          FROM_HERE,
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          base::Bind(
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              &DeviceProvider::QueryDevices,
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              *it,
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              base::Bind(&DevicesRequest::ProcessSerials, request, *it)));
23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    device_message_loop->ReleaseSoon(FROM_HERE, request);
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  explicit DevicesRequest(const DescriptorsCallback& callback)
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : response_message_loop_(base::MessageLoopProxy::current()),
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        callback_(callback),
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        descriptors_(new DeviceDescriptors()) {
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  friend class base::RefCountedThreadSafe<DevicesRequest>;
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ~DevicesRequest() {
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    response_message_loop_->PostTask(FROM_HERE,
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(callback_, descriptors_.release()));
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef std::vector<std::string> Serials;
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void ProcessSerials(scoped_refptr<DeviceProvider> provider,
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                      const Serials& serials) {
25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (Serials::const_iterator it = serials.begin(); it != serials.end();
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         ++it) {
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      descriptors_->resize(descriptors_->size() + 1);
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      descriptors_->back().provider = provider;
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      descriptors_->back().serial = *it;
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> response_message_loop_;
26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DescriptorsCallback callback_;
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<DeviceDescriptors> descriptors_;
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ReleaseDeviceAndProvider(
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    AndroidDeviceManager::DeviceProvider* provider,
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& serial) {
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  provider->ReleaseDevice(serial);
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  provider->Release();
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AndroidDeviceManager::BrowserInfo::BrowserInfo()
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : type(kTypeOther) {
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::DeviceInfo::DeviceInfo()
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : model(kModelOffline), connected(false) {
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::DeviceProvider::SendJsonRequest(
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& serial,
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& socket_name,
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& request,
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const CommandCallback& callback) {
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  OpenSocket(serial,
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             socket_name,
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             base::Bind(&HttpRequest::CommandRequest,
30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        base::StringPrintf(kHttpGetRequest, request.c_str()),
30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        callback));
30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::DeviceProvider::HttpUpgrade(
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& serial,
30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& socket_name,
30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& url,
30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const SocketCallback& callback) {
30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  OpenSocket(
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      serial,
31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      socket_name,
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&HttpRequest::SocketRequest,
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::StringPrintf(kWebSocketUpgradeRequest, url.c_str()),
31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 callback));
31546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& serial) {
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
321c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochAndroidDeviceManager::DeviceProvider::DeviceProvider() {
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
324c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochAndroidDeviceManager::DeviceProvider::~DeviceProvider() {
3251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::Device::QueryDeviceInfo(
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const DeviceInfoCallback& callback) {
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  device_message_loop_->PostTask(
33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FROM_HERE,
33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&DeviceProvider::QueryDeviceInfo,
33246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 provider_,
33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 serial_,
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Bind(&PostDeviceInfoCallback,
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            base::MessageLoopProxy::current(),
33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            callback)));
337c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name,
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                              const SocketCallback& callback) {
34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  device_message_loop_->PostTask(
34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FROM_HERE,
34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&DeviceProvider::OpenSocket,
34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 provider_,
34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 serial_,
34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 socket_name,
34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 callback));
348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
349c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::Device::SendJsonRequest(
35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& socket_name,
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& request,
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const CommandCallback& callback) {
35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  device_message_loop_->PostTask(
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FROM_HERE,
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&DeviceProvider::SendJsonRequest,
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 provider_,
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 serial_,
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 socket_name,
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 request,
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Bind(&PostCommandCallback,
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            base::MessageLoopProxy::current(),
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            callback)));
364c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
365c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::Device::HttpUpgrade(const std::string& socket_name,
36746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                               const std::string& url,
36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                               const SocketCallback& callback) {
36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  device_message_loop_->PostTask(
37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FROM_HERE,
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&DeviceProvider::HttpUpgrade,
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 provider_,
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 serial_,
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 socket_name,
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 url,
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Bind(&PostSocketCallback,
37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            base::MessageLoopProxy::current(),
37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            callback)));
379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::Device::Device(
38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> device_message_loop,
38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<DeviceProvider> provider,
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& serial)
38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : device_message_loop_(device_message_loop),
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      provider_(provider),
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      serial_(serial),
38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      weak_factory_(this) {
389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::Device::~Device() {
39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  provider_->AddRef();
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DeviceProvider* raw_ptr = provider_.get();
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  provider_ = NULL;
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  device_message_loop_->PostTask(
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FROM_HERE,
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&ReleaseDeviceAndProvider,
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Unretained(raw_ptr),
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 serial_));
400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::HandlerThread*
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::HandlerThread::instance_ = NULL;
40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_refptr<AndroidDeviceManager::HandlerThread>
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::HandlerThread::GetInstance() {
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!instance_)
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    new HandlerThread();
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return instance_;
412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
413c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::HandlerThread::HandlerThread() {
41546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  instance_ = this;
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::Thread::Options options;
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  options.message_loop_type = base::MessageLoop::TYPE_IO;
42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!thread_->StartWithOptions(options)) {
42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    delete thread_;
42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    thread_ = NULL;
423010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
425c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_refptr<base::MessageLoopProxy>
42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::HandlerThread::message_loop() {
42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return thread_ ? thread_->message_loop_proxy() : NULL;
429c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
430c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static
43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::HandlerThread::StopThread(
43346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::Thread* thread) {
43446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  thread->Stop();
435c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
436c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
43746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::HandlerThread::~HandlerThread() {
43846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  instance_ = NULL;
44046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!thread_)
441c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
44246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Shut down thread on FILE thread to join into IO.
44346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  content::BrowserThread::PostTask(
44446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      content::BrowserThread::FILE, FROM_HERE,
44546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&HandlerThread::StopThread, thread_));
44646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
447c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
44846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static
44946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
45046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return new AndroidDeviceManager();
45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::SetDeviceProviders(
45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const DeviceProviders& providers) {
45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (DeviceProviders::iterator it = providers_.begin();
45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it != providers_.end(); ++it) {
45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    (*it)->AddRef();
45846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DeviceProvider* raw_ptr = it->get();
45946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    *it = NULL;
46046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
46246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  providers_ = providers;
46346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
46446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
46546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) {
46646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DevicesRequest::Start(handler_thread_->message_loop(),
46746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        providers_,
46846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        base::Bind(&AndroidDeviceManager::UpdateDevices,
46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   this,
47046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   callback));
47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
47346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::AndroidDeviceManager()
47446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : handler_thread_(HandlerThread::GetInstance()) {
47546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
47746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AndroidDeviceManager::~AndroidDeviceManager() {
47846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SetDeviceProviders(DeviceProviders());
479c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
48146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AndroidDeviceManager::UpdateDevices(
48246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const DevicesCallback& callback,
48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DeviceDescriptors* descriptors_raw) {
48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<DeviceDescriptors> descriptors(descriptors_raw);
48546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Devices response;
48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DeviceWeakMap new_devices;
48746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (DeviceDescriptors::const_iterator it = descriptors->begin();
48846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != descriptors->end();
48946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       ++it) {
49046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DeviceWeakMap::iterator found = devices_.find(it->serial);
49146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<Device> device;
4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (found == devices_.end() || !found->second ||
4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        found->second->provider_.get() != it->provider.get()) {
49446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      device = new Device(handler_thread_->message_loop(),
49546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          it->provider, it->serial);
49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    } else {
49746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      device = found->second.get();
49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    response.push_back(device);
50046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    new_devices[it->serial] = device->weak_factory_.GetWeakPtr();
50146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
50246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  devices_.swap(new_devices);
50346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback.Run(response);
504c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
505