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