Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / devtools / adb_web_socket.cc
blobb31c7220c3ac6e44738606b566549e63e72f686d
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.
5 #include "chrome/browser/devtools/adb_web_socket.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/rand_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "net/base/net_errors.h"
12 #include "net/server/web_socket.h"
14 using content::BrowserThread;
15 using net::WebSocket;
17 const int kBufferSize = 16 * 1024;
19 static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n"
20 "Upgrade: WebSocket\r\n"
21 "Connection: Upgrade\r\n"
22 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
23 "Sec-WebSocket-Version: 13\r\n"
24 "\r\n";
26 AdbWebSocket::AdbWebSocket(
27 scoped_refptr<AndroidDevice> device,
28 const std::string& socket_name,
29 const std::string& url,
30 base::MessageLoop* adb_message_loop,
31 Delegate* delegate)
32 : device_(device),
33 socket_name_(socket_name),
34 url_(url),
35 adb_message_loop_(adb_message_loop),
36 delegate_(delegate) {
37 adb_message_loop_->PostTask(
38 FROM_HERE, base::Bind(&AdbWebSocket::ConnectOnHandlerThread, this));
41 void AdbWebSocket::Disconnect() {
42 adb_message_loop_->PostTask(
43 FROM_HERE,
44 base::Bind(&AdbWebSocket::DisconnectOnHandlerThread, this, false));
45 adb_message_loop_ = NULL;
48 void AdbWebSocket::SendFrame(const std::string& message) {
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
50 adb_message_loop_->PostTask(
51 FROM_HERE,
52 base::Bind(&AdbWebSocket::SendFrameOnHandlerThread, this, message));
55 void AdbWebSocket::SendFrameOnHandlerThread(const std::string& message) {
56 int mask = base::RandInt(0, 0x7FFFFFFF);
57 std::string encoded_frame = WebSocket::EncodeFrameHybi17(message, mask);
58 request_buffer_ += encoded_frame;
59 if (request_buffer_.length() == encoded_frame.length())
60 SendPendingRequests(0);
63 AdbWebSocket::~AdbWebSocket() {}
65 void AdbWebSocket::ConnectOnHandlerThread() {
66 device_->HttpUpgrade(
67 socket_name_,
68 base::StringPrintf(kWebSocketUpgradeRequest, url_.c_str()),
69 base::Bind(&AdbWebSocket::ConnectedOnHandlerThread, this));
72 void AdbWebSocket::ConnectedOnHandlerThread(
73 int result, net::StreamSocket* socket) {
74 if (result != net::OK || socket == NULL) {
75 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
76 base::Bind(&AdbWebSocket::OnSocketClosed, this, true));
77 return;
79 socket_.reset(socket);
80 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
81 base::Bind(&AdbWebSocket::OnSocketOpened, this));
82 StartListeningOnHandlerThread();
85 void AdbWebSocket::StartListeningOnHandlerThread() {
86 scoped_refptr<net::IOBuffer> response_buffer =
87 new net::IOBuffer(kBufferSize);
88 int result = socket_->Read(
89 response_buffer.get(),
90 kBufferSize,
91 base::Bind(&AdbWebSocket::OnBytesRead, this, response_buffer));
92 if (result != net::ERR_IO_PENDING)
93 OnBytesRead(response_buffer, result);
96 void AdbWebSocket::OnBytesRead(
97 scoped_refptr<net::IOBuffer> response_buffer, int result) {
98 if (!socket_)
99 return;
101 if (result <= 0) {
102 DisconnectOnHandlerThread(true);
103 return;
106 std::string data = std::string(response_buffer->data(), result);
107 response_buffer_ += data;
109 int bytes_consumed;
110 std::string output;
111 WebSocket::ParseResult parse_result = WebSocket::DecodeFrameHybi17(
112 response_buffer_, false, &bytes_consumed, &output);
114 while (parse_result == WebSocket::FRAME_OK) {
115 response_buffer_ = response_buffer_.substr(bytes_consumed);
116 if (!delegate_ || !delegate_->ProcessIncomingMessage(output)) {
117 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
118 base::Bind(&AdbWebSocket::OnFrameRead, this, output));
120 parse_result = WebSocket::DecodeFrameHybi17(
121 response_buffer_, false, &bytes_consumed, &output);
124 if (parse_result == WebSocket::FRAME_ERROR ||
125 parse_result == WebSocket::FRAME_CLOSE) {
126 DisconnectOnHandlerThread(true);
127 return;
130 result = socket_->Read(
131 response_buffer.get(),
132 kBufferSize,
133 base::Bind(&AdbWebSocket::OnBytesRead, this, response_buffer));
134 if (result != net::ERR_IO_PENDING)
135 OnBytesRead(response_buffer, result);
138 void AdbWebSocket::SendPendingRequests(int result) {
139 if (!socket_)
140 return;
141 if (result < 0) {
142 DisconnectOnHandlerThread(true);
143 return;
145 request_buffer_ = request_buffer_.substr(result);
146 if (request_buffer_.empty())
147 return;
149 scoped_refptr<net::StringIOBuffer> buffer =
150 new net::StringIOBuffer(request_buffer_);
151 result = socket_->Write(buffer.get(), buffer->size(),
152 base::Bind(&AdbWebSocket::SendPendingRequests,
153 this));
154 if (result != net::ERR_IO_PENDING)
155 SendPendingRequests(result);
158 void AdbWebSocket::DisconnectOnHandlerThread(bool closed_by_device) {
159 if (!socket_)
160 return;
161 // Wipe out socket_ first since Disconnect can re-enter this method.
162 scoped_ptr<net::StreamSocket> socket(socket_.release());
163 socket->Disconnect();
164 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
165 base::Bind(&AdbWebSocket::OnSocketClosed, this, closed_by_device));
168 void AdbWebSocket::OnSocketOpened() {
169 delegate_->OnSocketOpened();
172 void AdbWebSocket::OnFrameRead(const std::string& message) {
173 delegate_->OnFrameRead(message);
176 void AdbWebSocket::OnSocketClosed(bool closed_by_device) {
177 delegate_->OnSocketClosed(closed_by_device);