Update CrOS OOBE throbber to MD throbber; delete old asset
[chromium-blink-merge.git] / chrome / test / chromedriver / net / adb_client_socket.cc
blobe6c842f675c1ac7c384cd5c96ff155de7864a59c
1 // Copyright (c) 2013 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/test/chromedriver/net/adb_client_socket.h"
7 #include "base/bind.h"
8 #include "base/compiler_specific.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "net/base/address_list.h"
14 #include "net/base/completion_callback.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/net_util.h"
17 #include "net/socket/tcp_client_socket.h"
19 namespace {
21 const int kBufferSize = 16 * 1024;
22 const char kOkayResponse[] = "OKAY";
23 const char kHostTransportCommand[] = "host:transport:%s";
24 const char kLocalAbstractCommand[] = "localabstract:%s";
25 const char kLocalhost[] = "127.0.0.1";
27 typedef base::Callback<void(int, const std::string&)> CommandCallback;
28 typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback;
30 std::string EncodeMessage(const std::string& message) {
31 static const char kHexChars[] = "0123456789ABCDEF";
33 size_t length = message.length();
34 std::string result(4, '\0');
35 char b = reinterpret_cast<const char*>(&length)[1];
36 result[0] = kHexChars[(b >> 4) & 0xf];
37 result[1] = kHexChars[b & 0xf];
38 b = reinterpret_cast<const char*>(&length)[0];
39 result[2] = kHexChars[(b >> 4) & 0xf];
40 result[3] = kHexChars[b & 0xf];
41 return result + message;
44 class AdbTransportSocket : public AdbClientSocket {
45 public:
46 AdbTransportSocket(int port,
47 const std::string& serial,
48 const std::string& socket_name,
49 const SocketCallback& callback)
50 : AdbClientSocket(port),
51 serial_(serial),
52 socket_name_(socket_name),
53 callback_(callback) {
54 Connect(base::Bind(&AdbTransportSocket::OnConnected,
55 base::Unretained(this)));
58 private:
59 ~AdbTransportSocket() {}
61 void OnConnected(int result) {
62 if (!CheckNetResultOrDie(result))
63 return;
64 SendCommand(base::StringPrintf(kHostTransportCommand, serial_.c_str()),
65 true, base::Bind(&AdbTransportSocket::SendLocalAbstract,
66 base::Unretained(this)));
69 void SendLocalAbstract(int result, const std::string& response) {
70 if (!CheckNetResultOrDie(result))
71 return;
72 SendCommand(base::StringPrintf(kLocalAbstractCommand, socket_name_.c_str()),
73 true, base::Bind(&AdbTransportSocket::OnSocketAvailable,
74 base::Unretained(this)));
77 void OnSocketAvailable(int result, const std::string& response) {
78 if (!CheckNetResultOrDie(result))
79 return;
80 callback_.Run(net::OK, socket_.release());
81 delete this;
84 bool CheckNetResultOrDie(int result) {
85 if (result >= 0)
86 return true;
87 callback_.Run(result, NULL);
88 delete this;
89 return false;
92 std::string serial_;
93 std::string socket_name_;
94 SocketCallback callback_;
97 class HttpOverAdbSocket {
98 public:
99 HttpOverAdbSocket(int port,
100 const std::string& serial,
101 const std::string& socket_name,
102 const std::string& request,
103 const CommandCallback& callback)
104 : request_(request),
105 command_callback_(callback),
106 body_pos_(0) {
107 Connect(port, serial, socket_name);
110 HttpOverAdbSocket(int port,
111 const std::string& serial,
112 const std::string& socket_name,
113 const std::string& request,
114 const SocketCallback& callback)
115 : request_(request),
116 socket_callback_(callback),
117 body_pos_(0) {
118 Connect(port, serial, socket_name);
121 private:
122 ~HttpOverAdbSocket() {
125 void Connect(int port,
126 const std::string& serial,
127 const std::string& socket_name) {
128 AdbClientSocket::TransportQuery(
129 port, serial, socket_name,
130 base::Bind(&HttpOverAdbSocket::OnSocketAvailable,
131 base::Unretained(this)));
134 void OnSocketAvailable(int result,
135 net::StreamSocket* socket) {
136 if (!CheckNetResultOrDie(result))
137 return;
139 socket_.reset(socket);
141 scoped_refptr<net::StringIOBuffer> request_buffer =
142 new net::StringIOBuffer(request_);
144 result = socket_->Write(
145 request_buffer.get(),
146 request_buffer->size(),
147 base::Bind(&HttpOverAdbSocket::ReadResponse, base::Unretained(this)));
148 if (result != net::ERR_IO_PENDING)
149 ReadResponse(result);
152 void ReadResponse(int result) {
153 if (!CheckNetResultOrDie(result))
154 return;
156 scoped_refptr<net::IOBuffer> response_buffer =
157 new net::IOBuffer(kBufferSize);
159 result = socket_->Read(response_buffer.get(),
160 kBufferSize,
161 base::Bind(&HttpOverAdbSocket::OnResponseData,
162 base::Unretained(this),
163 response_buffer,
164 -1));
165 if (result != net::ERR_IO_PENDING)
166 OnResponseData(response_buffer, -1, result);
169 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
170 int bytes_total,
171 int result) {
172 if (!CheckNetResultOrDie(result))
173 return;
174 if (result == 0) {
175 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
176 return;
179 response_ += std::string(response_buffer->data(), result);
180 int expected_length = 0;
181 if (bytes_total < 0) {
182 size_t content_pos = response_.find("Content-Length:");
183 if (content_pos != std::string::npos) {
184 size_t endline_pos = response_.find("\n", content_pos);
185 if (endline_pos != std::string::npos) {
186 std::string len = response_.substr(content_pos + 15,
187 endline_pos - content_pos - 15);
188 base::TrimWhitespace(len, base::TRIM_ALL, &len);
189 if (!base::StringToInt(len, &expected_length)) {
190 CheckNetResultOrDie(net::ERR_FAILED);
191 return;
196 body_pos_ = response_.find("\r\n\r\n");
197 if (body_pos_ != std::string::npos) {
198 body_pos_ += 4;
199 bytes_total = body_pos_ + expected_length;
203 if (bytes_total == static_cast<int>(response_.length())) {
204 if (!command_callback_.is_null())
205 command_callback_.Run(body_pos_, response_);
206 else
207 socket_callback_.Run(net::OK, socket_.release());
208 delete this;
209 return;
212 result = socket_->Read(response_buffer.get(),
213 kBufferSize,
214 base::Bind(&HttpOverAdbSocket::OnResponseData,
215 base::Unretained(this),
216 response_buffer,
217 bytes_total));
218 if (result != net::ERR_IO_PENDING)
219 OnResponseData(response_buffer, bytes_total, result);
222 bool CheckNetResultOrDie(int result) {
223 if (result >= 0)
224 return true;
225 if (!command_callback_.is_null())
226 command_callback_.Run(result, std::string());
227 else
228 socket_callback_.Run(result, NULL);
229 delete this;
230 return false;
233 scoped_ptr<net::StreamSocket> socket_;
234 std::string request_;
235 std::string response_;
236 CommandCallback command_callback_;
237 SocketCallback socket_callback_;
238 size_t body_pos_;
241 class AdbQuerySocket : AdbClientSocket {
242 public:
243 AdbQuerySocket(int port,
244 const std::string& query,
245 const CommandCallback& callback)
246 : AdbClientSocket(port),
247 current_query_(0),
248 callback_(callback) {
249 queries_ = base::SplitString(
250 query, "|", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
251 if (queries_.empty()) {
252 CheckNetResultOrDie(net::ERR_INVALID_ARGUMENT);
253 return;
255 Connect(base::Bind(&AdbQuerySocket::SendNextQuery, base::Unretained(this)));
258 private:
259 ~AdbQuerySocket() {
262 void SendNextQuery(int result) {
263 if (!CheckNetResultOrDie(result))
264 return;
265 std::string query = queries_[current_query_];
266 if (query.length() > 0xFFFF) {
267 CheckNetResultOrDie(net::ERR_MSG_TOO_BIG);
268 return;
270 bool is_void = current_query_ < queries_.size() - 1;
271 SendCommand(query, is_void,
272 base::Bind(&AdbQuerySocket::OnResponse, base::Unretained(this)));
275 void OnResponse(int result, const std::string& response) {
276 if (++current_query_ < queries_.size()) {
277 SendNextQuery(net::OK);
278 } else {
279 callback_.Run(result, response);
280 delete this;
284 bool CheckNetResultOrDie(int result) {
285 if (result >= 0)
286 return true;
287 callback_.Run(result, std::string());
288 delete this;
289 return false;
292 std::vector<std::string> queries_;
293 size_t current_query_;
294 CommandCallback callback_;
297 } // namespace
299 // static
300 void AdbClientSocket::AdbQuery(int port,
301 const std::string& query,
302 const CommandCallback& callback) {
303 new AdbQuerySocket(port, query, callback);
306 #if defined(DEBUG_DEVTOOLS)
307 static void UseTransportQueryForDesktop(const SocketCallback& callback,
308 net::StreamSocket* socket,
309 int result) {
310 callback.Run(result, socket);
312 #endif // defined(DEBUG_DEVTOOLS)
314 // static
315 void AdbClientSocket::TransportQuery(int port,
316 const std::string& serial,
317 const std::string& socket_name,
318 const SocketCallback& callback) {
319 #if defined(DEBUG_DEVTOOLS)
320 if (serial.empty()) {
321 // Use plain socket for remote debugging on Desktop (debugging purposes).
322 net::IPAddressNumber ip_number;
323 net::ParseIPLiteralToNumber(kLocalhost, &ip_number);
325 int tcp_port = 0;
326 if (!base::StringToInt(socket_name, &tcp_port))
327 tcp_port = 9222;
329 net::AddressList address_list =
330 net::AddressList::CreateFromIPAddress(ip_number, tcp_port);
331 net::TCPClientSocket* socket = new net::TCPClientSocket(
332 address_list, NULL, net::NetLog::Source());
333 socket->Connect(base::Bind(&UseTransportQueryForDesktop, callback, socket));
334 return;
336 #endif // defined(DEBUG_DEVTOOLS)
337 new AdbTransportSocket(port, serial, socket_name, callback);
340 // static
341 void AdbClientSocket::HttpQuery(int port,
342 const std::string& serial,
343 const std::string& socket_name,
344 const std::string& request_path,
345 const CommandCallback& callback) {
346 new HttpOverAdbSocket(port, serial, socket_name, request_path,
347 callback);
350 // static
351 void AdbClientSocket::HttpQuery(int port,
352 const std::string& serial,
353 const std::string& socket_name,
354 const std::string& request_path,
355 const SocketCallback& callback) {
356 new HttpOverAdbSocket(port, serial, socket_name, request_path,
357 callback);
360 AdbClientSocket::AdbClientSocket(int port)
361 : host_(kLocalhost), port_(port) {
364 AdbClientSocket::~AdbClientSocket() {
367 void AdbClientSocket::Connect(const net::CompletionCallback& callback) {
368 net::IPAddressNumber ip_number;
369 if (!net::ParseIPLiteralToNumber(host_, &ip_number)) {
370 callback.Run(net::ERR_FAILED);
371 return;
374 net::AddressList address_list =
375 net::AddressList::CreateFromIPAddress(ip_number, port_);
376 socket_.reset(new net::TCPClientSocket(address_list, NULL,
377 net::NetLog::Source()));
378 int result = socket_->Connect(callback);
379 if (result != net::ERR_IO_PENDING)
380 callback.Run(result);
383 void AdbClientSocket::SendCommand(const std::string& command,
384 bool is_void,
385 const CommandCallback& callback) {
386 scoped_refptr<net::StringIOBuffer> request_buffer =
387 new net::StringIOBuffer(EncodeMessage(command));
388 int result = socket_->Write(request_buffer.get(),
389 request_buffer->size(),
390 base::Bind(&AdbClientSocket::ReadResponse,
391 base::Unretained(this),
392 callback,
393 is_void));
394 if (result != net::ERR_IO_PENDING)
395 ReadResponse(callback, is_void, result);
398 void AdbClientSocket::ReadResponse(const CommandCallback& callback,
399 bool is_void,
400 int result) {
401 if (result < 0) {
402 callback.Run(result, "IO error");
403 return;
405 scoped_refptr<net::IOBuffer> response_buffer =
406 new net::IOBuffer(kBufferSize);
407 result = socket_->Read(response_buffer.get(),
408 kBufferSize,
409 base::Bind(&AdbClientSocket::OnResponseHeader,
410 base::Unretained(this),
411 callback,
412 is_void,
413 response_buffer));
414 if (result != net::ERR_IO_PENDING)
415 OnResponseHeader(callback, is_void, response_buffer, result);
418 void AdbClientSocket::OnResponseHeader(
419 const CommandCallback& callback,
420 bool is_void,
421 scoped_refptr<net::IOBuffer> response_buffer,
422 int result) {
423 if (result <= 0) {
424 callback.Run(result == 0 ? net::ERR_CONNECTION_CLOSED : result,
425 "IO error");
426 return;
429 std::string data = std::string(response_buffer->data(), result);
430 if (result < 4) {
431 callback.Run(net::ERR_FAILED, "Response is too short: " + data);
432 return;
435 std::string status = data.substr(0, 4);
436 if (status != kOkayResponse) {
437 callback.Run(net::ERR_FAILED, data);
438 return;
441 data = data.substr(4);
443 if (!is_void) {
444 int payload_length = 0;
445 int bytes_left = -1;
446 if (data.length() >= 4 &&
447 base::HexStringToInt(data.substr(0, 4), &payload_length)) {
448 data = data.substr(4);
449 bytes_left = payload_length - result + 8;
450 } else {
451 bytes_left = -1;
453 OnResponseData(callback, data, response_buffer, bytes_left, 0);
454 } else {
455 callback.Run(net::OK, data);
459 void AdbClientSocket::OnResponseData(
460 const CommandCallback& callback,
461 const std::string& response,
462 scoped_refptr<net::IOBuffer> response_buffer,
463 int bytes_left,
464 int result) {
465 if (result < 0) {
466 callback.Run(result, "IO error");
467 return;
470 bytes_left -= result;
471 std::string new_response =
472 response + std::string(response_buffer->data(), result);
473 if (bytes_left == 0) {
474 callback.Run(net::OK, new_response);
475 return;
478 // Read tail
479 result = socket_->Read(response_buffer.get(),
480 kBufferSize,
481 base::Bind(&AdbClientSocket::OnResponseData,
482 base::Unretained(this),
483 callback,
484 new_response,
485 response_buffer,
486 bytes_left));
487 if (result > 0)
488 OnResponseData(callback, new_response, response_buffer, bytes_left, result);
489 else if (result != net::ERR_IO_PENDING)
490 callback.Run(net::OK, new_response);