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 |