diff options
author | ricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-08 02:27:51 +0000 |
---|---|---|
committer | ricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-08 02:27:51 +0000 |
commit | dab33ebca0faeda44104cd87e9cd6e631194b0b2 (patch) | |
tree | 40c0b926ae9b2c0bf89d611b4fb67f34bc72fe86 | |
parent | 72643a5fc7badce86d7763267196e51d8e744573 (diff) | |
download | chromium_src-dab33ebca0faeda44104cd87e9cd6e631194b0b2.zip chromium_src-dab33ebca0faeda44104cd87e9cd6e631194b0b2.tar.gz chromium_src-dab33ebca0faeda44104cd87e9cd6e631194b0b2.tar.bz2 |
Create WebSocketDispatcherHost and WebSocketHost classes. WebSocketDispatcherHost creates, destroys and routes messages to WebSocketHost objects. WebSocketHost objects own and communicate with net::WebSocketChannel.
Input validation is delegated to net::WebSocketChannel.
Unit tests seem to be unfashionable for these sorts of glue classes, so I haven't created any.
The code to insert WebSocketDispatcherHost as a message filter is not included in this CL, so WebSocket IPCs are still unhandled and this CL changes no behaviour.
There is a known bug in this CL that the WebSocketChannel can be deleted while it is looping through incoming messages, causing a use-after-free error. This will be fixed in a followup CL. See design for fix at https://docs.google.com/document/d/1fMxcEFiVj-H5vmuxhPqsxJAl98GS6_yZ-wqB6j9Wmy0/pub
BUG=301353
Review URL: https://codereview.chromium.org/12637007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@227435 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/renderer_host/websocket_dispatcher_host.cc | 116 | ||||
-rw-r--r-- | content/browser/renderer_host/websocket_dispatcher_host.h | 97 | ||||
-rw-r--r-- | content/browser/renderer_host/websocket_host.cc | 187 | ||||
-rw-r--r-- | content/browser/renderer_host/websocket_host.h | 69 | ||||
-rw-r--r-- | content/content_browser.gypi | 4 | ||||
-rw-r--r-- | net/websockets/websocket_channel.cc | 27 | ||||
-rw-r--r-- | net/websockets/websocket_channel.h | 19 | ||||
-rw-r--r-- | net/websockets/websocket_channel_test.cc | 6 |
8 files changed, 502 insertions, 23 deletions
diff --git a/content/browser/renderer_host/websocket_dispatcher_host.cc b/content/browser/renderer_host/websocket_dispatcher_host.cc new file mode 100644 index 0000000..81afd61 --- /dev/null +++ b/content/browser/renderer_host/websocket_dispatcher_host.cc @@ -0,0 +1,116 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/websocket_dispatcher_host.h" + +#include <string> + +#include "base/callback.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "content/browser/renderer_host/websocket_host.h" +#include "content/common/websocket_messages.h" + +namespace content { + +WebSocketDispatcherHost::WebSocketDispatcherHost( + const GetRequestContextCallback& get_context_callback) + : get_context_callback_(get_context_callback) {} + +bool WebSocketDispatcherHost::OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) { + switch (message.type()) { + case WebSocketHostMsg_AddChannelRequest::ID: + case WebSocketMsg_SendFrame::ID: + case WebSocketMsg_FlowControl::ID: + case WebSocketMsg_DropChannel::ID: + break; + + default: + // Every message that has not been handled by a previous filter passes + // through here, so it is good to pass them on as efficiently as possible. + return false; + } + + int routing_id = message.routing_id(); + WebSocketHost* host = GetHost(routing_id); + if (message.type() == WebSocketHostMsg_AddChannelRequest::ID) { + if (host) { + DVLOG(1) << "routing_id=" << routing_id << " already in use."; + // The websocket multiplexing spec says to should drop the physical + // connection in this case, but there isn't a real physical connection + // to the renderer, and killing the renderer for this would seem to be a + // little extreme. So for now just ignore the bogus request. + return true; // We handled the message (by ignoring it). + } + host = new WebSocketHost(routing_id, this, get_context_callback_.Run()); + hosts_.insert(WebSocketHostTable::value_type(routing_id, host)); + } + if (!host) { + DVLOG(1) << "Received invalid routing ID " << routing_id + << " from renderer."; + return true; // We handled the message (by ignoring it). + } + return host->OnMessageReceived(message, message_was_ok); +} + +WebSocketHost* WebSocketDispatcherHost::GetHost(int routing_id) const { + WebSocketHostTable::const_iterator it = hosts_.find(routing_id); + return it == hosts_.end() ? NULL : it->second; +} + +void WebSocketDispatcherHost::SendOrDrop(IPC::Message* message) { + if (!Send(message)) { + DVLOG(1) << "Sending of message type " << message->type() + << " failed. Dropping channel."; + DeleteWebSocketHost(message->routing_id()); + } +} + +void WebSocketDispatcherHost::SendAddChannelResponse( + int routing_id, + bool fail, + const std::string& selected_protocol, + const std::string& extensions) { + SendOrDrop(new WebSocketMsg_AddChannelResponse( + routing_id, fail, selected_protocol, extensions)); + if (fail) + DeleteWebSocketHost(routing_id); +} + +void WebSocketDispatcherHost::SendFrame(int routing_id, + bool fin, + WebSocketMessageType type, + const std::vector<char>& data) { + SendOrDrop(new WebSocketMsg_SendFrame(routing_id, fin, type, data)); +} + +void WebSocketDispatcherHost::SendFlowControl(int routing_id, int64 quota) { + SendOrDrop(new WebSocketMsg_FlowControl(routing_id, quota)); +} + +void WebSocketDispatcherHost::SendClosing(int routing_id) { + // TODO(ricea): Implement the SendClosing IPC. +} + +void WebSocketDispatcherHost::DoDropChannel(int routing_id, + uint16 code, + const std::string& reason) { + SendOrDrop(new WebSocketMsg_DropChannel(routing_id, code, reason)); + DeleteWebSocketHost(routing_id); +} + +WebSocketDispatcherHost::~WebSocketDispatcherHost() { + STLDeleteContainerPairSecondPointers(hosts_.begin(), hosts_.end()); +} + +void WebSocketDispatcherHost::DeleteWebSocketHost(int routing_id) { + WebSocketHostTable::iterator it = hosts_.find(routing_id); + if (it != hosts_.end()) { + delete it->second; + hosts_.erase(it); + } +} + +} // namespace content diff --git a/content/browser/renderer_host/websocket_dispatcher_host.h b/content/browser/renderer_host/websocket_dispatcher_host.h new file mode 100644 index 0000000..94d34f3 --- /dev/null +++ b/content/browser/renderer_host/websocket_dispatcher_host.h @@ -0,0 +1,97 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_DISPATCHER_HOST_H_ +#define CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_DISPATCHER_HOST_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/containers/hash_tables.h" +#include "content/common/websocket.h" +#include "content/public/browser/browser_message_filter.h" + +namespace net { +class URLRequestContext; +} // namespace net + +namespace content { + +class WebSocketHost; + +// Creates a WebSocketHost object for each WebSocket channel, and dispatches +// WebSocketMsg_* messages sent from renderer to the appropriate WebSocketHost. +class WebSocketDispatcherHost : public BrowserMessageFilter { + public: + typedef base::Callback<net::URLRequestContext*()> GetRequestContextCallback; + + explicit WebSocketDispatcherHost( + const GetRequestContextCallback& get_context_callback); + + // BrowserMessageFilter: + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE; + + // The following methods are used by WebSocketHost::EventInterface to send + // IPCs from the browser to the renderer or child process. Any of them may + // delete the WebSocketHost on failure, leading to the WebSocketChannel and + // EventInterface also being deleted. + + // Sends a WebSocketMsg_AddChannelResponse IPC, and then deletes and + // unregisters the WebSocketHost if |fail| is true. + void SendAddChannelResponse(int routing_id, + bool fail, + const std::string& selected_protocol, + const std::string& extensions); + + // Sends a WebSocketMsg_SendFrame IPC. + void SendFrame(int routing_id, + bool fin, + WebSocketMessageType type, + const std::vector<char>& data); + + // Sends a WebSocketMsg_FlowControl IPC. + void SendFlowControl(int routing_id, int64 quota); + + // Sends a WebSocketMsg_SendClosing IPC + void SendClosing(int routing_id); + + // Sends a WebSocketMsg_DropChannel IPC and delete and unregister the channel. + void DoDropChannel(int routing_id, uint16 code, const std::string& reason); + + private: + typedef base::hash_map<int, WebSocketHost*> WebSocketHostTable; + + virtual ~WebSocketDispatcherHost(); + + // Looks up a WebSocketHost object by |routing_id|. Returns the object if one + // is found, or NULL otherwise. + WebSocketHost* GetHost(int routing_id) const; + + // Sends the passed in IPC::Message via the BrowserMessageFilter::Send() + // method. If the Send() fails, logs it and deletes the corresponding + // WebSocketHost object (the client is probably dead). + void SendOrDrop(IPC::Message* message); + + // Deletes the WebSocketHost object associated with the given |routing_id| and + // removes it from the |hosts_| table. Does nothing if the |routing_id| is + // unknown, since SendAddChannelResponse() may call this method twice. + void DeleteWebSocketHost(int routing_id); + + // Table of WebSocketHost objects, owned by this object, indexed by + // routing_id. + WebSocketHostTable hosts_; + + // A callback which returns the appropriate net::URLRequestContext for us to + // use. + GetRequestContextCallback get_context_callback_; + + DISALLOW_COPY_AND_ASSIGN(WebSocketDispatcherHost); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_DISPATCHER_HOST_H_ diff --git a/content/browser/renderer_host/websocket_host.cc b/content/browser/renderer_host/websocket_host.cc new file mode 100644 index 0000000..4284743 --- /dev/null +++ b/content/browser/renderer_host/websocket_host.cc @@ -0,0 +1,187 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/websocket_host.h" + +#include "base/basictypes.h" +#include "base/strings/string_util.h" +#include "content/browser/renderer_host/websocket_dispatcher_host.h" +#include "content/common/websocket_messages.h" +#include "ipc/ipc_message_macros.h" +#include "net/websockets/websocket_channel.h" +#include "net/websockets/websocket_event_interface.h" +#include "net/websockets/websocket_frame.h" // for WebSocketFrameHeader::OpCode + +namespace content { + +namespace { + +// Convert a content::WebSocketMessageType to a +// net::WebSocketFrameHeader::OpCode +net::WebSocketFrameHeader::OpCode MessageTypeToOpCode( + WebSocketMessageType type) { + DCHECK(type == WEB_SOCKET_MESSAGE_TYPE_CONTINUATION || + type == WEB_SOCKET_MESSAGE_TYPE_TEXT || + type == WEB_SOCKET_MESSAGE_TYPE_BINARY); + typedef net::WebSocketFrameHeader::OpCode OpCode; + // These compile asserts verify that the same underlying values are used for + // both types, so we can simply cast between them. + COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_CONTINUATION) == + net::WebSocketFrameHeader::kOpCodeContinuation, + enum_values_must_match_for_opcode_continuation); + COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_TEXT) == + net::WebSocketFrameHeader::kOpCodeText, + enum_values_must_match_for_opcode_text); + COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_BINARY) == + net::WebSocketFrameHeader::kOpCodeBinary, + enum_values_must_match_for_opcode_binary); + return static_cast<OpCode>(type); +} + +WebSocketMessageType OpCodeToMessageType( + net::WebSocketFrameHeader::OpCode opCode) { + DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation || + opCode == net::WebSocketFrameHeader::kOpCodeText || + opCode == net::WebSocketFrameHeader::kOpCodeBinary); + // This cast is guaranteed valid by the COMPILE_ASSERT() statements above. + return static_cast<WebSocketMessageType>(opCode); +} + +// Implementation of net::WebSocketEventInterface. Receives events from our +// WebSocketChannel object. Each event is translated to an IPC and sent to the +// renderer or child process via WebSocketDispatcherHost. +class WebSocketEventHandler : public net::WebSocketEventInterface { + public: + WebSocketEventHandler(WebSocketDispatcherHost* dispatcher, int routing_id); + virtual ~WebSocketEventHandler(); + + // net::WebSocketEventInterface implementation + + // TODO(ricea): Add |extensions| parameter to pass the list of enabled + // WebSocket extensions through to the renderer to make it visible to + // Javascript. + virtual void OnAddChannelResponse( + bool fail, + const std::string& selected_subprotocol) OVERRIDE; + virtual void OnDataFrame(bool fin, + WebSocketMessageType type, + const std::vector<char>& data) OVERRIDE; + virtual void OnClosingHandshake() OVERRIDE; + virtual void OnFlowControl(int64 quota) OVERRIDE; + virtual void OnDropChannel(uint16 code, + const std::string& reason) OVERRIDE; + + private: + WebSocketDispatcherHost* const dispatcher_; + const int routing_id_; + + DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler); +}; + +WebSocketEventHandler::WebSocketEventHandler( + WebSocketDispatcherHost* dispatcher, + int routing_id) + : dispatcher_(dispatcher), routing_id_(routing_id) {} + +WebSocketEventHandler::~WebSocketEventHandler() { + DVLOG(1) << "WebSocketEventHandler destroyed routing_id= " << routing_id_; +} + +void WebSocketEventHandler::OnAddChannelResponse( + bool fail, + const std::string& selected_protocol) { + dispatcher_->SendAddChannelResponse( + routing_id_, fail, selected_protocol, std::string()); + // |this| may have been deleted here. +} + +void WebSocketEventHandler::OnDataFrame(bool fin, + net::WebSocketFrameHeader::OpCode type, + const std::vector<char>& data) { + dispatcher_->SendFrame(routing_id_, fin, OpCodeToMessageType(type), data); + // |this| may have been deleted here. +} + +void WebSocketEventHandler::OnClosingHandshake() { + dispatcher_->SendClosing(routing_id_); + // |this| may have been deleted here. +} + +void WebSocketEventHandler::OnFlowControl(int64 quota) { + dispatcher_->SendFlowControl(routing_id_, quota); + // |this| may have been deleted here. +} + +void WebSocketEventHandler::OnDropChannel(uint16 code, + const std::string& reason) { + dispatcher_->DoDropChannel(routing_id_, code, reason); + // |this| has been deleted here. +} + +} // namespace + +WebSocketHost::WebSocketHost(int routing_id, + WebSocketDispatcherHost* dispatcher, + net::URLRequestContext* url_request_context) { + DVLOG(1) << "WebSocketHost: created routing_id= " << routing_id; + scoped_ptr<net::WebSocketEventInterface> event_interface( + new WebSocketEventHandler(dispatcher, routing_id)); + channel_.reset( + new net::WebSocketChannel(event_interface.Pass(), url_request_context)); +} + +WebSocketHost::~WebSocketHost() {} + +bool WebSocketHost::OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(WebSocketHost, message, *message_was_ok) + IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest) + IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame) + IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl) + IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + return handled; +} + +void WebSocketHost::OnAddChannelRequest( + const GURL& socket_url, + const std::vector<std::string>& requested_protocols, + const GURL& origin) { + DVLOG(3) << "WebSocketHost::OnAddChannelRequest" + << " routing_id= " << routing_id_ << " socket_url= " << socket_url + << " requested_protocols= " << JoinString(requested_protocols, ", ") + << " origin= " << origin; + + channel_->SendAddChannelRequest(socket_url, requested_protocols, origin); +} + +void WebSocketHost::OnSendFrame(bool fin, + WebSocketMessageType type, + const std::vector<char>& data) { + DVLOG(3) << "WebSocketHost::OnSendFrame" + << " routing_id= " << routing_id_ << " fin= " << fin + << " type= " << type << " data is " << data.size() << " bytes"; + + channel_->SendFrame(fin, MessageTypeToOpCode(type), data); +} + +void WebSocketHost::OnFlowControl(int64 quota) { + DVLOG(3) << "WebSocketHost::OnFlowControl" + << " routing_id= " << routing_id_ << " quota= " << quota; + + channel_->SendFlowControl(quota); +} + +void WebSocketHost::OnDropChannel(uint16 code, const std::string& reason) { + DVLOG(3) << "WebSocketDispatcherHost::OnDropChannel" + << " routing_id= " << routing_id_ << " code= " << code + << " reason= " << reason; + + channel_->StartClosingHandshake(code, reason); +} + + +} // namespace content diff --git a/content/browser/renderer_host/websocket_host.h b/content/browser/renderer_host/websocket_host.h new file mode 100644 index 0000000..e2b7d12 --- /dev/null +++ b/content/browser/renderer_host/websocket_host.h @@ -0,0 +1,69 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_HOST_H_ +#define CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_HOST_H_ + +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "content/common/websocket.h" + +class GURL; + +namespace net { +class WebSocketChannel; +class URLRequestContext; +} // namespace net + +namespace IPC { +class Message; +} // namespace IPC + +namespace content { + +class WebSocketDispatcherHost; + +// Host of WebSocketChannel. The lifetime of an instance of this class is +// completely controlled by the WebSocketDispatcherHost. +class WebSocketHost { + public: + WebSocketHost(int routing_id, + WebSocketDispatcherHost* dispatcher, + net::URLRequestContext* url_request_context); + ~WebSocketHost(); + + // General message dispatch. WebSocketDispatcherHost::OnMessageReceived + // delegates to this method after looking up the |routing_id|. + bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok); + + private: + // Handlers for each message type, dispatched by OnMessageReceived(), as + // defined in content/common/websocket_messages.h + + void OnAddChannelRequest(const GURL& socket_url, + const std::vector<std::string>& requested_protocols, + const GURL& origin); + + void OnSendFrame(bool fin, + WebSocketMessageType type, + const std::vector<char>& data); + + void OnFlowControl(int64 quota); + + void OnDropChannel(uint16 code, const std::string& reason); + + // The channel we use to send events to the network. + scoped_ptr<net::WebSocketChannel> channel_; + + // The ID used to route messages. + int routing_id_; + + DISALLOW_COPY_AND_ASSIGN(WebSocketHost); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_HOST_H_ diff --git a/content/content_browser.gypi b/content/content_browser.gypi index aa9a47e..5e4a758 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -1046,6 +1046,10 @@ 'browser/renderer_host/web_input_event_aurax11.cc', 'browser/renderer_host/webmenurunner_mac.h', 'browser/renderer_host/webmenurunner_mac.mm', + 'browser/renderer_host/websocket_dispatcher_host.cc', + 'browser/renderer_host/websocket_dispatcher_host.h', + 'browser/renderer_host/websocket_host.cc', + 'browser/renderer_host/websocket_host.h', 'browser/resolve_proxy_msg_helper.cc', 'browser/resolve_proxy_msg_helper.h', 'browser/resource_context_impl.cc', diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc index d2150d4..c370bd7 100644 --- a/net/websockets/websocket_channel.cc +++ b/net/websockets/websocket_channel.cc @@ -82,10 +82,10 @@ class WebSocketChannel::ConnectDelegate }; WebSocketChannel::WebSocketChannel( - const GURL& socket_url, - scoped_ptr<WebSocketEventInterface> event_interface) - : socket_url_(socket_url), - event_interface_(event_interface.Pass()), + scoped_ptr<WebSocketEventInterface> event_interface, + URLRequestContext* url_request_context) + : event_interface_(event_interface.Pass()), + url_request_context_(url_request_context), send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark), send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark), current_send_quota_(0), @@ -99,14 +99,14 @@ WebSocketChannel::~WebSocketChannel() { } void WebSocketChannel::SendAddChannelRequest( + const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, - const GURL& origin, - URLRequestContext* url_request_context) { + const GURL& origin) { // Delegate to the tested version. SendAddChannelRequestWithFactory( + socket_url, requested_subprotocols, origin, - url_request_context, base::Bind(&WebSocketStream::CreateAndConnectStream)); } @@ -186,26 +186,29 @@ void WebSocketChannel::StartClosingHandshake(uint16 code, } void WebSocketChannel::SendAddChannelRequestForTesting( + const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const GURL& origin, - URLRequestContext* url_request_context, const WebSocketStreamFactory& factory) { - SendAddChannelRequestWithFactory( - requested_subprotocols, origin, url_request_context, factory); + SendAddChannelRequestWithFactory(socket_url, + requested_subprotocols, + origin, + factory); } void WebSocketChannel::SendAddChannelRequestWithFactory( + const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const GURL& origin, - URLRequestContext* url_request_context, const WebSocketStreamFactory& factory) { DCHECK_EQ(FRESHLY_CONSTRUCTED, state_); + socket_url_ = socket_url; scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate( new ConnectDelegate(this)); stream_request_ = factory.Run(socket_url_, requested_subprotocols, origin, - url_request_context, + url_request_context_, BoundNetLog(), connect_delegate.Pass()); state_ = CONNECTING; diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h index dda30cd..d391f0e 100644 --- a/net/websockets/websocket_channel.h +++ b/net/websockets/websocket_channel.h @@ -41,18 +41,18 @@ class NET_EXPORT WebSocketChannel { const BoundNetLog&, scoped_ptr<WebSocketStream::ConnectDelegate>)> WebSocketStreamFactory; - // Creates a new WebSocketChannel with the specified parameters. + // Creates a new WebSocketChannel in an idle state. // SendAddChannelRequest() must be called immediately afterwards to start the // connection process. - WebSocketChannel(const GURL& socket_url, - scoped_ptr<WebSocketEventInterface> event_interface); + WebSocketChannel(scoped_ptr<WebSocketEventInterface> event_interface, + URLRequestContext* url_request_context); virtual ~WebSocketChannel(); // Starts the connection process. void SendAddChannelRequest( + const GURL& socket_url, const std::vector<std::string>& requested_protocols, - const GURL& origin, - URLRequestContext* url_request_context); + const GURL& origin); // Sends a data frame to the remote side. The frame should usually be no // larger than 32KB to prevent the time required to copy the buffers from from @@ -88,9 +88,9 @@ class NET_EXPORT WebSocketChannel { // Starts the connection process, using a specified factory function rather // than the default. This is exposed for testing. void SendAddChannelRequestForTesting( + const GURL& socket_url, const std::vector<std::string>& requested_protocols, const GURL& origin, - URLRequestContext* url_request_context, const WebSocketStreamFactory& factory); private: @@ -129,9 +129,9 @@ class NET_EXPORT WebSocketChannel { // Starts the connection progress, using a specified factory function. void SendAddChannelRequestWithFactory( + const GURL& socket_url, const std::vector<std::string>& requested_protocols, const GURL& origin, - URLRequestContext* url_request_context, const WebSocketStreamFactory& factory); // Success callback from WebSocketStream::CreateAndConnectStream(). Reports @@ -210,11 +210,14 @@ class NET_EXPORT WebSocketChannel { std::string* reason); // The URL of the remote server. - const GURL socket_url_; + GURL socket_url_; // The object receiving events. const scoped_ptr<WebSocketEventInterface> event_interface_; + // The URLRequestContext to pass to the WebSocketStream factory. + URLRequestContext* const url_request_context_; + // The WebSocketStream on which to send and receive data. scoped_ptr<WebSocketStream> stream_; diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc index 361f69f..b9a8c30 100644 --- a/net/websockets/websocket_channel_test.cc +++ b/net/websockets/websocket_channel_test.cc @@ -633,12 +633,12 @@ class WebSocketChannelTest : public ::testing::Test { // Creates a new WebSocketChannel and connects it, using the settings stored // in |connect_data_|. void CreateChannelAndConnect() { - channel_.reset( - new WebSocketChannel(connect_data_.url, CreateEventInterface())); + channel_.reset(new WebSocketChannel(CreateEventInterface(), + &connect_data_.url_request_context)); channel_->SendAddChannelRequestForTesting( + connect_data_.url, connect_data_.requested_subprotocols, connect_data_.origin, - &connect_data_.url_request_context, base::Bind(&ArgumentCopyingWebSocketFactory::Factory, base::Unretained(&connect_data_.factory))); } |