Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / devtools / device / usb / android_usb_socket.cc
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.
4
5 #include "chrome/browser/devtools/device/usb/android_usb_socket.h"
6
7 #include "base/message_loop/message_loop.h"
8
9 namespace {
10
11 const int kMaxPayload = 4096;
12
13 }  // namespace
14
15 AndroidUsbSocket::IORequest::IORequest(
16     net::IOBuffer* buffer,
17     int length,
18     const net::CompletionCallback& callback)
19     : buffer(buffer),
20       length(length),
21       callback(callback) {
22 }
23
24 AndroidUsbSocket::IORequest::~IORequest() {
25 }
26
27 AndroidUsbSocket::AndroidUsbSocket(scoped_refptr<AndroidUsbDevice> device,
28                                    uint32 socket_id,
29                                    const std::string& command,
30                                    base::Callback<void(uint32)> delete_callback)
31     : device_(device),
32       command_(command),
33       delete_callback_(delete_callback),
34       local_id_(socket_id),
35       remote_id_(0),
36       is_connected_(false) {
37 }
38
39 AndroidUsbSocket::~AndroidUsbSocket() {
40   DCHECK(CalledOnValidThread());
41   if (is_connected_)
42     Disconnect();
43   if (!delete_callback_.is_null())
44     delete_callback_.Run(local_id_);
45 }
46
47 void AndroidUsbSocket::HandleIncoming(scoped_refptr<AdbMessage> message) {
48   if (!device_.get())
49     return;
50
51   CHECK_EQ(message->arg1, local_id_);
52   switch (message->command) {
53     case AdbMessage::kCommandOKAY:
54       if (!is_connected_) {
55         remote_id_ = message->arg0;
56         is_connected_ = true;
57         net::CompletionCallback callback = connect_callback_;
58         connect_callback_.Reset();
59         callback.Run(net::OK);
60         // "this" can be NULL.
61       } else {
62         RespondToWriters();
63         // "this" can be NULL.
64       }
65       break;
66     case AdbMessage::kCommandWRTE:
67       device_->Send(AdbMessage::kCommandOKAY, local_id_, message->arg0, "");
68       read_buffer_ += message->body;
69       // Allow WRTE over new connection even though OKAY ack was not received.
70       if (!is_connected_) {
71         remote_id_ = message->arg0;
72         is_connected_ = true;
73         net::CompletionCallback callback = connect_callback_;
74         connect_callback_.Reset();
75         callback.Run(net::OK);
76         // "this" can be NULL.
77       } else {
78         RespondToReaders(false);
79         // "this" can be NULL.
80       }
81       break;
82     case AdbMessage::kCommandCLSE:
83       if (is_connected_)
84         device_->Send(AdbMessage::kCommandCLSE, local_id_, 0, "");
85       Terminated(true);
86       // "this" can be NULL.
87       break;
88     default:
89       break;
90   }
91 }
92
93 void AndroidUsbSocket::Terminated(bool closed_by_device) {
94   is_connected_ = false;
95
96   // Break the socket -> device connection, release the device.
97   delete_callback_.Run(local_id_);
98   delete_callback_.Reset();
99   device_ = NULL;
100
101   if (!closed_by_device)
102     return;
103
104   // Respond to pending callbacks.
105   if (!connect_callback_.is_null()) {
106     net::CompletionCallback callback = connect_callback_;
107     connect_callback_.Reset();
108     callback.Run(net::ERR_FAILED);
109     // "this" can be NULL.
110     return;
111   }
112   RespondToReaders(true);
113 }
114
115 int AndroidUsbSocket::Read(net::IOBuffer* buffer,
116                            int length,
117                            const net::CompletionCallback& callback) {
118   if (!is_connected_)
119     return device_.get() ? net::ERR_SOCKET_NOT_CONNECTED : 0;
120
121   if (read_buffer_.empty()) {
122     read_requests_.push_back(IORequest(buffer, length, callback));
123     return net::ERR_IO_PENDING;
124   }
125
126   size_t bytes_to_copy = static_cast<size_t>(length) > read_buffer_.length() ?
127       read_buffer_.length() : static_cast<size_t>(length);
128   memcpy(buffer->data(), read_buffer_.data(), bytes_to_copy);
129   if (read_buffer_.length() > bytes_to_copy)
130     read_buffer_ = read_buffer_.substr(bytes_to_copy);
131   else
132     read_buffer_ = "";
133   return bytes_to_copy;
134 }
135
136 int AndroidUsbSocket::Write(net::IOBuffer* buffer,
137                             int length,
138                             const net::CompletionCallback& callback) {
139   if (!is_connected_)
140     return net::ERR_SOCKET_NOT_CONNECTED;
141
142   if (length > kMaxPayload)
143     length = kMaxPayload;
144   write_requests_.push_back(IORequest(NULL, length, callback));
145   device_->Send(AdbMessage::kCommandWRTE, local_id_, remote_id_,
146                  std::string(buffer->data(), length));
147   return net::ERR_IO_PENDING;
148 }
149
150 int AndroidUsbSocket::SetReceiveBufferSize(int32 size) {
151   NOTIMPLEMENTED();
152   return net::ERR_NOT_IMPLEMENTED;
153 }
154
155 int AndroidUsbSocket::SetSendBufferSize(int32 size) {
156   NOTIMPLEMENTED();
157   return net::ERR_NOT_IMPLEMENTED;
158 }
159
160 int AndroidUsbSocket::Connect(const net::CompletionCallback& callback) {
161   DCHECK(CalledOnValidThread());
162   if (!device_.get())
163     return net::ERR_FAILED;
164   connect_callback_ = callback;
165   device_->Send(AdbMessage::kCommandOPEN, local_id_, 0, command_);
166   return net::ERR_IO_PENDING;
167 }
168
169 void AndroidUsbSocket::Disconnect() {
170   if (!device_.get())
171     return;
172   device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, "");
173   Terminated(false);
174 }
175
176 bool AndroidUsbSocket::IsConnected() const {
177   DCHECK(CalledOnValidThread());
178   return is_connected_;
179 }
180
181 bool AndroidUsbSocket::IsConnectedAndIdle() const {
182   NOTIMPLEMENTED();
183   return false;
184 }
185
186 int AndroidUsbSocket::GetPeerAddress(net::IPEndPoint* address) const {
187   net::IPAddressNumber ip(net::kIPv4AddressSize);
188   *address = net::IPEndPoint(ip, 0);
189   return net::OK;
190 }
191
192 int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const {
193   NOTIMPLEMENTED();
194   return net::ERR_NOT_IMPLEMENTED;
195 }
196
197 const net::BoundNetLog& AndroidUsbSocket::NetLog() const {
198   return net_log_;
199 }
200
201 void AndroidUsbSocket::SetSubresourceSpeculation() {
202   NOTIMPLEMENTED();
203 }
204
205 void AndroidUsbSocket::SetOmniboxSpeculation() {
206   NOTIMPLEMENTED();
207 }
208
209 bool AndroidUsbSocket::WasEverUsed() const {
210   NOTIMPLEMENTED();
211   return true;
212 }
213
214 bool AndroidUsbSocket::UsingTCPFastOpen() const {
215   NOTIMPLEMENTED();
216   return true;
217 }
218
219 bool AndroidUsbSocket::WasNpnNegotiated() const {
220   NOTIMPLEMENTED();
221   return true;
222 }
223
224 net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const {
225   NOTIMPLEMENTED();
226   return net::kProtoUnknown;
227 }
228
229 bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
230   return false;
231 }
232
233 void AndroidUsbSocket::RespondToReaders(bool disconnect) {
234   std::deque<IORequest> read_requests;
235   read_requests.swap(read_requests_);
236   while (!read_requests.empty() && (!read_buffer_.empty() || disconnect)) {
237     IORequest read_request = read_requests.front();
238     read_requests.pop_front();
239     size_t bytes_to_copy =
240         static_cast<size_t>(read_request.length) > read_buffer_.length() ?
241             read_buffer_.length() : static_cast<size_t>(read_request.length);
242     memcpy(read_request.buffer->data(), read_buffer_.data(), bytes_to_copy);
243     if (read_buffer_.length() > bytes_to_copy)
244       read_buffer_ = read_buffer_.substr(bytes_to_copy);
245     else
246       read_buffer_ = "";
247     read_request.callback.Run(bytes_to_copy);
248   }
249 }
250
251 void AndroidUsbSocket::RespondToWriters() {
252   if (!write_requests_.empty()) {
253     IORequest write_request = write_requests_.front();
254     write_requests_.pop_front();
255     write_request.callback.Run(write_request.length);
256   }
257 }