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 "base/memory/weak_ptr.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/rand_util.h"
8 #include "chrome/browser/devtools/device/android_device_manager.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12 #include "net/server/web_socket_encoder.h"
13 #include "net/socket/stream_socket.h"
15 using content::BrowserThread
;
20 const int kBufferSize
= 16 * 1024;
24 class AndroidDeviceManager::AndroidWebSocket::WebSocketImpl
{
26 WebSocketImpl(scoped_refptr
<base::MessageLoopProxy
> response_message_loop
,
27 base::WeakPtr
<AndroidWebSocket
> weak_socket
,
28 const std::string
& extensions
,
29 scoped_ptr
<net::StreamSocket
> socket
)
30 : response_message_loop_(response_message_loop
),
31 weak_socket_(weak_socket
),
32 socket_(socket
.Pass()),
33 encoder_(net::WebSocketEncoder::CreateClient(extensions
)) {
34 thread_checker_
.DetachFromThread();
37 void StartListening() {
38 DCHECK(thread_checker_
.CalledOnValidThread());
40 scoped_refptr
<net::IOBuffer
> buffer(new net::IOBuffer(kBufferSize
));
44 void SendFrame(const std::string
& message
) {
45 DCHECK(thread_checker_
.CalledOnValidThread());
48 int mask
= base::RandInt(0, 0x7FFFFFFF);
49 std::string encoded_frame
;
50 encoder_
->EncodeFrame(message
, mask
, &encoded_frame
);
51 request_buffer_
+= encoded_frame
;
52 if (request_buffer_
.length() == encoded_frame
.length())
53 SendPendingRequests(0);
57 void Read(scoped_refptr
<net::IOBuffer
> response_buffer
) {
58 int result
= socket_
->Read(
59 response_buffer
.get(),
61 base::Bind(&WebSocketImpl::OnBytesRead
,
62 base::Unretained(this), response_buffer
));
63 if (result
!= net::ERR_IO_PENDING
)
64 OnBytesRead(response_buffer
, result
);
67 void OnBytesRead(scoped_refptr
<net::IOBuffer
> response_buffer
, int result
) {
68 DCHECK(thread_checker_
.CalledOnValidThread());
73 response_buffer_
.append(response_buffer
->data(), result
);
77 WebSocket::ParseResult parse_result
= encoder_
->DecodeFrame(
78 response_buffer_
, &bytes_consumed
, &output
);
80 while (parse_result
== WebSocket::FRAME_OK
) {
81 response_buffer_
= response_buffer_
.substr(bytes_consumed
);
82 response_message_loop_
->PostTask(
84 base::Bind(&AndroidWebSocket::OnFrameRead
, weak_socket_
, output
));
85 parse_result
= encoder_
->DecodeFrame(
86 response_buffer_
, &bytes_consumed
, &output
);
89 if (parse_result
== WebSocket::FRAME_ERROR
||
90 parse_result
== WebSocket::FRAME_CLOSE
) {
94 Read(response_buffer
);
97 void SendPendingRequests(int result
) {
98 DCHECK(thread_checker_
.CalledOnValidThread());
103 request_buffer_
= request_buffer_
.substr(result
);
104 if (request_buffer_
.empty())
107 scoped_refptr
<net::StringIOBuffer
> buffer
=
108 new net::StringIOBuffer(request_buffer_
);
109 result
= socket_
->Write(buffer
.get(), buffer
->size(),
110 base::Bind(&WebSocketImpl::SendPendingRequests
,
111 base::Unretained(this)));
112 if (result
!= net::ERR_IO_PENDING
)
113 SendPendingRequests(result
);
117 DCHECK(thread_checker_
.CalledOnValidThread());
119 response_message_loop_
->PostTask(
121 base::Bind(&AndroidWebSocket::OnSocketClosed
, weak_socket_
));
124 scoped_refptr
<base::MessageLoopProxy
> response_message_loop_
;
125 base::WeakPtr
<AndroidWebSocket
> weak_socket_
;
126 scoped_ptr
<net::StreamSocket
> socket_
;
127 scoped_ptr
<net::WebSocketEncoder
> encoder_
;
128 std::string response_buffer_
;
129 std::string request_buffer_
;
130 base::ThreadChecker thread_checker_
;
131 DISALLOW_COPY_AND_ASSIGN(WebSocketImpl
);
134 AndroidDeviceManager::AndroidWebSocket::AndroidWebSocket(
135 scoped_refptr
<Device
> device
,
136 const std::string
& socket_name
,
137 const std::string
& url
,
139 : device_(device
.get()),
140 socket_impl_(nullptr),
142 weak_factory_(this) {
143 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
146 device_
->sockets_
.insert(this);
147 device_
->HttpUpgrade(
148 socket_name
, url
, net::WebSocketEncoder::kClientExtensions
,
149 base::Bind(&AndroidWebSocket::Connected
, weak_factory_
.GetWeakPtr()));
152 AndroidDeviceManager::AndroidWebSocket::~AndroidWebSocket() {
153 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
157 void AndroidDeviceManager::AndroidWebSocket::SendFrame(
158 const std::string
& message
) {
159 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
160 DCHECK(socket_impl_
);
162 device_
->message_loop_proxy_
->PostTask(
164 base::Bind(&WebSocketImpl::SendFrame
,
165 base::Unretained(socket_impl_
), message
));
168 void AndroidDeviceManager::AndroidWebSocket::Connected(
170 const std::string
& extensions
,
171 scoped_ptr
<net::StreamSocket
> socket
) {
172 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
173 if (result
!= net::OK
|| !socket
.get()) {
177 socket_impl_
= new WebSocketImpl(base::MessageLoopProxy::current(),
178 weak_factory_
.GetWeakPtr(),
181 device_
->message_loop_proxy_
->PostTask(
183 base::Bind(&WebSocketImpl::StartListening
,
184 base::Unretained(socket_impl_
)));
185 delegate_
->OnSocketOpened();
188 void AndroidDeviceManager::AndroidWebSocket::OnFrameRead(
189 const std::string
& message
) {
190 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
191 delegate_
->OnFrameRead(message
);
194 void AndroidDeviceManager::AndroidWebSocket::OnSocketClosed() {
195 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
197 delegate_
->OnSocketClosed();
200 void AndroidDeviceManager::AndroidWebSocket::Terminate() {
201 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
204 device_
->message_loop_proxy_
->DeleteSoon(FROM_HERE
, socket_impl_
);
205 socket_impl_
= nullptr;
208 device_
->sockets_
.erase(this);
213 AndroidDeviceManager::AndroidWebSocket
*
214 AndroidDeviceManager::Device::CreateWebSocket(
215 const std::string
& socket_name
,
216 const std::string
& url
,
217 AndroidWebSocket::Delegate
* delegate
) {
218 return new AndroidWebSocket(this, socket_name
, url
, delegate
);