Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / devtools / adb_client_socket.cc
blobe16273ecf9ecf93197fc99e19abf67968f7c2049
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/browser/devtools/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_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "net/base/address_list.h"
13 #include "net/base/completion_callback.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/net_util.h"
16 #include "net/socket/tcp_client_socket.h"
18 namespace {
20 const int kBufferSize = 16 * 1024;
21 const char kOkayResponse[] = "OKAY";
22 const char kHostTransportCommand[] = "host:transport:%s";
23 const char kLocalhost[] = "127.0.0.1";
25 typedef base::Callback<void(int, const std::string&)> CommandCallback;
26 typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback;
28 std::string EncodeMessage(const std::string& message) {
29 static const char kHexChars[] = "0123456789ABCDEF";
31 size_t length = message.length();
32 std::string result(4, '\0');
33 char b = reinterpret_cast<const char*>(&length)[1];
34 result[0] = kHexChars[(b >> 4) & 0xf];
35 result[1] = kHexChars[b & 0xf];
36 b = reinterpret_cast<const char*>(&length)[0];
37 result[2] = kHexChars[(b >> 4) & 0xf];
38 result[3] = kHexChars[b & 0xf];
39 return result + message;
42 class AdbTransportSocket : public AdbClientSocket {
43 public:
44 AdbTransportSocket(int port,
45 const std::string& serial,
46 const std::string& socket_name,
47 const SocketCallback& callback)
48 : AdbClientSocket(port),
49 serial_(serial),
50 socket_name_(socket_name),
51 callback_(callback) {
52 Connect(base::Bind(&AdbTransportSocket::OnConnected,
53 base::Unretained(this)));
56 private:
57 ~AdbTransportSocket() {}
59 void OnConnected(int result) {
60 if (!CheckNetResultOrDie(result))
61 return;
62 SendCommand(base::StringPrintf(kHostTransportCommand, serial_.c_str()),
63 true, base::Bind(&AdbTransportSocket::SendLocalAbstract,
64 base::Unretained(this)));
67 void SendLocalAbstract(int result, const std::string& response) {
68 if (!CheckNetResultOrDie(result))
69 return;
70 SendCommand(socket_name_, true,
71 base::Bind(&AdbTransportSocket::OnSocketAvailable,
72 base::Unretained(this)));
75 void OnSocketAvailable(int result, const std::string& response) {
76 if (!CheckNetResultOrDie(result))
77 return;
78 callback_.Run(net::OK, socket_.release());
79 delete this;
82 bool CheckNetResultOrDie(int result) {
83 if (result >= 0)
84 return true;
85 callback_.Run(result, NULL);
86 delete this;
87 return false;
90 std::string serial_;
91 std::string socket_name_;
92 SocketCallback callback_;
95 class HttpOverAdbSocket {
96 public:
97 HttpOverAdbSocket(net::StreamSocket* socket,
98 const std::string& request,
99 const CommandCallback& callback)
100 : socket_(socket),
101 command_callback_(callback),
102 body_pos_(0) {
103 SendRequest(request);
106 HttpOverAdbSocket(net::StreamSocket* socket,
107 const std::string& request,
108 const SocketCallback& callback)
109 : socket_(socket),
110 socket_callback_(callback),
111 body_pos_(0) {
112 SendRequest(request);
115 private:
116 ~HttpOverAdbSocket() {
119 void SendRequest(const std::string& request) {
120 scoped_refptr<net::StringIOBuffer> request_buffer =
121 new net::StringIOBuffer(request);
123 int result = socket_->Write(
124 request_buffer.get(),
125 request_buffer->size(),
126 base::Bind(&HttpOverAdbSocket::ReadResponse, base::Unretained(this)));
127 if (result != net::ERR_IO_PENDING)
128 ReadResponse(result);
131 void ReadResponse(int result) {
132 if (!CheckNetResultOrDie(result))
133 return;
134 scoped_refptr<net::IOBuffer> response_buffer =
135 new net::IOBuffer(kBufferSize);
137 result = socket_->Read(response_buffer.get(),
138 kBufferSize,
139 base::Bind(&HttpOverAdbSocket::OnResponseData,
140 base::Unretained(this),
141 response_buffer,
142 -1));
143 if (result != net::ERR_IO_PENDING)
144 OnResponseData(response_buffer, -1, result);
147 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
148 int bytes_total,
149 int result) {
150 if (!CheckNetResultOrDie(result))
151 return;
152 if (result == 0) {
153 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
154 return;
157 response_ += std::string(response_buffer->data(), result);
158 int expected_length = 0;
159 if (bytes_total < 0) {
160 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
161 size_t content_pos = response_.find("Content-Length:");
162 if (content_pos != std::string::npos) {
163 size_t endline_pos = response_.find("\n", content_pos);
164 if (endline_pos != std::string::npos) {
165 std::string len = response_.substr(content_pos + 15,
166 endline_pos - content_pos - 15);
167 TrimWhitespace(len, TRIM_ALL, &len);
168 if (!base::StringToInt(len, &expected_length)) {
169 CheckNetResultOrDie(net::ERR_FAILED);
170 return;
175 body_pos_ = response_.find("\r\n\r\n");
176 if (body_pos_ != std::string::npos) {
177 body_pos_ += 4;
178 bytes_total = body_pos_ + expected_length;
182 if (bytes_total == static_cast<int>(response_.length())) {
183 if (!command_callback_.is_null())
184 command_callback_.Run(net::OK, response_.substr(body_pos_));
185 else
186 socket_callback_.Run(net::OK, socket_.release());
187 delete this;
188 return;
191 result = socket_->Read(response_buffer.get(),
192 kBufferSize,
193 base::Bind(&HttpOverAdbSocket::OnResponseData,
194 base::Unretained(this),
195 response_buffer,
196 bytes_total));
197 if (result != net::ERR_IO_PENDING)
198 OnResponseData(response_buffer, bytes_total, result);
201 bool CheckNetResultOrDie(int result) {
202 if (result >= 0)
203 return true;
204 if (!command_callback_.is_null())
205 command_callback_.Run(result, std::string());
206 else
207 socket_callback_.Run(result, NULL);
208 delete this;
209 return false;
212 scoped_ptr<net::StreamSocket> socket_;
213 std::string response_;
214 CommandCallback command_callback_;
215 SocketCallback socket_callback_;
216 size_t body_pos_;
219 class AdbQuerySocket : AdbClientSocket {
220 public:
221 AdbQuerySocket(int port,
222 const std::string& query,
223 const CommandCallback& callback)
224 : AdbClientSocket(port),
225 current_query_(0),
226 callback_(callback) {
227 if (Tokenize(query, "|", &queries_) == 0) {
228 CheckNetResultOrDie(net::ERR_INVALID_ARGUMENT);
229 return;
231 Connect(base::Bind(&AdbQuerySocket::SendNextQuery,
232 base::Unretained(this)));
235 private:
236 ~AdbQuerySocket() {
239 void SendNextQuery(int result) {
240 if (!CheckNetResultOrDie(result))
241 return;
242 std::string query = queries_[current_query_];
243 if (query.length() > 0xFFFF) {
244 CheckNetResultOrDie(net::ERR_MSG_TOO_BIG);
245 return;
247 bool is_void = current_query_ < queries_.size() - 1;
248 SendCommand(query, is_void,
249 base::Bind(&AdbQuerySocket::OnResponse, base::Unretained(this)));
252 void OnResponse(int result, const std::string& response) {
253 if (++current_query_ < queries_.size()) {
254 SendNextQuery(net::OK);
255 } else {
256 callback_.Run(result, response);
257 delete this;
261 bool CheckNetResultOrDie(int result) {
262 if (result >= 0)
263 return true;
264 callback_.Run(result, std::string());
265 delete this;
266 return false;
269 std::vector<std::string> queries_;
270 size_t current_query_;
271 CommandCallback callback_;
274 } // namespace
276 // static
277 void AdbClientSocket::AdbQuery(int port,
278 const std::string& query,
279 const CommandCallback& callback) {
280 new AdbQuerySocket(port, query, callback);
283 // static
284 void AdbClientSocket::TransportQuery(int port,
285 const std::string& serial,
286 const std::string& socket_name,
287 const SocketCallback& callback) {
288 new AdbTransportSocket(port, serial, socket_name, callback);
291 // static
292 void AdbClientSocket::HttpQuery(net::StreamSocket* socket,
293 const std::string& request_path,
294 const CommandCallback& callback) {
295 new HttpOverAdbSocket(socket, request_path, callback);
298 // static
299 void AdbClientSocket::HttpQuery(net::StreamSocket* socket,
300 const std::string& request_path,
301 const SocketCallback& callback) {
302 new HttpOverAdbSocket(socket, request_path, callback);
305 AdbClientSocket::AdbClientSocket(int port)
306 : host_(kLocalhost), port_(port) {
309 AdbClientSocket::~AdbClientSocket() {
312 void AdbClientSocket::Connect(const net::CompletionCallback& callback) {
313 net::IPAddressNumber ip_number;
314 if (!net::ParseIPLiteralToNumber(host_, &ip_number)) {
315 callback.Run(net::ERR_FAILED);
316 return;
319 net::AddressList address_list =
320 net::AddressList::CreateFromIPAddress(ip_number, port_);
321 socket_.reset(new net::TCPClientSocket(address_list, NULL,
322 net::NetLog::Source()));
323 int result = socket_->Connect(callback);
324 if (result != net::ERR_IO_PENDING)
325 callback.Run(result);
328 void AdbClientSocket::SendCommand(const std::string& command,
329 bool is_void,
330 const CommandCallback& callback) {
331 scoped_refptr<net::StringIOBuffer> request_buffer =
332 new net::StringIOBuffer(EncodeMessage(command));
333 int result = socket_->Write(request_buffer.get(),
334 request_buffer->size(),
335 base::Bind(&AdbClientSocket::ReadResponse,
336 base::Unretained(this),
337 callback,
338 is_void));
339 if (result != net::ERR_IO_PENDING)
340 ReadResponse(callback, is_void, result);
343 void AdbClientSocket::ReadResponse(const CommandCallback& callback,
344 bool is_void,
345 int result) {
346 if (result < 0) {
347 callback.Run(result, "IO error");
348 return;
350 scoped_refptr<net::IOBuffer> response_buffer =
351 new net::IOBuffer(kBufferSize);
352 result = socket_->Read(response_buffer.get(),
353 kBufferSize,
354 base::Bind(&AdbClientSocket::OnResponseHeader,
355 base::Unretained(this),
356 callback,
357 is_void,
358 response_buffer));
359 if (result != net::ERR_IO_PENDING)
360 OnResponseHeader(callback, is_void, response_buffer, result);
363 void AdbClientSocket::OnResponseHeader(
364 const CommandCallback& callback,
365 bool is_void,
366 scoped_refptr<net::IOBuffer> response_buffer,
367 int result) {
368 if (result <= 0) {
369 callback.Run(result == 0 ? net::ERR_CONNECTION_CLOSED : result,
370 "IO error");
371 return;
374 std::string data = std::string(response_buffer->data(), result);
375 if (result < 4) {
376 callback.Run(net::ERR_FAILED, "Response is too short: " + data);
377 return;
380 std::string status = data.substr(0, 4);
381 if (status != kOkayResponse) {
382 callback.Run(net::ERR_FAILED, data);
383 return;
386 data = data.substr(4);
388 if (!is_void) {
389 int payload_length = 0;
390 int bytes_left = -1;
391 if (data.length() >= 4 &&
392 base::HexStringToInt(data.substr(0, 4), &payload_length)) {
393 data = data.substr(4);
394 bytes_left = payload_length - result + 8;
395 } else {
396 bytes_left = -1;
398 OnResponseData(callback, data, response_buffer, bytes_left, 0);
399 } else {
400 callback.Run(net::OK, data);
404 void AdbClientSocket::OnResponseData(
405 const CommandCallback& callback,
406 const std::string& response,
407 scoped_refptr<net::IOBuffer> response_buffer,
408 int bytes_left,
409 int result) {
410 if (result < 0) {
411 callback.Run(result, "IO error");
412 return;
415 bytes_left -= result;
416 std::string new_response =
417 response + std::string(response_buffer->data(), result);
418 if (bytes_left == 0) {
419 callback.Run(net::OK, new_response);
420 return;
423 // Read tail
424 result = socket_->Read(response_buffer.get(),
425 kBufferSize,
426 base::Bind(&AdbClientSocket::OnResponseData,
427 base::Unretained(this),
428 callback,
429 new_response,
430 response_buffer,
431 bytes_left));
432 if (result > 0)
433 OnResponseData(callback, new_response, response_buffer, bytes_left, result);
434 else if (result != net::ERR_IO_PENDING)
435 callback.Run(net::OK, new_response);