Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / devtools / device / adb / adb_client_socket.cc
blob8a1feb4b460e976fb0a7d21f9b540fc4b3506f98
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/adb/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/net_errors.h"
14 #include "net/base/net_util.h"
15 #include "net/socket/tcp_client_socket.h"
17 namespace {
19 const int kBufferSize = 16 * 1024;
20 const char kOkayResponse[] = "OKAY";
21 const char kHostTransportCommand[] = "host:transport:%s";
22 const char kLocalhost[] = "127.0.0.1";
24 std::string EncodeMessage(const std::string& message) {
25 static const char kHexChars[] = "0123456789ABCDEF";
27 size_t length = message.length();
28 std::string result(4, '\0');
29 char b = reinterpret_cast<const char*>(&length)[1];
30 result[0] = kHexChars[(b >> 4) & 0xf];
31 result[1] = kHexChars[b & 0xf];
32 b = reinterpret_cast<const char*>(&length)[0];
33 result[2] = kHexChars[(b >> 4) & 0xf];
34 result[3] = kHexChars[b & 0xf];
35 return result + message;
38 class AdbTransportSocket : public AdbClientSocket {
39 public:
40 AdbTransportSocket(int port,
41 const std::string& serial,
42 const std::string& socket_name,
43 const SocketCallback& callback)
44 : AdbClientSocket(port),
45 serial_(serial),
46 socket_name_(socket_name),
47 callback_(callback) {
48 Connect(base::Bind(&AdbTransportSocket::OnConnected,
49 base::Unretained(this)));
52 private:
53 ~AdbTransportSocket() {}
55 void OnConnected(int result) {
56 if (!CheckNetResultOrDie(result))
57 return;
58 SendCommand(base::StringPrintf(kHostTransportCommand, serial_.c_str()),
59 true, base::Bind(&AdbTransportSocket::SendLocalAbstract,
60 base::Unretained(this)));
63 void SendLocalAbstract(int result, const std::string& response) {
64 if (!CheckNetResultOrDie(result))
65 return;
66 SendCommand(socket_name_, true,
67 base::Bind(&AdbTransportSocket::OnSocketAvailable,
68 base::Unretained(this)));
71 void OnSocketAvailable(int result, const std::string& response) {
72 if (!CheckNetResultOrDie(result))
73 return;
74 callback_.Run(net::OK, socket_.Pass());
75 delete this;
78 bool CheckNetResultOrDie(int result) {
79 if (result >= 0)
80 return true;
81 callback_.Run(result, make_scoped_ptr<net::StreamSocket>(NULL));
82 delete this;
83 return false;
86 std::string serial_;
87 std::string socket_name_;
88 SocketCallback callback_;
91 class AdbQuerySocket : AdbClientSocket {
92 public:
93 AdbQuerySocket(int port,
94 const std::string& query,
95 const CommandCallback& callback)
96 : AdbClientSocket(port),
97 current_query_(0),
98 callback_(callback) {
99 queries_ = base::SplitString(query, "|", base::KEEP_WHITESPACE,
100 base::SPLIT_WANT_NONEMPTY);
101 if (queries_.empty()) {
102 CheckNetResultOrDie(net::ERR_INVALID_ARGUMENT);
103 return;
105 Connect(base::Bind(&AdbQuerySocket::SendNextQuery,
106 base::Unretained(this)));
109 private:
110 ~AdbQuerySocket() {
113 void SendNextQuery(int result) {
114 if (!CheckNetResultOrDie(result))
115 return;
116 std::string query = queries_[current_query_];
117 if (query.length() > 0xFFFF) {
118 CheckNetResultOrDie(net::ERR_MSG_TOO_BIG);
119 return;
121 bool is_void = current_query_ < queries_.size() - 1;
122 SendCommand(query, is_void,
123 base::Bind(&AdbQuerySocket::OnResponse, base::Unretained(this)));
126 void OnResponse(int result, const std::string& response) {
127 if (++current_query_ < queries_.size()) {
128 SendNextQuery(net::OK);
129 } else {
130 callback_.Run(result, response);
131 delete this;
135 bool CheckNetResultOrDie(int result) {
136 if (result >= 0)
137 return true;
138 callback_.Run(result, std::string());
139 delete this;
140 return false;
143 std::vector<std::string> queries_;
144 size_t current_query_;
145 CommandCallback callback_;
148 } // namespace
150 // static
151 void AdbClientSocket::AdbQuery(int port,
152 const std::string& query,
153 const CommandCallback& callback) {
154 new AdbQuerySocket(port, query, callback);
157 // static
158 void AdbClientSocket::TransportQuery(int port,
159 const std::string& serial,
160 const std::string& socket_name,
161 const SocketCallback& callback) {
162 new AdbTransportSocket(port, serial, socket_name, callback);
165 AdbClientSocket::AdbClientSocket(int port)
166 : host_(kLocalhost), port_(port) {
169 AdbClientSocket::~AdbClientSocket() {
172 void AdbClientSocket::Connect(const net::CompletionCallback& callback) {
173 net::IPAddressNumber ip_number;
174 if (!net::ParseIPLiteralToNumber(host_, &ip_number)) {
175 callback.Run(net::ERR_FAILED);
176 return;
179 net::AddressList address_list =
180 net::AddressList::CreateFromIPAddress(ip_number, port_);
181 socket_.reset(new net::TCPClientSocket(address_list, NULL,
182 net::NetLog::Source()));
183 int result = socket_->Connect(callback);
184 if (result != net::ERR_IO_PENDING)
185 callback.Run(result);
188 void AdbClientSocket::SendCommand(const std::string& command,
189 bool is_void,
190 const CommandCallback& callback) {
191 scoped_refptr<net::StringIOBuffer> request_buffer =
192 new net::StringIOBuffer(EncodeMessage(command));
193 int result = socket_->Write(request_buffer.get(),
194 request_buffer->size(),
195 base::Bind(&AdbClientSocket::ReadResponse,
196 base::Unretained(this),
197 callback,
198 is_void));
199 if (result != net::ERR_IO_PENDING)
200 ReadResponse(callback, is_void, result);
203 void AdbClientSocket::ReadResponse(const CommandCallback& callback,
204 bool is_void,
205 int result) {
206 if (result < 0) {
207 callback.Run(result, "IO error");
208 return;
210 scoped_refptr<net::IOBuffer> response_buffer =
211 new net::IOBuffer(kBufferSize);
212 result = socket_->Read(response_buffer.get(),
213 kBufferSize,
214 base::Bind(&AdbClientSocket::OnResponseHeader,
215 base::Unretained(this),
216 callback,
217 is_void,
218 response_buffer));
219 if (result != net::ERR_IO_PENDING)
220 OnResponseHeader(callback, is_void, response_buffer, result);
223 void AdbClientSocket::OnResponseHeader(
224 const CommandCallback& callback,
225 bool is_void,
226 scoped_refptr<net::IOBuffer> response_buffer,
227 int result) {
228 if (result <= 0) {
229 callback.Run(result == 0 ? net::ERR_CONNECTION_CLOSED : result,
230 "IO error");
231 return;
234 std::string data = std::string(response_buffer->data(), result);
235 if (result < 4) {
236 callback.Run(net::ERR_FAILED, "Response is too short: " + data);
237 return;
240 std::string status = data.substr(0, 4);
241 if (status != kOkayResponse) {
242 callback.Run(net::ERR_FAILED, data);
243 return;
246 // Trim OKAY.
247 data = data.substr(4);
248 if (!is_void)
249 OnResponseData(callback, data, response_buffer, -1, 0);
250 else
251 callback.Run(net::OK, data);
254 void AdbClientSocket::OnResponseData(
255 const CommandCallback& callback,
256 const std::string& response,
257 scoped_refptr<net::IOBuffer> response_buffer,
258 int bytes_left,
259 int result) {
260 if (result < 0) {
261 callback.Run(result, "IO error");
262 return;
265 std::string new_response = response +
266 std::string(response_buffer->data(), result);
268 if (bytes_left == -1) {
269 // First read the response header.
270 int payload_length = 0;
271 if (new_response.length() >= 4 &&
272 base::HexStringToInt(new_response.substr(0, 4), &payload_length)) {
273 new_response = new_response.substr(4);
274 bytes_left = payload_length - new_response.size();
276 } else {
277 bytes_left -= result;
280 if (bytes_left == 0) {
281 callback.Run(net::OK, new_response);
282 return;
285 // Read tail
286 result = socket_->Read(response_buffer.get(),
287 kBufferSize,
288 base::Bind(&AdbClientSocket::OnResponseData,
289 base::Unretained(this),
290 callback,
291 new_response,
292 response_buffer,
293 bytes_left));
294 if (result > 0)
295 OnResponseData(callback, new_response, response_buffer, bytes_left, result);
296 else if (result != net::ERR_IO_PENDING)
297 callback.Run(net::OK, new_response);