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.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 scoped_ptr<net::StreamSocket> socket)
29 : response_message_loop_(response_message_loop),
30 weak_socket_(weak_socket),
31 socket_(socket.Pass()) {
32 thread_checker_.DetachFromThread();
35 void StartListening() {
36 DCHECK(thread_checker_.CalledOnValidThread());
38 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
42 void SendFrame(const std::string& message) {
43 DCHECK(thread_checker_.CalledOnValidThread());
46 int mask = base::RandInt(0, 0x7FFFFFFF);
47 std::string encoded_frame = WebSocket::EncodeFrameHybi17(message, mask);
48 request_buffer_ += encoded_frame;
49 if (request_buffer_.length() == encoded_frame.length())
50 SendPendingRequests(0);
54 void Read(scoped_refptr<net::IOBuffer> response_buffer) {
55 int result = socket_->Read(
56 response_buffer.get(),
58 base::Bind(&WebSocketImpl::OnBytesRead,
59 base::Unretained(this), response_buffer));
60 if (result != net::ERR_IO_PENDING)
61 OnBytesRead(response_buffer, result);
64 void OnBytesRead(scoped_refptr<net::IOBuffer> response_buffer, int result) {
65 DCHECK(thread_checker_.CalledOnValidThread());
70 response_buffer_.append(response_buffer->data(), result);
74 WebSocket::ParseResult parse_result = WebSocket::DecodeFrameHybi17(
75 response_buffer_, false, &bytes_consumed, &output);
77 while (parse_result == WebSocket::FRAME_OK) {
78 response_buffer_ = response_buffer_.substr(bytes_consumed);
79 response_message_loop_->PostTask(
81 base::Bind(&AndroidWebSocket::OnFrameRead, weak_socket_, output));
82 parse_result = WebSocket::DecodeFrameHybi17(
83 response_buffer_, false, &bytes_consumed, &output);
86 if (parse_result == WebSocket::FRAME_ERROR ||
87 parse_result == WebSocket::FRAME_CLOSE) {
91 Read(response_buffer);
94 void SendPendingRequests(int result) {
95 DCHECK(thread_checker_.CalledOnValidThread());
100 request_buffer_ = request_buffer_.substr(result);
101 if (request_buffer_.empty())
104 scoped_refptr<net::StringIOBuffer> buffer =
105 new net::StringIOBuffer(request_buffer_);
106 result = socket_->Write(buffer.get(), buffer->size(),
107 base::Bind(&WebSocketImpl::SendPendingRequests,
108 base::Unretained(this)));
109 if (result != net::ERR_IO_PENDING)
110 SendPendingRequests(result);
114 DCHECK(thread_checker_.CalledOnValidThread());
116 response_message_loop_->PostTask(
118 base::Bind(&AndroidWebSocket::OnSocketClosed, weak_socket_));
121 scoped_refptr<base::MessageLoopProxy> response_message_loop_;
122 base::WeakPtr<AndroidWebSocket> weak_socket_;
123 scoped_ptr<net::StreamSocket> socket_;
124 std::string response_buffer_;
125 std::string request_buffer_;
126 base::ThreadChecker thread_checker_;
127 DISALLOW_COPY_AND_ASSIGN(WebSocketImpl);
130 AndroidDeviceManager::AndroidWebSocket::AndroidWebSocket(
131 scoped_refptr<Device> device,
132 const std::string& socket_name,
133 const std::string& url,
135 : device_(device.get()),
136 socket_impl_(nullptr),
138 weak_factory_(this) {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
142 device_->sockets_.insert(this);
143 device_->HttpUpgrade(
145 base::Bind(&AndroidWebSocket::Connected, weak_factory_.GetWeakPtr()));
148 AndroidDeviceManager::AndroidWebSocket::~AndroidWebSocket() {
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
153 void AndroidDeviceManager::AndroidWebSocket::SendFrame(
154 const std::string& message) {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156 DCHECK(socket_impl_);
158 device_->message_loop_proxy_->PostTask(
160 base::Bind(&WebSocketImpl::SendFrame,
161 base::Unretained(socket_impl_), message));
164 void AndroidDeviceManager::AndroidWebSocket::Connected(
166 scoped_ptr<net::StreamSocket> socket) {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168 if (result != net::OK || !socket.get()) {
172 socket_impl_ = new WebSocketImpl(base::MessageLoopProxy::current(),
173 weak_factory_.GetWeakPtr(),
175 device_->message_loop_proxy_->PostTask(
177 base::Bind(&WebSocketImpl::StartListening,
178 base::Unretained(socket_impl_)));
179 delegate_->OnSocketOpened();
182 void AndroidDeviceManager::AndroidWebSocket::OnFrameRead(
183 const std::string& message) {
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
185 delegate_->OnFrameRead(message);
188 void AndroidDeviceManager::AndroidWebSocket::OnSocketClosed() {
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191 delegate_->OnSocketClosed();
194 void AndroidDeviceManager::AndroidWebSocket::Terminate() {
195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198 device_->message_loop_proxy_->DeleteSoon(FROM_HERE, socket_impl_);
199 socket_impl_ = nullptr;
202 device_->sockets_.erase(this);
207 AndroidDeviceManager::AndroidWebSocket*
208 AndroidDeviceManager::Device::CreateWebSocket(
209 const std::string& socket_name,
210 const std::string& url,
211 AndroidWebSocket::Delegate* delegate) {
212 return new AndroidWebSocket(this, socket_name, url, delegate);