OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/test/chromedriver/net/adb_client_socket.h" | 5 #include "chrome/test/chromedriver/net/adb_client_socket.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
15 #include "net/base/address_list.h" | 15 #include "net/base/address_list.h" |
16 #include "net/base/completion_callback.h" | 16 #include "net/base/completion_callback.h" |
17 #include "net/base/ip_address.h" | 17 #include "net/base/ip_address.h" |
18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
19 #include "net/log/net_log_source.h" | 19 #include "net/log/net_log_source.h" |
20 #include "net/socket/tcp_client_socket.h" | 20 #include "net/socket/tcp_client_socket.h" |
21 #include "third_party/WebKit/public/public_features.h" | 21 #include "third_party/WebKit/public/public_features.h" |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 const int kBufferSize = 16 * 1024; | 25 const int kBufferSize = 16 * 1024; |
| 26 const size_t kAdbDataChunkSize = 32 * 1024; |
26 const char kOkayResponse[] = "OKAY"; | 27 const char kOkayResponse[] = "OKAY"; |
27 const char kHostTransportCommand[] = "host:transport:%s"; | 28 const char kHostTransportCommand[] = "host:transport:%s"; |
28 const char kLocalAbstractCommand[] = "localabstract:%s"; | 29 const char kLocalAbstractCommand[] = "localabstract:%s"; |
| 30 const char kSyncCommand[] = "sync:"; |
| 31 const char kSendCommand[] = "SEND"; |
| 32 const char kDataCommand[] = "DATA"; |
| 33 const char kDoneCommand[] = "DONE"; |
29 | 34 |
30 typedef base::Callback<void(int, const std::string&)> CommandCallback; | 35 typedef base::Callback<void(int, const std::string&)> CommandCallback; |
31 typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback; | 36 typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback; |
32 | 37 |
33 std::string EncodeMessage(const std::string& message) { | 38 std::string EncodeMessage(const std::string& message) { |
34 static const char kHexChars[] = "0123456789ABCDEF"; | 39 static const char kHexChars[] = "0123456789ABCDEF"; |
35 | 40 |
36 size_t length = message.length(); | 41 size_t length = message.length(); |
37 std::string result(4, '\0'); | 42 std::string result(4, '\0'); |
38 char b = reinterpret_cast<const char*>(&length)[1]; | 43 char b = reinterpret_cast<const char*>(&length)[1]; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 callback_.Run(result, std::string()); | 299 callback_.Run(result, std::string()); |
295 delete this; | 300 delete this; |
296 return false; | 301 return false; |
297 } | 302 } |
298 | 303 |
299 std::vector<std::string> queries_; | 304 std::vector<std::string> queries_; |
300 size_t current_query_; | 305 size_t current_query_; |
301 CommandCallback callback_; | 306 CommandCallback callback_; |
302 }; | 307 }; |
303 | 308 |
| 309 // Implement the ADB protocol to send a file to the device. |
| 310 // The protocol consists of the following steps: |
| 311 // * Send "host:transport" command with device serial |
| 312 // * Send "sync:" command to initialize file transfer |
| 313 // * Send "SEND" command with name and mode of the file |
| 314 // * Send "DATA" command one or more times for the file content |
| 315 // * Send "DONE" command to indicate end of file transfer |
| 316 // The first two commands use normal ADB command format implemented by |
| 317 // AdbClientSocket::SendCommand. The remaining commands use a special |
| 318 // format implemented by AdbSendFileSocket::SendPayload. |
| 319 class AdbSendFileSocket : AdbClientSocket { |
| 320 public: |
| 321 AdbSendFileSocket(int port, |
| 322 const std::string& serial, |
| 323 const std::string& filename, |
| 324 const std::string& content, |
| 325 const CommandCallback& callback) |
| 326 : AdbClientSocket(port), |
| 327 serial_(serial), |
| 328 filename_(filename), |
| 329 content_(content), |
| 330 current_offset_(0), |
| 331 callback_(callback) { |
| 332 Connect( |
| 333 base::Bind(&AdbSendFileSocket::SendTransport, base::Unretained(this))); |
| 334 } |
| 335 |
| 336 private: |
| 337 ~AdbSendFileSocket() {} |
| 338 |
| 339 void SendTransport(int result) { |
| 340 if (!CheckNetResultOrDie(result)) |
| 341 return; |
| 342 SendCommand( |
| 343 base::StringPrintf(kHostTransportCommand, serial_.c_str()), true, true, |
| 344 base::Bind(&AdbSendFileSocket::SendSync, base::Unretained(this))); |
| 345 } |
| 346 |
| 347 void SendSync(int result, const std::string& response) { |
| 348 if (!CheckNetResultOrDie(result)) |
| 349 return; |
| 350 SendCommand( |
| 351 kSyncCommand, true, true, |
| 352 base::Bind(&AdbSendFileSocket::SendSend, base::Unretained(this))); |
| 353 } |
| 354 |
| 355 void SendSend(int result, const std::string& response) { |
| 356 if (!CheckNetResultOrDie(result)) |
| 357 return; |
| 358 // File mode. The following value is equivalent to S_IRUSR | S_IWUSR. |
| 359 // Can't use the symbolic names since they are not available on Windows. |
| 360 int mode = 0600; |
| 361 std::string payload = base::StringPrintf("%s,%d", filename_.c_str(), mode); |
| 362 SendPayload( |
| 363 kSendCommand, payload.length(), payload.c_str(), payload.length(), |
| 364 base::Bind(&AdbSendFileSocket::SendContent, base::Unretained(this))); |
| 365 } |
| 366 |
| 367 void SendContent(int result) { |
| 368 if (!CheckNetResultOrDie(result)) |
| 369 return; |
| 370 if (current_offset_ >= content_.length()) { |
| 371 SendDone(); |
| 372 return; |
| 373 } |
| 374 size_t offset = current_offset_; |
| 375 size_t length = std::min(content_.length() - offset, kAdbDataChunkSize); |
| 376 current_offset_ += length; |
| 377 SendPayload( |
| 378 kDataCommand, length, content_.c_str() + offset, length, |
| 379 base::Bind(&AdbSendFileSocket::SendContent, base::Unretained(this))); |
| 380 } |
| 381 |
| 382 void SendDone() { |
| 383 int data = time(NULL); |
| 384 SendPayload(kDoneCommand, data, nullptr, 0, |
| 385 base::Bind(&AdbSendFileSocket::ReadFinalResponse, |
| 386 base::Unretained(this))); |
| 387 } |
| 388 |
| 389 void ReadFinalResponse(int result) { |
| 390 ReadResponse(callback_, true, false, result); |
| 391 } |
| 392 |
| 393 // Send a special payload command ("SEND", "DATA", or "DONE"). |
| 394 // Each command consists of a command line, followed by a 4-byte integer |
| 395 // sent in raw little-endian format, followed by an optional payload. |
| 396 void SendPayload(const char* command, |
| 397 int data, |
| 398 const char* payload, |
| 399 size_t payloadLength, |
| 400 const net::CompletionCallback& callback) { |
| 401 std::string buffer(command); |
| 402 for (int i = 0; i < 4; i++) { |
| 403 buffer.append(1, static_cast<char>(data & 0xff)); |
| 404 data >>= 8; |
| 405 } |
| 406 if (payloadLength > 0) |
| 407 buffer.append(payload, payloadLength); |
| 408 |
| 409 scoped_refptr<net::StringIOBuffer> request_buffer = |
| 410 new net::StringIOBuffer(buffer); |
| 411 int result = |
| 412 socket_->Write(request_buffer.get(), request_buffer->size(), callback); |
| 413 if (result != net::ERR_IO_PENDING) |
| 414 callback.Run(result); |
| 415 } |
| 416 |
| 417 bool CheckNetResultOrDie(int result) { |
| 418 if (result >= 0) |
| 419 return true; |
| 420 callback_.Run(result, NULL); |
| 421 delete this; |
| 422 return false; |
| 423 } |
| 424 |
| 425 std::string serial_; |
| 426 std::string filename_; |
| 427 std::string content_; |
| 428 size_t current_offset_; |
| 429 CommandCallback callback_; |
| 430 }; |
| 431 |
304 } // namespace | 432 } // namespace |
305 | 433 |
306 // static | 434 // static |
307 void AdbClientSocket::AdbQuery(int port, | 435 void AdbClientSocket::AdbQuery(int port, |
308 const std::string& query, | 436 const std::string& query, |
309 const CommandCallback& callback) { | 437 const CommandCallback& callback) { |
310 new AdbQuerySocket(port, query, callback); | 438 new AdbQuerySocket(port, query, callback); |
311 } | 439 } |
312 | 440 |
| 441 // static |
| 442 void AdbClientSocket::SendFile(int port, |
| 443 const std::string& serial, |
| 444 const std::string& filename, |
| 445 const std::string& content, |
| 446 const CommandCallback& callback) { |
| 447 new AdbSendFileSocket(port, serial, filename, content, callback); |
| 448 } |
| 449 |
313 #if BUILDFLAG(DEBUG_DEVTOOLS) | 450 #if BUILDFLAG(DEBUG_DEVTOOLS) |
314 static void UseTransportQueryForDesktop(const SocketCallback& callback, | 451 static void UseTransportQueryForDesktop(const SocketCallback& callback, |
315 net::StreamSocket* socket, | 452 net::StreamSocket* socket, |
316 int result) { | 453 int result) { |
317 callback.Run(result, socket); | 454 callback.Run(result, socket); |
318 } | 455 } |
319 #endif // BUILDFLAG(DEBUG_DEVTOOLS) | 456 #endif // BUILDFLAG(DEBUG_DEVTOOLS) |
320 | 457 |
321 // static | 458 // static |
322 void AdbClientSocket::TransportQuery(int port, | 459 void AdbClientSocket::TransportQuery(int port, |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 base::Unretained(this), | 673 base::Unretained(this), |
537 callback, | 674 callback, |
538 new_response, | 675 new_response, |
539 response_buffer, | 676 response_buffer, |
540 bytes_left)); | 677 bytes_left)); |
541 if (result > 0) | 678 if (result > 0) |
542 OnResponseData(callback, new_response, response_buffer, bytes_left, result); | 679 OnResponseData(callback, new_response, response_buffer, bytes_left, result); |
543 else if (result != net::ERR_IO_PENDING) | 680 else if (result != net::ERR_IO_PENDING) |
544 callback.Run(net::OK, new_response); | 681 callback.Run(net::OK, new_response); |
545 } | 682 } |
OLD | NEW |