summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-08 02:27:51 +0000
committerricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-08 02:27:51 +0000
commitdab33ebca0faeda44104cd87e9cd6e631194b0b2 (patch)
tree40c0b926ae9b2c0bf89d611b4fb67f34bc72fe86
parent72643a5fc7badce86d7763267196e51d8e744573 (diff)
downloadchromium_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.cc116
-rw-r--r--content/browser/renderer_host/websocket_dispatcher_host.h97
-rw-r--r--content/browser/renderer_host/websocket_host.cc187
-rw-r--r--content/browser/renderer_host/websocket_host.h69
-rw-r--r--content/content_browser.gypi4
-rw-r--r--net/websockets/websocket_channel.cc27
-rw-r--r--net/websockets/websocket_channel.h19
-rw-r--r--net/websockets/websocket_channel_test.cc6
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)));
}