Remove GlobalRequestId parameter from SSLErrorHandler::Delegate.
[chromium-blink-merge.git] / content / browser / renderer_host / websocket_host.cc
bloba8951a9f6a16ebec4628287468586c33c673cdc2
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/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"
27 namespace content {
29 namespace {
31 typedef net::WebSocketEventInterface::ChannelState ChannelState;
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);
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);
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;
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);
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 virtual ~WebSocketEventHandler();
93 // net::WebSocketEventInterface implementation
95 virtual ChannelState OnAddChannelResponse(
96 bool fail,
97 const std::string& selected_subprotocol,
98 const std::string& extensions) OVERRIDE;
99 virtual ChannelState OnDataFrame(bool fin,
100 WebSocketMessageType type,
101 const std::vector<char>& data) OVERRIDE;
102 virtual ChannelState OnClosingHandshake() OVERRIDE;
103 virtual ChannelState OnFlowControl(int64 quota) OVERRIDE;
104 virtual ChannelState OnDropChannel(bool was_clean,
105 uint16 code,
106 const std::string& reason) OVERRIDE;
107 virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE;
108 virtual ChannelState OnStartOpeningHandshake(
109 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) OVERRIDE;
110 virtual ChannelState OnFinishOpeningHandshake(
111 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) OVERRIDE;
112 virtual ChannelState OnSSLCertificateError(
113 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
114 const GURL& url,
115 const net::SSLInfo& ssl_info,
116 bool fatal) OVERRIDE;
118 private:
119 class SSLErrorHandlerDelegate : public SSLErrorHandler::Delegate {
120 public:
121 SSLErrorHandlerDelegate(
122 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks);
123 virtual ~SSLErrorHandlerDelegate();
125 base::WeakPtr<SSLErrorHandler::Delegate> GetWeakPtr();
127 // SSLErrorHandler::Delegate methods
128 virtual void CancelSSLRequest(int error,
129 const net::SSLInfo* ssl_info) OVERRIDE;
130 virtual void ContinueSSLRequest() OVERRIDE;
132 private:
133 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
134 base::WeakPtrFactory<SSLErrorHandlerDelegate> weak_ptr_factory_;
136 DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDelegate);
139 WebSocketDispatcherHost* const dispatcher_;
140 const int routing_id_;
141 const int render_frame_id_;
142 scoped_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
144 DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
147 WebSocketEventHandler::WebSocketEventHandler(
148 WebSocketDispatcherHost* dispatcher,
149 int routing_id,
150 int render_frame_id)
151 : dispatcher_(dispatcher),
152 routing_id_(routing_id),
153 render_frame_id_(render_frame_id) {
156 WebSocketEventHandler::~WebSocketEventHandler() {
157 DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
160 ChannelState WebSocketEventHandler::OnAddChannelResponse(
161 bool fail,
162 const std::string& selected_protocol,
163 const std::string& extensions) {
164 DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
165 << " routing_id=" << routing_id_ << " fail=" << fail
166 << " selected_protocol=\"" << selected_protocol << "\""
167 << " extensions=\"" << extensions << "\"";
169 return StateCast(dispatcher_->SendAddChannelResponse(
170 routing_id_, fail, selected_protocol, extensions));
173 ChannelState WebSocketEventHandler::OnDataFrame(
174 bool fin,
175 net::WebSocketFrameHeader::OpCode type,
176 const std::vector<char>& data) {
177 DVLOG(3) << "WebSocketEventHandler::OnDataFrame"
178 << " routing_id=" << routing_id_ << " fin=" << fin
179 << " type=" << type << " data is " << data.size() << " bytes";
181 return StateCast(dispatcher_->SendFrame(
182 routing_id_, fin, OpCodeToMessageType(type), data));
185 ChannelState WebSocketEventHandler::OnClosingHandshake() {
186 DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
187 << " routing_id=" << routing_id_;
189 return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_));
192 ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
193 DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
194 << " routing_id=" << routing_id_ << " quota=" << quota;
196 return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
199 ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
200 uint16 code,
201 const std::string& reason) {
202 DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
203 << " routing_id=" << routing_id_ << " was_clean=" << was_clean
204 << " code=" << code << " reason=\"" << reason << "\"";
206 return StateCast(
207 dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason));
210 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
211 DVLOG(3) << "WebSocketEventHandler::OnFailChannel"
212 << " routing_id=" << routing_id_
213 << " message=\"" << message << "\"";
215 return StateCast(dispatcher_->NotifyFailure(routing_id_, message));
218 ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
219 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
220 bool should_send = dispatcher_->CanReadRawCookies();
221 DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake "
222 << "should_send=" << should_send;
224 if (!should_send)
225 return WebSocketEventInterface::CHANNEL_ALIVE;
227 WebSocketHandshakeRequest request_to_pass;
228 request_to_pass.url.Swap(&request->url);
229 net::HttpRequestHeaders::Iterator it(request->headers);
230 while (it.GetNext())
231 request_to_pass.headers.push_back(std::make_pair(it.name(), it.value()));
232 request_to_pass.headers_text =
233 base::StringPrintf("GET %s HTTP/1.1\r\n",
234 request_to_pass.url.spec().c_str()) +
235 request->headers.ToString();
236 request_to_pass.request_time = request->request_time;
238 return StateCast(dispatcher_->NotifyStartOpeningHandshake(routing_id_,
239 request_to_pass));
242 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
243 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
244 bool should_send = dispatcher_->CanReadRawCookies();
245 DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
246 << "should_send=" << should_send;
248 if (!should_send)
249 return WebSocketEventInterface::CHANNEL_ALIVE;
251 WebSocketHandshakeResponse response_to_pass;
252 response_to_pass.url.Swap(&response->url);
253 response_to_pass.status_code = response->status_code;
254 response_to_pass.status_text.swap(response->status_text);
255 void* iter = NULL;
256 std::string name, value;
257 while (response->headers->EnumerateHeaderLines(&iter, &name, &value))
258 response_to_pass.headers.push_back(std::make_pair(name, value));
259 response_to_pass.headers_text =
260 net::HttpUtil::ConvertHeadersBackToHTTPResponse(
261 response->headers->raw_headers());
262 response_to_pass.response_time = response->response_time;
264 return StateCast(dispatcher_->NotifyFinishOpeningHandshake(routing_id_,
265 response_to_pass));
268 ChannelState WebSocketEventHandler::OnSSLCertificateError(
269 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
270 const GURL& url,
271 const net::SSLInfo& ssl_info,
272 bool fatal) {
273 DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError"
274 << " routing_id=" << routing_id_ << " url=" << url.spec()
275 << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
276 ssl_error_handler_delegate_.reset(
277 new SSLErrorHandlerDelegate(callbacks.Pass()));
278 SSLManager::OnSSLCertificateError(ssl_error_handler_delegate_->GetWeakPtr(),
279 RESOURCE_TYPE_SUB_RESOURCE,
280 url,
281 dispatcher_->render_process_id(),
282 render_frame_id_,
283 ssl_info,
284 fatal);
285 // The above method is always asynchronous.
286 return WebSocketEventInterface::CHANNEL_ALIVE;
289 WebSocketEventHandler::SSLErrorHandlerDelegate::SSLErrorHandlerDelegate(
290 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks)
291 : callbacks_(callbacks.Pass()), weak_ptr_factory_(this) {}
293 WebSocketEventHandler::SSLErrorHandlerDelegate::~SSLErrorHandlerDelegate() {}
295 base::WeakPtr<SSLErrorHandler::Delegate>
296 WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
297 return weak_ptr_factory_.GetWeakPtr();
300 void WebSocketEventHandler::SSLErrorHandlerDelegate::CancelSSLRequest(
301 int error,
302 const net::SSLInfo* ssl_info) {
303 DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
304 << " error=" << error
305 << " cert_status=" << (ssl_info ? ssl_info->cert_status
306 : static_cast<net::CertStatus>(-1));
307 callbacks_->CancelSSLRequest(error, ssl_info);
310 void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest() {
311 DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
312 callbacks_->ContinueSSLRequest();
315 } // namespace
317 WebSocketHost::WebSocketHost(int routing_id,
318 WebSocketDispatcherHost* dispatcher,
319 net::URLRequestContext* url_request_context)
320 : dispatcher_(dispatcher),
321 url_request_context_(url_request_context),
322 routing_id_(routing_id) {
323 DVLOG(1) << "WebSocketHost: created routing_id=" << routing_id;
326 WebSocketHost::~WebSocketHost() {}
328 void WebSocketHost::GoAway() {
329 OnDropChannel(false, static_cast<uint16>(net::kWebSocketErrorGoingAway), "");
332 bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
333 bool handled = true;
334 IPC_BEGIN_MESSAGE_MAP(WebSocketHost, message)
335 IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
336 IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
337 IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
338 IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
339 IPC_MESSAGE_UNHANDLED(handled = false)
340 IPC_END_MESSAGE_MAP()
341 return handled;
344 void WebSocketHost::OnAddChannelRequest(
345 const GURL& socket_url,
346 const std::vector<std::string>& requested_protocols,
347 const url::Origin& origin,
348 int render_frame_id) {
349 DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
350 << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
351 << "\" requested_protocols=\""
352 << JoinString(requested_protocols, ", ") << "\" origin=\""
353 << origin.string() << "\"";
355 DCHECK(!channel_);
356 scoped_ptr<net::WebSocketEventInterface> event_interface(
357 new WebSocketEventHandler(dispatcher_, routing_id_, render_frame_id));
358 channel_.reset(
359 new net::WebSocketChannel(event_interface.Pass(), url_request_context_));
360 channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
363 void WebSocketHost::OnSendFrame(bool fin,
364 WebSocketMessageType type,
365 const std::vector<char>& data) {
366 DVLOG(3) << "WebSocketHost::OnSendFrame"
367 << " routing_id=" << routing_id_ << " fin=" << fin
368 << " type=" << type << " data is " << data.size() << " bytes";
370 DCHECK(channel_);
371 channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
374 void WebSocketHost::OnFlowControl(int64 quota) {
375 DVLOG(3) << "WebSocketHost::OnFlowControl"
376 << " routing_id=" << routing_id_ << " quota=" << quota;
378 DCHECK(channel_);
379 channel_->SendFlowControl(quota);
382 void WebSocketHost::OnDropChannel(bool was_clean,
383 uint16 code,
384 const std::string& reason) {
385 DVLOG(3) << "WebSocketHost::OnDropChannel"
386 << " routing_id=" << routing_id_ << " was_clean=" << was_clean
387 << " code=" << code << " reason=\"" << reason << "\"";
389 DCHECK(channel_);
390 // TODO(yhirano): Handle |was_clean| appropriately.
391 channel_->StartClosingHandshake(code, reason);
394 } // namespace content