Chromium Code Reviews| 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 = content_.length() - offset; | |
|
jbudorick
2017/07/13 15:25:30
nit: length = std::min(content_.length() - offset,
| |
| 376 if (length > kAdbDataChunkSize) | |
| 377 length = kAdbDataChunkSize; | |
| 378 current_offset_ += length; | |
| 379 SendPayload( | |
| 380 kDataCommand, length, content_.c_str() + offset, length, | |
| 381 base::Bind(&AdbSendFileSocket::SendContent, base::Unretained(this))); | |
| 382 } | |
| 383 | |
| 384 void SendDone() { | |
| 385 int data = time(NULL); | |
| 386 SendPayload(kDoneCommand, data, nullptr, 0, | |
| 387 base::Bind(&AdbSendFileSocket::ReadFinalResponse, | |
| 388 base::Unretained(this))); | |
| 389 } | |
| 390 | |
| 391 void ReadFinalResponse(int result) { | |
| 392 ReadResponse(callback_, true, false, result); | |
| 393 } | |
| 394 | |
| 395 // Send a special payload command ("SEND", "DATA", or "DONE"). | |
| 396 // Each command consists of a command line, followed by a 4-byte integer | |
| 397 // sent in raw little-endian format, followed by an optional payload. | |
| 398 void SendPayload(const char* command, | |
| 399 int data, | |
| 400 const char* payload, | |
| 401 size_t payloadLength, | |
| 402 const net::CompletionCallback& callback) { | |
| 403 std::string buffer(command); | |
| 404 for (int i = 0; i < 4; i++) { | |
|
jbudorick
2017/07/13 15:25:30
I'm looking for a way to do this using something i
| |
| 405 buffer.append(1, (char)(data & 0xff)); | |
|
jbudorick
2017/07/13 15:25:30
nit: static_cast<char>
| |
| 406 data >>= 8; | |
| 407 } | |
| 408 if (payloadLength > 0) | |
| 409 buffer.append(payload, payloadLength); | |
| 410 | |
| 411 scoped_refptr<net::StringIOBuffer> request_buffer = | |
| 412 new net::StringIOBuffer(buffer); | |
| 413 int result = | |
| 414 socket_->Write(request_buffer.get(), request_buffer->size(), callback); | |
| 415 if (result != net::ERR_IO_PENDING) | |
| 416 callback.Run(result); | |
| 417 } | |
| 418 | |
| 419 bool CheckNetResultOrDie(int result) { | |
| 420 if (result >= 0) | |
| 421 return true; | |
| 422 callback_.Run(result, NULL); | |
| 423 delete this; | |
| 424 return false; | |
| 425 } | |
| 426 | |
| 427 std::string serial_; | |
| 428 std::string filename_; | |
| 429 std::string content_; | |
| 430 size_t current_offset_; | |
| 431 CommandCallback callback_; | |
| 432 }; | |
| 433 | |
| 304 } // namespace | 434 } // namespace |
| 305 | 435 |
| 306 // static | 436 // static |
| 307 void AdbClientSocket::AdbQuery(int port, | 437 void AdbClientSocket::AdbQuery(int port, |
| 308 const std::string& query, | 438 const std::string& query, |
| 309 const CommandCallback& callback) { | 439 const CommandCallback& callback) { |
| 310 new AdbQuerySocket(port, query, callback); | 440 new AdbQuerySocket(port, query, callback); |
| 311 } | 441 } |
| 312 | 442 |
| 443 // static | |
| 444 void AdbClientSocket::SendFile(int port, | |
| 445 const std::string& serial, | |
| 446 const std::string& filename, | |
| 447 const std::string& content, | |
| 448 const CommandCallback& callback) { | |
| 449 new AdbSendFileSocket(port, serial, filename, content, callback); | |
| 450 } | |
| 451 | |
| 313 #if BUILDFLAG(DEBUG_DEVTOOLS) | 452 #if BUILDFLAG(DEBUG_DEVTOOLS) |
| 314 static void UseTransportQueryForDesktop(const SocketCallback& callback, | 453 static void UseTransportQueryForDesktop(const SocketCallback& callback, |
| 315 net::StreamSocket* socket, | 454 net::StreamSocket* socket, |
| 316 int result) { | 455 int result) { |
| 317 callback.Run(result, socket); | 456 callback.Run(result, socket); |
| 318 } | 457 } |
| 319 #endif // BUILDFLAG(DEBUG_DEVTOOLS) | 458 #endif // BUILDFLAG(DEBUG_DEVTOOLS) |
| 320 | 459 |
| 321 // static | 460 // static |
| 322 void AdbClientSocket::TransportQuery(int port, | 461 void AdbClientSocket::TransportQuery(int port, |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 base::Unretained(this), | 675 base::Unretained(this), |
| 537 callback, | 676 callback, |
| 538 new_response, | 677 new_response, |
| 539 response_buffer, | 678 response_buffer, |
| 540 bytes_left)); | 679 bytes_left)); |
| 541 if (result > 0) | 680 if (result > 0) |
| 542 OnResponseData(callback, new_response, response_buffer, bytes_left, result); | 681 OnResponseData(callback, new_response, response_buffer, bytes_left, result); |
| 543 else if (result != net::ERR_IO_PENDING) | 682 else if (result != net::ERR_IO_PENDING) |
| 544 callback.Run(net::OK, new_response); | 683 callback.Run(net::OK, new_response); |
| 545 } | 684 } |
| OLD | NEW |