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/message_loop/message_loop.h"
6 #include "base/rand_util.h"
7 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "net/server/web_socket.h"
12 #include "net/socket/stream_socket.h"
14 using content::BrowserThread;
19 const int kBufferSize = 16 * 1024;
21 class WebSocketImpl : public DevToolsAndroidBridge::AndroidWebSocket {
23 WebSocketImpl(scoped_refptr<DevToolsAndroidBridge> android_bridge,
24 AndroidDeviceManager* device_manager,
25 base::MessageLoop* device_message_loop,
26 const std::string& serial,
27 const std::string& socket_name,
28 const std::string& url,
31 virtual void Connect() OVERRIDE;
32 virtual void Disconnect() OVERRIDE;
34 virtual void SendFrame(const std::string& message) OVERRIDE;
37 friend class base::RefCountedThreadSafe<AndroidWebSocket>;
39 virtual ~WebSocketImpl();
41 void ConnectOnHandlerThread();
42 void ConnectedOnHandlerThread(int result, net::StreamSocket* socket);
43 void StartListeningOnHandlerThread();
44 void OnBytesRead(scoped_refptr<net::IOBuffer> response_buffer, int result);
45 void SendFrameOnHandlerThread(const std::string& message);
46 void SendPendingRequests(int result);
47 void DisconnectOnHandlerThread(bool closed_by_device);
49 void OnSocketOpened();
50 void OnFrameRead(const std::string& message);
51 void OnSocketClosed(bool closed_by_device);
53 scoped_refptr<DevToolsAndroidBridge> android_bridge_;
54 AndroidDeviceManager* device_manager_;
55 base::MessageLoop* device_message_loop_;
57 std::string socket_name_;
59 scoped_ptr<net::StreamSocket> socket_;
61 std::string response_buffer_;
62 std::string request_buffer_;
65 WebSocketImpl::WebSocketImpl(
66 scoped_refptr<DevToolsAndroidBridge> android_bridge,
67 AndroidDeviceManager* device_manager,
68 base::MessageLoop* device_message_loop,
69 const std::string& serial,
70 const std::string& socket_name,
71 const std::string& url,
73 : android_bridge_(android_bridge),
74 device_manager_(device_manager),
75 device_message_loop_(device_message_loop),
77 socket_name_(socket_name),
82 void WebSocketImpl::Connect() {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
84 device_message_loop_->PostTask(
85 FROM_HERE, base::Bind(&WebSocketImpl::ConnectOnHandlerThread, this));
88 void WebSocketImpl::Disconnect() {
89 device_message_loop_->PostTask(
91 base::Bind(&WebSocketImpl::DisconnectOnHandlerThread, this, false));
94 void WebSocketImpl::SendFrame(const std::string& message) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
96 device_message_loop_->PostTask(
98 base::Bind(&WebSocketImpl::SendFrameOnHandlerThread, this, message));
101 void WebSocketImpl::SendFrameOnHandlerThread(const std::string& message) {
102 int mask = base::RandInt(0, 0x7FFFFFFF);
103 std::string encoded_frame = WebSocket::EncodeFrameHybi17(message, mask);
104 request_buffer_ += encoded_frame;
105 if (request_buffer_.length() == encoded_frame.length())
106 SendPendingRequests(0);
109 WebSocketImpl::~WebSocketImpl() {}
111 void WebSocketImpl::ConnectOnHandlerThread() {
112 device_manager_->HttpUpgrade(
116 base::Bind(&WebSocketImpl::ConnectedOnHandlerThread, this));
119 void WebSocketImpl::ConnectedOnHandlerThread(
120 int result, net::StreamSocket* socket) {
121 if (result != net::OK || socket == NULL) {
122 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
123 base::Bind(&WebSocketImpl::OnSocketClosed, this, true));
126 socket_.reset(socket);
127 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
128 base::Bind(&WebSocketImpl::OnSocketOpened, this));
129 StartListeningOnHandlerThread();
132 void WebSocketImpl::StartListeningOnHandlerThread() {
133 scoped_refptr<net::IOBuffer> response_buffer =
134 new net::IOBuffer(kBufferSize);
135 int result = socket_->Read(
136 response_buffer.get(),
138 base::Bind(&WebSocketImpl::OnBytesRead, this, response_buffer));
139 if (result != net::ERR_IO_PENDING)
140 OnBytesRead(response_buffer, result);
143 void WebSocketImpl::OnBytesRead(
144 scoped_refptr<net::IOBuffer> response_buffer, int result) {
149 DisconnectOnHandlerThread(true);
153 std::string data = std::string(response_buffer->data(), result);
154 response_buffer_ += data;
158 WebSocket::ParseResult parse_result = WebSocket::DecodeFrameHybi17(
159 response_buffer_, false, &bytes_consumed, &output);
161 while (parse_result == WebSocket::FRAME_OK) {
162 response_buffer_ = response_buffer_.substr(bytes_consumed);
163 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
164 base::Bind(&WebSocketImpl::OnFrameRead, this, output));
165 parse_result = WebSocket::DecodeFrameHybi17(
166 response_buffer_, false, &bytes_consumed, &output);
169 if (parse_result == WebSocket::FRAME_ERROR ||
170 parse_result == WebSocket::FRAME_CLOSE) {
171 DisconnectOnHandlerThread(true);
175 result = socket_->Read(
176 response_buffer.get(),
178 base::Bind(&WebSocketImpl::OnBytesRead, this, response_buffer));
179 if (result != net::ERR_IO_PENDING)
180 OnBytesRead(response_buffer, result);
183 void WebSocketImpl::SendPendingRequests(int result) {
187 DisconnectOnHandlerThread(true);
190 request_buffer_ = request_buffer_.substr(result);
191 if (request_buffer_.empty())
194 scoped_refptr<net::StringIOBuffer> buffer =
195 new net::StringIOBuffer(request_buffer_);
196 result = socket_->Write(buffer.get(), buffer->size(),
197 base::Bind(&WebSocketImpl::SendPendingRequests,
199 if (result != net::ERR_IO_PENDING)
200 SendPendingRequests(result);
203 void WebSocketImpl::DisconnectOnHandlerThread(bool closed_by_device) {
206 // Wipe out socket_ first since Disconnect can re-enter this method.
207 scoped_ptr<net::StreamSocket> socket(socket_.release());
208 socket->Disconnect();
209 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
210 base::Bind(&WebSocketImpl::OnSocketClosed, this, closed_by_device));
213 void WebSocketImpl::OnSocketOpened() {
214 delegate_->OnSocketOpened();
217 void WebSocketImpl::OnFrameRead(const std::string& message) {
218 delegate_->OnFrameRead(message);
221 void WebSocketImpl::OnSocketClosed(bool closed_by_device) {
222 delegate_->OnSocketClosed(closed_by_device);
227 scoped_refptr<DevToolsAndroidBridge::AndroidWebSocket>
228 DevToolsAndroidBridge::RemoteBrowser::CreateWebSocket(
229 const std::string& url,
230 DevToolsAndroidBridge::AndroidWebSocket::Delegate* delegate) {
231 return new WebSocketImpl(
233 android_bridge_->device_manager(),
234 android_bridge_->device_message_loop(),
235 serial_, socket_, url, delegate);