Make castv2 performance test work.
[chromium-blink-merge.git] / chrome / browser / devtools / device / android_device_manager.cc
blob0459dc89f533cd1e351ed6630fd3f615947929ec
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.
5 #include "chrome/browser/devtools/device/android_device_manager.h"
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"
14 using content::BrowserThread;
16 namespace {
18 const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
20 const int kBufferSize = 16 * 1024;
22 static const char kModelOffline[] = "Offline";
24 static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n";
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 "%s"
32 "\r\n";
34 static void PostDeviceInfoCallback(
35 scoped_refptr<base::MessageLoopProxy> response_message_loop,
36 const AndroidDeviceManager::DeviceInfoCallback& callback,
37 const AndroidDeviceManager::DeviceInfo& device_info) {
38 response_message_loop->PostTask(FROM_HERE, base::Bind(callback, device_info));
41 static void PostCommandCallback(
42 scoped_refptr<base::MessageLoopProxy> response_message_loop,
43 const AndroidDeviceManager::CommandCallback& callback,
44 int result,
45 const std::string& response) {
46 response_message_loop->PostTask(FROM_HERE,
47 base::Bind(callback, result, response));
50 static void PostHttpUpgradeCallback(
51 scoped_refptr<base::MessageLoopProxy> response_message_loop,
52 const AndroidDeviceManager::HttpUpgradeCallback& callback,
53 int result,
54 const std::string& extensions,
55 scoped_ptr<net::StreamSocket> socket) {
56 response_message_loop->PostTask(
57 FROM_HERE,
58 base::Bind(callback, result, extensions, base::Passed(&socket)));
61 class HttpRequest {
62 public:
63 typedef AndroidDeviceManager::CommandCallback CommandCallback;
64 typedef AndroidDeviceManager::HttpUpgradeCallback HttpUpgradeCallback;
66 static void CommandRequest(const std::string& request,
67 const CommandCallback& callback,
68 int result,
69 scoped_ptr<net::StreamSocket> socket) {
70 if (result != net::OK) {
71 callback.Run(result, std::string());
72 return;
74 new HttpRequest(socket.Pass(), request, callback);
77 static void HttpUpgradeRequest(const std::string& request,
78 const HttpUpgradeCallback& callback,
79 int result,
80 scoped_ptr<net::StreamSocket> socket) {
81 if (result != net::OK) {
82 callback.Run(result, "", make_scoped_ptr<net::StreamSocket>(nullptr));
83 return;
85 new HttpRequest(socket.Pass(), request, callback);
88 private:
89 HttpRequest(scoped_ptr<net::StreamSocket> socket,
90 const std::string& request,
91 const CommandCallback& callback)
92 : socket_(socket.Pass()),
93 command_callback_(callback),
94 body_pos_(0) {
95 SendRequest(request);
98 HttpRequest(scoped_ptr<net::StreamSocket> socket,
99 const std::string& request,
100 const HttpUpgradeCallback& callback)
101 : socket_(socket.Pass()),
102 http_upgrade_callback_(callback),
103 body_pos_(0) {
104 SendRequest(request);
107 ~HttpRequest() {
110 void SendRequest(const std::string& request) {
111 scoped_refptr<net::StringIOBuffer> request_buffer =
112 new net::StringIOBuffer(request);
114 int result = socket_->Write(
115 request_buffer.get(),
116 request_buffer->size(),
117 base::Bind(&HttpRequest::ReadResponse, base::Unretained(this)));
118 if (result != net::ERR_IO_PENDING)
119 ReadResponse(result);
122 void ReadResponse(int result) {
123 if (!CheckNetResultOrDie(result))
124 return;
125 scoped_refptr<net::IOBuffer> response_buffer =
126 new net::IOBuffer(kBufferSize);
128 result = socket_->Read(
129 response_buffer.get(),
130 kBufferSize,
131 base::Bind(&HttpRequest::OnResponseData, base::Unretained(this),
132 response_buffer,
133 -1));
134 if (result != net::ERR_IO_PENDING)
135 OnResponseData(response_buffer, -1, result);
138 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
139 int bytes_total,
140 int result) {
141 if (!CheckNetResultOrDie(result))
142 return;
143 if (result == 0) {
144 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
145 return;
148 response_ += std::string(response_buffer->data(), result);
149 int expected_length = 0;
150 if (bytes_total < 0) {
151 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
152 std::string content_length = ExtractHeader("Content-Length:");
153 if (!content_length.empty()) {
154 if (!base::StringToInt(content_length, &expected_length)) {
155 CheckNetResultOrDie(net::ERR_FAILED);
156 return;
160 body_pos_ = response_.find("\r\n\r\n");
161 if (body_pos_ != std::string::npos) {
162 body_pos_ += 4;
163 bytes_total = body_pos_ + expected_length;
167 if (bytes_total == static_cast<int>(response_.length())) {
168 if (!command_callback_.is_null()) {
169 command_callback_.Run(net::OK, response_.substr(body_pos_));
170 } else {
171 http_upgrade_callback_.Run(net::OK,
172 ExtractHeader("Sec-WebSocket-Extensions:"), socket_.Pass());
174 delete this;
175 return;
178 result = socket_->Read(
179 response_buffer.get(),
180 kBufferSize,
181 base::Bind(&HttpRequest::OnResponseData,
182 base::Unretained(this),
183 response_buffer,
184 bytes_total));
185 if (result != net::ERR_IO_PENDING)
186 OnResponseData(response_buffer, bytes_total, result);
189 std::string ExtractHeader(const std::string& header) {
190 size_t start_pos = response_.find(header);
191 if (start_pos == std::string::npos)
192 return std::string();
194 size_t endline_pos = response_.find("\n", start_pos);
195 if (endline_pos == std::string::npos)
196 return std::string();
198 std::string value = response_.substr(
199 start_pos + header.length(), endline_pos - start_pos - header.length());
200 base::TrimWhitespace(value, base::TRIM_ALL, &value);
201 return value;
204 bool CheckNetResultOrDie(int result) {
205 if (result >= 0)
206 return true;
207 if (!command_callback_.is_null()) {
208 command_callback_.Run(result, std::string());
209 } else {
210 http_upgrade_callback_.Run(
211 result, "", make_scoped_ptr<net::StreamSocket>(nullptr));
213 delete this;
214 return false;
217 scoped_ptr<net::StreamSocket> socket_;
218 std::string response_;
219 CommandCallback command_callback_;
220 HttpUpgradeCallback http_upgrade_callback_;
221 size_t body_pos_;
224 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> {
225 public:
226 typedef AndroidDeviceManager::DeviceInfo DeviceInfo;
227 typedef AndroidDeviceManager::DeviceProvider DeviceProvider;
228 typedef AndroidDeviceManager::DeviceProviders DeviceProviders;
229 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors;
230 typedef base::Callback<void(scoped_ptr<DeviceDescriptors>)>
231 DescriptorsCallback;
233 static void Start(scoped_refptr<base::MessageLoopProxy> device_message_loop,
234 const DeviceProviders& providers,
235 const DescriptorsCallback& callback) {
236 // Don't keep counted reference on calling thread;
237 DevicesRequest* request = new DevicesRequest(callback);
238 // Avoid destruction while sending requests
239 request->AddRef();
240 for (DeviceProviders::const_iterator it = providers.begin();
241 it != providers.end(); ++it) {
242 device_message_loop->PostTask(
243 FROM_HERE,
244 base::Bind(
245 &DeviceProvider::QueryDevices,
246 *it,
247 base::Bind(&DevicesRequest::ProcessSerials, request, *it)));
249 device_message_loop->ReleaseSoon(FROM_HERE, request);
252 private:
253 explicit DevicesRequest(const DescriptorsCallback& callback)
254 : response_message_loop_(base::MessageLoopProxy::current()),
255 callback_(callback),
256 descriptors_(new DeviceDescriptors()) {
259 friend class base::RefCountedThreadSafe<DevicesRequest>;
260 ~DevicesRequest() {
261 response_message_loop_->PostTask(FROM_HERE,
262 base::Bind(callback_, base::Passed(&descriptors_)));
265 typedef std::vector<std::string> Serials;
267 void ProcessSerials(scoped_refptr<DeviceProvider> provider,
268 const Serials& serials) {
269 for (Serials::const_iterator it = serials.begin(); it != serials.end();
270 ++it) {
271 descriptors_->resize(descriptors_->size() + 1);
272 descriptors_->back().provider = provider;
273 descriptors_->back().serial = *it;
277 scoped_refptr<base::MessageLoopProxy> response_message_loop_;
278 DescriptorsCallback callback_;
279 scoped_ptr<DeviceDescriptors> descriptors_;
282 void ReleaseDeviceAndProvider(
283 AndroidDeviceManager::DeviceProvider* provider,
284 const std::string& serial) {
285 provider->ReleaseDevice(serial);
286 provider->Release();
289 } // namespace
291 AndroidDeviceManager::BrowserInfo::BrowserInfo()
292 : type(kTypeOther) {
295 AndroidDeviceManager::DeviceInfo::DeviceInfo()
296 : model(kModelOffline), connected(false) {
299 AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
302 AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
305 AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
308 void AndroidDeviceManager::DeviceProvider::SendJsonRequest(
309 const std::string& serial,
310 const std::string& socket_name,
311 const std::string& request,
312 const CommandCallback& callback) {
313 OpenSocket(serial,
314 socket_name,
315 base::Bind(&HttpRequest::CommandRequest,
316 base::StringPrintf(kHttpGetRequest, request.c_str()),
317 callback));
320 void AndroidDeviceManager::DeviceProvider::HttpUpgrade(
321 const std::string& serial,
322 const std::string& socket_name,
323 const std::string& url,
324 const std::string& extensions,
325 const HttpUpgradeCallback& callback) {
326 std::string extensions_with_new_line =
327 extensions.empty() ? std::string() : extensions + "\r\n";
328 OpenSocket(
329 serial,
330 socket_name,
331 base::Bind(&HttpRequest::HttpUpgradeRequest,
332 base::StringPrintf(kWebSocketUpgradeRequest,
333 url.c_str(),
334 extensions_with_new_line.c_str()),
335 callback));
338 void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
339 const std::string& serial) {
342 AndroidDeviceManager::DeviceProvider::DeviceProvider() {
345 AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
348 void AndroidDeviceManager::Device::QueryDeviceInfo(
349 const DeviceInfoCallback& callback) {
350 message_loop_proxy_->PostTask(
351 FROM_HERE,
352 base::Bind(&DeviceProvider::QueryDeviceInfo,
353 provider_,
354 serial_,
355 base::Bind(&PostDeviceInfoCallback,
356 base::MessageLoopProxy::current(),
357 callback)));
360 void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name,
361 const SocketCallback& callback) {
362 message_loop_proxy_->PostTask(
363 FROM_HERE,
364 base::Bind(&DeviceProvider::OpenSocket,
365 provider_,
366 serial_,
367 socket_name,
368 callback));
371 void AndroidDeviceManager::Device::SendJsonRequest(
372 const std::string& socket_name,
373 const std::string& request,
374 const CommandCallback& callback) {
375 message_loop_proxy_->PostTask(
376 FROM_HERE,
377 base::Bind(&DeviceProvider::SendJsonRequest,
378 provider_,
379 serial_,
380 socket_name,
381 request,
382 base::Bind(&PostCommandCallback,
383 base::MessageLoopProxy::current(),
384 callback)));
387 void AndroidDeviceManager::Device::HttpUpgrade(
388 const std::string& socket_name,
389 const std::string& url,
390 const std::string& extensions,
391 const HttpUpgradeCallback& callback) {
392 message_loop_proxy_->PostTask(
393 FROM_HERE,
394 base::Bind(&DeviceProvider::HttpUpgrade,
395 provider_,
396 serial_,
397 socket_name,
398 url,
399 extensions,
400 base::Bind(&PostHttpUpgradeCallback,
401 base::MessageLoopProxy::current(),
402 callback)));
405 AndroidDeviceManager::Device::Device(
406 scoped_refptr<base::MessageLoopProxy> device_message_loop,
407 scoped_refptr<DeviceProvider> provider,
408 const std::string& serial)
409 : message_loop_proxy_(device_message_loop),
410 provider_(provider),
411 serial_(serial),
412 weak_factory_(this) {
415 AndroidDeviceManager::Device::~Device() {
416 std::set<AndroidWebSocket*> sockets_copy(sockets_);
417 for (AndroidWebSocket* socket : sockets_copy)
418 socket->OnSocketClosed();
420 provider_->AddRef();
421 DeviceProvider* raw_ptr = provider_.get();
422 provider_ = NULL;
423 message_loop_proxy_->PostTask(
424 FROM_HERE,
425 base::Bind(&ReleaseDeviceAndProvider,
426 base::Unretained(raw_ptr),
427 serial_));
430 AndroidDeviceManager::HandlerThread*
431 AndroidDeviceManager::HandlerThread::instance_ = NULL;
433 // static
434 scoped_refptr<AndroidDeviceManager::HandlerThread>
435 AndroidDeviceManager::HandlerThread::GetInstance() {
436 DCHECK_CURRENTLY_ON(BrowserThread::UI);
437 if (!instance_)
438 new HandlerThread();
439 return instance_;
442 AndroidDeviceManager::HandlerThread::HandlerThread() {
443 DCHECK_CURRENTLY_ON(BrowserThread::UI);
444 instance_ = this;
445 thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
446 base::Thread::Options options;
447 options.message_loop_type = base::MessageLoop::TYPE_IO;
448 if (!thread_->StartWithOptions(options)) {
449 delete thread_;
450 thread_ = NULL;
454 scoped_refptr<base::MessageLoopProxy>
455 AndroidDeviceManager::HandlerThread::message_loop() {
456 return thread_ ? thread_->message_loop_proxy() : NULL;
459 // static
460 void AndroidDeviceManager::HandlerThread::StopThread(
461 base::Thread* thread) {
462 thread->Stop();
465 AndroidDeviceManager::HandlerThread::~HandlerThread() {
466 DCHECK_CURRENTLY_ON(BrowserThread::UI);
467 instance_ = NULL;
468 if (!thread_)
469 return;
470 // Shut down thread on FILE thread to join into IO.
471 content::BrowserThread::PostTask(
472 content::BrowserThread::FILE, FROM_HERE,
473 base::Bind(&HandlerThread::StopThread, thread_));
476 // static
477 scoped_ptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
478 return make_scoped_ptr(new AndroidDeviceManager());
481 void AndroidDeviceManager::SetDeviceProviders(
482 const DeviceProviders& providers) {
483 for (DeviceProviders::iterator it = providers_.begin();
484 it != providers_.end(); ++it) {
485 (*it)->AddRef();
486 DeviceProvider* raw_ptr = it->get();
487 *it = NULL;
488 handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
490 providers_ = providers;
493 void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) {
494 DevicesRequest::Start(handler_thread_->message_loop(),
495 providers_,
496 base::Bind(&AndroidDeviceManager::UpdateDevices,
497 weak_factory_.GetWeakPtr(),
498 callback));
501 AndroidDeviceManager::AndroidDeviceManager()
502 : handler_thread_(HandlerThread::GetInstance()),
503 weak_factory_(this) {
506 AndroidDeviceManager::~AndroidDeviceManager() {
507 SetDeviceProviders(DeviceProviders());
510 void AndroidDeviceManager::UpdateDevices(
511 const DevicesCallback& callback,
512 scoped_ptr<DeviceDescriptors> descriptors) {
513 Devices response;
514 DeviceWeakMap new_devices;
515 for (DeviceDescriptors::const_iterator it = descriptors->begin();
516 it != descriptors->end();
517 ++it) {
518 DeviceWeakMap::iterator found = devices_.find(it->serial);
519 scoped_refptr<Device> device;
520 if (found == devices_.end() || !found->second ||
521 found->second->provider_.get() != it->provider.get()) {
522 device = new Device(handler_thread_->message_loop(),
523 it->provider, it->serial);
524 } else {
525 device = found->second.get();
527 response.push_back(device);
528 new_devices[it->serial] = device->weak_factory_.GetWeakPtr();
530 devices_.swap(new_devices);
531 callback.Run(response);