- add sources.
[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/strings/string_util.h"
9 #include "content/browser/renderer_host/websocket_dispatcher_host.h"
10 #include "content/common/websocket_messages.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "net/websockets/websocket_channel.h"
13 #include "net/websockets/websocket_event_interface.h"
14 #include "net/websockets/websocket_frame.h"  // for WebSocketFrameHeader::OpCode
15
16 namespace content {
17
18 namespace {
19
20 typedef net::WebSocketEventInterface::ChannelState ChannelState;
21
22 // Convert a content::WebSocketMessageType to a
23 // net::WebSocketFrameHeader::OpCode
24 net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
25     WebSocketMessageType type) {
26   DCHECK(type == WEB_SOCKET_MESSAGE_TYPE_CONTINUATION ||
27          type == WEB_SOCKET_MESSAGE_TYPE_TEXT ||
28          type == WEB_SOCKET_MESSAGE_TYPE_BINARY);
29   typedef net::WebSocketFrameHeader::OpCode OpCode;
30   // These compile asserts verify that the same underlying values are used for
31   // both types, so we can simply cast between them.
32   COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_CONTINUATION) ==
33                      net::WebSocketFrameHeader::kOpCodeContinuation,
34                  enum_values_must_match_for_opcode_continuation);
35   COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_TEXT) ==
36                      net::WebSocketFrameHeader::kOpCodeText,
37                  enum_values_must_match_for_opcode_text);
38   COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_BINARY) ==
39                      net::WebSocketFrameHeader::kOpCodeBinary,
40                  enum_values_must_match_for_opcode_binary);
41   return static_cast<OpCode>(type);
42 }
43
44 WebSocketMessageType OpCodeToMessageType(
45     net::WebSocketFrameHeader::OpCode opCode) {
46   DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
47          opCode == net::WebSocketFrameHeader::kOpCodeText ||
48          opCode == net::WebSocketFrameHeader::kOpCodeBinary);
49   // This cast is guaranteed valid by the COMPILE_ASSERT() statements above.
50   return static_cast<WebSocketMessageType>(opCode);
51 }
52
53 ChannelState StateCast(WebSocketDispatcherHost::WebSocketHostState host_state) {
54   const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_ALIVE =
55       WebSocketDispatcherHost::WEBSOCKET_HOST_ALIVE;
56   const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_DELETED =
57       WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED;
58
59   DCHECK(host_state == WEBSOCKET_HOST_ALIVE ||
60          host_state == WEBSOCKET_HOST_DELETED);
61   // These compile asserts verify that we can get away with using static_cast<>
62   // for the conversion.
63   COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_ALIVE) ==
64                      net::WebSocketEventInterface::CHANNEL_ALIVE,
65                  enum_values_must_match_for_state_alive);
66   COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_DELETED) ==
67                      net::WebSocketEventInterface::CHANNEL_DELETED,
68                  enum_values_must_match_for_state_deleted);
69   return static_cast<ChannelState>(host_state);
70 }
71
72 // Implementation of net::WebSocketEventInterface. Receives events from our
73 // WebSocketChannel object. Each event is translated to an IPC and sent to the
74 // renderer or child process via WebSocketDispatcherHost.
75 class WebSocketEventHandler : public net::WebSocketEventInterface {
76  public:
77   WebSocketEventHandler(WebSocketDispatcherHost* dispatcher, int routing_id);
78   virtual ~WebSocketEventHandler();
79
80   // net::WebSocketEventInterface implementation
81
82   // TODO(ricea): Add |extensions| parameter to pass the list of enabled
83   // WebSocket extensions through to the renderer to make it visible to
84   // Javascript.
85   virtual ChannelState OnAddChannelResponse(
86       bool fail,
87       const std::string& selected_subprotocol) OVERRIDE;
88   virtual ChannelState OnDataFrame(bool fin,
89                                    WebSocketMessageType type,
90                                    const std::vector<char>& data) OVERRIDE;
91   virtual ChannelState OnClosingHandshake() OVERRIDE;
92   virtual ChannelState OnFlowControl(int64 quota) OVERRIDE;
93   virtual ChannelState OnDropChannel(uint16 code,
94                                      const std::string& reason) OVERRIDE;
95
96  private:
97   WebSocketDispatcherHost* const dispatcher_;
98   const int routing_id_;
99
100   DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
101 };
102
103 WebSocketEventHandler::WebSocketEventHandler(
104     WebSocketDispatcherHost* dispatcher,
105     int routing_id)
106     : dispatcher_(dispatcher), routing_id_(routing_id) {}
107
108 WebSocketEventHandler::~WebSocketEventHandler() {
109   DVLOG(1) << "WebSocketEventHandler destroyed routing_id= " << routing_id_;
110 }
111
112 ChannelState WebSocketEventHandler::OnAddChannelResponse(
113     bool fail,
114     const std::string& selected_protocol) {
115   return StateCast(dispatcher_->SendAddChannelResponse(
116       routing_id_, fail, selected_protocol, std::string()));
117 }
118
119 ChannelState WebSocketEventHandler::OnDataFrame(
120     bool fin,
121     net::WebSocketFrameHeader::OpCode type,
122     const std::vector<char>& data) {
123   return StateCast(dispatcher_->SendFrame(
124       routing_id_, fin, OpCodeToMessageType(type), data));
125 }
126
127 ChannelState WebSocketEventHandler::OnClosingHandshake() {
128   return StateCast(dispatcher_->SendClosing(routing_id_));
129 }
130
131 ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
132   return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
133 }
134
135 ChannelState WebSocketEventHandler::OnDropChannel(uint16 code,
136                                                   const std::string& reason) {
137   return StateCast(dispatcher_->DoDropChannel(routing_id_, code, reason));
138 }
139
140 }  // namespace
141
142 WebSocketHost::WebSocketHost(int routing_id,
143                              WebSocketDispatcherHost* dispatcher,
144                              net::URLRequestContext* url_request_context) {
145   DVLOG(1) << "WebSocketHost: created routing_id= " << routing_id;
146   scoped_ptr<net::WebSocketEventInterface> event_interface(
147       new WebSocketEventHandler(dispatcher, routing_id));
148   channel_.reset(
149       new net::WebSocketChannel(event_interface.Pass(), url_request_context));
150 }
151
152 WebSocketHost::~WebSocketHost() {}
153
154 bool WebSocketHost::OnMessageReceived(const IPC::Message& message,
155                                       bool* message_was_ok) {
156   bool handled = true;
157   IPC_BEGIN_MESSAGE_MAP_EX(WebSocketHost, message, *message_was_ok)
158     IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
159     IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
160     IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
161     IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
162     IPC_MESSAGE_UNHANDLED(handled = false)
163   IPC_END_MESSAGE_MAP_EX()
164   return handled;
165 }
166
167 void WebSocketHost::OnAddChannelRequest(
168     const GURL& socket_url,
169     const std::vector<std::string>& requested_protocols,
170     const GURL& origin) {
171   DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
172            << " routing_id= " << routing_id_ << " socket_url= " << socket_url
173            << " requested_protocols= " << JoinString(requested_protocols, ", ")
174            << " origin= " << origin;
175
176   channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
177 }
178
179 void WebSocketHost::OnSendFrame(bool fin,
180                                 WebSocketMessageType type,
181                                 const std::vector<char>& data) {
182   DVLOG(3) << "WebSocketHost::OnSendFrame"
183            << " routing_id= " << routing_id_ << " fin= " << fin
184            << " type= " << type << " data is " << data.size() << " bytes";
185
186   channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
187 }
188
189 void WebSocketHost::OnFlowControl(int64 quota) {
190   DVLOG(3) << "WebSocketHost::OnFlowControl"
191            << " routing_id= " << routing_id_ << " quota= " << quota;
192
193   channel_->SendFlowControl(quota);
194 }
195
196 void WebSocketHost::OnDropChannel(uint16 code, const std::string& reason) {
197   DVLOG(3) << "WebSocketDispatcherHost::OnDropChannel"
198            << " routing_id= " << routing_id_ << " code= " << code
199            << " reason= " << reason;
200
201   channel_->StartClosingHandshake(code, reason);
202 }
203
204
205 }  // namespace content