Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/weak_ptr.h" | 5 #include "base/memory/weak_ptr.h" |
| 6 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
| 7 #include "base/rand_util.h" | 7 #include "base/rand_util.h" |
| 8 #include "chrome/browser/devtools/device/android_device_manager.h" | 8 #include "chrome/browser/devtools/device/android_device_manager.h" |
| 9 #include "content/public/browser/browser_thread.h" | 9 #include "content/public/browser/browser_thread.h" |
| 10 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
| 11 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
| 12 #include "net/server/web_socket.h" | 12 #include "net/server/web_socket.h" |
| 13 #include "net/socket/stream_socket.h" | 13 #include "net/socket/stream_socket.h" |
| 14 | 14 |
| 15 using content::BrowserThread; | 15 using content::BrowserThread; |
| 16 using net::WebSocket; | 16 using net::WebSocket; |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 const int kBufferSize = 16 * 1024; | 20 const int kBufferSize = 16 * 1024; |
| 21 | 21 |
| 22 class WebSocketImpl { | 22 } // namespace |
| 23 | |
| 24 class AndroidDeviceManager::AndroidWebSocket::WebSocketImpl { | |
| 23 public: | 25 public: |
| 24 typedef AndroidDeviceManager::AndroidWebSocket::Delegate Delegate; | 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(); | |
| 33 } | |
| 25 | 34 |
| 26 WebSocketImpl(Delegate* delegate, | 35 void StartListening() { |
| 27 scoped_ptr<net::StreamSocket> socket); | 36 DCHECK(thread_checker_.CalledOnValidThread()); |
| 28 void StartListening(); | 37 DCHECK(socket_); |
| 29 void SendFrame(const std::string& message); | 38 Read(new net::IOBuffer(kBufferSize)); |
| 39 } | |
| 40 | |
| 41 void SendFrame(const std::string& message) { | |
| 42 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 43 if (!socket_) | |
| 44 return; | |
| 45 int mask = base::RandInt(0, 0x7FFFFFFF); | |
| 46 std::string encoded_frame = WebSocket::EncodeFrameHybi17(message, mask); | |
| 47 request_buffer_ += encoded_frame; | |
| 48 if (request_buffer_.length() == encoded_frame.length()) | |
| 49 SendPendingRequests(0); | |
| 50 } | |
| 30 | 51 |
| 31 private: | 52 private: |
| 32 void OnBytesRead(scoped_refptr<net::IOBuffer> response_buffer, int result); | 53 void Read(scoped_refptr<net::IOBuffer> response_buffer) { |
| 33 void SendPendingRequests(int result); | 54 int result = socket_->Read( |
| 34 void Disconnect(); | 55 response_buffer.get(), |
| 56 kBufferSize, | |
| 57 base::Bind(&WebSocketImpl::OnBytesRead, | |
| 58 base::Unretained(this), response_buffer)); | |
| 59 if (result != net::ERR_IO_PENDING) | |
| 60 OnBytesRead(response_buffer, result); | |
| 61 } | |
| 35 | 62 |
| 36 Delegate* delegate_; | 63 void OnBytesRead(scoped_refptr<net::IOBuffer> response_buffer, int result) { |
| 64 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 65 if (result <= 0) { | |
| 66 Disconnect(); | |
| 67 return; | |
| 68 } | |
| 69 response_buffer_.append(response_buffer->data(), result); | |
| 70 | |
| 71 int bytes_consumed; | |
| 72 std::string output; | |
| 73 WebSocket::ParseResult parse_result = WebSocket::DecodeFrameHybi17( | |
| 74 response_buffer_, false, &bytes_consumed, &output); | |
| 75 | |
| 76 while (parse_result == WebSocket::FRAME_OK) { | |
| 77 response_buffer_ = response_buffer_.substr(bytes_consumed); | |
| 78 response_message_loop_->PostTask( | |
| 79 FROM_HERE, | |
| 80 base::Bind(&AndroidWebSocket::OnFrameRead, weak_socket_, output)); | |
| 81 parse_result = WebSocket::DecodeFrameHybi17( | |
| 82 response_buffer_, false, &bytes_consumed, &output); | |
| 83 } | |
| 84 | |
| 85 if (parse_result == WebSocket::FRAME_ERROR || | |
| 86 parse_result == WebSocket::FRAME_CLOSE) { | |
| 87 Disconnect(); | |
| 88 return; | |
| 89 } | |
| 90 Read(response_buffer); | |
| 91 } | |
| 92 | |
| 93 void SendPendingRequests(int result) { | |
| 94 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 95 if (result < 0) { | |
| 96 Disconnect(); | |
| 97 return; | |
| 98 } | |
| 99 request_buffer_ = request_buffer_.substr(result); | |
| 100 if (request_buffer_.empty()) | |
| 101 return; | |
| 102 | |
| 103 scoped_refptr<net::StringIOBuffer> buffer = | |
| 104 new net::StringIOBuffer(request_buffer_); | |
| 105 result = socket_->Write(buffer.get(), buffer->size(), | |
| 106 base::Bind(&WebSocketImpl::SendPendingRequests, | |
| 107 base::Unretained(this))); | |
| 108 if (result != net::ERR_IO_PENDING) | |
| 109 SendPendingRequests(result); | |
| 110 } | |
| 111 | |
| 112 void Disconnect() { | |
| 113 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 114 socket_.reset(); | |
| 115 response_message_loop_->PostTask( | |
| 116 FROM_HERE, | |
| 117 base::Bind(&AndroidWebSocket::OnSocketClosed, weak_socket_)); | |
| 118 } | |
| 119 | |
| 120 scoped_refptr<base::MessageLoopProxy> response_message_loop_; | |
| 121 base::WeakPtr<AndroidWebSocket> weak_socket_; | |
| 37 scoped_ptr<net::StreamSocket> socket_; | 122 scoped_ptr<net::StreamSocket> socket_; |
| 38 std::string response_buffer_; | 123 std::string response_buffer_; |
| 39 std::string request_buffer_; | 124 std::string request_buffer_; |
| 40 base::ThreadChecker thread_checker_; | 125 base::ThreadChecker thread_checker_; |
| 41 DISALLOW_COPY_AND_ASSIGN(WebSocketImpl); | 126 DISALLOW_COPY_AND_ASSIGN(WebSocketImpl); |
| 42 }; | 127 }; |
| 43 | 128 |
| 44 class DelegateWrapper | 129 AndroidDeviceManager::AndroidWebSocket::AndroidWebSocket( |
| 45 : public AndroidDeviceManager::AndroidWebSocket::Delegate { | |
| 46 public: | |
| 47 DelegateWrapper(base::WeakPtr<Delegate> weak_delegate, | |
| 48 scoped_refptr<base::MessageLoopProxy> message_loop) | |
| 49 : weak_delegate_(weak_delegate), | |
| 50 message_loop_(message_loop) { | |
| 51 } | |
| 52 | |
| 53 virtual ~DelegateWrapper() {} | |
| 54 | |
| 55 // AndroidWebSocket::Delegate implementation | |
| 56 virtual void OnSocketOpened() OVERRIDE { | |
| 57 message_loop_->PostTask(FROM_HERE, | |
| 58 base::Bind(&Delegate::OnSocketOpened, weak_delegate_)); | |
| 59 } | |
| 60 | |
| 61 virtual void OnFrameRead(const std::string& message) OVERRIDE { | |
| 62 message_loop_->PostTask(FROM_HERE, | |
| 63 base::Bind(&Delegate::OnFrameRead, weak_delegate_, message)); | |
| 64 } | |
| 65 | |
| 66 virtual void OnSocketClosed() OVERRIDE { | |
| 67 message_loop_->PostTask(FROM_HERE, | |
| 68 base::Bind(&Delegate::OnSocketClosed, weak_delegate_)); | |
| 69 } | |
| 70 | |
| 71 private: | |
| 72 base::WeakPtr<Delegate> weak_delegate_; | |
| 73 scoped_refptr<base::MessageLoopProxy> message_loop_; | |
| 74 }; | |
| 75 | |
| 76 class AndroidWebSocketImpl | |
| 77 : public AndroidDeviceManager::AndroidWebSocket, | |
| 78 public AndroidDeviceManager::AndroidWebSocket::Delegate { | |
| 79 public: | |
| 80 typedef AndroidDeviceManager::Device Device; | |
| 81 AndroidWebSocketImpl( | |
| 82 scoped_refptr<base::MessageLoopProxy> device_message_loop, | |
| 83 scoped_refptr<Device> device, | |
| 84 const std::string& socket_name, | |
| 85 const std::string& url, | |
| 86 AndroidWebSocket::Delegate* delegate); | |
| 87 | |
| 88 virtual ~AndroidWebSocketImpl(); | |
| 89 | |
| 90 // AndroidWebSocket implementation | |
| 91 virtual void SendFrame(const std::string& message) OVERRIDE; | |
| 92 | |
| 93 // AndroidWebSocket::Delegate implementation | |
| 94 virtual void OnSocketOpened() OVERRIDE; | |
| 95 virtual void OnFrameRead(const std::string& message) OVERRIDE; | |
| 96 virtual void OnSocketClosed() OVERRIDE; | |
| 97 | |
| 98 private: | |
| 99 void Connected(int result, scoped_ptr<net::StreamSocket> socket); | |
| 100 | |
| 101 scoped_refptr<base::MessageLoopProxy> device_message_loop_; | |
| 102 scoped_refptr<Device> device_; | |
| 103 std::string socket_name_; | |
| 104 std::string url_; | |
| 105 WebSocketImpl* connection_; | |
| 106 DelegateWrapper* delegate_wrapper_; | |
| 107 AndroidWebSocket::Delegate* delegate_; | |
| 108 base::WeakPtrFactory<AndroidWebSocketImpl> weak_factory_; | |
| 109 DISALLOW_COPY_AND_ASSIGN(AndroidWebSocketImpl); | |
| 110 }; | |
| 111 | |
| 112 AndroidWebSocketImpl::AndroidWebSocketImpl( | |
| 113 scoped_refptr<base::MessageLoopProxy> device_message_loop, | |
| 114 scoped_refptr<Device> device, | 130 scoped_refptr<Device> device, |
| 115 const std::string& socket_name, | 131 const std::string& socket_name, |
| 116 const std::string& url, | 132 const std::string& url, |
| 117 AndroidWebSocket::Delegate* delegate) | 133 Delegate* delegate) |
| 118 : device_message_loop_(device_message_loop), | 134 : device_(device), |
| 119 device_(device), | |
| 120 socket_name_(socket_name), | |
| 121 url_(url), | 135 url_(url), |
| 122 delegate_(delegate), | 136 delegate_(delegate), |
| 123 weak_factory_(this) { | 137 weak_factory_(this) { |
|
dgozman
2014/10/03 19:25:17
socket_impl_(nullptr)
vkuzkokov
2014/10/06 14:31:43
Done.
| |
| 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 125 DCHECK(delegate_); | 139 DCHECK(delegate_); |
| 126 device_->HttpUpgrade( | 140 device_->HttpUpgrade( |
| 127 socket_name_, url_, | 141 socket_name, url_, |
| 128 base::Bind(&AndroidWebSocketImpl::Connected, weak_factory_.GetWeakPtr())); | 142 base::Bind(&AndroidWebSocket::Connected, weak_factory_.GetWeakPtr())); |
| 129 } | 143 } |
| 130 | 144 |
| 131 void AndroidWebSocketImpl::SendFrame(const std::string& message) { | 145 AndroidDeviceManager::AndroidWebSocket::~AndroidWebSocket() { |
| 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 133 device_message_loop_->PostTask( | 147 device_->device_message_loop_->DeleteSoon(FROM_HERE, socket_impl_); |
|
dgozman
2014/10/03 19:25:16
if (socket_impl_)
...
vkuzkokov
2014/10/06 14:31:43
Done.
| |
| 148 } | |
| 149 | |
| 150 void AndroidDeviceManager::AndroidWebSocket::SendFrame( | |
| 151 const std::string& message) { | |
| 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 153 device_->device_message_loop_->PostTask( | |
|
dgozman
2014/10/03 19:25:17
DCHECK(socket_impl_)
vkuzkokov
2014/10/06 14:31:43
Done.
| |
| 134 FROM_HERE, | 154 FROM_HERE, |
| 135 base::Bind(&WebSocketImpl::SendFrame, | 155 base::Bind(&WebSocketImpl::SendFrame, |
| 136 base::Unretained(connection_), message)); | 156 base::Unretained(socket_impl_), message)); |
| 137 } | 157 } |
| 138 | 158 |
| 139 void WebSocketImpl::SendFrame(const std::string& message) { | 159 void AndroidDeviceManager::AndroidWebSocket::Connected( |
| 140 DCHECK(thread_checker_.CalledOnValidThread()); | 160 int result, |
| 141 if (!socket_) | 161 scoped_ptr<net::StreamSocket> socket) { |
| 142 return; | |
| 143 int mask = base::RandInt(0, 0x7FFFFFFF); | |
| 144 std::string encoded_frame = WebSocket::EncodeFrameHybi17(message, mask); | |
| 145 request_buffer_ += encoded_frame; | |
| 146 if (request_buffer_.length() == encoded_frame.length()) | |
| 147 SendPendingRequests(0); | |
| 148 } | |
| 149 | |
| 150 AndroidWebSocketImpl::~AndroidWebSocketImpl() { | |
| 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 152 device_message_loop_->DeleteSoon(FROM_HERE, connection_); | |
| 153 device_message_loop_->DeleteSoon(FROM_HERE, delegate_wrapper_); | |
| 154 } | |
| 155 | |
| 156 WebSocketImpl::WebSocketImpl(Delegate* delegate, | |
| 157 scoped_ptr<net::StreamSocket> socket) | |
| 158 : delegate_(delegate), | |
| 159 socket_(socket.Pass()) { | |
| 160 thread_checker_.DetachFromThread(); | |
| 161 } | |
| 162 | |
| 163 void AndroidWebSocketImpl::Connected(int result, | |
| 164 scoped_ptr<net::StreamSocket> socket) { | |
| 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 166 if (result != net::OK || socket == NULL) { | 163 if (result != net::OK || socket == NULL) { |
| 167 OnSocketClosed(); | 164 OnSocketClosed(); |
| 168 return; | 165 return; |
| 169 } | 166 } |
| 170 delegate_wrapper_ = new DelegateWrapper(weak_factory_.GetWeakPtr(), | 167 socket_impl_ = new WebSocketImpl(base::MessageLoopProxy::current(), |
| 171 base::MessageLoopProxy::current()); | 168 weak_factory_.GetWeakPtr(), |
| 172 connection_ = new WebSocketImpl(delegate_wrapper_, socket.Pass()); | 169 socket.Pass()); |
| 173 device_message_loop_->PostTask( | 170 device_->device_message_loop_->PostTask( |
| 174 FROM_HERE, | 171 FROM_HERE, |
| 175 base::Bind(&WebSocketImpl::StartListening, | 172 base::Bind(&WebSocketImpl::StartListening, |
| 176 base::Unretained(connection_))); | 173 base::Unretained(socket_impl_))); |
| 177 OnSocketOpened(); | |
| 178 } | |
| 179 | |
| 180 void WebSocketImpl::StartListening() { | |
| 181 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 182 DCHECK(socket_); | |
| 183 scoped_refptr<net::IOBuffer> response_buffer = | |
| 184 new net::IOBuffer(kBufferSize); | |
| 185 int result = socket_->Read( | |
| 186 response_buffer.get(), | |
| 187 kBufferSize, | |
| 188 base::Bind(&WebSocketImpl::OnBytesRead, | |
| 189 base::Unretained(this), response_buffer)); | |
| 190 if (result != net::ERR_IO_PENDING) | |
| 191 OnBytesRead(response_buffer, result); | |
| 192 } | |
| 193 | |
| 194 void WebSocketImpl::OnBytesRead(scoped_refptr<net::IOBuffer> response_buffer, | |
| 195 int result) { | |
| 196 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 197 if (result <= 0) { | |
| 198 Disconnect(); | |
| 199 return; | |
| 200 } | |
| 201 | |
| 202 response_buffer_.append(response_buffer->data(), result); | |
| 203 | |
| 204 int bytes_consumed; | |
| 205 std::string output; | |
| 206 WebSocket::ParseResult parse_result = WebSocket::DecodeFrameHybi17( | |
| 207 response_buffer_, false, &bytes_consumed, &output); | |
| 208 | |
| 209 while (parse_result == WebSocket::FRAME_OK) { | |
| 210 response_buffer_ = response_buffer_.substr(bytes_consumed); | |
| 211 delegate_->OnFrameRead(output); | |
| 212 parse_result = WebSocket::DecodeFrameHybi17( | |
| 213 response_buffer_, false, &bytes_consumed, &output); | |
| 214 } | |
| 215 | |
| 216 if (parse_result == WebSocket::FRAME_ERROR || | |
| 217 parse_result == WebSocket::FRAME_CLOSE) { | |
| 218 Disconnect(); | |
| 219 return; | |
| 220 } | |
| 221 | |
| 222 result = socket_->Read( | |
| 223 response_buffer.get(), | |
| 224 kBufferSize, | |
| 225 base::Bind(&WebSocketImpl::OnBytesRead, | |
| 226 base::Unretained(this), response_buffer)); | |
| 227 if (result != net::ERR_IO_PENDING) | |
| 228 OnBytesRead(response_buffer, result); | |
| 229 } | |
| 230 | |
| 231 void WebSocketImpl::SendPendingRequests(int result) { | |
| 232 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 233 if (result < 0) { | |
| 234 Disconnect(); | |
| 235 return; | |
| 236 } | |
| 237 request_buffer_ = request_buffer_.substr(result); | |
| 238 if (request_buffer_.empty()) | |
| 239 return; | |
| 240 | |
| 241 scoped_refptr<net::StringIOBuffer> buffer = | |
| 242 new net::StringIOBuffer(request_buffer_); | |
| 243 result = socket_->Write(buffer.get(), buffer->size(), | |
| 244 base::Bind(&WebSocketImpl::SendPendingRequests, | |
| 245 base::Unretained(this))); | |
| 246 if (result != net::ERR_IO_PENDING) | |
| 247 SendPendingRequests(result); | |
| 248 } | |
| 249 | |
| 250 void WebSocketImpl::Disconnect() { | |
| 251 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 252 socket_.reset(); | |
| 253 delegate_->OnSocketClosed(); | |
| 254 } | |
| 255 | |
| 256 void AndroidWebSocketImpl::OnSocketOpened() { | |
| 257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 258 delegate_->OnSocketOpened(); | 174 delegate_->OnSocketOpened(); |
| 259 } | 175 } |
| 260 | 176 |
| 261 void AndroidWebSocketImpl::OnFrameRead(const std::string& message) { | 177 void AndroidDeviceManager::AndroidWebSocket::OnFrameRead( |
| 178 const std::string& message) { | |
| 262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 263 delegate_->OnFrameRead(message); | 180 delegate_->OnFrameRead(message); |
| 264 } | 181 } |
| 265 | 182 |
| 266 void AndroidWebSocketImpl::OnSocketClosed() { | 183 void AndroidDeviceManager::AndroidWebSocket::OnSocketClosed() { |
| 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 268 delegate_->OnSocketClosed(); | 185 delegate_->OnSocketClosed(); |
| 269 } | 186 } |
| 270 | 187 |
| 271 } // namespace | |
| 272 | |
| 273 AndroidDeviceManager::AndroidWebSocket* | 188 AndroidDeviceManager::AndroidWebSocket* |
| 274 AndroidDeviceManager::Device::CreateWebSocket( | 189 AndroidDeviceManager::Device::CreateWebSocket( |
|
dgozman
2014/10/03 19:25:17
What if you make AndroidWebSocket::Create(device,
vkuzkokov
2014/10/06 14:31:44
Friend declarations will still be needed, especial
| |
| 275 const std::string& socket, | 190 const std::string& socket, |
| 276 const std::string& url, | 191 const std::string& url, |
| 277 AndroidDeviceManager::AndroidWebSocket::Delegate* delegate) { | 192 AndroidWebSocket::Delegate* delegate) { |
| 278 return new AndroidWebSocketImpl( | 193 return new AndroidWebSocket(this, socket, url, delegate); |
| 279 device_message_loop_, this, socket, url, delegate); | |
| 280 } | 194 } |
| OLD | NEW |