IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / renderer_host / websocket_host.cc
blobb1a0bab3bfd5af67fda8ac7b617c34bca52f9152
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.
5 #include "content/browser/renderer_host/websocket_host.h"
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
16 namespace content {
18 namespace {
20 typedef net::WebSocketEventInterface::ChannelState ChannelState;
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);
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);
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;
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);
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();
80 // net::WebSocketEventInterface implementation
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 virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE;
97 private:
98 WebSocketDispatcherHost* const dispatcher_;
99 const int routing_id_;
101 DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
104 WebSocketEventHandler::WebSocketEventHandler(
105 WebSocketDispatcherHost* dispatcher,
106 int routing_id)
107 : dispatcher_(dispatcher), routing_id_(routing_id) {}
109 WebSocketEventHandler::~WebSocketEventHandler() {
110 DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
113 ChannelState WebSocketEventHandler::OnAddChannelResponse(
114 bool fail,
115 const std::string& selected_protocol) {
116 DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
117 << " routing_id=" << routing_id_ << " fail=" << fail
118 << " selected_protocol=\"" << selected_protocol << "\"";
119 return StateCast(dispatcher_->SendAddChannelResponse(
120 routing_id_, fail, selected_protocol, std::string()));
123 ChannelState WebSocketEventHandler::OnDataFrame(
124 bool fin,
125 net::WebSocketFrameHeader::OpCode type,
126 const std::vector<char>& data) {
127 DVLOG(3) << "WebSocketEventHandler::OnDataFrame"
128 << " routing_id=" << routing_id_ << " fin=" << fin
129 << " type=" << type << " data is " << data.size() << " bytes";
130 return StateCast(dispatcher_->SendFrame(
131 routing_id_, fin, OpCodeToMessageType(type), data));
134 ChannelState WebSocketEventHandler::OnClosingHandshake() {
135 DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
136 << " routing_id=" << routing_id_;
137 return StateCast(dispatcher_->SendClosing(routing_id_));
140 ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
141 DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
142 << " routing_id=" << routing_id_ << " quota=" << quota;
143 return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
146 ChannelState WebSocketEventHandler::OnDropChannel(uint16 code,
147 const std::string& reason) {
148 DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
149 << " routing_id=" << routing_id_ << " code=" << code
150 << " reason=\"" << reason << "\"";
151 return StateCast(dispatcher_->DoDropChannel(routing_id_, code, reason));
154 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
155 DVLOG(3) << "WebSocketEventHandler::OnFailChannel"
156 << " routing_id=" << routing_id_
157 << " message=\"" << message << "\"";
158 return StateCast(dispatcher_->NotifyFailure(routing_id_, message));
161 } // namespace
163 WebSocketHost::WebSocketHost(int routing_id,
164 WebSocketDispatcherHost* dispatcher,
165 net::URLRequestContext* url_request_context)
166 : routing_id_(routing_id) {
167 DVLOG(1) << "WebSocketHost: created routing_id=" << routing_id;
168 scoped_ptr<net::WebSocketEventInterface> event_interface(
169 new WebSocketEventHandler(dispatcher, routing_id));
170 channel_.reset(
171 new net::WebSocketChannel(event_interface.Pass(), url_request_context));
174 WebSocketHost::~WebSocketHost() {}
176 bool WebSocketHost::OnMessageReceived(const IPC::Message& message,
177 bool* message_was_ok) {
178 bool handled = true;
179 IPC_BEGIN_MESSAGE_MAP_EX(WebSocketHost, message, *message_was_ok)
180 IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
181 IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
182 IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
183 IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
184 IPC_MESSAGE_UNHANDLED(handled = false)
185 IPC_END_MESSAGE_MAP_EX()
186 return handled;
189 void WebSocketHost::OnAddChannelRequest(
190 const GURL& socket_url,
191 const std::vector<std::string>& requested_protocols,
192 const GURL& origin) {
193 DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
194 << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
195 << "\" requested_protocols=\""
196 << JoinString(requested_protocols, ", ") << "\" origin=\"" << origin
197 << "\"";
199 channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
202 void WebSocketHost::OnSendFrame(bool fin,
203 WebSocketMessageType type,
204 const std::vector<char>& data) {
205 DVLOG(3) << "WebSocketHost::OnSendFrame"
206 << " routing_id=" << routing_id_ << " fin=" << fin
207 << " type=" << type << " data is " << data.size() << " bytes";
209 channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
212 void WebSocketHost::OnFlowControl(int64 quota) {
213 DVLOG(3) << "WebSocketHost::OnFlowControl"
214 << " routing_id=" << routing_id_ << " quota=" << quota;
216 channel_->SendFlowControl(quota);
219 void WebSocketHost::OnDropChannel(bool was_clean,
220 uint16 code,
221 const std::string& reason) {
222 DVLOG(3) << "WebSocketHost::OnDropChannel"
223 << " routing_id=" << routing_id_ << " was_clean=" << was_clean
224 << " code=" << code << " reason=\"" << reason << "\"";
226 // TODO(yhirano): Handle |was_clean| appropriately.
227 channel_->StartClosingHandshake(code, reason);
231 } // namespace content