14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/browser/renderer_host/websocket_host.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/basictypes.h"
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/memory/weak_ptr.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/strings/string_util.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/browser/renderer_host/websocket_dispatcher_host.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/browser/ssl/ssl_error_handler.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/browser/ssl/ssl_manager.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/common/websocket_messages.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ipc/ipc_message_macros.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_request_headers.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_response_headers.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_util.h"
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/ssl/ssl_info.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/websockets/websocket_channel.h"
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/websockets/websocket_errors.h"
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/websockets/websocket_event_interface.h"
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/websockets/websocket_frame.h"  // for WebSocketFrameHeader::OpCode
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_request_info.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_response_info.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/origin.h"
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace content {
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)typedef net::WebSocketEventInterface::ChannelState ChannelState;
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Convert a content::WebSocketMessageType to a
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// net::WebSocketFrameHeader::OpCode
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WebSocketMessageType type) {
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(type == WEB_SOCKET_MESSAGE_TYPE_CONTINUATION ||
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         type == WEB_SOCKET_MESSAGE_TYPE_TEXT ||
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         type == WEB_SOCKET_MESSAGE_TYPE_BINARY);
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  typedef net::WebSocketFrameHeader::OpCode OpCode;
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // These compile asserts verify that the same underlying values are used for
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // both types, so we can simply cast between them.
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_CONTINUATION) ==
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     net::WebSocketFrameHeader::kOpCodeContinuation,
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 enum_values_must_match_for_opcode_continuation);
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_TEXT) ==
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     net::WebSocketFrameHeader::kOpCodeText,
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 enum_values_must_match_for_opcode_text);
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_BINARY) ==
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     net::WebSocketFrameHeader::kOpCodeBinary,
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 enum_values_must_match_for_opcode_binary);
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return static_cast<OpCode>(type);
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)WebSocketMessageType OpCodeToMessageType(
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    net::WebSocketFrameHeader::OpCode opCode) {
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         opCode == net::WebSocketFrameHeader::kOpCodeText ||
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         opCode == net::WebSocketFrameHeader::kOpCodeBinary);
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // This cast is guaranteed valid by the COMPILE_ASSERT() statements above.
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return static_cast<WebSocketMessageType>(opCode);
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ChannelState StateCast(WebSocketDispatcherHost::WebSocketHostState host_state) {
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_ALIVE =
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      WebSocketDispatcherHost::WEBSOCKET_HOST_ALIVE;
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_DELETED =
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED;
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(host_state == WEBSOCKET_HOST_ALIVE ||
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         host_state == WEBSOCKET_HOST_DELETED);
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // These compile asserts verify that we can get away with using static_cast<>
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // for the conversion.
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_ALIVE) ==
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     net::WebSocketEventInterface::CHANNEL_ALIVE,
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 enum_values_must_match_for_state_alive);
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_DELETED) ==
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     net::WebSocketEventInterface::CHANNEL_DELETED,
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 enum_values_must_match_for_state_deleted);
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return static_cast<ChannelState>(host_state);
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Implementation of net::WebSocketEventInterface. Receives events from our
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// WebSocketChannel object. Each event is translated to an IPC and sent to the
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// renderer or child process via WebSocketDispatcherHost.
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class WebSocketEventHandler : public net::WebSocketEventInterface {
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WebSocketEventHandler(WebSocketDispatcherHost* dispatcher,
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        int routing_id,
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        int render_frame_id);
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual ~WebSocketEventHandler();
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // net::WebSocketEventInterface implementation
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ChannelState OnAddChannelResponse(
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      bool fail,
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& selected_subprotocol,
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& extensions) OVERRIDE;
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ChannelState OnDataFrame(bool fin,
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                   WebSocketMessageType type,
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                   const std::vector<char>& data) OVERRIDE;
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ChannelState OnClosingHandshake() OVERRIDE;
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ChannelState OnFlowControl(int64 quota) OVERRIDE;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ChannelState OnDropChannel(bool was_clean,
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     uint16 code,
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                     const std::string& reason) OVERRIDE;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ChannelState OnStartOpeningHandshake(
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<net::WebSocketHandshakeRequestInfo> request) OVERRIDE;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ChannelState OnFinishOpeningHandshake(
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<net::WebSocketHandshakeResponseInfo> response) OVERRIDE;
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ChannelState OnSSLCertificateError(
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const GURL& url,
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const net::SSLInfo& ssl_info,
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bool fatal) OVERRIDE;
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  class SSLErrorHandlerDelegate : public SSLErrorHandler::Delegate {
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   public:
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SSLErrorHandlerDelegate(
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks);
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    virtual ~SSLErrorHandlerDelegate();
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::WeakPtr<SSLErrorHandler::Delegate> GetWeakPtr();
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // SSLErrorHandler::Delegate methods
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    virtual void CancelSSLRequest(const GlobalRequestID& id,
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  int error,
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  const net::SSLInfo* ssl_info) OVERRIDE;
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    virtual void ContinueSSLRequest(const GlobalRequestID& id) OVERRIDE;
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   private:
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::WeakPtrFactory<SSLErrorHandlerDelegate> weak_ptr_factory_;
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDelegate);
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebSocketDispatcherHost* const dispatcher_;
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const int routing_id_;
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const int render_frame_id_;
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)WebSocketEventHandler::WebSocketEventHandler(
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WebSocketDispatcherHost* dispatcher,
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int routing_id,
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int render_frame_id)
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : dispatcher_(dispatcher),
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      routing_id_(routing_id),
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      render_frame_id_(render_frame_id) {
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)WebSocketEventHandler::~WebSocketEventHandler() {
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ChannelState WebSocketEventHandler::OnAddChannelResponse(
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    bool fail,
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& selected_protocol,
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& extensions) {
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_ << " fail=" << fail
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " selected_protocol=\"" << selected_protocol << "\""
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " extensions=\"" << extensions << "\"";
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return StateCast(dispatcher_->SendAddChannelResponse(
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      routing_id_, fail, selected_protocol, extensions));
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ChannelState WebSocketEventHandler::OnDataFrame(
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    bool fin,
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    net::WebSocketFrameHeader::OpCode type,
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::vector<char>& data) {
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(3) << "WebSocketEventHandler::OnDataFrame"
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_ << " fin=" << fin
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " type=" << type << " data is " << data.size() << " bytes";
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return StateCast(dispatcher_->SendFrame(
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      routing_id_, fin, OpCodeToMessageType(type), data));
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ChannelState WebSocketEventHandler::OnClosingHandshake() {
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_;
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_));
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_ << " quota=" << quota;
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                  uint16 code,
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                  const std::string& reason) {
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " routing_id=" << routing_id_ << " was_clean=" << was_clean
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " code=" << code << " reason=\"" << reason << "\"";
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return StateCast(
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason));
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(3) << "WebSocketEventHandler::OnFailChannel"
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " routing_id=" << routing_id_
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " message=\"" << message << "\"";
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return StateCast(dispatcher_->NotifyFailure(routing_id_, message));
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool should_send = dispatcher_->CanReadRawCookies();
222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake "
223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch           << "should_send=" << should_send;
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!should_send)
226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return WebSocketEventInterface::CHANNEL_ALIVE;
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebSocketHandshakeRequest request_to_pass;
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request_to_pass.url.Swap(&request->url);
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net::HttpRequestHeaders::Iterator it(request->headers);
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (it.GetNext())
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request_to_pass.headers.push_back(std::make_pair(it.name(), it.value()));
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  request_to_pass.headers_text =
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::StringPrintf("GET %s HTTP/1.1\r\n",
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         request_to_pass.url.spec().c_str()) +
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      request->headers.ToString();
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request_to_pass.request_time = request->request_time;
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
23923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return StateCast(dispatcher_->NotifyStartOpeningHandshake(routing_id_,
24023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                            request_to_pass));
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool should_send = dispatcher_->CanReadRawCookies();
246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch           << "should_send=" << should_send;
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!should_send)
250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return WebSocketEventInterface::CHANNEL_ALIVE;
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebSocketHandshakeResponse response_to_pass;
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  response_to_pass.url.Swap(&response->url);
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  response_to_pass.status_code = response->status_code;
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  response_to_pass.status_text.swap(response->status_text);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void* iter = NULL;
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string name, value;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (response->headers->EnumerateHeaderLines(&iter, &name, &value))
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    response_to_pass.headers.push_back(std::make_pair(name, value));
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  response_to_pass.headers_text =
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      net::HttpUtil::ConvertHeadersBackToHTTPResponse(
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          response->headers->raw_headers());
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  response_to_pass.response_time = response->response_time;
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return StateCast(dispatcher_->NotifyFinishOpeningHandshake(routing_id_,
26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                             response_to_pass));
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ChannelState WebSocketEventHandler::OnSSLCertificateError(
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GURL& url,
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const net::SSLInfo& ssl_info,
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool fatal) {
27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError"
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           << " routing_id=" << routing_id_ << " url=" << url.spec()
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ssl_error_handler_delegate_.reset(
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new SSLErrorHandlerDelegate(callbacks.Pass()));
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // We don't need request_id to be unique so just make a fake one.
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  GlobalRequestID request_id(-1, -1);
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SSLManager::OnSSLCertificateError(ssl_error_handler_delegate_->GetWeakPtr(),
28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    request_id,
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    RESOURCE_TYPE_SUB_RESOURCE,
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    url,
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    dispatcher_->render_process_id(),
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    render_frame_id_,
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    ssl_info,
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    fatal);
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The above method is always asynchronous.
29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return WebSocketEventInterface::CHANNEL_ALIVE;
29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)WebSocketEventHandler::SSLErrorHandlerDelegate::SSLErrorHandlerDelegate(
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks)
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : callbacks_(callbacks.Pass()), weak_ptr_factory_(this) {}
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)WebSocketEventHandler::SSLErrorHandlerDelegate::~SSLErrorHandlerDelegate() {}
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)base::WeakPtr<SSLErrorHandler::Delegate>
30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return weak_ptr_factory_.GetWeakPtr();
30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebSocketEventHandler::SSLErrorHandlerDelegate::CancelSSLRequest(
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GlobalRequestID& id,
30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int error,
30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const net::SSLInfo* ssl_info) {
30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           << " error=" << error
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           << " cert_status=" << (ssl_info ? ssl_info->cert_status
31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           : static_cast<net::CertStatus>(-1));
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callbacks_->CancelSSLRequest(error, ssl_info);
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest(
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GlobalRequestID& id) {
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callbacks_->ContinueSSLRequest();
31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)WebSocketHost::WebSocketHost(int routing_id,
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             WebSocketDispatcherHost* dispatcher,
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             net::URLRequestContext* url_request_context)
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : dispatcher_(dispatcher),
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      url_request_context_(url_request_context),
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      routing_id_(routing_id) {
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "WebSocketHost: created routing_id=" << routing_id;
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)WebSocketHost::~WebSocketHost() {}
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WebSocketHost::GoAway() {
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OnDropChannel(false, static_cast<uint16>(net::kWebSocketErrorGoingAway), "");
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool handled = true;
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(WebSocketHost, message)
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return handled;
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebSocketHost::OnAddChannelRequest(
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GURL& socket_url,
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::vector<std::string>& requested_protocols,
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const url::Origin& origin,
35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int render_frame_id) {
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "\" requested_protocols=\""
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << JoinString(requested_protocols, ", ") << "\" origin=\""
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << origin.string() << "\"";
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!channel_);
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<net::WebSocketEventInterface> event_interface(
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new WebSocketEventHandler(dispatcher_, routing_id_, render_frame_id));
36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  channel_.reset(
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new net::WebSocketChannel(event_interface.Pass(), url_request_context_));
36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebSocketHost::OnSendFrame(bool fin,
3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                WebSocketMessageType type,
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                const std::vector<char>& data) {
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DVLOG(3) << "WebSocketHost::OnSendFrame"
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_ << " fin=" << fin
374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " type=" << type << " data is " << data.size() << " bytes";
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(channel_);
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebSocketHost::OnFlowControl(int64 quota) {
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DVLOG(3) << "WebSocketHost::OnFlowControl"
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_ << " quota=" << quota;
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(channel_);
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  channel_->SendFlowControl(quota);
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebSocketHost::OnDropChannel(bool was_clean,
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  uint16 code,
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  const std::string& reason) {
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(3) << "WebSocketHost::OnDropChannel"
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " routing_id=" << routing_id_ << " was_clean=" << was_clean
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " code=" << code << " reason=\"" << reason << "\"";
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(channel_);
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(yhirano): Handle |was_clean| appropriately.
3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  channel_->StartClosingHandshake(code, reason);
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace content
401