Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / mojo / services / network / web_socket_impl.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 "mojo/services/network/web_socket_impl.h"
6
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h"
9 #include "mojo/common/handle_watcher.h"
10 #include "mojo/services/network/network_context.h"
11 #include "mojo/services/public/cpp/network/web_socket_read_queue.h"
12 #include "mojo/services/public/cpp/network/web_socket_write_queue.h"
13 #include "net/websockets/websocket_channel.h"
14 #include "net/websockets/websocket_errors.h"
15 #include "net/websockets/websocket_event_interface.h"
16 #include "net/websockets/websocket_frame.h"  // for WebSocketFrameHeader::OpCode
17 #include "net/websockets/websocket_handshake_request_info.h"
18 #include "net/websockets/websocket_handshake_response_info.h"
19 #include "url/origin.h"
20
21 namespace mojo {
22
23 template <>
24 struct TypeConverter<net::WebSocketFrameHeader::OpCode,
25                      WebSocket::MessageType> {
26   static net::WebSocketFrameHeader::OpCode Convert(
27       WebSocket::MessageType type) {
28     DCHECK(type == WebSocket::MESSAGE_TYPE_CONTINUATION ||
29            type == WebSocket::MESSAGE_TYPE_TEXT ||
30            type == WebSocket::MESSAGE_TYPE_BINARY);
31     typedef net::WebSocketFrameHeader::OpCode OpCode;
32     // These compile asserts verify that the same underlying values are used for
33     // both types, so we can simply cast between them.
34     COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_CONTINUATION) ==
35                        net::WebSocketFrameHeader::kOpCodeContinuation,
36                    enum_values_must_match_for_opcode_continuation);
37     COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_TEXT) ==
38                        net::WebSocketFrameHeader::kOpCodeText,
39                    enum_values_must_match_for_opcode_text);
40     COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_BINARY) ==
41                        net::WebSocketFrameHeader::kOpCodeBinary,
42                    enum_values_must_match_for_opcode_binary);
43     return static_cast<OpCode>(type);
44   }
45 };
46
47 template <>
48 struct TypeConverter<WebSocket::MessageType,
49                      net::WebSocketFrameHeader::OpCode> {
50   static WebSocket::MessageType Convert(
51       net::WebSocketFrameHeader::OpCode type) {
52     DCHECK(type == net::WebSocketFrameHeader::kOpCodeContinuation ||
53            type == net::WebSocketFrameHeader::kOpCodeText ||
54            type == net::WebSocketFrameHeader::kOpCodeBinary);
55     return static_cast<WebSocket::MessageType>(type);
56   }
57 };
58
59 namespace {
60
61 typedef net::WebSocketEventInterface::ChannelState ChannelState;
62
63 struct WebSocketEventHandler : public net::WebSocketEventInterface {
64  public:
65   WebSocketEventHandler(WebSocketClientPtr client)
66       : client_(client.Pass()) {
67   }
68   ~WebSocketEventHandler() override {}
69
70  private:
71   // net::WebSocketEventInterface methods:
72   ChannelState OnAddChannelResponse(bool fail,
73                                     const std::string& selected_subprotocol,
74                                     const std::string& extensions) override;
75   ChannelState OnDataFrame(bool fin,
76                            WebSocketMessageType type,
77                            const std::vector<char>& data) override;
78   ChannelState OnClosingHandshake() override;
79   ChannelState OnFlowControl(int64 quota) override;
80   ChannelState OnDropChannel(bool was_clean,
81                              uint16 code,
82                              const std::string& reason) override;
83   ChannelState OnFailChannel(const std::string& message) override;
84   ChannelState OnStartOpeningHandshake(
85       scoped_ptr<net::WebSocketHandshakeRequestInfo> request) override;
86   ChannelState OnFinishOpeningHandshake(
87       scoped_ptr<net::WebSocketHandshakeResponseInfo> response) override;
88   ChannelState OnSSLCertificateError(
89       scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
90       const GURL& url,
91       const net::SSLInfo& ssl_info,
92       bool fatal) override;
93
94   // Called once we've written to |receive_stream_|.
95   void DidWriteToReceiveStream(bool fin,
96                                net::WebSocketFrameHeader::OpCode type,
97                                uint32_t num_bytes,
98                                const char* buffer);
99   WebSocketClientPtr client_;
100   ScopedDataPipeProducerHandle receive_stream_;
101   scoped_ptr<WebSocketWriteQueue> write_queue_;
102
103   DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
104 };
105
106 ChannelState WebSocketEventHandler::OnAddChannelResponse(
107     bool fail,
108     const std::string& selected_protocol,
109     const std::string& extensions) {
110   DataPipe data_pipe;
111   receive_stream_ = data_pipe.producer_handle.Pass();
112   write_queue_.reset(new WebSocketWriteQueue(receive_stream_.get()));
113   client_->DidConnect(
114       fail, selected_protocol, extensions, data_pipe.consumer_handle.Pass());
115   if (fail)
116     return WebSocketEventInterface::CHANNEL_DELETED;
117   return WebSocketEventInterface::CHANNEL_ALIVE;
118 }
119
120 ChannelState WebSocketEventHandler::OnDataFrame(
121     bool fin,
122     net::WebSocketFrameHeader::OpCode type,
123     const std::vector<char>& data) {
124   uint32_t size = static_cast<uint32_t>(data.size());
125   write_queue_->Write(
126       &data[0], size,
127       base::Bind(&WebSocketEventHandler::DidWriteToReceiveStream,
128                  base::Unretained(this),
129                  fin, type, size));
130   return WebSocketEventInterface::CHANNEL_ALIVE;
131 }
132
133 ChannelState WebSocketEventHandler::OnClosingHandshake() {
134   return WebSocketEventInterface::CHANNEL_ALIVE;
135 }
136
137 ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
138   client_->DidReceiveFlowControl(quota);
139   return WebSocketEventInterface::CHANNEL_ALIVE;
140 }
141
142 ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
143                                                   uint16 code,
144                                                   const std::string& reason) {
145   client_->DidClose(was_clean, code, reason);
146   return WebSocketEventInterface::CHANNEL_DELETED;
147 }
148
149 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
150   client_->DidFail(message);
151   return WebSocketEventInterface::CHANNEL_DELETED;
152 }
153
154 ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
155     scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
156   return WebSocketEventInterface::CHANNEL_ALIVE;
157 }
158
159 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
160     scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
161   return WebSocketEventInterface::CHANNEL_ALIVE;
162 }
163
164 ChannelState WebSocketEventHandler::OnSSLCertificateError(
165     scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
166     const GURL& url,
167     const net::SSLInfo& ssl_info,
168     bool fatal) {
169   client_->DidFail("SSL Error");
170   return WebSocketEventInterface::CHANNEL_DELETED;
171 }
172
173 void WebSocketEventHandler::DidWriteToReceiveStream(
174     bool fin,
175     net::WebSocketFrameHeader::OpCode type,
176     uint32_t num_bytes,
177     const char* buffer) {
178   client_->DidReceiveData(
179       fin, ConvertTo<WebSocket::MessageType>(type), num_bytes);
180 }
181
182 }  // namespace mojo
183
184 WebSocketImpl::WebSocketImpl(NetworkContext* context) : context_(context) {
185 }
186
187 WebSocketImpl::~WebSocketImpl() {
188 }
189
190 void WebSocketImpl::Connect(const String& url,
191                             Array<String> protocols,
192                             const String& origin,
193                             ScopedDataPipeConsumerHandle send_stream,
194                             WebSocketClientPtr client) {
195   DCHECK(!channel_);
196   send_stream_ = send_stream.Pass();
197   read_queue_.reset(new WebSocketReadQueue(send_stream_.get()));
198   scoped_ptr<net::WebSocketEventInterface> event_interface(
199       new WebSocketEventHandler(client.Pass()));
200   channel_.reset(new net::WebSocketChannel(event_interface.Pass(),
201                                            context_->url_request_context()));
202   channel_->SendAddChannelRequest(GURL(url.get()),
203                                   protocols.To<std::vector<std::string> >(),
204                                   url::Origin(origin.get()));
205 }
206
207 void WebSocketImpl::Send(bool fin,
208                          WebSocket::MessageType type,
209                          uint32_t num_bytes) {
210   DCHECK(channel_);
211   read_queue_->Read(num_bytes,
212                     base::Bind(&WebSocketImpl::DidReadFromSendStream,
213                                base::Unretained(this),
214                                fin, type, num_bytes));
215 }
216
217 void WebSocketImpl::FlowControl(int64_t quota) {
218   DCHECK(channel_);
219   channel_->SendFlowControl(quota);
220 }
221
222 void WebSocketImpl::Close(uint16_t code, const String& reason) {
223   DCHECK(channel_);
224   channel_->StartClosingHandshake(code, reason);
225 }
226
227 void WebSocketImpl::DidReadFromSendStream(bool fin,
228                                           WebSocket::MessageType type,
229                                           uint32_t num_bytes,
230                                           const char* data) {
231   std::vector<char> buffer(num_bytes);
232   memcpy(&buffer[0], data, num_bytes);
233   DCHECK(channel_);
234   channel_->SendFrame(
235       fin, ConvertTo<net::WebSocketFrameHeader::OpCode>(type), buffer);
236 }
237
238 }  // namespace mojo