Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / devtools / device / android_web_socket.cc
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.
4
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"
14
15 using content::BrowserThread;
16 using net::WebSocket;
17
18 namespace {
19
20 const int kBufferSize = 16 * 1024;
21
22 }  // namespace
23
24 class AndroidDeviceManager::AndroidWebSocket::WebSocketImpl {
25  public:
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   }
34
35   void StartListening() {
36     DCHECK(thread_checker_.CalledOnValidThread());
37     DCHECK(socket_);
38     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
39     Read(buffer);
40   }
41
42   void SendFrame(const std::string& message) {
43     DCHECK(thread_checker_.CalledOnValidThread());
44     if (!socket_)
45       return;
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);
51   }
52
53  private:
54   void Read(scoped_refptr<net::IOBuffer> response_buffer) {
55     int result = socket_->Read(
56         response_buffer.get(),
57         kBufferSize,
58         base::Bind(&WebSocketImpl::OnBytesRead,
59                    base::Unretained(this), response_buffer));
60     if (result != net::ERR_IO_PENDING)
61       OnBytesRead(response_buffer, result);
62   }
63
64   void OnBytesRead(scoped_refptr<net::IOBuffer> response_buffer, int result) {
65     DCHECK(thread_checker_.CalledOnValidThread());
66     if (result <= 0) {
67       Disconnect();
68       return;
69     }
70     response_buffer_.append(response_buffer->data(), result);
71
72     int bytes_consumed;
73     std::string output;
74     WebSocket::ParseResult parse_result = WebSocket::DecodeFrameHybi17(
75         response_buffer_, false, &bytes_consumed, &output);
76
77     while (parse_result == WebSocket::FRAME_OK) {
78       response_buffer_ = response_buffer_.substr(bytes_consumed);
79       response_message_loop_->PostTask(
80           FROM_HERE,
81           base::Bind(&AndroidWebSocket::OnFrameRead, weak_socket_, output));
82       parse_result = WebSocket::DecodeFrameHybi17(
83           response_buffer_, false, &bytes_consumed, &output);
84     }
85
86     if (parse_result == WebSocket::FRAME_ERROR ||
87         parse_result == WebSocket::FRAME_CLOSE) {
88       Disconnect();
89       return;
90     }
91     Read(response_buffer);
92   }
93
94   void SendPendingRequests(int result) {
95     DCHECK(thread_checker_.CalledOnValidThread());
96     if (result < 0) {
97       Disconnect();
98       return;
99     }
100     request_buffer_ = request_buffer_.substr(result);
101     if (request_buffer_.empty())
102       return;
103
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);
111   }
112
113   void Disconnect() {
114     DCHECK(thread_checker_.CalledOnValidThread());
115     socket_.reset();
116     response_message_loop_->PostTask(
117         FROM_HERE,
118         base::Bind(&AndroidWebSocket::OnSocketClosed, weak_socket_));
119   }
120
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);
128 };
129
130 AndroidDeviceManager::AndroidWebSocket::AndroidWebSocket(
131     scoped_refptr<Device> device,
132     const std::string& socket_name,
133     const std::string& url,
134     Delegate* delegate)
135     : device_(device.get()),
136       socket_impl_(nullptr),
137       delegate_(delegate),
138       weak_factory_(this) {
139   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140   DCHECK(delegate_);
141   DCHECK(device_);
142   device_->sockets_.insert(this);
143   device_->HttpUpgrade(
144       socket_name, url,
145       base::Bind(&AndroidWebSocket::Connected, weak_factory_.GetWeakPtr()));
146 }
147
148 AndroidDeviceManager::AndroidWebSocket::~AndroidWebSocket() {
149   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
150   Terminate();
151 }
152
153 void AndroidDeviceManager::AndroidWebSocket::SendFrame(
154     const std::string& message) {
155   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156   DCHECK(socket_impl_);
157   DCHECK(device_);
158   device_->message_loop_proxy_->PostTask(
159       FROM_HERE,
160       base::Bind(&WebSocketImpl::SendFrame,
161                  base::Unretained(socket_impl_), message));
162 }
163
164 void AndroidDeviceManager::AndroidWebSocket::Connected(
165     int result,
166     scoped_ptr<net::StreamSocket> socket) {
167   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168   if (result != net::OK || !socket.get()) {
169     OnSocketClosed();
170     return;
171   }
172   socket_impl_ = new WebSocketImpl(base::MessageLoopProxy::current(),
173                                    weak_factory_.GetWeakPtr(),
174                                    socket.Pass());
175   device_->message_loop_proxy_->PostTask(
176       FROM_HERE,
177       base::Bind(&WebSocketImpl::StartListening,
178                  base::Unretained(socket_impl_)));
179   delegate_->OnSocketOpened();
180 }
181
182 void AndroidDeviceManager::AndroidWebSocket::OnFrameRead(
183     const std::string& message) {
184   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
185   delegate_->OnFrameRead(message);
186 }
187
188 void AndroidDeviceManager::AndroidWebSocket::OnSocketClosed() {
189   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
190   Terminate();
191   delegate_->OnSocketClosed();
192 }
193
194 void AndroidDeviceManager::AndroidWebSocket::Terminate() {
195   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
196   if (socket_impl_) {
197     DCHECK(device_);
198     device_->message_loop_proxy_->DeleteSoon(FROM_HERE, socket_impl_);
199     socket_impl_ = nullptr;
200   }
201   if (device_) {
202     device_->sockets_.erase(this);
203     device_ = nullptr;
204   }
205 }
206
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);
213 }