Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / websocket_host.cc
1 // Copyright 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.
4
5 #include "content/browser/renderer_host/websocket_host.h"
6
7 #include "base/basictypes.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/strings/string_util.h"
10 #include "content/browser/renderer_host/websocket_dispatcher_host.h"
11 #include "content/browser/ssl/ssl_error_handler.h"
12 #include "content/browser/ssl/ssl_manager.h"
13 #include "content/common/websocket_messages.h"
14 #include "ipc/ipc_message_macros.h"
15 #include "net/http/http_request_headers.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_util.h"
18 #include "net/ssl/ssl_info.h"
19 #include "net/websockets/websocket_channel.h"
20 #include "net/websockets/websocket_errors.h"
21 #include "net/websockets/websocket_event_interface.h"
22 #include "net/websockets/websocket_frame.h"  // for WebSocketFrameHeader::OpCode
23 #include "net/websockets/websocket_handshake_request_info.h"
24 #include "net/websockets/websocket_handshake_response_info.h"
25 #include "url/origin.h"
26
27 namespace content {
28
29 namespace {
30
31 typedef net::WebSocketEventInterface::ChannelState ChannelState;
32
33 // Convert a content::WebSocketMessageType to a
34 // net::WebSocketFrameHeader::OpCode
35 net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
36     WebSocketMessageType type) {
37   DCHECK(type == WEB_SOCKET_MESSAGE_TYPE_CONTINUATION ||
38          type == WEB_SOCKET_MESSAGE_TYPE_TEXT ||
39          type == WEB_SOCKET_MESSAGE_TYPE_BINARY);
40   typedef net::WebSocketFrameHeader::OpCode OpCode;
41   // These compile asserts verify that the same underlying values are used for
42   // both types, so we can simply cast between them.
43   COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_CONTINUATION) ==
44                      net::WebSocketFrameHeader::kOpCodeContinuation,
45                  enum_values_must_match_for_opcode_continuation);
46   COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_TEXT) ==
47                      net::WebSocketFrameHeader::kOpCodeText,
48                  enum_values_must_match_for_opcode_text);
49   COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_BINARY) ==
50                      net::WebSocketFrameHeader::kOpCodeBinary,
51                  enum_values_must_match_for_opcode_binary);
52   return static_cast<OpCode>(type);
53 }
54
55 WebSocketMessageType OpCodeToMessageType(
56     net::WebSocketFrameHeader::OpCode opCode) {
57   DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
58          opCode == net::WebSocketFrameHeader::kOpCodeText ||
59          opCode == net::WebSocketFrameHeader::kOpCodeBinary);
60   // This cast is guaranteed valid by the COMPILE_ASSERT() statements above.
61   return static_cast<WebSocketMessageType>(opCode);
62 }
63
64 ChannelState StateCast(WebSocketDispatcherHost::WebSocketHostState host_state) {
65   const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_ALIVE =
66       WebSocketDispatcherHost::WEBSOCKET_HOST_ALIVE;
67   const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_DELETED =
68       WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED;
69
70   DCHECK(host_state == WEBSOCKET_HOST_ALIVE ||
71          host_state == WEBSOCKET_HOST_DELETED);
72   // These compile asserts verify that we can get away with using static_cast<>
73   // for the conversion.
74   COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_ALIVE) ==
75                      net::WebSocketEventInterface::CHANNEL_ALIVE,
76                  enum_values_must_match_for_state_alive);
77   COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_DELETED) ==
78                      net::WebSocketEventInterface::CHANNEL_DELETED,
79                  enum_values_must_match_for_state_deleted);
80   return static_cast<ChannelState>(host_state);
81 }
82
83 // Implementation of net::WebSocketEventInterface. Receives events from our
84 // WebSocketChannel object. Each event is translated to an IPC and sent to the
85 // renderer or child process via WebSocketDispatcherHost.
86 class WebSocketEventHandler : public net::WebSocketEventInterface {
87  public:
88   WebSocketEventHandler(WebSocketDispatcherHost* dispatcher,
89                         int routing_id,
90                         int render_frame_id);
91   ~WebSocketEventHandler() override;
92
93   // net::WebSocketEventInterface implementation
94
95   ChannelState OnAddChannelResponse(bool fail,
96                                     const std::string& selected_subprotocol,
97                                     const std::string& extensions) override;
98   ChannelState OnDataFrame(bool fin,
99                            WebSocketMessageType type,
100                            const std::vector<char>& data) override;
101   ChannelState OnClosingHandshake() override;
102   ChannelState OnFlowControl(int64 quota) override;
103   ChannelState OnDropChannel(bool was_clean,
104                              uint16 code,
105                              const std::string& reason) override;
106   ChannelState OnFailChannel(const std::string& message) override;
107   ChannelState OnStartOpeningHandshake(
108       scoped_ptr<net::WebSocketHandshakeRequestInfo> request) override;
109   ChannelState OnFinishOpeningHandshake(
110       scoped_ptr<net::WebSocketHandshakeResponseInfo> response) override;
111   ChannelState OnSSLCertificateError(
112       scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
113       const GURL& url,
114       const net::SSLInfo& ssl_info,
115       bool fatal) override;
116
117  private:
118   class SSLErrorHandlerDelegate : public SSLErrorHandler::Delegate {
119    public:
120     SSLErrorHandlerDelegate(
121         scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks);
122     ~SSLErrorHandlerDelegate() override;
123
124     base::WeakPtr<SSLErrorHandler::Delegate> GetWeakPtr();
125
126     // SSLErrorHandler::Delegate methods
127     void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) override;
128     void ContinueSSLRequest() override;
129
130    private:
131     scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
132     base::WeakPtrFactory<SSLErrorHandlerDelegate> weak_ptr_factory_;
133
134     DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDelegate);
135   };
136
137   WebSocketDispatcherHost* const dispatcher_;
138   const int routing_id_;
139   const int render_frame_id_;
140   scoped_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
141
142   DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
143 };
144
145 WebSocketEventHandler::WebSocketEventHandler(
146     WebSocketDispatcherHost* dispatcher,
147     int routing_id,
148     int render_frame_id)
149     : dispatcher_(dispatcher),
150       routing_id_(routing_id),
151       render_frame_id_(render_frame_id) {
152 }
153
154 WebSocketEventHandler::~WebSocketEventHandler() {
155   DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
156 }
157
158 ChannelState WebSocketEventHandler::OnAddChannelResponse(
159     bool fail,
160     const std::string& selected_protocol,
161     const std::string& extensions) {
162   DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
163            << " routing_id=" << routing_id_ << " fail=" << fail
164            << " selected_protocol=\"" << selected_protocol << "\""
165            << " extensions=\"" << extensions << "\"";
166
167   return StateCast(dispatcher_->SendAddChannelResponse(
168       routing_id_, fail, selected_protocol, extensions));
169 }
170
171 ChannelState WebSocketEventHandler::OnDataFrame(
172     bool fin,
173     net::WebSocketFrameHeader::OpCode type,
174     const std::vector<char>& data) {
175   DVLOG(3) << "WebSocketEventHandler::OnDataFrame"
176            << " routing_id=" << routing_id_ << " fin=" << fin
177            << " type=" << type << " data is " << data.size() << " bytes";
178
179   return StateCast(dispatcher_->SendFrame(
180       routing_id_, fin, OpCodeToMessageType(type), data));
181 }
182
183 ChannelState WebSocketEventHandler::OnClosingHandshake() {
184   DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
185            << " routing_id=" << routing_id_;
186
187   return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_));
188 }
189
190 ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
191   DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
192            << " routing_id=" << routing_id_ << " quota=" << quota;
193
194   return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
195 }
196
197 ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
198                                                   uint16 code,
199                                                   const std::string& reason) {
200   DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
201            << " routing_id=" << routing_id_ << " was_clean=" << was_clean
202            << " code=" << code << " reason=\"" << reason << "\"";
203
204   return StateCast(
205       dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason));
206 }
207
208 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
209   DVLOG(3) << "WebSocketEventHandler::OnFailChannel"
210            << " routing_id=" << routing_id_
211            << " message=\"" << message << "\"";
212
213   return StateCast(dispatcher_->NotifyFailure(routing_id_, message));
214 }
215
216 ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
217     scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
218   bool should_send = dispatcher_->CanReadRawCookies();
219   DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake "
220            << "should_send=" << should_send;
221
222   if (!should_send)
223     return WebSocketEventInterface::CHANNEL_ALIVE;
224
225   WebSocketHandshakeRequest request_to_pass;
226   request_to_pass.url.Swap(&request->url);
227   net::HttpRequestHeaders::Iterator it(request->headers);
228   while (it.GetNext())
229     request_to_pass.headers.push_back(std::make_pair(it.name(), it.value()));
230   request_to_pass.headers_text =
231       base::StringPrintf("GET %s HTTP/1.1\r\n",
232                          request_to_pass.url.spec().c_str()) +
233       request->headers.ToString();
234   request_to_pass.request_time = request->request_time;
235
236   return StateCast(dispatcher_->NotifyStartOpeningHandshake(routing_id_,
237                                                             request_to_pass));
238 }
239
240 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
241     scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
242   bool should_send = dispatcher_->CanReadRawCookies();
243   DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
244            << "should_send=" << should_send;
245
246   if (!should_send)
247     return WebSocketEventInterface::CHANNEL_ALIVE;
248
249   WebSocketHandshakeResponse response_to_pass;
250   response_to_pass.url.Swap(&response->url);
251   response_to_pass.status_code = response->status_code;
252   response_to_pass.status_text.swap(response->status_text);
253   void* iter = NULL;
254   std::string name, value;
255   while (response->headers->EnumerateHeaderLines(&iter, &name, &value))
256     response_to_pass.headers.push_back(std::make_pair(name, value));
257   response_to_pass.headers_text =
258       net::HttpUtil::ConvertHeadersBackToHTTPResponse(
259           response->headers->raw_headers());
260   response_to_pass.response_time = response->response_time;
261
262   return StateCast(dispatcher_->NotifyFinishOpeningHandshake(routing_id_,
263                                                              response_to_pass));
264 }
265
266 ChannelState WebSocketEventHandler::OnSSLCertificateError(
267     scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
268     const GURL& url,
269     const net::SSLInfo& ssl_info,
270     bool fatal) {
271   DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError"
272            << " routing_id=" << routing_id_ << " url=" << url.spec()
273            << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
274   ssl_error_handler_delegate_.reset(
275       new SSLErrorHandlerDelegate(callbacks.Pass()));
276   SSLManager::OnSSLCertificateError(ssl_error_handler_delegate_->GetWeakPtr(),
277                                     RESOURCE_TYPE_SUB_RESOURCE,
278                                     url,
279                                     dispatcher_->render_process_id(),
280                                     render_frame_id_,
281                                     ssl_info,
282                                     fatal);
283   // The above method is always asynchronous.
284   return WebSocketEventInterface::CHANNEL_ALIVE;
285 }
286
287 WebSocketEventHandler::SSLErrorHandlerDelegate::SSLErrorHandlerDelegate(
288     scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks)
289     : callbacks_(callbacks.Pass()), weak_ptr_factory_(this) {}
290
291 WebSocketEventHandler::SSLErrorHandlerDelegate::~SSLErrorHandlerDelegate() {}
292
293 base::WeakPtr<SSLErrorHandler::Delegate>
294 WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
295   return weak_ptr_factory_.GetWeakPtr();
296 }
297
298 void WebSocketEventHandler::SSLErrorHandlerDelegate::CancelSSLRequest(
299     int error,
300     const net::SSLInfo* ssl_info) {
301   DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
302            << " error=" << error
303            << " cert_status=" << (ssl_info ? ssl_info->cert_status
304                                            : static_cast<net::CertStatus>(-1));
305   callbacks_->CancelSSLRequest(error, ssl_info);
306 }
307
308 void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest() {
309   DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
310   callbacks_->ContinueSSLRequest();
311 }
312
313 }  // namespace
314
315 WebSocketHost::WebSocketHost(int routing_id,
316                              WebSocketDispatcherHost* dispatcher,
317                              net::URLRequestContext* url_request_context)
318     : dispatcher_(dispatcher),
319       url_request_context_(url_request_context),
320       routing_id_(routing_id) {
321   DVLOG(1) << "WebSocketHost: created routing_id=" << routing_id;
322 }
323
324 WebSocketHost::~WebSocketHost() {}
325
326 void WebSocketHost::GoAway() {
327   OnDropChannel(false, static_cast<uint16>(net::kWebSocketErrorGoingAway), "");
328 }
329
330 bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
331   bool handled = true;
332   IPC_BEGIN_MESSAGE_MAP(WebSocketHost, message)
333     IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
334     IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
335     IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
336     IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
337     IPC_MESSAGE_UNHANDLED(handled = false)
338   IPC_END_MESSAGE_MAP()
339   return handled;
340 }
341
342 void WebSocketHost::OnAddChannelRequest(
343     const GURL& socket_url,
344     const std::vector<std::string>& requested_protocols,
345     const url::Origin& origin,
346     int render_frame_id) {
347   DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
348            << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
349            << "\" requested_protocols=\""
350            << JoinString(requested_protocols, ", ") << "\" origin=\""
351            << origin.string() << "\"";
352
353   DCHECK(!channel_);
354   scoped_ptr<net::WebSocketEventInterface> event_interface(
355       new WebSocketEventHandler(dispatcher_, routing_id_, render_frame_id));
356   channel_.reset(
357       new net::WebSocketChannel(event_interface.Pass(), url_request_context_));
358   channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
359 }
360
361 void WebSocketHost::OnSendFrame(bool fin,
362                                 WebSocketMessageType type,
363                                 const std::vector<char>& data) {
364   DVLOG(3) << "WebSocketHost::OnSendFrame"
365            << " routing_id=" << routing_id_ << " fin=" << fin
366            << " type=" << type << " data is " << data.size() << " bytes";
367
368   DCHECK(channel_);
369   channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
370 }
371
372 void WebSocketHost::OnFlowControl(int64 quota) {
373   DVLOG(3) << "WebSocketHost::OnFlowControl"
374            << " routing_id=" << routing_id_ << " quota=" << quota;
375
376   DCHECK(channel_);
377   channel_->SendFlowControl(quota);
378 }
379
380 void WebSocketHost::OnDropChannel(bool was_clean,
381                                   uint16 code,
382                                   const std::string& reason) {
383   DVLOG(3) << "WebSocketHost::OnDropChannel"
384            << " routing_id=" << routing_id_ << " was_clean=" << was_clean
385            << " code=" << code << " reason=\"" << reason << "\"";
386
387   DCHECK(channel_);
388   // TODO(yhirano): Handle |was_clean| appropriately.
389   channel_->StartClosingHandshake(code, reason);
390 }
391
392 }  // namespace content