summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorricea <ricea@chromium.org>2014-11-08 06:21:56 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-08 14:22:14 +0000
commit5563c9df40ff8738c49cb1b86633c0ca91ac07c2 (patch)
treeef37780813f290e1904c70a4e689a06782b8a6c3
parent626256ab20378c1aba947414a84ab3868d2efad9 (diff)
downloadchromium_src-5563c9df40ff8738c49cb1b86633c0ca91ac07c2.zip
chromium_src-5563c9df40ff8738c49cb1b86633c0ca91ac07c2.tar.gz
chromium_src-5563c9df40ff8738c49cb1b86633c0ca91ac07c2.tar.bz2
Delete the old WebSocket implementation from net/
The removal of NetworkDelegate::OnBeforeSocketStreamConnect() is in http://crrev.com/652363005 so not too many reviewers will need to review this more-complex CL. BUG=423201 TEST=net_unittests, browser_tests Review URL: https://codereview.chromium.org/679273005 Cr-Commit-Position: refs/heads/master@{#303387}
-rw-r--r--chrome/browser/io_thread.cc9
-rw-r--r--chrome/browser/io_thread.h1
-rw-r--r--chrome/browser/resources/net_internals/source_entry.js5
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--net/BUILD.gn22
-rw-r--r--net/base/net_error_list.h8
-rw-r--r--net/base/net_log.h2
-rw-r--r--net/base/net_log_event_type_list.h46
-rw-r--r--net/base/net_log_source_type_list.h1
-rw-r--r--net/base/network_delegate.cc13
-rw-r--r--net/base/network_delegate.h3
-rw-r--r--net/http/http_network_session.cc1
-rw-r--r--net/http/http_network_session.h1
-rw-r--r--net/net.gyp7
-rw-r--r--net/net.gypi25
-rw-r--r--net/socket_stream/socket_stream.cc1353
-rw-r--r--net/socket_stream/socket_stream.h404
-rw-r--r--net/socket_stream/socket_stream_job.cc92
-rw-r--r--net/socket_stream/socket_stream_job.h94
-rw-r--r--net/socket_stream/socket_stream_job_manager.cc68
-rw-r--r--net/socket_stream/socket_stream_job_manager.h46
-rw-r--r--net/socket_stream/socket_stream_metrics.cc86
-rw-r--r--net/socket_stream/socket_stream_metrics.h70
-rw-r--r--net/socket_stream/socket_stream_metrics_unittest.cc221
-rw-r--r--net/socket_stream/socket_stream_unittest.cc1041
-rw-r--r--net/spdy/spdy_framer.h4
-rw-r--r--net/spdy/spdy_test_util_common.cc3
-rw-r--r--net/spdy/spdy_test_util_common.h1
-rw-r--r--net/spdy/spdy_websocket_stream.cc130
-rw-r--r--net/spdy/spdy_websocket_stream.h104
-rw-r--r--net/spdy/spdy_websocket_stream_unittest.cc669
-rw-r--r--net/spdy/spdy_websocket_test_util.cc111
-rw-r--r--net/spdy/spdy_websocket_test_util.h78
-rw-r--r--net/websockets/PRESUBMIT.py57
-rw-r--r--net/websockets/README91
-rw-r--r--net/websockets/websocket_handshake_handler.cc477
-rw-r--r--net/websockets/websocket_handshake_handler.h111
-rw-r--r--net/websockets/websocket_handshake_handler_spdy_test.cc187
-rw-r--r--net/websockets/websocket_handshake_handler_test.cc230
-rw-r--r--net/websockets/websocket_job.cc693
-rw-r--r--net/websockets/websocket_job.h154
-rw-r--r--net/websockets/websocket_job_test.cc1287
-rw-r--r--net/websockets/websocket_net_log_params.cc49
-rw-r--r--net/websockets/websocket_net_log_params.h21
-rw-r--r--net/websockets/websocket_net_log_params_test.cc50
-rw-r--r--net/websockets/websocket_throttle.cc144
-rw-r--r--net/websockets/websocket_throttle.h75
-rw-r--r--net/websockets/websocket_throttle_test.cc359
-rw-r--r--storage/common/fileapi/file_system_util.cc2
50 files changed, 14 insertions, 8696 deletions
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 24064c6..e5c9e03 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -803,18 +803,11 @@ void IOThread::InitializeNetworkOptions(const CommandLine& command_line) {
} else if (command_line.HasSwitch(switches::kEnableNpnHttpOnly)) {
globals_->next_protos = net::NextProtosHttpOnly();
globals_->use_alternate_protocols.set(false);
- } else if (command_line.HasSwitch(switches::kEnableWebSocketOverSpdy)) {
- // Use the current SPDY default (SPDY/3.1).
- globals_->next_protos = net::NextProtosSpdy31();
- globals_->use_alternate_protocols.set(true);
} else {
// No SPDY command-line flags have been specified. Examine trial groups.
ConfigureSpdyFromTrial(
base::FieldTrialList::FindFullName(kSpdyFieldTrialName), globals_);
}
-
- if (command_line.HasSwitch(switches::kEnableWebSocketOverSpdy))
- globals_->enable_websocket_over_spdy.set(true);
}
ConfigureTCPFastOpen(command_line);
@@ -1028,8 +1021,6 @@ void IOThread::InitializeNetworkSessionParamsFromGlobals(
&params->use_alternate_protocols);
globals.alternate_protocol_probability_threshold.CopyToIfSet(
&params->alternate_protocol_probability_threshold);
- globals.enable_websocket_over_spdy.CopyToIfSet(
- &params->enable_websocket_over_spdy);
globals.enable_quic.CopyToIfSet(&params->enable_quic);
globals.quic_always_require_handshake_confirmation.CopyToIfSet(
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index 6df3171..4fa68e0 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -184,7 +184,6 @@ class IOThread : public content::BrowserThreadDelegate {
std::set<net::HostPortPair> forced_spdy_exclusions;
Optional<bool> use_alternate_protocols;
Optional<double> alternate_protocol_probability_threshold;
- Optional<bool> enable_websocket_over_spdy;
Optional<bool> enable_quic;
Optional<bool> enable_quic_port_selection;
diff --git a/chrome/browser/resources/net_internals/source_entry.js b/chrome/browser/resources/net_internals/source_entry.js
index fafd4e3..974adc9 100644
--- a/chrome/browser/resources/net_internals/source_entry.js
+++ b/chrome/browser/resources/net_internals/source_entry.js
@@ -79,6 +79,7 @@ var SourceEntry = (function() {
switch (e.source.type) {
case EventSourceType.URL_REQUEST:
+ // TODO(ricea): Remove SOCKET_STREAM after M41 is released.
case EventSourceType.SOCKET_STREAM:
case EventSourceType.HTTP_STREAM_JOB:
case EventSourceType.ASYNC_REVALIDATION:
@@ -181,8 +182,8 @@ var SourceEntry = (function() {
/**
* Returns the starting entry for this source. Conceptually this is the
* first entry that was logged to this source. However, we skip over the
- * TYPE_REQUEST_ALIVE entries which wrap TYPE_URL_REQUEST_START_JOB /
- * TYPE_SOCKET_STREAM_CONNECT.
+ * TYPE_REQUEST_ALIVE entries which wrap TYPE_URL_REQUEST_START_JO
+ * entries.
*/
getStartEntry_: function() {
if (this.entries_.length < 1)
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 8c5ef48..577f648 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -631,9 +631,6 @@ const char kEnableTranslateNewUX[] = "enable-translate-new-ux";
const char kEnableUserAlternateProtocolPorts[] =
"enable-user-controlled-alternate-protocol-ports";
-// Uses WebSocket over SPDY.
-const char kEnableWebSocketOverSpdy[] = "enable-websocket-over-spdy";
-
// Enables the Website Settings page on the Settings page.
const char kEnableWebsiteSettingsManager[] = "enable-website-settings-manager";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index b3b00fa..9cca880 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -182,7 +182,6 @@ extern const char kEnableTabAudioMuting[];
extern const char kEnableThumbnailRetargeting[];
extern const char kEnableTranslateNewUX[];
extern const char kEnableUserAlternateProtocolPorts[];
-extern const char kEnableWebSocketOverSpdy[];
extern const char kEnableWebsiteSettingsManager[];
extern const char kEnhancedBookmarksExperiment[];
extern const char kExplicitlyAllowedPorts[];
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 04d976d..acaf231 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -381,16 +381,6 @@ component("net") {
if (!enable_websockets) {
sources -= [
- "socket_stream/socket_stream.cc",
- "socket_stream/socket_stream.h",
- "socket_stream/socket_stream_job.cc",
- "socket_stream/socket_stream_job.h",
- "socket_stream/socket_stream_job_manager.cc",
- "socket_stream/socket_stream_job_manager.h",
- "socket_stream/socket_stream_metrics.cc",
- "socket_stream/socket_stream_metrics.h",
- "spdy/spdy_websocket_stream.cc",
- "spdy/spdy_websocket_stream.h",
"websockets/websocket_basic_handshake_stream.cc",
"websockets/websocket_basic_handshake_stream.h",
"websockets/websocket_basic_stream.cc",
@@ -427,15 +417,9 @@ component("net") {
"websockets/websocket_handshake_stream_create_helper.h",
"websockets/websocket_inflater.cc",
"websockets/websocket_inflater.h",
- "websockets/websocket_job.cc",
- "websockets/websocket_job.h",
"websockets/websocket_mux.h",
- "websockets/websocket_net_log_params.cc",
- "websockets/websocket_net_log_params.h",
"websockets/websocket_stream.cc",
"websockets/websocket_stream.h",
- "websockets/websocket_throttle.cc",
- "websockets/websocket_throttle.h",
]
}
@@ -1226,9 +1210,6 @@ test("net_unittests") {
if (!enable_websockets) {
sources -= [
- "socket_stream/socket_stream_metrics_unittest.cc",
- "socket_stream/socket_stream_unittest.cc",
- "spdy/spdy_websocket_stream_unittest.cc",
"websockets/websocket_basic_stream_test.cc",
"websockets/websocket_channel_test.cc",
"websockets/websocket_deflate_predictor_impl_test.cc",
@@ -1242,12 +1223,9 @@ test("net_unittests") {
"websockets/websocket_handshake_handler_test.cc",
"websockets/websocket_handshake_stream_create_helper_test.cc",
"websockets/websocket_inflater_test.cc",
- "websockets/websocket_job_test.cc",
- "websockets/websocket_net_log_params_test.cc",
"websockets/websocket_stream_test.cc",
"websockets/websocket_test_util.cc",
"websockets/websocket_test_util.h",
- "websockets/websocket_throttle_test.cc",
]
}
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 4b61e0e..7cee212 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -271,9 +271,7 @@ NET_ERROR(SPDY_SESSION_ALREADY_EXISTS, -143)
// due to a malformed frame or other protocol violation.
NET_ERROR(WS_PROTOCOL_ERROR, -145)
-// Connection was aborted for switching to another ptotocol.
-// WebSocket abort SocketStream connection when alternate protocol is found.
-NET_ERROR(PROTOCOL_SWITCHED, -146)
+// Error -146 was removed (PROTOCOL_SWITCHED)
// Returned when attempting to bind an address that is already in use.
NET_ERROR(ADDRESS_IN_USE, -147)
@@ -305,9 +303,7 @@ NET_ERROR(SSL_DECRYPT_ERROR_ALERT, -153)
// pushed to the queue.
NET_ERROR(WS_THROTTLE_QUEUE_TOO_LARGE, -154)
-// There are too many active SocketStream instances, so the new connect request
-// was rejected.
-NET_ERROR(TOO_MANY_SOCKET_STREAMS, -155)
+// Error -155 was removed (TOO_MANY_SOCKET_STREAMS)
// The SSL server certificate changed in a renegotiation.
NET_ERROR(SSL_SERVER_CERT_CHANGED, -156)
diff --git a/net/base/net_log.h b/net/base/net_log.h
index 1b598ed..5fb2791 100644
--- a/net/base/net_log.h
+++ b/net/base/net_log.h
@@ -27,7 +27,7 @@ namespace net {
// NetLog is the destination for log messages generated by the network stack.
// Each log message has a "source" field which identifies the specific entity
// that generated the message (for example, which URLRequest or which
-// SocketStream).
+// SpdySession).
//
// To avoid needing to pass in the "source ID" to the logging functions, NetLog
// is usually accessed through a BoundNetLog, which will always pass in a
diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h
index 823cde1..814cf33 100644
--- a/net/base/net_log_event_type_list.h
+++ b/net/base/net_log_event_type_list.h
@@ -26,8 +26,7 @@ EVENT_TYPE(CANCELLED)
// }
EVENT_TYPE(FAILED)
-// Marks the creation/destruction of a request (net::URLRequest or
-// SocketStream).
+// Marks the creation/destruction of a request (net::URLRequest).
EVENT_TYPE(REQUEST_ALIVE)
// ------------------------------------------------------------------------
@@ -1694,49 +1693,6 @@ EVENT_TYPE(QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS)
EVENT_TYPE(HTTP_STREAM_PARSER_READ_HEADERS)
// ------------------------------------------------------------------------
-// SocketStream
-// ------------------------------------------------------------------------
-
-// Measures the time between SocketStream::Connect() and
-// SocketStream::DidEstablishConnection()
-//
-// For the BEGIN phase, the following parameters are attached:
-// {
-// "url": <String of URL being loaded>,
-// }
-//
-// For the END phase, if there was an error, the following parameters are
-// attached:
-// {
-// "net_error": <Net error code of the failure>,
-// }
-EVENT_TYPE(SOCKET_STREAM_CONNECT)
-
-// A message sent on the SocketStream.
-EVENT_TYPE(SOCKET_STREAM_SENT)
-
-// A message received on the SocketStream.
-EVENT_TYPE(SOCKET_STREAM_RECEIVED)
-
-// ------------------------------------------------------------------------
-// WebSocketJob
-// ------------------------------------------------------------------------
-
-// This event is sent for a WebSocket handshake request.
-// The following parameters are attached:
-// {
-// "headers": <handshake request message>,
-// }
-EVENT_TYPE(WEB_SOCKET_SEND_REQUEST_HEADERS)
-
-// This event is sent on receipt of the WebSocket handshake response headers.
-// The following parameters are attached:
-// {
-// "headers": <handshake response message>,
-// }
-EVENT_TYPE(WEB_SOCKET_READ_RESPONSE_HEADERS)
-
-// ------------------------------------------------------------------------
// SOCKS5ClientSocket
// ------------------------------------------------------------------------
diff --git a/net/base/net_log_source_type_list.h b/net/base/net_log_source_type_list.h
index 9d66c17..1a12cd4 100644
--- a/net/base/net_log_source_type_list.h
+++ b/net/base/net_log_source_type_list.h
@@ -9,7 +9,6 @@
SOURCE_TYPE(NONE)
SOURCE_TYPE(URL_REQUEST)
-SOURCE_TYPE(SOCKET_STREAM)
SOURCE_TYPE(PROXY_SCRIPT_DECIDER)
SOURCE_TYPE(CONNECT_JOB)
SOURCE_TYPE(SOCKET)
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc
index 9cad50a..5b69cfb 100644
--- a/net/base/network_delegate.cc
+++ b/net/base/network_delegate.cc
@@ -176,19 +176,6 @@ NetworkDelegate::AuthRequiredResponse NetworkDelegate::NotifyAuthRequired(
return OnAuthRequired(request, auth_info, callback, credentials);
}
-int NetworkDelegate::NotifyBeforeSocketStreamConnect(
- SocketStream* socket,
- const CompletionCallback& callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(socket);
- DCHECK(!callback.is_null());
- // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "423948 NetworkDelegate::OnBeforeSocketStreamConnect"));
- return OnBeforeSocketStreamConnect(socket, callback);
-}
-
bool NetworkDelegate::CanGetCookies(const URLRequest& request,
const CookieList& cookie_list) {
DCHECK(CalledOnValidThread());
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h
index 299989c..03dee0b 100644
--- a/net/base/network_delegate.h
+++ b/net/base/network_delegate.h
@@ -105,9 +105,6 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
bool CanEnablePrivacyMode(const GURL& url,
const GURL& first_party_for_cookies) const;
- int NotifyBeforeSocketStreamConnect(SocketStream* socket,
- const CompletionCallback& callback);
-
bool CancelURLRequestWithPolicyViolatingReferrerHeader(
const URLRequest& request,
const GURL& target_url,
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 3ec607e..28b3b22 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -89,7 +89,6 @@ HttpNetworkSession::Params::Params()
force_spdy_always(false),
use_alternate_protocols(false),
alternate_protocol_probability_threshold(1),
- enable_websocket_over_spdy(false),
enable_quic(false),
enable_quic_port_selection(true),
quic_always_require_handshake_confirmation(false),
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index a3f70aa..557b84e 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -109,7 +109,6 @@ class NET_EXPORT HttpNetworkSession
// trying SSL and then falling back to http.
bool use_alternate_protocols;
double alternate_protocol_probability_threshold;
- bool enable_websocket_over_spdy;
bool enable_quic;
bool enable_quic_port_selection;
diff --git a/net/net.gyp b/net/net.gyp
index 7b4b5d6..6f264fb 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -376,13 +376,8 @@
}],
[ 'enable_websockets != 1', {
'sources/': [
- ['exclude', '^socket_stream/'],
['exclude', '^websockets/'],
],
- 'sources!': [
- 'spdy/spdy_websocket_stream.cc',
- 'spdy/spdy_websocket_stream.h',
- ],
}],
[ 'enable_mdns != 1', {
'sources!' : [
@@ -654,9 +649,7 @@
}],
[ 'enable_websockets != 1', {
'sources/': [
- ['exclude', '^socket_stream/'],
['exclude', '^websockets/'],
- ['exclude', '^spdy/spdy_websocket_stream_unittest\\.cc$'],
],
}],
['disable_file_support==1', {
diff --git a/net/net.gypi b/net/net.gypi
index f43c67f..fef6136 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -1016,14 +1016,6 @@
'socket/websocket_transport_client_socket_pool.h',
'socket/websocket_transport_connect_sub_job.cc',
'socket/websocket_transport_connect_sub_job.h',
- 'socket_stream/socket_stream.cc',
- 'socket_stream/socket_stream.h',
- 'socket_stream/socket_stream_job.cc',
- 'socket_stream/socket_stream_job.h',
- 'socket_stream/socket_stream_job_manager.cc',
- 'socket_stream/socket_stream_job_manager.h',
- 'socket_stream/socket_stream_metrics.cc',
- 'socket_stream/socket_stream_metrics.h',
'spdy/buffered_spdy_framer.cc',
'spdy/buffered_spdy_framer.h',
'spdy/fuzzing/hpack_fuzz_util.cc',
@@ -1089,8 +1081,6 @@
'spdy/spdy_session_pool.h',
'spdy/spdy_stream.cc',
'spdy/spdy_stream.h',
- 'spdy/spdy_websocket_stream.cc',
- 'spdy/spdy_websocket_stream.h',
'spdy/spdy_write_queue.cc',
'spdy/spdy_write_queue.h',
'spdy/write_blocked_list.h',
@@ -1249,15 +1239,9 @@
'websockets/websocket_handshake_stream_create_helper.h',
'websockets/websocket_inflater.cc',
'websockets/websocket_inflater.h',
- 'websockets/websocket_job.cc',
- 'websockets/websocket_job.h',
'websockets/websocket_mux.h',
- 'websockets/websocket_net_log_params.cc',
- 'websockets/websocket_net_log_params.h',
'websockets/websocket_stream.cc',
'websockets/websocket_stream.h',
- 'websockets/websocket_throttle.cc',
- 'websockets/websocket_throttle.h',
],
'net_extras_sources': [
'extras/sqlite/sqlite_channel_id_store.cc',
@@ -1613,8 +1597,6 @@
'socket/unix_domain_server_socket_posix_unittest.cc',
'socket/websocket_endpoint_lock_manager_unittest.cc',
'socket/websocket_transport_client_socket_pool_unittest.cc',
- 'socket_stream/socket_stream_metrics_unittest.cc',
- 'socket_stream/socket_stream_unittest.cc',
'spdy/buffered_spdy_framer_unittest.cc',
'spdy/fuzzing/hpack_fuzz_util_test.cc',
'spdy/hpack_decoder_test.cc',
@@ -1657,9 +1639,6 @@
'spdy/spdy_test_util_common.h',
'spdy/spdy_test_utils.cc',
'spdy/spdy_test_utils.h',
- 'spdy/spdy_websocket_stream_unittest.cc',
- 'spdy/spdy_websocket_test_util.cc',
- 'spdy/spdy_websocket_test_util.h',
'spdy/spdy_write_queue_unittest.cc',
'spdy/write_blocked_list_test.cc',
'ssl/channel_id_service_unittest.cc',
@@ -1722,16 +1701,12 @@
'websockets/websocket_extension_parser_test.cc',
'websockets/websocket_frame_parser_test.cc',
'websockets/websocket_frame_test.cc',
- 'websockets/websocket_handshake_handler_spdy_test.cc',
'websockets/websocket_handshake_handler_test.cc',
'websockets/websocket_handshake_stream_create_helper_test.cc',
'websockets/websocket_inflater_test.cc',
- 'websockets/websocket_job_test.cc',
- 'websockets/websocket_net_log_params_test.cc',
'websockets/websocket_stream_test.cc',
'websockets/websocket_test_util.cc',
'websockets/websocket_test_util.h',
- 'websockets/websocket_throttle_test.cc',
],
'net_linux_test_sources': [
'quic/quic_end_to_end_unittest.cc',
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc
deleted file mode 100644
index 422d61d..0000000
--- a/net/socket_stream/socket_stream.cc
+++ /dev/null
@@ -1,1353 +0,0 @@
-// Copyright (c) 2012 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.
-//
-// TODO(ukai): code is similar with http_network_transaction.cc. We should
-// think about ways to share code, if possible.
-
-#include "net/socket_stream/socket_stream.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "net/base/auth.h"
-#include "net/base/io_buffer.h"
-#include "net/base/load_flags.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/dns/host_resolver.h"
-#include "net/http/http_auth_controller.h"
-#include "net/http/http_network_session.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_stream_factory.h"
-#include "net/http/http_transaction_factory.h"
-#include "net/http/http_util.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/socks5_client_socket.h"
-#include "net/socket/socks_client_socket.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/socket_stream/socket_stream_metrics.h"
-#include "net/ssl/ssl_cert_request_info.h"
-#include "net/ssl/ssl_info.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-
-static const int kMaxPendingSendAllowed = 32768; // 32 kilobytes.
-static const int kReadBufferSize = 4096;
-
-namespace net {
-
-int SocketStream::Delegate::OnStartOpenConnection(
- SocketStream* socket, const CompletionCallback& callback) {
- return OK;
-}
-
-void SocketStream::Delegate::OnAuthRequired(SocketStream* socket,
- AuthChallengeInfo* auth_info) {
- // By default, no credential is available and close the connection.
- socket->Close();
-}
-
-void SocketStream::Delegate::OnSSLCertificateError(
- SocketStream* socket,
- const SSLInfo& ssl_info,
- bool fatal) {
- socket->CancelWithSSLError(ssl_info);
-}
-
-bool SocketStream::Delegate::CanGetCookies(SocketStream* socket,
- const GURL& url) {
- return true;
-}
-
-bool SocketStream::Delegate::CanSetCookie(SocketStream* request,
- const GURL& url,
- const std::string& cookie_line,
- CookieOptions* options) {
- return true;
-}
-
-SocketStream::ResponseHeaders::ResponseHeaders() : IOBuffer() {}
-
-void SocketStream::ResponseHeaders::Realloc(size_t new_size) {
- headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
-}
-
-SocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; }
-
-SocketStream::SocketStream(const GURL& url, Delegate* delegate,
- URLRequestContext* context,
- CookieStore* cookie_store)
- : delegate_(delegate),
- url_(url),
- max_pending_send_allowed_(kMaxPendingSendAllowed),
- context_(context),
- next_state_(STATE_NONE),
- factory_(ClientSocketFactory::GetDefaultFactory()),
- proxy_mode_(kDirectConnection),
- proxy_url_(url),
- pac_request_(NULL),
- connection_(new ClientSocketHandle),
- privacy_mode_(PRIVACY_MODE_DISABLED),
- // Unretained() is required; without it, Bind() creates a circular
- // dependency and the SocketStream object will not be freed.
- io_callback_(base::Bind(&SocketStream::OnIOCompleted,
- base::Unretained(this))),
- read_buf_(NULL),
- current_write_buf_(NULL),
- waiting_for_write_completion_(false),
- closing_(false),
- server_closed_(false),
- metrics_(new SocketStreamMetrics(url)),
- cookie_store_(cookie_store) {
- DCHECK(base::MessageLoop::current())
- << "The current base::MessageLoop must exist";
- DCHECK(base::MessageLoopForIO::IsCurrent())
- << "The current base::MessageLoop must be TYPE_IO";
- DCHECK(delegate_);
-
- if (context_) {
- if (!cookie_store_.get())
- cookie_store_ = context_->cookie_store();
-
- net_log_ = BoundNetLog::Make(
- context->net_log(),
- NetLog::SOURCE_SOCKET_STREAM);
-
- net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE);
- }
-}
-
-SocketStream::UserData* SocketStream::GetUserData(
- const void* key) const {
- UserDataMap::const_iterator found = user_data_.find(key);
- if (found != user_data_.end())
- return found->second.get();
- return NULL;
-}
-
-void SocketStream::SetUserData(const void* key, UserData* data) {
- user_data_[key] = linked_ptr<UserData>(data);
-}
-
-bool SocketStream::is_secure() const {
- return url_.SchemeIs("wss");
-}
-
-void SocketStream::DetachContext() {
- if (!context_)
- return;
-
- if (pac_request_) {
- context_->proxy_service()->CancelPacRequest(pac_request_);
- pac_request_ = NULL;
- }
-
- net_log_.EndEvent(NetLog::TYPE_REQUEST_ALIVE);
- net_log_ = BoundNetLog();
-
- context_ = NULL;
- cookie_store_ = NULL;
-}
-
-void SocketStream::CheckPrivacyMode() {
- if (context_ && context_->network_delegate()) {
- bool enable = context_->network_delegate()->CanEnablePrivacyMode(url_,
- url_);
- privacy_mode_ = enable ? PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED;
- // Disable Channel ID if privacy mode is enabled.
- if (enable)
- server_ssl_config_.channel_id_enabled = false;
- }
-}
-
-void SocketStream::Connect() {
- DCHECK(base::MessageLoop::current())
- << "The current base::MessageLoop must exist";
- DCHECK(base::MessageLoopForIO::IsCurrent())
- << "The current base::MessageLoop must be TYPE_IO";
- if (context_) {
- context_->ssl_config_service()->GetSSLConfig(&server_ssl_config_);
- proxy_ssl_config_ = server_ssl_config_;
- }
- CheckPrivacyMode();
-
- DCHECK_EQ(next_state_, STATE_NONE);
-
- AddRef(); // Released in Finish()
- // Open a connection asynchronously, so that delegate won't be called
- // back before returning Connect().
- next_state_ = STATE_BEFORE_CONNECT;
- net_log_.BeginEvent(
- NetLog::TYPE_SOCKET_STREAM_CONNECT,
- NetLog::StringCallback("url", &url_.possibly_invalid_spec()));
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK));
-}
-
-size_t SocketStream::GetTotalSizeOfPendingWriteBufs() const {
- size_t total_size = 0;
- for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin();
- iter != pending_write_bufs_.end();
- ++iter)
- total_size += (*iter)->size();
- return total_size;
-}
-
-bool SocketStream::SendData(const char* data, int len) {
- DCHECK(base::MessageLoop::current())
- << "The current base::MessageLoop must exist";
- DCHECK(base::MessageLoopForIO::IsCurrent())
- << "The current base::MessageLoop must be TYPE_IO";
- DCHECK_GT(len, 0);
-
- if (!connection_->socket() ||
- !connection_->socket()->IsConnected() || next_state_ == STATE_NONE) {
- return false;
- }
-
- int total_buffered_bytes = len;
- if (current_write_buf_.get()) {
- // Since
- // - the purpose of this check is to limit the amount of buffer used by
- // this instance.
- // - the DrainableIOBuffer doesn't release consumed memory.
- // we need to use not BytesRemaining() but size() here.
- total_buffered_bytes += current_write_buf_->size();
- }
- total_buffered_bytes += GetTotalSizeOfPendingWriteBufs();
- if (total_buffered_bytes > max_pending_send_allowed_)
- return false;
-
- // TODO(tyoshino): Split data into smaller chunks e.g. 8KiB to free consumed
- // buffer progressively
- pending_write_bufs_.push_back(make_scoped_refptr(
- new IOBufferWithSize(len)));
- memcpy(pending_write_bufs_.back()->data(), data, len);
-
- // If current_write_buf_ is not NULL, it means that a) there's ongoing write
- // operation or b) the connection is being closed. If a), the buffer we just
- // pushed will be automatically handled when the completion callback runs
- // the loop, and therefore we don't need to enqueue DoLoop(). If b), it's ok
- // to do nothing. If current_write_buf_ is NULL, to make sure DoLoop() is
- // ran soon, enequeue it.
- if (!current_write_buf_.get()) {
- // Send pending data asynchronously, so that delegate won't be called
- // back before returning from SendData().
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK));
- }
-
- return true;
-}
-
-void SocketStream::Close() {
- DCHECK(base::MessageLoop::current())
- << "The current base::MessageLoop must exist";
- DCHECK(base::MessageLoopForIO::IsCurrent())
- << "The current base::MessageLoop must be TYPE_IO";
- // If next_state_ is STATE_NONE, the socket was not opened, or already
- // closed. So, return immediately.
- // Otherwise, it might call Finish() more than once, so breaks balance
- // of AddRef() and Release() in Connect() and Finish(), respectively.
- if (next_state_ == STATE_NONE)
- return;
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoClose, this));
-}
-
-void SocketStream::RestartWithAuth(const AuthCredentials& credentials) {
- DCHECK(base::MessageLoop::current())
- << "The current base::MessageLoop must exist";
- DCHECK(base::MessageLoopForIO::IsCurrent())
- << "The current base::MessageLoop must be TYPE_IO";
- DCHECK(proxy_auth_controller_.get());
- if (!connection_->socket()) {
- DVLOG(1) << "Socket is closed before restarting with auth.";
- return;
- }
-
- proxy_auth_controller_->ResetAuth(credentials);
-
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoRestartWithAuth, this));
-}
-
-void SocketStream::DetachDelegate() {
- if (!delegate_)
- return;
- delegate_ = NULL;
- // Prevent the rest of the function from executing if we are being called from
- // within Finish().
- if (next_state_ == STATE_NONE)
- return;
- net_log_.AddEvent(NetLog::TYPE_CANCELLED);
- // We don't need to send pending data when client detach the delegate.
- pending_write_bufs_.clear();
- Close();
-}
-
-const ProxyServer& SocketStream::proxy_server() const {
- return proxy_info_.proxy_server();
-}
-
-void SocketStream::SetClientSocketFactory(
- ClientSocketFactory* factory) {
- DCHECK(factory);
- factory_ = factory;
-}
-
-void SocketStream::CancelWithError(int error) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoLoop, this, error));
-}
-
-void SocketStream::CancelWithSSLError(const SSLInfo& ssl_info) {
- CancelWithError(MapCertStatusToNetError(ssl_info.cert_status));
-}
-
-void SocketStream::ContinueDespiteError() {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK));
-}
-
-SocketStream::~SocketStream() {
- DetachContext();
- DCHECK(!delegate_);
- DCHECK(!pac_request_);
-}
-
-SocketStream::RequestHeaders::~RequestHeaders() { data_ = NULL; }
-
-void SocketStream::set_addresses(const AddressList& addresses) {
- addresses_ = addresses;
-}
-
-void SocketStream::DoClose() {
- closing_ = true;
- // If next_state_ is:
- // - STATE_TCP_CONNECT_COMPLETE, it's waiting other socket establishing
- // connection.
- // - STATE_AUTH_REQUIRED, it's waiting for restarting.
- // - STATE_RESOLVE_PROTOCOL_COMPLETE, it's waiting for delegate_ to finish
- // OnStartOpenConnection method call
- // In these states, we'll close the SocketStream now.
- if (next_state_ == STATE_TCP_CONNECT_COMPLETE ||
- next_state_ == STATE_AUTH_REQUIRED ||
- next_state_ == STATE_RESOLVE_PROTOCOL_COMPLETE) {
- DoLoop(ERR_ABORTED);
- return;
- }
- // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close
- // the SocketStream.
- // If it's writing now, we should defer the closing after the current
- // writing is completed.
- if (next_state_ == STATE_READ_WRITE && !current_write_buf_.get())
- DoLoop(ERR_ABORTED);
-
- // In other next_state_, we'll wait for callback of other APIs, such as
- // ResolveProxy().
-}
-
-void SocketStream::Finish(int result) {
- DCHECK(base::MessageLoop::current())
- << "The current base::MessageLoop must exist";
- DCHECK(base::MessageLoopForIO::IsCurrent())
- << "The current base::MessageLoop must be TYPE_IO";
- DCHECK_LE(result, OK);
- if (result == OK)
- result = ERR_CONNECTION_CLOSED;
- DCHECK_EQ(next_state_, STATE_NONE);
- DVLOG(1) << "Finish result=" << ErrorToString(result);
-
- metrics_->OnClose();
-
- if (result != ERR_CONNECTION_CLOSED && delegate_)
- delegate_->OnError(this, result);
- if (result != ERR_PROTOCOL_SWITCHED && delegate_)
- delegate_->OnClose(this);
- delegate_ = NULL;
-
- Release();
-}
-
-int SocketStream::DidEstablishConnection() {
- if (!connection_->socket() || !connection_->socket()->IsConnected()) {
- next_state_ = STATE_CLOSE;
- return ERR_CONNECTION_FAILED;
- }
- next_state_ = STATE_READ_WRITE;
- metrics_->OnConnected();
-
- net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT);
- if (delegate_)
- delegate_->OnConnected(this, max_pending_send_allowed_);
-
- return OK;
-}
-
-int SocketStream::DidReceiveData(int result) {
- DCHECK(read_buf_.get());
- DCHECK_GT(result, 0);
- net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_RECEIVED);
- int len = result;
- metrics_->OnRead(len);
- if (delegate_) {
- // Notify recevied data to delegate.
- delegate_->OnReceivedData(this, read_buf_->data(), len);
- }
- read_buf_ = NULL;
- return OK;
-}
-
-void SocketStream::DidSendData(int result) {
- DCHECK_GT(result, 0);
- DCHECK(current_write_buf_.get());
- net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_SENT);
-
- int bytes_sent = result;
-
- metrics_->OnWrite(bytes_sent);
-
- current_write_buf_->DidConsume(result);
-
- if (current_write_buf_->BytesRemaining())
- return;
-
- size_t bytes_freed = current_write_buf_->size();
-
- current_write_buf_ = NULL;
-
- // We freed current_write_buf_ and this instance is now able to accept more
- // data via SendData() (note that DidConsume() doesn't free consumed memory).
- // We can tell that to delegate_ by calling OnSentData().
- if (delegate_)
- delegate_->OnSentData(this, bytes_freed);
-}
-
-void SocketStream::OnIOCompleted(int result) {
- DoLoop(result);
-}
-
-void SocketStream::OnReadCompleted(int result) {
- if (result == 0) {
- // 0 indicates end-of-file, so socket was closed.
- // Don't close the socket if it's still writing.
- server_closed_ = true;
- } else if (result > 0 && read_buf_.get()) {
- result = DidReceiveData(result);
- }
- DoLoop(result);
-}
-
-void SocketStream::OnWriteCompleted(int result) {
- waiting_for_write_completion_ = false;
- if (result > 0) {
- DidSendData(result);
- result = OK;
- }
- DoLoop(result);
-}
-
-void SocketStream::DoLoop(int result) {
- if (next_state_ == STATE_NONE)
- return;
-
- // If context was not set, close immediately.
- if (!context_)
- next_state_ = STATE_CLOSE;
-
- do {
- State state = next_state_;
- next_state_ = STATE_NONE;
- switch (state) {
- case STATE_BEFORE_CONNECT:
- DCHECK_EQ(OK, result);
- result = DoBeforeConnect();
- break;
- case STATE_BEFORE_CONNECT_COMPLETE:
- result = DoBeforeConnectComplete(result);
- break;
- case STATE_RESOLVE_PROXY:
- DCHECK_EQ(OK, result);
- result = DoResolveProxy();
- break;
- case STATE_RESOLVE_PROXY_COMPLETE:
- result = DoResolveProxyComplete(result);
- break;
- case STATE_RESOLVE_HOST:
- DCHECK_EQ(OK, result);
- result = DoResolveHost();
- break;
- case STATE_RESOLVE_HOST_COMPLETE:
- result = DoResolveHostComplete(result);
- break;
- case STATE_RESOLVE_PROTOCOL:
- result = DoResolveProtocol(result);
- break;
- case STATE_RESOLVE_PROTOCOL_COMPLETE:
- result = DoResolveProtocolComplete(result);
- break;
- case STATE_TCP_CONNECT:
- result = DoTcpConnect(result);
- break;
- case STATE_TCP_CONNECT_COMPLETE:
- result = DoTcpConnectComplete(result);
- break;
- case STATE_GENERATE_PROXY_AUTH_TOKEN:
- result = DoGenerateProxyAuthToken();
- break;
- case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
- result = DoGenerateProxyAuthTokenComplete(result);
- break;
- case STATE_WRITE_TUNNEL_HEADERS:
- DCHECK_EQ(OK, result);
- result = DoWriteTunnelHeaders();
- break;
- case STATE_WRITE_TUNNEL_HEADERS_COMPLETE:
- result = DoWriteTunnelHeadersComplete(result);
- break;
- case STATE_READ_TUNNEL_HEADERS:
- DCHECK_EQ(OK, result);
- result = DoReadTunnelHeaders();
- break;
- case STATE_READ_TUNNEL_HEADERS_COMPLETE:
- result = DoReadTunnelHeadersComplete(result);
- break;
- case STATE_SOCKS_CONNECT:
- DCHECK_EQ(OK, result);
- result = DoSOCKSConnect();
- break;
- case STATE_SOCKS_CONNECT_COMPLETE:
- result = DoSOCKSConnectComplete(result);
- break;
- case STATE_SECURE_PROXY_CONNECT:
- DCHECK_EQ(OK, result);
- result = DoSecureProxyConnect();
- break;
- case STATE_SECURE_PROXY_CONNECT_COMPLETE:
- result = DoSecureProxyConnectComplete(result);
- break;
- case STATE_SECURE_PROXY_HANDLE_CERT_ERROR:
- result = DoSecureProxyHandleCertError(result);
- break;
- case STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE:
- result = DoSecureProxyHandleCertErrorComplete(result);
- break;
- case STATE_SSL_CONNECT:
- DCHECK_EQ(OK, result);
- result = DoSSLConnect();
- break;
- case STATE_SSL_CONNECT_COMPLETE:
- result = DoSSLConnectComplete(result);
- break;
- case STATE_SSL_HANDLE_CERT_ERROR:
- result = DoSSLHandleCertError(result);
- break;
- case STATE_SSL_HANDLE_CERT_ERROR_COMPLETE:
- result = DoSSLHandleCertErrorComplete(result);
- break;
- case STATE_READ_WRITE:
- result = DoReadWrite(result);
- break;
- case STATE_AUTH_REQUIRED:
- // It might be called when DoClose is called while waiting in
- // STATE_AUTH_REQUIRED.
- Finish(result);
- return;
- case STATE_CLOSE:
- DCHECK_LE(result, OK);
- Finish(result);
- return;
- default:
- NOTREACHED() << "bad state " << state;
- Finish(result);
- return;
- }
- if (state == STATE_RESOLVE_PROTOCOL && result == ERR_PROTOCOL_SWITCHED)
- continue;
- // If the connection is not established yet and had actual errors,
- // record the error. In next iteration, it will close the connection.
- if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
- net_log_.EndEventWithNetErrorCode(
- NetLog::TYPE_SOCKET_STREAM_CONNECT, result);
- }
- } while (result != ERR_IO_PENDING);
-}
-
-int SocketStream::DoBeforeConnect() {
- next_state_ = STATE_BEFORE_CONNECT_COMPLETE;
- if (!context_ || !context_->network_delegate())
- return OK;
-
- int result = context_->network_delegate()->NotifyBeforeSocketStreamConnect(
- this, io_callback_);
- if (result != OK && result != ERR_IO_PENDING)
- next_state_ = STATE_CLOSE;
-
- return result;
-}
-
-int SocketStream::DoBeforeConnectComplete(int result) {
- DCHECK_NE(ERR_IO_PENDING, result);
-
- if (result == OK)
- next_state_ = STATE_RESOLVE_PROXY;
- else
- next_state_ = STATE_CLOSE;
-
- return result;
-}
-
-int SocketStream::DoResolveProxy() {
- DCHECK(context_);
- DCHECK(!pac_request_);
- next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
-
- if (!proxy_url_.is_valid()) {
- next_state_ = STATE_CLOSE;
- return ERR_INVALID_ARGUMENT;
- }
-
- // TODO(toyoshim): Check server advertisement of SPDY through the HTTP
- // Alternate-Protocol header, then switch to SPDY if SPDY is available.
- // Usually we already have a session to the SPDY server because JavaScript
- // running WebSocket itself would be served by SPDY. But, in some situation
- // (E.g. Used by Chrome Extensions or used for cross origin connection), this
- // connection might be the first one. At that time, we should check
- // Alternate-Protocol header here for ws:// or TLS NPN extension for wss:// .
-
- return context_->proxy_service()->ResolveProxy(
- proxy_url_, net::LOAD_NORMAL, &proxy_info_, io_callback_, &pac_request_,
- NULL, net_log_);
-}
-
-int SocketStream::DoResolveProxyComplete(int result) {
- pac_request_ = NULL;
- if (result != OK) {
- DVLOG(1) << "Failed to resolve proxy: " << result;
- if (delegate_)
- delegate_->OnError(this, result);
- proxy_info_.UseDirect();
- }
- if (proxy_info_.is_direct()) {
- // If proxy was not found for original URL (i.e. websocket URL),
- // try again with https URL, like Safari implementation.
- // Note that we don't want to use http proxy, because we'll use tunnel
- // proxy using CONNECT method, which is used by https proxy.
- if (!proxy_url_.SchemeIs("https")) {
- const std::string scheme = "https";
- GURL::Replacements repl;
- repl.SetSchemeStr(scheme);
- proxy_url_ = url_.ReplaceComponents(repl);
- DVLOG(1) << "Try https proxy: " << proxy_url_;
- next_state_ = STATE_RESOLVE_PROXY;
- return OK;
- }
- }
-
- if (proxy_info_.is_empty()) {
- // No proxies/direct to choose from. This happens when we don't support any
- // of the proxies in the returned list.
- return ERR_NO_SUPPORTED_PROXIES;
- }
-
- next_state_ = STATE_RESOLVE_HOST;
- return OK;
-}
-
-int SocketStream::DoResolveHost() {
- next_state_ = STATE_RESOLVE_HOST_COMPLETE;
-
- DCHECK(!proxy_info_.is_empty());
- if (proxy_info_.is_direct())
- proxy_mode_ = kDirectConnection;
- else if (proxy_info_.proxy_server().is_socks())
- proxy_mode_ = kSOCKSProxy;
- else
- proxy_mode_ = kTunnelProxy;
-
- // Determine the host and port to connect to.
- HostPortPair host_port_pair;
- if (proxy_mode_ != kDirectConnection) {
- host_port_pair = proxy_info_.proxy_server().host_port_pair();
- } else {
- host_port_pair = HostPortPair::FromURL(url_);
- }
-
- HostResolver::RequestInfo resolve_info(host_port_pair);
-
- DCHECK(context_->host_resolver());
- resolver_.reset(new SingleRequestHostResolver(context_->host_resolver()));
- return resolver_->Resolve(resolve_info,
- DEFAULT_PRIORITY,
- &addresses_,
- base::Bind(&SocketStream::OnIOCompleted, this),
- net_log_);
-}
-
-int SocketStream::DoResolveHostComplete(int result) {
- if (result == OK)
- next_state_ = STATE_RESOLVE_PROTOCOL;
- else
- next_state_ = STATE_CLOSE;
- // TODO(ukai): if error occured, reconsider proxy after error.
- return result;
-}
-
-int SocketStream::DoResolveProtocol(int result) {
- DCHECK_EQ(OK, result);
-
- if (!delegate_) {
- next_state_ = STATE_CLOSE;
- return result;
- }
-
- next_state_ = STATE_RESOLVE_PROTOCOL_COMPLETE;
- result = delegate_->OnStartOpenConnection(this, io_callback_);
- if (result == ERR_IO_PENDING)
- metrics_->OnWaitConnection();
- else if (result != OK && result != ERR_PROTOCOL_SWITCHED)
- next_state_ = STATE_CLOSE;
- return result;
-}
-
-int SocketStream::DoResolveProtocolComplete(int result) {
- DCHECK_NE(ERR_IO_PENDING, result);
-
- if (result == ERR_PROTOCOL_SWITCHED) {
- next_state_ = STATE_CLOSE;
- metrics_->OnCountWireProtocolType(
- SocketStreamMetrics::WIRE_PROTOCOL_SPDY);
- } else if (result == OK) {
- next_state_ = STATE_TCP_CONNECT;
- metrics_->OnCountWireProtocolType(
- SocketStreamMetrics::WIRE_PROTOCOL_WEBSOCKET);
- } else {
- next_state_ = STATE_CLOSE;
- }
- return result;
-}
-
-int SocketStream::DoTcpConnect(int result) {
- if (result != OK) {
- next_state_ = STATE_CLOSE;
- return result;
- }
- next_state_ = STATE_TCP_CONNECT_COMPLETE;
- DCHECK(factory_);
- connection_->SetSocket(
- factory_->CreateTransportClientSocket(addresses_,
- net_log_.net_log(),
- net_log_.source()));
- metrics_->OnStartConnection();
- return connection_->socket()->Connect(io_callback_);
-}
-
-int SocketStream::DoTcpConnectComplete(int result) {
- // TODO(ukai): if error occured, reconsider proxy after error.
- if (result != OK) {
- next_state_ = STATE_CLOSE;
- return result;
- }
-
- if (proxy_mode_ == kTunnelProxy) {
- if (proxy_info_.is_https())
- next_state_ = STATE_SECURE_PROXY_CONNECT;
- else
- next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
- } else if (proxy_mode_ == kSOCKSProxy) {
- next_state_ = STATE_SOCKS_CONNECT;
- } else if (is_secure()) {
- next_state_ = STATE_SSL_CONNECT;
- } else {
- result = DidEstablishConnection();
- }
- return result;
-}
-
-int SocketStream::DoGenerateProxyAuthToken() {
- next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
- if (!proxy_auth_controller_.get()) {
- DCHECK(context_);
- DCHECK(context_->http_transaction_factory());
- DCHECK(context_->http_transaction_factory()->GetSession());
- HttpNetworkSession* session =
- context_->http_transaction_factory()->GetSession();
- const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
- GURL auth_url(scheme +
- proxy_info_.proxy_server().host_port_pair().ToString());
- proxy_auth_controller_ =
- new HttpAuthController(HttpAuth::AUTH_PROXY,
- auth_url,
- session->http_auth_cache(),
- session->http_auth_handler_factory());
- }
- HttpRequestInfo request_info;
- request_info.url = url_;
- request_info.method = "CONNECT";
- return proxy_auth_controller_->MaybeGenerateAuthToken(
- &request_info, io_callback_, net_log_);
-}
-
-int SocketStream::DoGenerateProxyAuthTokenComplete(int result) {
- if (result != OK) {
- next_state_ = STATE_CLOSE;
- return result;
- }
-
- next_state_ = STATE_WRITE_TUNNEL_HEADERS;
- return result;
-}
-
-int SocketStream::DoWriteTunnelHeaders() {
- DCHECK_EQ(kTunnelProxy, proxy_mode_);
-
- next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE;
-
- if (!tunnel_request_headers_.get()) {
- metrics_->OnCountConnectionType(SocketStreamMetrics::TUNNEL_CONNECTION);
- tunnel_request_headers_ = new RequestHeaders();
- tunnel_request_headers_bytes_sent_ = 0;
- }
- if (tunnel_request_headers_->headers_.empty()) {
- HttpRequestHeaders request_headers;
- request_headers.SetHeader("Host", GetHostAndOptionalPort(url_));
- request_headers.SetHeader("Proxy-Connection", "keep-alive");
- if (proxy_auth_controller_.get() && proxy_auth_controller_->HaveAuth())
- proxy_auth_controller_->AddAuthorizationHeader(&request_headers);
- tunnel_request_headers_->headers_ = base::StringPrintf(
- "CONNECT %s HTTP/1.1\r\n"
- "%s",
- GetHostAndPort(url_).c_str(),
- request_headers.ToString().c_str());
- }
- tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_);
- int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() -
- tunnel_request_headers_bytes_sent_);
- DCHECK_GT(buf_len, 0);
- return connection_->socket()->Write(
- tunnel_request_headers_.get(), buf_len, io_callback_);
-}
-
-int SocketStream::DoWriteTunnelHeadersComplete(int result) {
- DCHECK_EQ(kTunnelProxy, proxy_mode_);
-
- if (result < 0) {
- next_state_ = STATE_CLOSE;
- return result;
- }
-
- tunnel_request_headers_bytes_sent_ += result;
- if (tunnel_request_headers_bytes_sent_ <
- tunnel_request_headers_->headers_.size()) {
- next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
- } else {
- // Handling a cert error or a client cert request requires reconnection.
- // DoWriteTunnelHeaders() will be called again.
- // Thus |tunnel_request_headers_bytes_sent_| should be reset to 0 for
- // sending |tunnel_request_headers_| correctly.
- tunnel_request_headers_bytes_sent_ = 0;
- next_state_ = STATE_READ_TUNNEL_HEADERS;
- }
- return OK;
-}
-
-int SocketStream::DoReadTunnelHeaders() {
- DCHECK_EQ(kTunnelProxy, proxy_mode_);
-
- next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE;
-
- if (!tunnel_response_headers_.get()) {
- tunnel_response_headers_ = new ResponseHeaders();
- tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize;
- tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_);
- tunnel_response_headers_len_ = 0;
- }
-
- int buf_len = tunnel_response_headers_capacity_ -
- tunnel_response_headers_len_;
- tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_);
- CHECK(tunnel_response_headers_->data());
-
- return connection_->socket()->Read(
- tunnel_response_headers_.get(), buf_len, io_callback_);
-}
-
-int SocketStream::DoReadTunnelHeadersComplete(int result) {
- DCHECK_EQ(kTunnelProxy, proxy_mode_);
-
- if (result < 0) {
- next_state_ = STATE_CLOSE;
- return result;
- }
-
- if (result == 0) {
- // 0 indicates end-of-file, so socket was closed.
- next_state_ = STATE_CLOSE;
- return ERR_CONNECTION_CLOSED;
- }
-
- tunnel_response_headers_len_ += result;
- DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_);
-
- int eoh = HttpUtil::LocateEndOfHeaders(
- tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0);
- if (eoh == -1) {
- if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) {
- next_state_ = STATE_CLOSE;
- return ERR_RESPONSE_HEADERS_TOO_BIG;
- }
-
- next_state_ = STATE_READ_TUNNEL_HEADERS;
- return OK;
- }
- // DidReadResponseHeaders
- scoped_refptr<HttpResponseHeaders> headers;
- headers = new HttpResponseHeaders(
- HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh));
- if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
- // Require the "HTTP/1.x" status line.
- next_state_ = STATE_CLOSE;
- return ERR_TUNNEL_CONNECTION_FAILED;
- }
- switch (headers->response_code()) {
- case 200: // OK
- if (is_secure()) {
- DCHECK_EQ(eoh, tunnel_response_headers_len_);
- next_state_ = STATE_SSL_CONNECT;
- } else {
- result = DidEstablishConnection();
- if (result < 0) {
- next_state_ = STATE_CLOSE;
- return result;
- }
- if ((eoh < tunnel_response_headers_len_) && delegate_)
- delegate_->OnReceivedData(
- this, tunnel_response_headers_->headers() + eoh,
- tunnel_response_headers_len_ - eoh);
- }
- return OK;
- case 407: // Proxy Authentication Required.
- if (proxy_mode_ != kTunnelProxy)
- return ERR_UNEXPECTED_PROXY_AUTH;
-
- result = proxy_auth_controller_->HandleAuthChallenge(
- headers, false, true, net_log_);
- if (result != OK)
- return result;
- DCHECK(!proxy_info_.is_empty());
- next_state_ = STATE_AUTH_REQUIRED;
- if (proxy_auth_controller_->HaveAuth()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoRestartWithAuth, this));
- return ERR_IO_PENDING;
- }
- if (delegate_) {
- // Wait until RestartWithAuth or Close is called.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&SocketStream::DoAuthRequired, this));
- return ERR_IO_PENDING;
- }
- break;
- default:
- break;
- }
- next_state_ = STATE_CLOSE;
- return ERR_TUNNEL_CONNECTION_FAILED;
-}
-
-int SocketStream::DoSOCKSConnect() {
- DCHECK_EQ(kSOCKSProxy, proxy_mode_);
-
- next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
-
- HostResolver::RequestInfo req_info(HostPortPair::FromURL(url_));
-
- DCHECK(!proxy_info_.is_empty());
- scoped_ptr<StreamSocket> s;
- if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5) {
- s.reset(new SOCKS5ClientSocket(connection_.Pass(), req_info));
- } else {
- s.reset(new SOCKSClientSocket(connection_.Pass(),
- req_info,
- DEFAULT_PRIORITY,
- context_->host_resolver()));
- }
- connection_.reset(new ClientSocketHandle);
- connection_->SetSocket(s.Pass());
- metrics_->OnCountConnectionType(SocketStreamMetrics::SOCKS_CONNECTION);
- return connection_->socket()->Connect(io_callback_);
-}
-
-int SocketStream::DoSOCKSConnectComplete(int result) {
- DCHECK_EQ(kSOCKSProxy, proxy_mode_);
-
- if (result == OK) {
- if (is_secure())
- next_state_ = STATE_SSL_CONNECT;
- else
- result = DidEstablishConnection();
- } else {
- next_state_ = STATE_CLOSE;
- }
- return result;
-}
-
-int SocketStream::DoSecureProxyConnect() {
- DCHECK(factory_);
- SSLClientSocketContext ssl_context;
- ssl_context.cert_verifier = context_->cert_verifier();
- ssl_context.transport_security_state = context_->transport_security_state();
- ssl_context.channel_id_service = context_->channel_id_service();
- scoped_ptr<StreamSocket> socket(factory_->CreateSSLClientSocket(
- connection_.Pass(),
- proxy_info_.proxy_server().host_port_pair(),
- proxy_ssl_config_,
- ssl_context));
- connection_.reset(new ClientSocketHandle);
- connection_->SetSocket(socket.Pass());
- next_state_ = STATE_SECURE_PROXY_CONNECT_COMPLETE;
- metrics_->OnCountConnectionType(SocketStreamMetrics::SECURE_PROXY_CONNECTION);
- return connection_->socket()->Connect(io_callback_);
-}
-
-int SocketStream::DoSecureProxyConnectComplete(int result) {
- DCHECK_EQ(STATE_NONE, next_state_);
- // Reconnect with client authentication.
- if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
- return HandleCertificateRequest(result, &proxy_ssl_config_);
-
- if (IsCertificateError(result))
- next_state_ = STATE_SECURE_PROXY_HANDLE_CERT_ERROR;
- else if (result == OK)
- next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
- else
- next_state_ = STATE_CLOSE;
- return result;
-}
-
-int SocketStream::DoSecureProxyHandleCertError(int result) {
- DCHECK_EQ(STATE_NONE, next_state_);
- DCHECK(IsCertificateError(result));
- result = HandleCertificateError(result);
- if (result == ERR_IO_PENDING)
- next_state_ = STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE;
- else
- next_state_ = STATE_CLOSE;
- return result;
-}
-
-int SocketStream::DoSecureProxyHandleCertErrorComplete(int result) {
- DCHECK_EQ(STATE_NONE, next_state_);
- if (result == OK) {
- if (!connection_->socket()->IsConnectedAndIdle())
- return AllowCertErrorForReconnection(&proxy_ssl_config_);
- next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
- } else {
- next_state_ = STATE_CLOSE;
- }
- return result;
-}
-
-int SocketStream::DoSSLConnect() {
- DCHECK(factory_);
- SSLClientSocketContext ssl_context;
- ssl_context.cert_verifier = context_->cert_verifier();
- ssl_context.transport_security_state = context_->transport_security_state();
- ssl_context.channel_id_service = context_->channel_id_service();
- scoped_ptr<StreamSocket> socket(
- factory_->CreateSSLClientSocket(connection_.Pass(),
- HostPortPair::FromURL(url_),
- server_ssl_config_,
- ssl_context));
- connection_.reset(new ClientSocketHandle);
- connection_->SetSocket(socket.Pass());
- next_state_ = STATE_SSL_CONNECT_COMPLETE;
- metrics_->OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION);
- return connection_->socket()->Connect(io_callback_);
-}
-
-int SocketStream::DoSSLConnectComplete(int result) {
- DCHECK_EQ(STATE_NONE, next_state_);
- // Reconnect with client authentication.
- if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
- return HandleCertificateRequest(result, &server_ssl_config_);
-
- if (IsCertificateError(result))
- next_state_ = STATE_SSL_HANDLE_CERT_ERROR;
- else if (result == OK)
- result = DidEstablishConnection();
- else
- next_state_ = STATE_CLOSE;
- return result;
-}
-
-int SocketStream::DoSSLHandleCertError(int result) {
- DCHECK_EQ(STATE_NONE, next_state_);
- DCHECK(IsCertificateError(result));
- result = HandleCertificateError(result);
- if (result == OK || result == ERR_IO_PENDING)
- next_state_ = STATE_SSL_HANDLE_CERT_ERROR_COMPLETE;
- else
- next_state_ = STATE_CLOSE;
- return result;
-}
-
-int SocketStream::DoSSLHandleCertErrorComplete(int result) {
- DCHECK_EQ(STATE_NONE, next_state_);
- // TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible.
- // If we use HTTPS and this is the first connection to the SPDY server,
- // we should take care of TLS NPN extension here.
-
- if (result == OK) {
- if (!connection_->socket()->IsConnectedAndIdle())
- return AllowCertErrorForReconnection(&server_ssl_config_);
- result = DidEstablishConnection();
- } else {
- next_state_ = STATE_CLOSE;
- }
- return result;
-}
-
-int SocketStream::DoReadWrite(int result) {
- if (result < OK) {
- next_state_ = STATE_CLOSE;
- return result;
- }
- if (!connection_->socket() || !connection_->socket()->IsConnected()) {
- next_state_ = STATE_CLOSE;
- return ERR_CONNECTION_CLOSED;
- }
-
- // If client has requested close(), and there's nothing to write, then
- // let's close the socket.
- // We don't care about receiving data after the socket is closed.
- if (closing_ && !current_write_buf_.get() && pending_write_bufs_.empty()) {
- connection_->socket()->Disconnect();
- next_state_ = STATE_CLOSE;
- return OK;
- }
-
- next_state_ = STATE_READ_WRITE;
-
- // If server already closed the socket, we don't try to read.
- if (!server_closed_) {
- if (!read_buf_.get()) {
- // No read pending and server didn't close the socket.
- read_buf_ = new IOBuffer(kReadBufferSize);
- result = connection_->socket()->Read(
- read_buf_.get(),
- kReadBufferSize,
- base::Bind(&SocketStream::OnReadCompleted, base::Unretained(this)));
- if (result > 0) {
- return DidReceiveData(result);
- } else if (result == 0) {
- // 0 indicates end-of-file, so socket was closed.
- next_state_ = STATE_CLOSE;
- server_closed_ = true;
- return ERR_CONNECTION_CLOSED;
- }
- // If read is pending, try write as well.
- // Otherwise, return the result and do next loop (to close the
- // connection).
- if (result != ERR_IO_PENDING) {
- next_state_ = STATE_CLOSE;
- server_closed_ = true;
- return result;
- }
- }
- // Read is pending.
- DCHECK(read_buf_.get());
- }
-
- if (waiting_for_write_completion_)
- return ERR_IO_PENDING;
-
- if (!current_write_buf_.get()) {
- if (pending_write_bufs_.empty()) {
- // Nothing buffered for send.
- return ERR_IO_PENDING;
- }
-
- current_write_buf_ = new DrainableIOBuffer(
- pending_write_bufs_.front().get(), pending_write_bufs_.front()->size());
- pending_write_bufs_.pop_front();
- }
-
- result = connection_->socket()->Write(
- current_write_buf_.get(),
- current_write_buf_->BytesRemaining(),
- base::Bind(&SocketStream::OnWriteCompleted, base::Unretained(this)));
-
- if (result == ERR_IO_PENDING) {
- waiting_for_write_completion_ = true;
- } else if (result < 0) {
- // Shortcut. Enter STATE_CLOSE now by changing next_state_ here than by
- // calling DoReadWrite() again with the error code.
- next_state_ = STATE_CLOSE;
- } else if (result > 0) {
- // Write is not pending. Return OK and do next loop.
- DidSendData(result);
- result = OK;
- }
-
- return result;
-}
-
-GURL SocketStream::ProxyAuthOrigin() const {
- DCHECK(!proxy_info_.is_empty());
- return GURL("http://" +
- proxy_info_.proxy_server().host_port_pair().ToString());
-}
-
-int SocketStream::HandleCertificateRequest(int result, SSLConfig* ssl_config) {
- if (ssl_config->send_client_cert) {
- // We already have performed SSL client authentication once and failed.
- return result;
- }
-
- DCHECK(connection_->socket());
- scoped_refptr<SSLCertRequestInfo> cert_request_info = new SSLCertRequestInfo;
- SSLClientSocket* ssl_socket =
- static_cast<SSLClientSocket*>(connection_->socket());
- ssl_socket->GetSSLCertRequestInfo(cert_request_info.get());
-
- HttpTransactionFactory* factory = context_->http_transaction_factory();
- if (!factory)
- return result;
- scoped_refptr<HttpNetworkSession> session = factory->GetSession();
- if (!session.get())
- return result;
-
- // If the user selected one of the certificates in client_certs or declined
- // to provide one for this server before, use the past decision
- // automatically.
- scoped_refptr<X509Certificate> client_cert;
- if (!session->ssl_client_auth_cache()->Lookup(
- cert_request_info->host_and_port, &client_cert)) {
- return result;
- }
-
- // Note: |client_cert| may be NULL, indicating that the caller
- // wishes to proceed anonymously (eg: continue the handshake
- // without sending a client cert)
- //
- // Check that the certificate selected is still a certificate the server
- // is likely to accept, based on the criteria supplied in the
- // CertificateRequest message.
- const std::vector<std::string>& cert_authorities =
- cert_request_info->cert_authorities;
- if (client_cert.get() && !cert_authorities.empty() &&
- !client_cert->IsIssuedByEncoded(cert_authorities)) {
- return result;
- }
-
- ssl_config->send_client_cert = true;
- ssl_config->client_cert = client_cert;
- next_state_ = STATE_TCP_CONNECT;
- return OK;
-}
-
-int SocketStream::AllowCertErrorForReconnection(SSLConfig* ssl_config) {
- DCHECK(ssl_config);
- // The SSL handshake didn't finish, or the server closed the SSL connection.
- // So, we should restart establishing connection with the certificate in
- // allowed bad certificates in |ssl_config|.
- // See also net/http/http_network_transaction.cc HandleCertificateError() and
- // RestartIgnoringLastError().
- SSLClientSocket* ssl_socket =
- static_cast<SSLClientSocket*>(connection_->socket());
- SSLInfo ssl_info;
- ssl_socket->GetSSLInfo(&ssl_info);
- if (ssl_info.cert.get() == NULL ||
- ssl_config->IsAllowedBadCert(ssl_info.cert.get(), NULL)) {
- // If we already have the certificate in the set of allowed bad
- // certificates, we did try it and failed again, so we should not
- // retry again: the connection should fail at last.
- next_state_ = STATE_CLOSE;
- return ERR_UNEXPECTED;
- }
- // Add the bad certificate to the set of allowed certificates in the
- // SSL config object.
- SSLConfig::CertAndStatus bad_cert;
- if (!X509Certificate::GetDEREncoded(ssl_info.cert->os_cert_handle(),
- &bad_cert.der_cert)) {
- next_state_ = STATE_CLOSE;
- return ERR_UNEXPECTED;
- }
- bad_cert.cert_status = ssl_info.cert_status;
- ssl_config->allowed_bad_certs.push_back(bad_cert);
- // Restart connection ignoring the bad certificate.
- connection_->socket()->Disconnect();
- connection_->SetSocket(scoped_ptr<StreamSocket>());
- next_state_ = STATE_TCP_CONNECT;
- return OK;
-}
-
-void SocketStream::DoAuthRequired() {
- if (delegate_ && proxy_auth_controller_.get())
- delegate_->OnAuthRequired(this, proxy_auth_controller_->auth_info().get());
- else
- DoLoop(ERR_UNEXPECTED);
-}
-
-void SocketStream::DoRestartWithAuth() {
- DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED);
- tunnel_request_headers_ = NULL;
- tunnel_request_headers_bytes_sent_ = 0;
- tunnel_response_headers_ = NULL;
- tunnel_response_headers_capacity_ = 0;
- tunnel_response_headers_len_ = 0;
-
- next_state_ = STATE_TCP_CONNECT;
- DoLoop(OK);
-}
-
-int SocketStream::HandleCertificateError(int result) {
- DCHECK(IsCertificateError(result));
- SSLClientSocket* ssl_socket =
- static_cast<SSLClientSocket*>(connection_->socket());
- DCHECK(ssl_socket);
-
- if (!context_)
- return result;
-
- if (SSLClientSocket::IgnoreCertError(result, LOAD_IGNORE_ALL_CERT_ERRORS)) {
- const HttpNetworkSession::Params* session_params =
- context_->GetNetworkSessionParams();
- if (session_params && session_params->ignore_certificate_errors)
- return OK;
- }
-
- if (!delegate_)
- return result;
-
- SSLInfo ssl_info;
- ssl_socket->GetSSLInfo(&ssl_info);
-
- TransportSecurityState* state = context_->transport_security_state();
- const bool fatal = state && state->ShouldSSLErrorsBeFatal(url_.host());
-
- delegate_->OnSSLCertificateError(this, ssl_info, fatal);
- return ERR_IO_PENDING;
-}
-
-CookieStore* SocketStream::cookie_store() const {
- return cookie_store_.get();
-}
-
-} // namespace net
diff --git a/net/socket_stream/socket_stream.h b/net/socket_stream/socket_stream.h
deleted file mode 100644
index 7387eb6..0000000
--- a/net/socket_stream/socket_stream.h
+++ /dev/null
@@ -1,404 +0,0 @@
-// Copyright (c) 2012 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 NET_SOCKET_STREAM_SOCKET_STREAM_H_
-#define NET_SOCKET_STREAM_SOCKET_STREAM_H_
-
-#include <deque>
-#include <map>
-#include <string>
-
-#include "base/memory/linked_ptr.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_export.h"
-#include "net/base/net_log.h"
-#include "net/base/privacy_mode.h"
-#include "net/cookies/cookie_store.h"
-#include "net/proxy/proxy_service.h"
-#include "net/ssl/ssl_config_service.h"
-#include "net/url_request/url_request.h"
-
-namespace net {
-
-class AuthChallengeInfo;
-class CertVerifier;
-class ChannelIDService;
-class ClientSocketFactory;
-class ClientSocketHandle;
-class CookieOptions;
-class HostResolver;
-class HttpAuthController;
-class SSLInfo;
-class SingleRequestHostResolver;
-class SocketStreamMetrics;
-class TransportSecurityState;
-class URLRequestContext;
-
-// SocketStream is used to implement Web Sockets.
-// It provides plain full-duplex stream with proxy and SSL support.
-// For proxy authentication, only basic mechanisum is supported. It will try
-// authentication identity for proxy URL first. If server requires proxy
-// authentication, it will try authentication identity for realm that server
-// requests.
-class NET_EXPORT SocketStream
- : public base::RefCountedThreadSafe<SocketStream> {
- public:
- // Derive from this class and add your own data members to associate extra
- // information with a SocketStream. Use GetUserData(key) and
- // SetUserData(key, data).
- class UserData {
- public:
- UserData() {}
- virtual ~UserData() {}
- };
-
- class NET_EXPORT Delegate {
- public:
- virtual int OnStartOpenConnection(SocketStream* socket,
- const CompletionCallback& callback);
-
- // Called when a socket stream has been connected. The socket stream is
- // allowed to buffer pending send data at most |max_pending_send_allowed|
- // bytes. A client of the socket stream should keep track of how much
- // pending send data it has and must not call SendData() if the pending
- // data goes over |max_pending_send_allowed| bytes.
- virtual void OnConnected(SocketStream* socket,
- int max_pending_send_allowed) = 0;
-
- // Called when |amount_sent| bytes of data are sent.
- virtual void OnSentData(SocketStream* socket,
- int amount_sent) = 0;
-
- // Called when |len| bytes of |data| are received.
- virtual void OnReceivedData(SocketStream* socket,
- const char* data, int len) = 0;
-
- // Called when the socket stream has been closed.
- virtual void OnClose(SocketStream* socket) = 0;
-
- // Called when proxy authentication required.
- // The delegate should call RestartWithAuth() if credential for |auth_info|
- // is found in password database, or call Close() to close the connection.
- virtual void OnAuthRequired(SocketStream* socket,
- AuthChallengeInfo* auth_info);
-
- // Called when using SSL and the server responds with a certificate with an
- // error. The delegate should call CancelBecauseOfCertError() or
- // ContinueDespiteCertError() to resume connection handling.
- virtual void OnSSLCertificateError(SocketStream* socket,
- const SSLInfo& ssl_info,
- bool fatal);
-
- // Called when an error occured.
- // This is only for error reporting to the delegate.
- // |error| is net::Error.
- virtual void OnError(const SocketStream* socket, int error) {}
-
- // Called when reading cookies to allow the delegate to block access to the
- // cookie.
- virtual bool CanGetCookies(SocketStream* socket, const GURL& url);
-
- // Called when a cookie is set to allow the delegate to block access to the
- // cookie.
- virtual bool CanSetCookie(SocketStream* request,
- const GURL& url,
- const std::string& cookie_line,
- CookieOptions* options);
-
- protected:
- virtual ~Delegate() {}
- };
-
- SocketStream(const GURL& url, Delegate* delegate, URLRequestContext* context,
- CookieStore* cookie_store);
-
- // The user data allows the clients to associate data with this job.
- // Multiple user data values can be stored under different keys.
- // This job will TAKE OWNERSHIP of the given data pointer, and will
- // delete the object if it is changed or the job is destroyed.
- UserData* GetUserData(const void* key) const;
- void SetUserData(const void* key, UserData* data);
-
- const GURL& url() const { return url_; }
- bool is_secure() const;
- const AddressList& address_list() const { return addresses_; }
- Delegate* delegate() const { return delegate_; }
- int max_pending_send_allowed() const { return max_pending_send_allowed_; }
-
- URLRequestContext* context() { return context_; }
-
- const SSLConfig& server_ssl_config() const { return server_ssl_config_; }
- PrivacyMode privacy_mode() const { return privacy_mode_; }
- void CheckPrivacyMode();
-
- BoundNetLog* net_log() { return &net_log_; }
-
- // Opens the connection on the IO thread.
- // Once the connection is established, calls delegate's OnConnected.
- virtual void Connect();
-
- // Buffers |data| of |len| bytes for send and returns true if successful.
- // If size of buffered data exceeds |max_pending_send_allowed_|, sends no
- // data and returns false. |len| must be positive.
- virtual bool SendData(const char* data, int len);
-
- // Requests to close the connection.
- // Once the connection is closed, calls delegate's OnClose.
- virtual void Close();
-
- // Restarts with authentication info.
- // Should be used for response of OnAuthRequired.
- virtual void RestartWithAuth(const AuthCredentials& credentials);
-
- // Detach delegate. Call before delegate is deleted.
- // Once delegate is detached, close the socket stream and never call delegate
- // back.
- virtual void DetachDelegate();
-
- // Detach the context.
- virtual void DetachContext();
-
- const ProxyServer& proxy_server() const;
-
- // Sets an alternative ClientSocketFactory. Doesn't take ownership of
- // |factory|. For testing purposes only.
- void SetClientSocketFactory(ClientSocketFactory* factory);
-
- // Cancels the connection because of an error.
- // |error| is net::Error which represents the error.
- void CancelWithError(int error);
-
- // Cancels the connection because of receiving a certificate with an error.
- void CancelWithSSLError(const SSLInfo& ssl_info);
-
- // Continues to establish the connection in spite of an error. Usually this
- // case happens because users allow certificate with an error by manual
- // actions on alert dialog or browser cached such kinds of user actions.
- void ContinueDespiteError();
-
- CookieStore* cookie_store() const;
-
- protected:
- friend class base::RefCountedThreadSafe<SocketStream>;
- virtual ~SocketStream();
-
- Delegate* delegate_;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, IOPending);
- FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, SwitchAfterPending);
- FRIEND_TEST_ALL_PREFIXES(SocketStreamTest,
- NullContextSocketStreamShouldNotCrash);
-
- friend class WebSocketThrottleTest;
-
- typedef std::map<const void*, linked_ptr<UserData> > UserDataMap;
- typedef std::deque< scoped_refptr<IOBufferWithSize> > PendingDataQueue;
-
- class RequestHeaders : public IOBuffer {
- public:
- RequestHeaders() : IOBuffer() {}
-
- void SetDataOffset(size_t offset) {
- data_ = const_cast<char*>(headers_.data()) + offset;
- }
-
- std::string headers_;
-
- private:
- ~RequestHeaders() override;
- };
-
- class ResponseHeaders : public IOBuffer {
- public:
- ResponseHeaders();
-
- void SetDataOffset(size_t offset) { data_ = headers_.get() + offset; }
- char* headers() const { return headers_.get(); }
- void Reset() { headers_.reset(); }
- void Realloc(size_t new_size);
-
- private:
- ~ResponseHeaders() override;
-
- scoped_ptr<char, base::FreeDeleter> headers_;
- };
-
- enum State {
- STATE_NONE,
- STATE_BEFORE_CONNECT,
- STATE_BEFORE_CONNECT_COMPLETE,
- STATE_RESOLVE_PROXY,
- STATE_RESOLVE_PROXY_COMPLETE,
- STATE_RESOLVE_HOST,
- STATE_RESOLVE_HOST_COMPLETE,
- STATE_RESOLVE_PROTOCOL,
- STATE_RESOLVE_PROTOCOL_COMPLETE,
- STATE_TCP_CONNECT,
- STATE_TCP_CONNECT_COMPLETE,
- STATE_GENERATE_PROXY_AUTH_TOKEN,
- STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE,
- STATE_WRITE_TUNNEL_HEADERS,
- STATE_WRITE_TUNNEL_HEADERS_COMPLETE,
- STATE_READ_TUNNEL_HEADERS,
- STATE_READ_TUNNEL_HEADERS_COMPLETE,
- STATE_SOCKS_CONNECT,
- STATE_SOCKS_CONNECT_COMPLETE,
- STATE_SECURE_PROXY_CONNECT,
- STATE_SECURE_PROXY_CONNECT_COMPLETE,
- STATE_SECURE_PROXY_HANDLE_CERT_ERROR,
- STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE,
- STATE_SSL_CONNECT,
- STATE_SSL_CONNECT_COMPLETE,
- STATE_SSL_HANDLE_CERT_ERROR,
- STATE_SSL_HANDLE_CERT_ERROR_COMPLETE,
- STATE_READ_WRITE,
- STATE_AUTH_REQUIRED,
- STATE_CLOSE,
- };
-
- enum ProxyMode {
- kDirectConnection, // If using a direct connection
- kTunnelProxy, // If using a tunnel (CONNECT method as HTTPS)
- kSOCKSProxy, // If using a SOCKS proxy
- };
-
- // Use the same number as HttpNetworkTransaction::kMaxHeaderBufSize.
- enum { kMaxTunnelResponseHeadersSize = 32768 }; // 32 kilobytes.
-
- // Used for WebSocketThrottleTest.
- void set_addresses(const AddressList& addresses);
-
- void DoClose();
-
- // Finishes the job.
- // Calls OnError and OnClose of delegate, and no more
- // notifications will be sent to delegate.
- void Finish(int result);
-
- int DidEstablishConnection();
- int DidReceiveData(int result);
- // Given the number of bytes sent,
- // - notifies the |delegate_| and |metrics_| of this event.
- // - drains sent data from |current_write_buf_|.
- // - if |current_write_buf_| has been fully sent, sets NULL to
- // |current_write_buf_| to get ready for next write.
- // and then, returns OK.
- void DidSendData(int result);
-
- void OnIOCompleted(int result);
- void OnReadCompleted(int result);
- void OnWriteCompleted(int result);
-
- void DoLoop(int result);
-
- int DoBeforeConnect();
- int DoBeforeConnectComplete(int result);
- int DoResolveProxy();
- int DoResolveProxyComplete(int result);
- int DoResolveHost();
- int DoResolveHostComplete(int result);
- int DoResolveProtocol(int result);
- int DoResolveProtocolComplete(int result);
- int DoTcpConnect(int result);
- int DoTcpConnectComplete(int result);
- int DoGenerateProxyAuthToken();
- int DoGenerateProxyAuthTokenComplete(int result);
- int DoWriteTunnelHeaders();
- int DoWriteTunnelHeadersComplete(int result);
- int DoReadTunnelHeaders();
- int DoReadTunnelHeadersComplete(int result);
- int DoSOCKSConnect();
- int DoSOCKSConnectComplete(int result);
- int DoSecureProxyConnect();
- int DoSecureProxyConnectComplete(int result);
- int DoSecureProxyHandleCertError(int result);
- int DoSecureProxyHandleCertErrorComplete(int result);
- int DoSSLConnect();
- int DoSSLConnectComplete(int result);
- int DoSSLHandleCertError(int result);
- int DoSSLHandleCertErrorComplete(int result);
- int DoReadWrite(int result);
-
- GURL ProxyAuthOrigin() const;
- int HandleAuthChallenge(const HttpResponseHeaders* headers);
- int HandleCertificateRequest(int result, SSLConfig* ssl_config);
- void DoAuthRequired();
- void DoRestartWithAuth();
-
- int HandleCertificateError(int result);
- int AllowCertErrorForReconnection(SSLConfig* ssl_config);
-
- // Returns the sum of the size of buffers in |pending_write_bufs_|.
- size_t GetTotalSizeOfPendingWriteBufs() const;
-
- BoundNetLog net_log_;
-
- GURL url_;
- // The number of bytes allowed to be buffered in this object. If the size of
- // buffered data which is
- // current_write_buf_.BytesRemaining() +
- // sum of the size of buffers in |pending_write_bufs_|
- // exceeds this limit, SendData() fails.
- int max_pending_send_allowed_;
- URLRequestContext* context_;
-
- UserDataMap user_data_;
-
- State next_state_;
- ClientSocketFactory* factory_;
-
- ProxyMode proxy_mode_;
-
- GURL proxy_url_;
- ProxyService::PacRequest* pac_request_;
- ProxyInfo proxy_info_;
-
- scoped_refptr<HttpAuthController> proxy_auth_controller_;
-
- scoped_refptr<RequestHeaders> tunnel_request_headers_;
- size_t tunnel_request_headers_bytes_sent_;
- scoped_refptr<ResponseHeaders> tunnel_response_headers_;
- int tunnel_response_headers_capacity_;
- int tunnel_response_headers_len_;
-
- scoped_ptr<SingleRequestHostResolver> resolver_;
- AddressList addresses_;
- scoped_ptr<ClientSocketHandle> connection_;
-
- SSLConfig server_ssl_config_;
- SSLConfig proxy_ssl_config_;
- PrivacyMode privacy_mode_;
-
- CompletionCallback io_callback_;
-
- scoped_refptr<IOBuffer> read_buf_;
- int read_buf_size_;
-
- // Buffer to hold data to pass to socket_.
- scoped_refptr<DrainableIOBuffer> current_write_buf_;
- // True iff there's no error and this instance is waiting for completion of
- // Write operation by socket_.
- bool waiting_for_write_completion_;
- PendingDataQueue pending_write_bufs_;
-
- bool closing_;
- bool server_closed_;
-
- scoped_ptr<SocketStreamMetrics> metrics_;
-
- // Cookie store to use for this socket stream.
- scoped_refptr<CookieStore> cookie_store_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStream);
-};
-
-} // namespace net
-
-#endif // NET_SOCKET_STREAM_SOCKET_STREAM_H_
diff --git a/net/socket_stream/socket_stream_job.cc b/net/socket_stream/socket_stream_job.cc
deleted file mode 100644
index 66da741..0000000
--- a/net/socket_stream/socket_stream_job.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2012 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 "net/socket_stream/socket_stream_job.h"
-
-#include "base/memory/singleton.h"
-#include "net/http/transport_security_state.h"
-#include "net/socket_stream/socket_stream_job_manager.h"
-#include "net/ssl/ssl_config_service.h"
-#include "net/url_request/url_request_context.h"
-
-namespace net {
-
-// static
-SocketStreamJob::ProtocolFactory* SocketStreamJob::RegisterProtocolFactory(
- const std::string& scheme, ProtocolFactory* factory) {
- return SocketStreamJobManager::GetInstance()->RegisterProtocolFactory(
- scheme, factory);
-}
-
-// static
-SocketStreamJob* SocketStreamJob::CreateSocketStreamJob(
- const GURL& url,
- SocketStream::Delegate* delegate,
- TransportSecurityState* sts,
- SSLConfigService* ssl,
- URLRequestContext* context,
- CookieStore* cookie_store) {
- GURL socket_url(url);
- if (url.scheme() == "ws" && sts &&
- sts->ShouldUpgradeToSSL(url.host())) {
- url::Replacements<char> replacements;
- static const char kNewScheme[] = "wss";
- replacements.SetScheme(kNewScheme, url::Component(0, strlen(kNewScheme)));
- socket_url = url.ReplaceComponents(replacements);
- }
- return SocketStreamJobManager::GetInstance()->CreateJob(
- socket_url, delegate, context, cookie_store);
-}
-
-SocketStreamJob::SocketStreamJob() {}
-
-SocketStream::UserData* SocketStreamJob::GetUserData(const void* key) const {
- return socket_->GetUserData(key);
-}
-
-void SocketStreamJob::SetUserData(const void* key,
- SocketStream::UserData* data) {
- socket_->SetUserData(key, data);
-}
-
-void SocketStreamJob::Connect() {
- socket_->Connect();
-}
-
-bool SocketStreamJob::SendData(const char* data, int len) {
- return socket_->SendData(data, len);
-}
-
-void SocketStreamJob::Close() {
- socket_->Close();
-}
-
-void SocketStreamJob::RestartWithAuth(const AuthCredentials& credentials) {
- socket_->RestartWithAuth(credentials);
-}
-
-void SocketStreamJob::CancelWithError(int error) {
- socket_->CancelWithError(error);
-}
-
-void SocketStreamJob::CancelWithSSLError(const net::SSLInfo& ssl_info) {
- socket_->CancelWithSSLError(ssl_info);
-}
-
-void SocketStreamJob::ContinueDespiteError() {
- socket_->ContinueDespiteError();
-}
-
-void SocketStreamJob::DetachDelegate() {
- socket_->DetachDelegate();
-}
-
-void SocketStreamJob::DetachContext() {
- if (socket_.get())
- socket_->DetachContext();
-}
-
-SocketStreamJob::~SocketStreamJob() {}
-
-} // namespace net
diff --git a/net/socket_stream/socket_stream_job.h b/net/socket_stream/socket_stream_job.h
deleted file mode 100644
index 9fc27d9..0000000
--- a/net/socket_stream/socket_stream_job.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2012 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 NET_SOCKET_STREAM_SOCKET_STREAM_JOB_H_
-#define NET_SOCKET_STREAM_SOCKET_STREAM_JOB_H_
-
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "net/base/net_export.h"
-#include "net/socket_stream/socket_stream.h"
-
-class GURL;
-
-namespace net {
-
-class CookieStore;
-class SSLConfigService;
-class SSLInfo;
-class TransportSecurityState;
-
-// SocketStreamJob represents full-duplex communication over SocketStream.
-// If a protocol (e.g. WebSocket protocol) needs to inspect/modify data
-// over SocketStream, you can implement protocol specific job (e.g.
-// WebSocketJob) to do some work on data over SocketStream.
-// Registers the protocol specific SocketStreamJob by RegisterProtocolFactory
-// and call CreateSocketStreamJob to create SocketStreamJob for the URL.
-class NET_EXPORT SocketStreamJob
- : public base::RefCountedThreadSafe<SocketStreamJob> {
- public:
- // Callback function implemented by protocol handlers to create new jobs.
- typedef SocketStreamJob* (ProtocolFactory)(const GURL& url,
- SocketStream::Delegate* delegate,
- URLRequestContext* context,
- CookieStore* cookie_store);
-
- static ProtocolFactory* RegisterProtocolFactory(const std::string& scheme,
- ProtocolFactory* factory);
-
- static SocketStreamJob* CreateSocketStreamJob(
- const GURL& url,
- SocketStream::Delegate* delegate,
- TransportSecurityState* sts,
- SSLConfigService* ssl,
- URLRequestContext* context,
- CookieStore* cookie_store);
-
- SocketStreamJob();
- void InitSocketStream(SocketStream* socket) {
- socket_ = socket;
- }
-
- virtual SocketStream::UserData* GetUserData(const void* key) const;
- virtual void SetUserData(const void* key, SocketStream::UserData* data);
-
- URLRequestContext* context() const {
- return socket_.get() ? socket_->context() : 0;
- }
- CookieStore* cookie_store() const {
- return socket_.get() ? socket_->cookie_store() : 0;
- }
-
- virtual void Connect();
-
- virtual bool SendData(const char* data, int len);
-
- virtual void Close();
-
- virtual void RestartWithAuth(const AuthCredentials& credentials);
-
- virtual void CancelWithError(int error);
-
- virtual void CancelWithSSLError(const net::SSLInfo& ssl_info);
-
- virtual void ContinueDespiteError();
-
- virtual void DetachDelegate();
-
- virtual void DetachContext();
-
- protected:
- friend class WebSocketJobTest;
- friend class base::RefCountedThreadSafe<SocketStreamJob>;
- virtual ~SocketStreamJob();
-
- scoped_refptr<SocketStream> socket_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamJob);
-};
-
-} // namespace net
-
-#endif // NET_SOCKET_STREAM_SOCKET_STREAM_JOB_H_
diff --git a/net/socket_stream/socket_stream_job_manager.cc b/net/socket_stream/socket_stream_job_manager.cc
deleted file mode 100644
index 6418be4..0000000
--- a/net/socket_stream/socket_stream_job_manager.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2011 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 "net/socket_stream/socket_stream_job_manager.h"
-
-#include "base/memory/singleton.h"
-
-namespace net {
-
-SocketStreamJobManager::SocketStreamJobManager() {
-}
-
-SocketStreamJobManager::~SocketStreamJobManager() {
-}
-
-// static
-SocketStreamJobManager* SocketStreamJobManager::GetInstance() {
- return Singleton<SocketStreamJobManager>::get();
-}
-
-SocketStreamJob* SocketStreamJobManager::CreateJob(
- const GURL& url, SocketStream::Delegate* delegate,
- URLRequestContext* context, CookieStore* cookie_store) const {
- // If url is invalid, create plain SocketStreamJob, which will close
- // the socket immediately.
- if (!url.is_valid()) {
- SocketStreamJob* job = new SocketStreamJob();
- job->InitSocketStream(new SocketStream(url, delegate, context,
- cookie_store));
- return job;
- }
-
- const std::string& scheme = url.scheme(); // already lowercase
-
- base::AutoLock locked(lock_);
- FactoryMap::const_iterator found = factories_.find(scheme);
- if (found != factories_.end()) {
- SocketStreamJob* job = found->second(url, delegate, context, cookie_store);
- if (job)
- return job;
- }
- SocketStreamJob* job = new SocketStreamJob();
- job->InitSocketStream(new SocketStream(url, delegate, context, cookie_store));
- return job;
-}
-
-SocketStreamJob::ProtocolFactory*
-SocketStreamJobManager::RegisterProtocolFactory(
- const std::string& scheme, SocketStreamJob::ProtocolFactory* factory) {
- base::AutoLock locked(lock_);
-
- SocketStreamJob::ProtocolFactory* old_factory;
- FactoryMap::iterator found = factories_.find(scheme);
- if (found != factories_.end()) {
- old_factory = found->second;
- } else {
- old_factory = NULL;
- }
- if (factory) {
- factories_[scheme] = factory;
- } else if (found != factories_.end()) {
- factories_.erase(found);
- }
- return old_factory;
-}
-
-} // namespace net
diff --git a/net/socket_stream/socket_stream_job_manager.h b/net/socket_stream/socket_stream_job_manager.h
deleted file mode 100644
index 2363fb5..0000000
--- a/net/socket_stream/socket_stream_job_manager.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2010 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 NET_SOCKET_STREAM_SOCKET_STREAM_JOB_MANAGER_H_
-#define NET_SOCKET_STREAM_SOCKET_STREAM_JOB_MANAGER_H_
-
-#include <map>
-#include <string>
-
-#include "net/socket_stream/socket_stream.h"
-#include "net/socket_stream/socket_stream_job.h"
-
-template <typename T> struct DefaultSingletonTraits;
-class GURL;
-
-namespace net {
-
-class SocketStreamJobManager {
- public:
- // Returns the singleton instance.
- static SocketStreamJobManager* GetInstance();
-
- SocketStreamJob* CreateJob(
- const GURL& url, SocketStream::Delegate* delegate,
- URLRequestContext* context, CookieStore* cookie_store) const;
-
- SocketStreamJob::ProtocolFactory* RegisterProtocolFactory(
- const std::string& scheme, SocketStreamJob::ProtocolFactory* factory);
-
- private:
- friend struct DefaultSingletonTraits<SocketStreamJobManager>;
- typedef std::map<std::string, SocketStreamJob::ProtocolFactory*> FactoryMap;
-
- SocketStreamJobManager();
- ~SocketStreamJobManager();
-
- mutable base::Lock lock_;
- FactoryMap factories_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamJobManager);
-};
-
-} // namespace net
-
-#endif // NET_SOCKET_STREAM_SOCKET_STREAM_JOB_MANAGER_H_
diff --git a/net/socket_stream/socket_stream_metrics.cc b/net/socket_stream/socket_stream_metrics.cc
deleted file mode 100644
index e026887..0000000
--- a/net/socket_stream/socket_stream_metrics.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2011 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 "net/socket_stream/socket_stream_metrics.h"
-
-#include <string.h>
-
-#include "base/metrics/histogram.h"
-#include "base/time/time.h"
-#include "url/gurl.h"
-
-namespace net {
-
-SocketStreamMetrics::SocketStreamMetrics(const GURL& url)
- : received_bytes_(0),
- received_counts_(0),
- sent_bytes_(0),
- sent_counts_(0) {
- ProtocolType protocol_type = PROTOCOL_UNKNOWN;
- if (url.SchemeIs("ws"))
- protocol_type = PROTOCOL_WEBSOCKET;
- else if (url.SchemeIs("wss"))
- protocol_type = PROTOCOL_WEBSOCKET_SECURE;
-
- UMA_HISTOGRAM_ENUMERATION("Net.SocketStream.ProtocolType",
- protocol_type, NUM_PROTOCOL_TYPES);
-}
-
-SocketStreamMetrics::~SocketStreamMetrics() {}
-
-void SocketStreamMetrics::OnWaitConnection() {
- wait_start_time_ = base::TimeTicks::Now();
-}
-
-void SocketStreamMetrics::OnStartConnection() {
- connect_start_time_ = base::TimeTicks::Now();
- if (!wait_start_time_.is_null())
- UMA_HISTOGRAM_TIMES("Net.SocketStream.ConnectionLatency",
- connect_start_time_ - wait_start_time_);
- OnCountConnectionType(ALL_CONNECTIONS);
-}
-
-void SocketStreamMetrics::OnConnected() {
- connect_establish_time_ = base::TimeTicks::Now();
- UMA_HISTOGRAM_TIMES("Net.SocketStream.ConnectionEstablish",
- connect_establish_time_ - connect_start_time_);
-}
-
-void SocketStreamMetrics::OnRead(int len) {
- received_bytes_ += len;
- ++received_counts_;
-}
-
-void SocketStreamMetrics::OnWrite(int len) {
- sent_bytes_ += len;
- ++sent_counts_;
-}
-
-void SocketStreamMetrics::OnClose() {
- base::TimeTicks closed_time = base::TimeTicks::Now();
- if (!connect_establish_time_.is_null()) {
- UMA_HISTOGRAM_LONG_TIMES("Net.SocketStream.Duration",
- closed_time - connect_establish_time_);
- UMA_HISTOGRAM_COUNTS("Net.SocketStream.ReceivedBytes",
- received_bytes_);
- UMA_HISTOGRAM_COUNTS("Net.SocketStream.ReceivedCounts",
- received_counts_);
- UMA_HISTOGRAM_COUNTS("Net.SocketStream.SentBytes",
- sent_bytes_);
- UMA_HISTOGRAM_COUNTS("Net.SocketStream.SentCounts",
- sent_counts_);
- }
-}
-
-void SocketStreamMetrics::OnCountConnectionType(ConnectionType type) {
- UMA_HISTOGRAM_ENUMERATION("Net.SocketStream.ConnectionType", type,
- NUM_CONNECTION_TYPES);
-}
-
-void SocketStreamMetrics::OnCountWireProtocolType(WireProtocolType type) {
- UMA_HISTOGRAM_ENUMERATION("Net.SocketStream.WireProtocolType", type,
- NUM_WIRE_PROTOCOL_TYPES);
-}
-
-} // namespace net
diff --git a/net/socket_stream/socket_stream_metrics.h b/net/socket_stream/socket_stream_metrics.h
deleted file mode 100644
index 0040a9a..0000000
--- a/net/socket_stream/socket_stream_metrics.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2011 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.
-//
-// Collect metrics of SocketStream usage.
-// TODO(ukai): collect WebSocket specific metrics (e.g. handshake time, etc).
-
-#ifndef NET_SOCKET_STREAM_SOCKET_STREAM_METRICS_H_
-#define NET_SOCKET_STREAM_SOCKET_STREAM_METRICS_H_
-
-#include "base/basictypes.h"
-#include "base/time/time.h"
-#include "net/base/net_export.h"
-
-class GURL;
-
-namespace net {
-
-class NET_EXPORT_PRIVATE SocketStreamMetrics {
- public:
- enum ProtocolType {
- PROTOCOL_UNKNOWN,
- PROTOCOL_WEBSOCKET,
- PROTOCOL_WEBSOCKET_SECURE,
- NUM_PROTOCOL_TYPES,
- };
-
- enum ConnectionType {
- CONNECTION_NONE,
- ALL_CONNECTIONS,
- TUNNEL_CONNECTION,
- SOCKS_CONNECTION,
- SSL_CONNECTION,
- SECURE_PROXY_CONNECTION,
- NUM_CONNECTION_TYPES,
- };
-
- enum WireProtocolType {
- WIRE_PROTOCOL_WEBSOCKET,
- WIRE_PROTOCOL_SPDY,
- NUM_WIRE_PROTOCOL_TYPES,
- };
-
- explicit SocketStreamMetrics(const GURL& url);
- ~SocketStreamMetrics();
-
- void OnWaitConnection();
- void OnStartConnection();
- void OnConnected();
- void OnRead(int len);
- void OnWrite(int len);
- void OnClose();
- void OnCountConnectionType(ConnectionType type);
- void OnCountWireProtocolType(WireProtocolType type);
-
- private:
- base::TimeTicks wait_start_time_;
- base::TimeTicks connect_start_time_;
- base::TimeTicks connect_establish_time_;
- int received_bytes_;
- int received_counts_;
- int sent_bytes_;
- int sent_counts_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamMetrics);
-};
-
-} // namespace net
-
-#endif // NET_SOCKET_STREAM_SOCKET_STREAM_METRICS_H_
diff --git a/net/socket_stream/socket_stream_metrics_unittest.cc b/net/socket_stream/socket_stream_metrics_unittest.cc
deleted file mode 100644
index 219e692..0000000
--- a/net/socket_stream/socket_stream_metrics_unittest.cc
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright (c) 2012 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 "net/socket_stream/socket_stream_metrics.h"
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/metrics/statistics_recorder.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "url/gurl.h"
-
-using base::Histogram;
-using base::HistogramBase;
-using base::HistogramSamples;
-using base::StatisticsRecorder;
-
-namespace net {
-
-TEST(SocketStreamMetricsTest, ProtocolType) {
- // First we'll preserve the original values. We need to do this
- // as histograms can get affected by other tests. In particular,
- // SocketStreamTest and WebSocketTest can affect the histograms.
- scoped_ptr<HistogramSamples> original;
- HistogramBase* histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ProtocolType");
- if (histogram) {
- original = histogram->SnapshotSamples();
- }
-
- SocketStreamMetrics unknown(GURL("unknown://www.example.com/"));
- SocketStreamMetrics ws1(GURL("ws://www.example.com/"));
- SocketStreamMetrics ws2(GURL("ws://www.example.com/"));
- SocketStreamMetrics wss1(GURL("wss://www.example.com/"));
- SocketStreamMetrics wss2(GURL("wss://www.example.com/"));
- SocketStreamMetrics wss3(GURL("wss://www.example.com/"));
-
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ProtocolType");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
-
- scoped_ptr<HistogramSamples> samples(histogram->SnapshotSamples());
- if (original.get()) {
- samples->Subtract(*original); // Cancel the original values.
- }
- EXPECT_EQ(1, samples->GetCount(SocketStreamMetrics::PROTOCOL_UNKNOWN));
- EXPECT_EQ(2, samples->GetCount(SocketStreamMetrics::PROTOCOL_WEBSOCKET));
- EXPECT_EQ(3,
- samples->GetCount(SocketStreamMetrics::PROTOCOL_WEBSOCKET_SECURE));
-}
-
-TEST(SocketStreamMetricsTest, ConnectionType) {
- // First we'll preserve the original values.
- scoped_ptr<HistogramSamples> original;
- HistogramBase* histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ConnectionType");
- if (histogram) {
- original = histogram->SnapshotSamples();
- }
-
- SocketStreamMetrics metrics(GURL("ws://www.example.com/"));
- for (int i = 0; i < 1; ++i)
- metrics.OnStartConnection();
- for (int i = 0; i < 2; ++i)
- metrics.OnCountConnectionType(SocketStreamMetrics::TUNNEL_CONNECTION);
- for (int i = 0; i < 3; ++i)
- metrics.OnCountConnectionType(SocketStreamMetrics::SOCKS_CONNECTION);
- for (int i = 0; i < 4; ++i)
- metrics.OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION);
-
-
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ConnectionType");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
-
- scoped_ptr<HistogramSamples> samples(histogram->SnapshotSamples());
- if (original.get()) {
- samples->Subtract(*original); // Cancel the original values.
- }
- EXPECT_EQ(1, samples->GetCount(SocketStreamMetrics::ALL_CONNECTIONS));
- EXPECT_EQ(2, samples->GetCount(SocketStreamMetrics::TUNNEL_CONNECTION));
- EXPECT_EQ(3, samples->GetCount(SocketStreamMetrics::SOCKS_CONNECTION));
- EXPECT_EQ(4, samples->GetCount(SocketStreamMetrics::SSL_CONNECTION));
-}
-
-TEST(SocketStreamMetricsTest, WireProtocolType) {
- // First we'll preserve the original values.
- scoped_ptr<HistogramSamples> original;
- HistogramBase* histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.WireProtocolType");
- if (histogram) {
- original = histogram->SnapshotSamples();
- }
-
- SocketStreamMetrics metrics(GURL("ws://www.example.com/"));
- for (int i = 0; i < 3; ++i)
- metrics.OnCountWireProtocolType(
- SocketStreamMetrics::WIRE_PROTOCOL_WEBSOCKET);
- for (int i = 0; i < 7; ++i)
- metrics.OnCountWireProtocolType(SocketStreamMetrics::WIRE_PROTOCOL_SPDY);
-
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.WireProtocolType");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
-
- scoped_ptr<HistogramSamples> samples(histogram->SnapshotSamples());
- if (original.get()) {
- samples->Subtract(*original); // Cancel the original values.
- }
- EXPECT_EQ(3, samples->GetCount(SocketStreamMetrics::WIRE_PROTOCOL_WEBSOCKET));
- EXPECT_EQ(7, samples->GetCount(SocketStreamMetrics::WIRE_PROTOCOL_SPDY));
-}
-
-TEST(SocketStreamMetricsTest, OtherNumbers) {
- // First we'll preserve the original values.
- int64 original_received_bytes = 0;
- int64 original_received_counts = 0;
- int64 original_sent_bytes = 0;
- int64 original_sent_counts = 0;
-
- scoped_ptr<HistogramSamples> original;
-
- HistogramBase* histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ReceivedBytes");
- if (histogram) {
- original = histogram->SnapshotSamples();
- original_received_bytes = original->sum();
- }
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ReceivedCounts");
- if (histogram) {
- original = histogram->SnapshotSamples();
- original_received_counts = original->sum();
- }
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.SentBytes");
- if (histogram) {
- original = histogram->SnapshotSamples();
- original_sent_bytes = original->sum();
- }
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.SentCounts");
- if (histogram) {
- original = histogram->SnapshotSamples();
- original_sent_counts = original->sum();
- }
-
- SocketStreamMetrics metrics(GURL("ws://www.example.com/"));
- metrics.OnWaitConnection();
- metrics.OnStartConnection();
- metrics.OnConnected();
- metrics.OnRead(1);
- metrics.OnRead(10);
- metrics.OnWrite(2);
- metrics.OnWrite(20);
- metrics.OnWrite(200);
- metrics.OnClose();
-
- scoped_ptr<HistogramSamples> samples;
-
- // ConnectionLatency.
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ConnectionLatency");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
- // We don't check the contents of the histogram as it's time sensitive.
-
- // ConnectionEstablish.
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ConnectionEstablish");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
- // We don't check the contents of the histogram as it's time sensitive.
-
- // Duration.
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.Duration");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
- // We don't check the contents of the histogram as it's time sensitive.
-
- // ReceivedBytes.
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ReceivedBytes");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
- samples = histogram->SnapshotSamples();
- EXPECT_EQ(11, samples->sum() - original_received_bytes); // 11 bytes read.
-
- // ReceivedCounts.
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.ReceivedCounts");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
- samples = histogram->SnapshotSamples();
- EXPECT_EQ(2, samples->sum() - original_received_counts); // 2 read requests.
-
- // SentBytes.
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.SentBytes");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
- samples = histogram->SnapshotSamples();
- EXPECT_EQ(222, samples->sum() - original_sent_bytes); // 222 bytes sent.
-
- // SentCounts.
- histogram =
- StatisticsRecorder::FindHistogram("Net.SocketStream.SentCounts");
- ASSERT_TRUE(histogram != NULL);
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histogram->flags());
- samples = histogram->SnapshotSamples();
- EXPECT_EQ(3, samples->sum() - original_sent_counts); // 3 write requests.
-}
-
-} // namespace net
diff --git a/net/socket_stream/socket_stream_unittest.cc b/net/socket_stream/socket_stream_unittest.cc
deleted file mode 100644
index b5ee002..0000000
--- a/net/socket_stream/socket_stream_unittest.cc
+++ /dev/null
@@ -1,1041 +0,0 @@
-// Copyright (c) 2012 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 "net/socket_stream/socket_stream.h"
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/strings/utf_string_conversions.h"
-#include "net/base/auth.h"
-#include "net/base/net_log.h"
-#include "net/base/net_log_unittest.h"
-#include "net/base/test_completion_callback.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/http/http_network_session.h"
-#include "net/proxy/proxy_service.h"
-#include "net/socket/socket_test_util.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-using base::ASCIIToUTF16;
-
-namespace net {
-
-namespace {
-
-struct SocketStreamEvent {
- enum EventType {
- EVENT_START_OPEN_CONNECTION, EVENT_CONNECTED, EVENT_SENT_DATA,
- EVENT_RECEIVED_DATA, EVENT_CLOSE, EVENT_AUTH_REQUIRED, EVENT_ERROR,
- };
-
- SocketStreamEvent(EventType type,
- SocketStream* socket_stream,
- int num,
- const std::string& str,
- AuthChallengeInfo* auth_challenge_info,
- int error)
- : event_type(type), socket(socket_stream), number(num), data(str),
- auth_info(auth_challenge_info), error_code(error) {}
-
- EventType event_type;
- SocketStream* socket;
- int number;
- std::string data;
- scoped_refptr<AuthChallengeInfo> auth_info;
- int error_code;
-};
-
-class SocketStreamEventRecorder : public SocketStream::Delegate {
- public:
- // |callback| will be run when the OnClose() or OnError() method is called.
- // For OnClose(), |callback| is called with OK. For OnError(), it's called
- // with the error code.
- explicit SocketStreamEventRecorder(const CompletionCallback& callback)
- : callback_(callback) {}
- ~SocketStreamEventRecorder() override {}
-
- void SetOnStartOpenConnection(
- const base::Callback<int(SocketStreamEvent*)>& callback) {
- on_start_open_connection_ = callback;
- }
- void SetOnConnected(
- const base::Callback<void(SocketStreamEvent*)>& callback) {
- on_connected_ = callback;
- }
- void SetOnSentData(
- const base::Callback<void(SocketStreamEvent*)>& callback) {
- on_sent_data_ = callback;
- }
- void SetOnReceivedData(
- const base::Callback<void(SocketStreamEvent*)>& callback) {
- on_received_data_ = callback;
- }
- void SetOnClose(const base::Callback<void(SocketStreamEvent*)>& callback) {
- on_close_ = callback;
- }
- void SetOnAuthRequired(
- const base::Callback<void(SocketStreamEvent*)>& callback) {
- on_auth_required_ = callback;
- }
- void SetOnError(const base::Callback<void(SocketStreamEvent*)>& callback) {
- on_error_ = callback;
- }
-
- int OnStartOpenConnection(SocketStream* socket,
- const CompletionCallback& callback) override {
- connection_callback_ = callback;
- events_.push_back(
- SocketStreamEvent(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- socket, 0, std::string(), NULL, OK));
- if (!on_start_open_connection_.is_null())
- return on_start_open_connection_.Run(&events_.back());
- return OK;
- }
- void OnConnected(SocketStream* socket,
- int num_pending_send_allowed) override {
- events_.push_back(
- SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED,
- socket, num_pending_send_allowed, std::string(),
- NULL, OK));
- if (!on_connected_.is_null())
- on_connected_.Run(&events_.back());
- }
- void OnSentData(SocketStream* socket, int amount_sent) override {
- events_.push_back(
- SocketStreamEvent(SocketStreamEvent::EVENT_SENT_DATA, socket,
- amount_sent, std::string(), NULL, OK));
- if (!on_sent_data_.is_null())
- on_sent_data_.Run(&events_.back());
- }
- void OnReceivedData(SocketStream* socket,
- const char* data,
- int len) override {
- events_.push_back(
- SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA, socket, len,
- std::string(data, len), NULL, OK));
- if (!on_received_data_.is_null())
- on_received_data_.Run(&events_.back());
- }
- void OnClose(SocketStream* socket) override {
- events_.push_back(
- SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE, socket, 0,
- std::string(), NULL, OK));
- if (!on_close_.is_null())
- on_close_.Run(&events_.back());
- if (!callback_.is_null())
- callback_.Run(OK);
- }
- void OnAuthRequired(SocketStream* socket,
- AuthChallengeInfo* auth_info) override {
- events_.push_back(
- SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED, socket, 0,
- std::string(), auth_info, OK));
- if (!on_auth_required_.is_null())
- on_auth_required_.Run(&events_.back());
- }
- void OnError(const SocketStream* socket, int error) override {
- events_.push_back(
- SocketStreamEvent(SocketStreamEvent::EVENT_ERROR, NULL, 0,
- std::string(), NULL, error));
- if (!on_error_.is_null())
- on_error_.Run(&events_.back());
- if (!callback_.is_null())
- callback_.Run(error);
- }
-
- void DoClose(SocketStreamEvent* event) {
- event->socket->Close();
- }
- void DoRestartWithAuth(SocketStreamEvent* event) {
- VLOG(1) << "RestartWithAuth username=" << credentials_.username()
- << " password=" << credentials_.password();
- event->socket->RestartWithAuth(credentials_);
- }
- void SetAuthInfo(const AuthCredentials& credentials) {
- credentials_ = credentials;
- }
- // Wakes up the SocketStream waiting for completion of OnStartOpenConnection()
- // of its delegate.
- void CompleteConnection(int result) {
- connection_callback_.Run(result);
- }
-
- const std::vector<SocketStreamEvent>& GetSeenEvents() const {
- return events_;
- }
-
- private:
- std::vector<SocketStreamEvent> events_;
- base::Callback<int(SocketStreamEvent*)> on_start_open_connection_;
- base::Callback<void(SocketStreamEvent*)> on_connected_;
- base::Callback<void(SocketStreamEvent*)> on_sent_data_;
- base::Callback<void(SocketStreamEvent*)> on_received_data_;
- base::Callback<void(SocketStreamEvent*)> on_close_;
- base::Callback<void(SocketStreamEvent*)> on_auth_required_;
- base::Callback<void(SocketStreamEvent*)> on_error_;
- const CompletionCallback callback_;
- CompletionCallback connection_callback_;
- AuthCredentials credentials_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder);
-};
-
-// This is used for the test OnErrorDetachDelegate.
-class SelfDeletingDelegate : public SocketStream::Delegate {
- public:
- // |callback| must cause the test message loop to exit when called.
- explicit SelfDeletingDelegate(const CompletionCallback& callback)
- : socket_stream_(), callback_(callback) {}
-
- ~SelfDeletingDelegate() override {}
-
- // Call DetachDelegate(), delete |this|, then run the callback.
- void OnError(const SocketStream* socket, int error) override {
- // callback_ will be deleted when we delete |this|, so copy it to call it
- // afterwards.
- CompletionCallback callback = callback_;
- socket_stream_->DetachDelegate();
- delete this;
- callback.Run(OK);
- }
-
- // This can't be passed in the constructor because this object needs to be
- // created before SocketStream.
- void set_socket_stream(const scoped_refptr<SocketStream>& socket_stream) {
- socket_stream_ = socket_stream;
- EXPECT_EQ(socket_stream_->delegate(), this);
- }
-
- void OnConnected(SocketStream* socket,
- int max_pending_send_allowed) override {
- ADD_FAILURE() << "OnConnected() should not be called";
- }
- void OnSentData(SocketStream* socket, int amount_sent) override {
- ADD_FAILURE() << "OnSentData() should not be called";
- }
- void OnReceivedData(SocketStream* socket,
- const char* data,
- int len) override {
- ADD_FAILURE() << "OnReceivedData() should not be called";
- }
- void OnClose(SocketStream* socket) override {
- ADD_FAILURE() << "OnClose() should not be called";
- }
-
- private:
- scoped_refptr<SocketStream> socket_stream_;
- const CompletionCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(SelfDeletingDelegate);
-};
-
-class TestURLRequestContextWithProxy : public TestURLRequestContext {
- public:
- explicit TestURLRequestContextWithProxy(const std::string& proxy)
- : TestURLRequestContext(true) {
- context_storage_.set_proxy_service(ProxyService::CreateFixed(proxy));
- Init();
- }
- ~TestURLRequestContextWithProxy() override {}
-};
-
-class TestSocketStreamNetworkDelegate : public TestNetworkDelegate {
- public:
- TestSocketStreamNetworkDelegate()
- : before_connect_result_(OK) {}
- ~TestSocketStreamNetworkDelegate() override {}
-
- int OnBeforeSocketStreamConnect(SocketStream* stream,
- const CompletionCallback& callback) override {
- return before_connect_result_;
- }
-
- void SetBeforeConnectResult(int result) {
- before_connect_result_ = result;
- }
-
- private:
- int before_connect_result_;
-};
-
-} // namespace
-
-class SocketStreamTest : public PlatformTest {
- public:
- ~SocketStreamTest() override {}
- void SetUp() override {
- mock_socket_factory_.reset();
- handshake_request_ = kWebSocketHandshakeRequest;
- handshake_response_ = kWebSocketHandshakeResponse;
- }
- void TearDown() override { mock_socket_factory_.reset(); }
-
- virtual void SetWebSocketHandshakeMessage(
- const char* request, const char* response) {
- handshake_request_ = request;
- handshake_response_ = response;
- }
- virtual void AddWebSocketMessage(const std::string& message) {
- messages_.push_back(message);
- }
-
- virtual MockClientSocketFactory* GetMockClientSocketFactory() {
- mock_socket_factory_.reset(new MockClientSocketFactory);
- return mock_socket_factory_.get();
- }
-
- // Functions for SocketStreamEventRecorder to handle calls to the
- // SocketStream::Delegate methods from the SocketStream.
-
- virtual void DoSendWebSocketHandshake(SocketStreamEvent* event) {
- event->socket->SendData(
- handshake_request_.data(), handshake_request_.size());
- }
-
- virtual void DoCloseFlushPendingWriteTest(SocketStreamEvent* event) {
- // handshake response received.
- for (size_t i = 0; i < messages_.size(); i++) {
- std::vector<char> frame;
- frame.push_back('\0');
- frame.insert(frame.end(), messages_[i].begin(), messages_[i].end());
- frame.push_back('\xff');
- EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size()));
- }
- // Actual StreamSocket close must happen after all frames queued by
- // SendData above are sent out.
- event->socket->Close();
- }
-
- virtual void DoCloseFlushPendingWriteTestWithSetContextNull(
- SocketStreamEvent* event) {
- event->socket->DetachContext();
- // handshake response received.
- for (size_t i = 0; i < messages_.size(); i++) {
- std::vector<char> frame;
- frame.push_back('\0');
- frame.insert(frame.end(), messages_[i].begin(), messages_[i].end());
- frame.push_back('\xff');
- EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size()));
- }
- // Actual StreamSocket close must happen after all frames queued by
- // SendData above are sent out.
- event->socket->Close();
- }
-
- virtual void DoFailByTooBigDataAndClose(SocketStreamEvent* event) {
- std::string frame(event->number + 1, 0x00);
- VLOG(1) << event->number;
- EXPECT_FALSE(event->socket->SendData(&frame[0], frame.size()));
- event->socket->Close();
- }
-
- virtual int DoSwitchToSpdyTest(SocketStreamEvent* event) {
- return ERR_PROTOCOL_SWITCHED;
- }
-
- // Notifies |io_test_callback_| of that this method is called, and keeps the
- // SocketStream waiting.
- virtual int DoIOPending(SocketStreamEvent* event) {
- io_test_callback_.callback().Run(OK);
- return ERR_IO_PENDING;
- }
-
- static const char kWebSocketHandshakeRequest[];
- static const char kWebSocketHandshakeResponse[];
-
- protected:
- TestCompletionCallback io_test_callback_;
-
- private:
- std::string handshake_request_;
- std::string handshake_response_;
- std::vector<std::string> messages_;
-
- scoped_ptr<MockClientSocketFactory> mock_socket_factory_;
-};
-
-const char SocketStreamTest::kWebSocketHandshakeRequest[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Upgrade: WebSocket\r\n"
- "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
- "Origin: http://example.com\r\n"
- "\r\n"
- "^n:ds[4U";
-
-const char SocketStreamTest::kWebSocketHandshakeResponse[] =
- "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Location: ws://example.com/demo\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n"
- "8jKS'y:G*Co,Wxa-";
-
-TEST_F(SocketStreamTest, CloseFlushPendingWrite) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnConnected(base::Bind(
- &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
- delegate->SetOnReceivedData(base::Bind(
- &SocketStreamTest::DoCloseFlushPendingWriteTest,
- base::Unretained(this)));
-
- TestURLRequestContext context;
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- MockWrite data_writes[] = {
- MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
- MockWrite(ASYNC, "\0message1\xff", 10),
- MockWrite(ASYNC, "\0message2\xff", 10)
- };
- MockRead data_reads[] = {
- MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
- // Server doesn't close the connection after handshake.
- MockRead(ASYNC, ERR_IO_PENDING)
- };
- AddWebSocketMessage("message1");
- AddWebSocketMessage("message2");
-
- DelayedSocketData data_provider(
- 1, data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
-
- MockClientSocketFactory* mock_socket_factory =
- GetMockClientSocketFactory();
- mock_socket_factory->AddSocketDataProvider(&data_provider);
-
- socket_stream->SetClientSocketFactory(mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- EXPECT_TRUE(data_provider.at_read_eof());
- EXPECT_TRUE(data_provider.at_write_eof());
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(7U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
-}
-
-TEST_F(SocketStreamTest, ResolveFailure) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
-
- // Make resolver fail.
- TestURLRequestContext context;
- scoped_ptr<MockHostResolver> mock_host_resolver(
- new MockHostResolver());
- mock_host_resolver->rules()->AddSimulatedFailure("example.com");
- context.set_host_resolver(mock_host_resolver.get());
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- // No read/write on socket is expected.
- StaticSocketDataProvider data_provider(NULL, 0, NULL, 0);
- MockClientSocketFactory* mock_socket_factory =
- GetMockClientSocketFactory();
- mock_socket_factory->AddSocketDataProvider(&data_provider);
- socket_stream->SetClientSocketFactory(mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(2U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type);
-}
-
-TEST_F(SocketStreamTest, ExceedMaxPendingSendAllowed) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnConnected(base::Bind(
- &SocketStreamTest::DoFailByTooBigDataAndClose, base::Unretained(this)));
-
- TestURLRequestContext context;
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- DelayedSocketData data_provider(1, NULL, 0, NULL, 0);
-
- MockClientSocketFactory* mock_socket_factory =
- GetMockClientSocketFactory();
- mock_socket_factory->AddSocketDataProvider(&data_provider);
-
- socket_stream->SetClientSocketFactory(mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(4U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
-}
-
-TEST_F(SocketStreamTest, BasicAuthProxy) {
- MockClientSocketFactory mock_socket_factory;
- MockWrite data_writes1[] = {
- MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
- };
- MockRead data_reads1[] = {
- MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
- MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
- MockRead("\r\n"),
- };
- StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
- data_writes1, arraysize(data_writes1));
- mock_socket_factory.AddSocketDataProvider(&data1);
-
- MockWrite data_writes2[] = {
- MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
- };
- MockRead data_reads2[] = {
- MockRead("HTTP/1.1 200 Connection Established\r\n"),
- MockRead("Proxy-agent: Apache/2.2.8\r\n"),
- MockRead("\r\n"),
- // SocketStream::DoClose is run asynchronously. Socket can be read after
- // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate
- // server doesn't close the connection.
- MockRead(ASYNC, ERR_IO_PENDING)
- };
- StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
- data_writes2, arraysize(data_writes2));
- mock_socket_factory.AddSocketDataProvider(&data2);
-
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
- base::Unretained(delegate.get())));
- delegate->SetAuthInfo(AuthCredentials(ASCIIToUTF16("foo"),
- ASCIIToUTF16("bar")));
- delegate->SetOnAuthRequired(base::Bind(
- &SocketStreamEventRecorder::DoRestartWithAuth,
- base::Unretained(delegate.get())));
-
- TestURLRequestContextWithProxy context("myproxy:70");
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->SetClientSocketFactory(&mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(5U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED, events[1].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[2].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[3].event_type);
- EXPECT_EQ(ERR_ABORTED, events[3].error_code);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type);
-
- // TODO(eroman): Add back NetLogTest here...
-}
-
-TEST_F(SocketStreamTest, BasicAuthProxyWithAuthCache) {
- MockClientSocketFactory mock_socket_factory;
- MockWrite data_writes[] = {
- // WebSocket(SocketStream) always uses CONNECT when it is configured to use
- // proxy so the port may not be 443.
- MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
- };
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 Connection Established\r\n"),
- MockRead("Proxy-agent: Apache/2.2.8\r\n"),
- MockRead("\r\n"),
- MockRead(ASYNC, ERR_IO_PENDING)
- };
- StaticSocketDataProvider data(data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
- mock_socket_factory.AddSocketDataProvider(&data);
-
- TestCompletionCallback test_callback;
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
- base::Unretained(delegate.get())));
-
- TestURLRequestContextWithProxy context("myproxy:70");
- HttpAuthCache* auth_cache =
- context.http_transaction_factory()->GetSession()->http_auth_cache();
- auth_cache->Add(GURL("http://myproxy:70"),
- "MyRealm1",
- HttpAuth::AUTH_SCHEME_BASIC,
- "Basic realm=MyRealm1",
- AuthCredentials(ASCIIToUTF16("foo"),
- ASCIIToUTF16("bar")),
- "/");
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->SetClientSocketFactory(&mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(4U, events.size());
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
- EXPECT_EQ(ERR_ABORTED, events[2].error_code);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
-}
-
-TEST_F(SocketStreamTest, WSSBasicAuthProxyWithAuthCache) {
- MockClientSocketFactory mock_socket_factory;
- MockWrite data_writes1[] = {
- MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Proxy-Connection: keep-alive\r\n"
- "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
- };
- MockRead data_reads1[] = {
- MockRead("HTTP/1.1 200 Connection Established\r\n"),
- MockRead("Proxy-agent: Apache/2.2.8\r\n"),
- MockRead("\r\n"),
- MockRead(ASYNC, ERR_IO_PENDING)
- };
- StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
- data_writes1, arraysize(data_writes1));
- mock_socket_factory.AddSocketDataProvider(&data1);
-
- SSLSocketDataProvider data2(ASYNC, OK);
- mock_socket_factory.AddSSLSocketDataProvider(&data2);
-
- TestCompletionCallback test_callback;
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
- base::Unretained(delegate.get())));
-
- TestURLRequestContextWithProxy context("myproxy:70");
- HttpAuthCache* auth_cache =
- context.http_transaction_factory()->GetSession()->http_auth_cache();
- auth_cache->Add(GURL("http://myproxy:70"),
- "MyRealm1",
- HttpAuth::AUTH_SCHEME_BASIC,
- "Basic realm=MyRealm1",
- AuthCredentials(ASCIIToUTF16("foo"),
- ASCIIToUTF16("bar")),
- "/");
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("wss://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->SetClientSocketFactory(&mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(4U, events.size());
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
- EXPECT_EQ(ERR_ABORTED, events[2].error_code);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
-}
-
-TEST_F(SocketStreamTest, IOPending) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnStartOpenConnection(base::Bind(
- &SocketStreamTest::DoIOPending, base::Unretained(this)));
- delegate->SetOnConnected(base::Bind(
- &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
- delegate->SetOnReceivedData(base::Bind(
- &SocketStreamTest::DoCloseFlushPendingWriteTest,
- base::Unretained(this)));
-
- TestURLRequestContext context;
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- MockWrite data_writes[] = {
- MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
- MockWrite(ASYNC, "\0message1\xff", 10),
- MockWrite(ASYNC, "\0message2\xff", 10)
- };
- MockRead data_reads[] = {
- MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
- // Server doesn't close the connection after handshake.
- MockRead(ASYNC, ERR_IO_PENDING)
- };
- AddWebSocketMessage("message1");
- AddWebSocketMessage("message2");
-
- DelayedSocketData data_provider(
- 1, data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
-
- MockClientSocketFactory* mock_socket_factory =
- GetMockClientSocketFactory();
- mock_socket_factory->AddSocketDataProvider(&data_provider);
-
- socket_stream->SetClientSocketFactory(mock_socket_factory);
-
- socket_stream->Connect();
- io_test_callback_.WaitForResult();
- EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE,
- socket_stream->next_state_);
- delegate->CompleteConnection(OK);
-
- EXPECT_EQ(OK, test_callback.WaitForResult());
-
- EXPECT_TRUE(data_provider.at_read_eof());
- EXPECT_TRUE(data_provider.at_write_eof());
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(7U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
-}
-
-TEST_F(SocketStreamTest, SwitchToSpdy) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnStartOpenConnection(base::Bind(
- &SocketStreamTest::DoSwitchToSpdyTest, base::Unretained(this)));
-
- TestURLRequestContext context;
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->Connect();
-
- EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult());
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(2U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
- EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code);
-}
-
-TEST_F(SocketStreamTest, SwitchAfterPending) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnStartOpenConnection(base::Bind(
- &SocketStreamTest::DoIOPending, base::Unretained(this)));
-
- TestURLRequestContext context;
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->Connect();
- io_test_callback_.WaitForResult();
-
- EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE,
- socket_stream->next_state_);
- delegate->CompleteConnection(ERR_PROTOCOL_SWITCHED);
-
- EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult());
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(2U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
- EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code);
-}
-
-// Test a connection though a secure proxy.
-TEST_F(SocketStreamTest, SecureProxyConnectError) {
- MockClientSocketFactory mock_socket_factory;
- MockWrite data_writes[] = {
- MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n")
- };
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 Connection Established\r\n"),
- MockRead("Proxy-agent: Apache/2.2.8\r\n"),
- MockRead("\r\n"),
- // SocketStream::DoClose is run asynchronously. Socket can be read after
- // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate
- // server doesn't close the connection.
- MockRead(ASYNC, ERR_IO_PENDING)
- };
- StaticSocketDataProvider data(data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
- mock_socket_factory.AddSocketDataProvider(&data);
- SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory.AddSSLSocketDataProvider(&ssl);
-
- TestCompletionCallback test_callback;
- TestURLRequestContextWithProxy context("https://myproxy:70");
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
- base::Unretained(delegate.get())));
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->SetClientSocketFactory(&mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(3U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
- EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, events[1].error_code);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[2].event_type);
-}
-
-// Test a connection though a secure proxy.
-TEST_F(SocketStreamTest, SecureProxyConnect) {
- MockClientSocketFactory mock_socket_factory;
- MockWrite data_writes[] = {
- MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n")
- };
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 Connection Established\r\n"),
- MockRead("Proxy-agent: Apache/2.2.8\r\n"),
- MockRead("\r\n"),
- // SocketStream::DoClose is run asynchronously. Socket can be read after
- // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate
- // server doesn't close the connection.
- MockRead(ASYNC, ERR_IO_PENDING)
- };
- StaticSocketDataProvider data(data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
- mock_socket_factory.AddSocketDataProvider(&data);
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- mock_socket_factory.AddSSLSocketDataProvider(&ssl);
-
- TestCompletionCallback test_callback;
- TestURLRequestContextWithProxy context("https://myproxy:70");
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
- base::Unretained(delegate.get())));
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->SetClientSocketFactory(&mock_socket_factory);
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(4U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type);
- EXPECT_EQ(ERR_ABORTED, events[2].error_code);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
-}
-
-TEST_F(SocketStreamTest, BeforeConnectFailed) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
-
- TestURLRequestContext context;
- TestSocketStreamNetworkDelegate network_delegate;
- network_delegate.SetBeforeConnectResult(ERR_ACCESS_DENIED);
- context.set_network_delegate(&network_delegate);
-
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
-
- socket_stream->Connect();
-
- test_callback.WaitForResult();
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(2U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type);
- EXPECT_EQ(ERR_ACCESS_DENIED, events[0].error_code);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type);
-}
-
-// Check that a connect failure, followed by the delegate calling DetachDelegate
-// and deleting itself in the OnError callback, is handled correctly.
-TEST_F(SocketStreamTest, OnErrorDetachDelegate) {
- MockClientSocketFactory mock_socket_factory;
- TestCompletionCallback test_callback;
-
- // SelfDeletingDelegate is self-owning; we just need a pointer to it to
- // connect it and the SocketStream.
- SelfDeletingDelegate* delegate =
- new SelfDeletingDelegate(test_callback.callback());
- MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
- StaticSocketDataProvider data;
- data.set_connect_data(mock_connect);
- mock_socket_factory.AddSocketDataProvider(&data);
-
- TestURLRequestContext context;
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://localhost:9998/echo"), delegate,
- &context, NULL));
- socket_stream->SetClientSocketFactory(&mock_socket_factory);
- delegate->set_socket_stream(socket_stream);
- // The delegate pointer will become invalid during the test. Set it to NULL to
- // avoid holding a dangling pointer.
- delegate = NULL;
-
- socket_stream->Connect();
-
- EXPECT_EQ(OK, test_callback.WaitForResult());
-}
-
-TEST_F(SocketStreamTest, NullContextSocketStreamShouldNotCrash) {
- TestCompletionCallback test_callback;
-
- scoped_ptr<SocketStreamEventRecorder> delegate(
- new SocketStreamEventRecorder(test_callback.callback()));
- TestURLRequestContext context;
- scoped_refptr<SocketStream> socket_stream(
- new SocketStream(GURL("ws://example.com/demo"), delegate.get(),
- &context, NULL));
- delegate->SetOnStartOpenConnection(base::Bind(
- &SocketStreamTest::DoIOPending, base::Unretained(this)));
- delegate->SetOnConnected(base::Bind(
- &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
- delegate->SetOnReceivedData(base::Bind(
- &SocketStreamTest::DoCloseFlushPendingWriteTestWithSetContextNull,
- base::Unretained(this)));
-
- MockWrite data_writes[] = {
- MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
- };
- MockRead data_reads[] = {
- MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
- };
- AddWebSocketMessage("message1");
- AddWebSocketMessage("message2");
-
- DelayedSocketData data_provider(
- 1, data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
-
- MockClientSocketFactory* mock_socket_factory = GetMockClientSocketFactory();
- mock_socket_factory->AddSocketDataProvider(&data_provider);
- socket_stream->SetClientSocketFactory(mock_socket_factory);
-
- socket_stream->Connect();
- io_test_callback_.WaitForResult();
- delegate->CompleteConnection(OK);
- EXPECT_EQ(OK, test_callback.WaitForResult());
-
- EXPECT_TRUE(data_provider.at_read_eof());
- EXPECT_TRUE(data_provider.at_write_eof());
-
- const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
- ASSERT_EQ(5U, events.size());
-
- EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
- events[0].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
- EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type);
-}
-
-} // namespace net
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h
index 1421b55..1bbafe5 100644
--- a/net/spdy/spdy_framer.h
+++ b/net/spdy/spdy_framer.h
@@ -37,8 +37,6 @@ class SpdyNetworkTransactionTest;
class SpdyProxyClientSocketTest;
class SpdySessionTest;
class SpdyStreamTest;
-class SpdyWebSocketStreamTest;
-class WebSocketJobTest;
class SpdyFramer;
class SpdyFrameBuilder;
@@ -624,8 +622,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
friend class net::SpdyProxyClientSocketTest;
friend class net::SpdySessionTest;
friend class net::SpdyStreamTest;
- friend class net::SpdyWebSocketStreamTest;
- friend class net::WebSocketJobTest;
friend class test::TestSpdyVisitor;
private:
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 0faab29..7a5060b 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -373,7 +373,6 @@ SpdySessionDependencies::SpdySessionDependencies(NextProto protocol)
force_spdy_over_ssl(false),
force_spdy_always(false),
use_alternate_protocols(false),
- enable_websocket_over_spdy(false),
net_log(NULL) {
DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
@@ -407,7 +406,6 @@ SpdySessionDependencies::SpdySessionDependencies(
force_spdy_over_ssl(false),
force_spdy_always(false),
use_alternate_protocols(false),
- enable_websocket_over_spdy(false),
net_log(NULL) {
DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
}
@@ -467,7 +465,6 @@ net::HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
params.force_spdy_over_ssl = session_deps->force_spdy_over_ssl;
params.force_spdy_always = session_deps->force_spdy_always;
params.use_alternate_protocols = session_deps->use_alternate_protocols;
- params.enable_websocket_over_spdy = session_deps->enable_websocket_over_spdy;
params.net_log = session_deps->net_log;
return params;
}
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index e91800d..178d2e1 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -222,7 +222,6 @@ struct SpdySessionDependencies {
bool force_spdy_over_ssl;
bool force_spdy_always;
bool use_alternate_protocols;
- bool enable_websocket_over_spdy;
NetLog* net_log;
};
diff --git a/net/spdy/spdy_websocket_stream.cc b/net/spdy/spdy_websocket_stream.cc
deleted file mode 100644
index 54e668c..0000000
--- a/net/spdy/spdy_websocket_stream.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2012 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 "net/spdy/spdy_websocket_stream.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-#include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_stream.h"
-#include "url/gurl.h"
-
-namespace net {
-
-SpdyWebSocketStream::SpdyWebSocketStream(
- const base::WeakPtr<SpdySession>& spdy_session, Delegate* delegate)
- : spdy_session_(spdy_session),
- pending_send_data_length_(0),
- delegate_(delegate),
- weak_ptr_factory_(this) {
- DCHECK(spdy_session_.get());
- DCHECK(delegate_);
-}
-
-SpdyWebSocketStream::~SpdyWebSocketStream() {
- delegate_ = NULL;
- Close();
-}
-
-int SpdyWebSocketStream::InitializeStream(const GURL& url,
- RequestPriority request_priority,
- const BoundNetLog& net_log) {
- if (!spdy_session_)
- return ERR_SOCKET_NOT_CONNECTED;
-
- int rv = stream_request_.StartRequest(
- SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url, request_priority, net_log,
- base::Bind(&SpdyWebSocketStream::OnSpdyStreamCreated,
- weak_ptr_factory_.GetWeakPtr()));
-
- if (rv == OK) {
- stream_ = stream_request_.ReleaseStream();
- DCHECK(stream_.get());
- stream_->SetDelegate(this);
- }
- return rv;
-}
-
-int SpdyWebSocketStream::SendRequest(scoped_ptr<SpdyHeaderBlock> headers) {
- if (!stream_.get()) {
- NOTREACHED();
- return ERR_UNEXPECTED;
- }
- int result = stream_->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND);
- if (result < OK && result != ERR_IO_PENDING)
- Close();
- return result;
-}
-
-int SpdyWebSocketStream::SendData(const char* data, int length) {
- if (!stream_.get()) {
- NOTREACHED();
- return ERR_UNEXPECTED;
- }
- DCHECK_GE(length, 0);
- pending_send_data_length_ = static_cast<size_t>(length);
- scoped_refptr<IOBuffer> buf(new IOBuffer(length));
- memcpy(buf->data(), data, length);
- stream_->SendData(buf.get(), length, MORE_DATA_TO_SEND);
- return ERR_IO_PENDING;
-}
-
-void SpdyWebSocketStream::Close() {
- if (stream_.get()) {
- stream_->Close();
- DCHECK(!stream_.get());
- }
-}
-
-void SpdyWebSocketStream::OnRequestHeadersSent() {
- DCHECK(delegate_);
- delegate_->OnSentSpdyHeaders();
-}
-
-SpdyResponseHeadersStatus SpdyWebSocketStream::OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) {
- DCHECK(delegate_);
- delegate_->OnSpdyResponseHeadersUpdated(response_headers);
- return RESPONSE_HEADERS_ARE_COMPLETE;
-}
-
-void SpdyWebSocketStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) {
- DCHECK(delegate_);
- delegate_->OnReceivedSpdyData(buffer.Pass());
-}
-
-void SpdyWebSocketStream::OnDataSent() {
- DCHECK(delegate_);
- delegate_->OnSentSpdyData(pending_send_data_length_);
- pending_send_data_length_ = 0;
-}
-
-void SpdyWebSocketStream::OnClose(int status) {
- stream_.reset();
-
- // Destruction without Close() call OnClose() with delegate_ being NULL.
- if (!delegate_)
- return;
- Delegate* delegate = delegate_;
- delegate_ = NULL;
- delegate->OnCloseSpdyStream();
-}
-
-void SpdyWebSocketStream::OnSpdyStreamCreated(int result) {
- DCHECK_NE(ERR_IO_PENDING, result);
- if (result == OK) {
- stream_ = stream_request_.ReleaseStream();
- DCHECK(stream_.get());
- stream_->SetDelegate(this);
- }
- DCHECK(delegate_);
- delegate_->OnCreatedSpdyStream(result);
-}
-
-} // namespace net
diff --git a/net/spdy/spdy_websocket_stream.h b/net/spdy/spdy_websocket_stream.h
deleted file mode 100644
index 854afbf..0000000
--- a/net/spdy/spdy_websocket_stream.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2012 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 NET_SPDY_SPDY_WEBSOCKET_STREAM_H_
-#define NET_SPDY_SPDY_WEBSOCKET_STREAM_H_
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "net/base/completion_callback.h"
-#include "net/base/request_priority.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_header_block.h"
-#include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_stream.h"
-
-namespace net {
-
-// The SpdyWebSocketStream is a WebSocket-specific type of stream known to a
-// SpdySession. WebSocket's opening handshake is converted to SPDY's
-// SYN_STREAM/SYN_REPLY. WebSocket frames are encapsulated as SPDY data frames.
-class NET_EXPORT_PRIVATE SpdyWebSocketStream
- : public SpdyStream::Delegate {
- public:
- // Delegate handles asynchronous events.
- class NET_EXPORT_PRIVATE Delegate {
- public:
- // Called when InitializeStream() finishes asynchronously. This delegate is
- // called if InitializeStream() returns ERR_IO_PENDING. |status| indicates
- // network error.
- virtual void OnCreatedSpdyStream(int status) = 0;
-
- // Called on corresponding to OnSendHeadersComplete() or SPDY's SYN frame
- // has been sent.
- virtual void OnSentSpdyHeaders() = 0;
-
- // Called on corresponding to OnResponseHeadersUpdated() or
- // SPDY's SYN_STREAM, SYN_REPLY, or HEADERS frames are
- // received. This callback may be called multiple times as SPDY's
- // delegate does.
- virtual void OnSpdyResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) = 0;
-
- // Called when data is sent.
- virtual void OnSentSpdyData(size_t bytes_sent) = 0;
-
- // Called when data is received.
- virtual void OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) = 0;
-
- // Called when SpdyStream is closed.
- virtual void OnCloseSpdyStream() = 0;
-
- protected:
- virtual ~Delegate() {}
- };
-
- SpdyWebSocketStream(const base::WeakPtr<SpdySession>& spdy_session,
- Delegate* delegate);
- ~SpdyWebSocketStream() override;
-
- // Initializes SPDY stream for the WebSocket.
- // It might create SPDY stream asynchronously. In this case, this method
- // returns ERR_IO_PENDING and call OnCreatedSpdyStream delegate with result
- // after completion. In other cases, delegate does not be called.
- int InitializeStream(const GURL& url,
- RequestPriority request_priority,
- const BoundNetLog& stream_net_log);
-
- int SendRequest(scoped_ptr<SpdyHeaderBlock> headers);
- int SendData(const char* data, int length);
- void Close();
-
- // SpdyStream::Delegate
- void OnRequestHeadersSent() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
- void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override;
- void OnDataSent() override;
- void OnClose(int status) override;
-
- private:
- friend class SpdyWebSocketStreamTest;
- FRIEND_TEST_ALL_PREFIXES(SpdyWebSocketStreamTest, Basic);
-
- void OnSpdyStreamCreated(int status);
-
- SpdyStreamRequest stream_request_;
- base::WeakPtr<SpdyStream> stream_;
- const base::WeakPtr<SpdySession> spdy_session_;
- size_t pending_send_data_length_;
- Delegate* delegate_;
-
- base::WeakPtrFactory<SpdyWebSocketStream> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyWebSocketStream);
-};
-
-} // namespace net
-
-#endif // NET_SPDY_SPDY_WEBSOCKET_STREAM_H_
diff --git a/net/spdy/spdy_websocket_stream_unittest.cc b/net/spdy/spdy_websocket_stream_unittest.cc
deleted file mode 100644
index fc54884..0000000
--- a/net/spdy/spdy_websocket_stream_unittest.cc
+++ /dev/null
@@ -1,669 +0,0 @@
-// 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 "net/spdy/spdy_websocket_stream.h"
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "net/base/completion_callback.h"
-#include "net/proxy/proxy_server.h"
-#include "net/socket/next_proto.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/spdy/spdy_http_utils.h"
-#include "net/spdy/spdy_protocol.h"
-#include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_websocket_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace {
-
-struct SpdyWebSocketStreamEvent {
- enum EventType {
- EVENT_CREATED,
- EVENT_SENT_HEADERS,
- EVENT_RECEIVED_HEADER,
- EVENT_SENT_DATA,
- EVENT_RECEIVED_DATA,
- EVENT_CLOSE,
- };
- SpdyWebSocketStreamEvent(EventType type,
- const SpdyHeaderBlock& headers,
- int result,
- const std::string& data)
- : event_type(type),
- headers(headers),
- result(result),
- data(data) {}
-
- EventType event_type;
- SpdyHeaderBlock headers;
- int result;
- std::string data;
-};
-
-class SpdyWebSocketStreamEventRecorder : public SpdyWebSocketStream::Delegate {
- public:
- explicit SpdyWebSocketStreamEventRecorder(const CompletionCallback& callback)
- : callback_(callback) {}
- ~SpdyWebSocketStreamEventRecorder() override {}
-
- typedef base::Callback<void(SpdyWebSocketStreamEvent*)> StreamEventCallback;
-
- void SetOnCreated(const StreamEventCallback& callback) {
- on_created_ = callback;
- }
- void SetOnSentHeaders(const StreamEventCallback& callback) {
- on_sent_headers_ = callback;
- }
- void SetOnReceivedHeader(const StreamEventCallback& callback) {
- on_received_header_ = callback;
- }
- void SetOnSentData(const StreamEventCallback& callback) {
- on_sent_data_ = callback;
- }
- void SetOnReceivedData(const StreamEventCallback& callback) {
- on_received_data_ = callback;
- }
- void SetOnClose(const StreamEventCallback& callback) {
- on_close_ = callback;
- }
-
- void OnCreatedSpdyStream(int result) override {
- events_.push_back(
- SpdyWebSocketStreamEvent(SpdyWebSocketStreamEvent::EVENT_CREATED,
- SpdyHeaderBlock(),
- result,
- std::string()));
- if (!on_created_.is_null())
- on_created_.Run(&events_.back());
- }
- void OnSentSpdyHeaders() override {
- events_.push_back(
- SpdyWebSocketStreamEvent(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
- SpdyHeaderBlock(),
- OK,
- std::string()));
- if (!on_sent_data_.is_null())
- on_sent_data_.Run(&events_.back());
- }
- void OnSpdyResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override {
- events_.push_back(
- SpdyWebSocketStreamEvent(
- SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
- response_headers,
- OK,
- std::string()));
- if (!on_received_header_.is_null())
- on_received_header_.Run(&events_.back());
- }
- void OnSentSpdyData(size_t bytes_sent) override {
- events_.push_back(
- SpdyWebSocketStreamEvent(
- SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- SpdyHeaderBlock(),
- static_cast<int>(bytes_sent),
- std::string()));
- if (!on_sent_data_.is_null())
- on_sent_data_.Run(&events_.back());
- }
- void OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) override {
- std::string buffer_data;
- size_t buffer_len = 0;
- if (buffer) {
- buffer_len = buffer->GetRemainingSize();
- buffer_data.append(buffer->GetRemainingData(), buffer_len);
- }
- events_.push_back(
- SpdyWebSocketStreamEvent(
- SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- SpdyHeaderBlock(),
- buffer_len,
- buffer_data));
- if (!on_received_data_.is_null())
- on_received_data_.Run(&events_.back());
- }
- void OnCloseSpdyStream() override {
- events_.push_back(
- SpdyWebSocketStreamEvent(
- SpdyWebSocketStreamEvent::EVENT_CLOSE,
- SpdyHeaderBlock(),
- OK,
- std::string()));
- if (!on_close_.is_null())
- on_close_.Run(&events_.back());
- if (!callback_.is_null())
- callback_.Run(OK);
- }
-
- const std::vector<SpdyWebSocketStreamEvent>& GetSeenEvents() const {
- return events_;
- }
-
- private:
- std::vector<SpdyWebSocketStreamEvent> events_;
- StreamEventCallback on_created_;
- StreamEventCallback on_sent_headers_;
- StreamEventCallback on_received_header_;
- StreamEventCallback on_sent_data_;
- StreamEventCallback on_received_data_;
- StreamEventCallback on_close_;
- CompletionCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyWebSocketStreamEventRecorder);
-};
-
-} // namespace
-
-class SpdyWebSocketStreamTest
- : public ::testing::Test,
- public ::testing::WithParamInterface<NextProto> {
- public:
- OrderedSocketData* data() { return data_.get(); }
-
- void DoSendHelloFrame(SpdyWebSocketStreamEvent* event) {
- // Record the actual stream_id.
- created_stream_id_ = websocket_stream_->stream_->stream_id();
- websocket_stream_->SendData(kMessageFrame, kMessageFrameLength);
- }
-
- void DoSendClosingFrame(SpdyWebSocketStreamEvent* event) {
- websocket_stream_->SendData(kClosingFrame, kClosingFrameLength);
- }
-
- void DoClose(SpdyWebSocketStreamEvent* event) {
- websocket_stream_->Close();
- }
-
- void DoSync(SpdyWebSocketStreamEvent* event) {
- sync_callback_.callback().Run(OK);
- }
-
- protected:
- SpdyWebSocketStreamTest()
- : spdy_util_(GetParam()),
- spdy_settings_id_to_set_(SETTINGS_MAX_CONCURRENT_STREAMS),
- spdy_settings_flags_to_set_(SETTINGS_FLAG_PLEASE_PERSIST),
- spdy_settings_value_to_set_(1),
- session_deps_(GetParam()),
- stream_id_(0),
- created_stream_id_(0) {}
- virtual ~SpdyWebSocketStreamTest() {}
-
- void SetUp() override {
- host_port_pair_.set_host("example.com");
- host_port_pair_.set_port(80);
- spdy_session_key_ = SpdySessionKey(host_port_pair_,
- ProxyServer::Direct(),
- PRIVACY_MODE_DISABLED);
-
- spdy_settings_to_send_[spdy_settings_id_to_set_] =
- SettingsFlagsAndValue(
- SETTINGS_FLAG_PERSISTED, spdy_settings_value_to_set_);
- }
-
- void TearDown() override { base::MessageLoop::current()->RunUntilIdle(); }
-
- void Prepare(SpdyStreamId stream_id) {
- stream_id_ = stream_id;
-
- request_frame_.reset(spdy_util_.ConstructSpdyWebSocketSynStream(
- stream_id_,
- "/echo",
- "example.com",
- "http://example.com/wsdemo"));
-
- response_frame_.reset(
- spdy_util_.ConstructSpdyWebSocketSynReply(stream_id_));
-
- message_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
- kMessageFrame,
- kMessageFrameLength,
- stream_id_,
- false));
-
- closing_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
- kClosingFrame,
- kClosingFrameLength,
- stream_id_,
- false));
-
- closing_frame_fin_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
- kClosingFrame,
- kClosingFrameLength,
- stream_id_,
- true));
- }
-
- void InitSession(MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count) {
- data_.reset(new OrderedSocketData(reads, reads_count,
- writes, writes_count));
- session_deps_.socket_factory->AddSocketDataProvider(data_.get());
- http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
- session_ = CreateInsecureSpdySession(
- http_session_, spdy_session_key_, BoundNetLog());
- }
-
- void SendRequest() {
- scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
- spdy_util_.SetHeader("path", "/echo", headers.get());
- spdy_util_.SetHeader("host", "example.com", headers.get());
- spdy_util_.SetHeader("version", "WebSocket/13", headers.get());
- spdy_util_.SetHeader("scheme", "ws", headers.get());
- spdy_util_.SetHeader("origin", "http://example.com/wsdemo", headers.get());
- websocket_stream_->SendRequest(headers.Pass());
- }
-
- SpdyWebSocketTestUtil spdy_util_;
- SpdySettingsIds spdy_settings_id_to_set_;
- SpdySettingsFlags spdy_settings_flags_to_set_;
- uint32 spdy_settings_value_to_set_;
- SettingsMap spdy_settings_to_send_;
- SpdySessionDependencies session_deps_;
- scoped_ptr<OrderedSocketData> data_;
- scoped_refptr<HttpNetworkSession> http_session_;
- base::WeakPtr<SpdySession> session_;
- scoped_ptr<SpdyWebSocketStream> websocket_stream_;
- SpdyStreamId stream_id_;
- SpdyStreamId created_stream_id_;
- scoped_ptr<SpdyFrame> request_frame_;
- scoped_ptr<SpdyFrame> response_frame_;
- scoped_ptr<SpdyFrame> message_frame_;
- scoped_ptr<SpdyFrame> closing_frame_;
- scoped_ptr<SpdyFrame> closing_frame_fin_;
- HostPortPair host_port_pair_;
- SpdySessionKey spdy_session_key_;
- TestCompletionCallback completion_callback_;
- TestCompletionCallback sync_callback_;
-
- static const char kMessageFrame[];
- static const char kClosingFrame[];
- static const size_t kMessageFrameLength;
- static const size_t kClosingFrameLength;
-};
-
-INSTANTIATE_TEST_CASE_P(
- NextProto,
- SpdyWebSocketStreamTest,
- testing::Values(kProtoDeprecatedSPDY2,
- kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
-
-// TODO(toyoshim): Replace old framing data to new one, then use HEADERS and
-// data frames.
-const char SpdyWebSocketStreamTest::kMessageFrame[] = "\x81\x05hello";
-const char SpdyWebSocketStreamTest::kClosingFrame[] = "\x88\0";
-const size_t SpdyWebSocketStreamTest::kMessageFrameLength =
- arraysize(SpdyWebSocketStreamTest::kMessageFrame) - 1;
-const size_t SpdyWebSocketStreamTest::kClosingFrameLength =
- arraysize(SpdyWebSocketStreamTest::kClosingFrame) - 1;
-
-TEST_P(SpdyWebSocketStreamTest, Basic) {
- Prepare(1);
- MockWrite writes[] = {
- CreateMockWrite(*request_frame_.get(), 1),
- CreateMockWrite(*message_frame_.get(), 3),
- CreateMockWrite(*closing_frame_.get(), 5)
- };
-
- MockRead reads[] = {
- CreateMockRead(*response_frame_.get(), 2),
- CreateMockRead(*message_frame_.get(), 4),
- // Skip sequence 6 to notify closing has been sent.
- CreateMockRead(*closing_frame_.get(), 7),
- MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event.
- };
-
- InitSession(reads, arraysize(reads), writes, arraysize(writes));
-
- SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
- delegate.SetOnReceivedHeader(
- base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
- base::Unretained(this)));
- delegate.SetOnReceivedData(
- base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
- base::Unretained(this)));
-
- websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
-
- BoundNetLog net_log;
- GURL url("ws://example.com/echo");
- ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
-
- ASSERT_TRUE(websocket_stream_->stream_.get());
-
- SendRequest();
-
- completion_callback_.WaitForResult();
-
- EXPECT_EQ(stream_id_, created_stream_id_);
-
- websocket_stream_.reset();
-
- const std::vector<SpdyWebSocketStreamEvent>& events =
- delegate.GetSeenEvents();
- ASSERT_EQ(7U, events.size());
-
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
- events[0].event_type);
- EXPECT_EQ(OK, events[0].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
- events[1].event_type);
- EXPECT_EQ(OK, events[1].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- events[2].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- events[3].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- events[4].event_type);
- EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[4].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- events[5].event_type);
- EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
- events[6].event_type);
- EXPECT_EQ(OK, events[6].result);
-
- // EOF close SPDY session.
- EXPECT_FALSE(
- HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
- EXPECT_TRUE(data()->at_read_eof());
- EXPECT_TRUE(data()->at_write_eof());
-}
-
-// A SPDY websocket may still send it's close frame after
-// recieving a close with SPDY stream FIN.
-TEST_P(SpdyWebSocketStreamTest, RemoteCloseWithFin) {
- Prepare(1);
- MockWrite writes[] = {
- CreateMockWrite(*request_frame_.get(), 1),
- CreateMockWrite(*closing_frame_.get(), 4),
- };
- MockRead reads[] = {
- CreateMockRead(*response_frame_.get(), 2),
- CreateMockRead(*closing_frame_fin_.get(), 3),
- MockRead(SYNCHRONOUS, 0, 5) // EOF cause OnCloseSpdyStream event.
- };
- InitSession(reads, arraysize(reads), writes, arraysize(writes));
-
- SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
- delegate.SetOnReceivedData(
- base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
- base::Unretained(this)));
-
- websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
- BoundNetLog net_log;
- GURL url("ws://example.com/echo");
- ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
-
- SendRequest();
- completion_callback_.WaitForResult();
- websocket_stream_.reset();
-
- const std::vector<SpdyWebSocketStreamEvent>& events =
- delegate.GetSeenEvents();
- EXPECT_EQ(5U, events.size());
-
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
- events[0].event_type);
- EXPECT_EQ(OK, events[0].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
- events[1].event_type);
- EXPECT_EQ(OK, events[1].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- events[2].event_type);
- EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[2].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- events[3].event_type);
- EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[3].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
- events[4].event_type);
- EXPECT_EQ(OK, events[4].result);
-
- // EOF closes SPDY session.
- EXPECT_FALSE(
- HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
- EXPECT_TRUE(data()->at_read_eof());
- EXPECT_TRUE(data()->at_write_eof());
-}
-
-TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) {
- Prepare(1);
- MockWrite writes[] = {
- CreateMockWrite(*request_frame_.get(), 1),
- CreateMockWrite(*message_frame_.get(), 3)
- };
-
- MockRead reads[] = {
- CreateMockRead(*response_frame_.get(), 2),
- CreateMockRead(*message_frame_.get(), 4),
- MockRead(ASYNC, ERR_IO_PENDING, 5)
- };
-
- InitSession(reads, arraysize(reads), writes, arraysize(writes));
-
- SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
- delegate.SetOnReceivedHeader(
- base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
- base::Unretained(this)));
- delegate.SetOnReceivedData(
- base::Bind(&SpdyWebSocketStreamTest::DoSync,
- base::Unretained(this)));
-
- websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
-
- BoundNetLog net_log;
- GURL url("ws://example.com/echo");
- ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
-
- SendRequest();
-
- sync_callback_.WaitForResult();
-
- // WebSocketStream destruction remove its SPDY stream from the session.
- EXPECT_TRUE(session_->IsStreamActive(stream_id_));
- websocket_stream_.reset();
- EXPECT_FALSE(session_->IsStreamActive(stream_id_));
-
- const std::vector<SpdyWebSocketStreamEvent>& events =
- delegate.GetSeenEvents();
- ASSERT_GE(4U, events.size());
-
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
- events[0].event_type);
- EXPECT_EQ(OK, events[0].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
- events[1].event_type);
- EXPECT_EQ(OK, events[1].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- events[2].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- events[3].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
-
- EXPECT_TRUE(
- HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
- EXPECT_TRUE(data()->at_read_eof());
- EXPECT_TRUE(data()->at_write_eof());
-}
-
-TEST_P(SpdyWebSocketStreamTest, DestructionAfterExplicitClose) {
- Prepare(1);
- MockWrite writes[] = {
- CreateMockWrite(*request_frame_.get(), 1),
- CreateMockWrite(*message_frame_.get(), 3),
- CreateMockWrite(*closing_frame_.get(), 5)
- };
-
- MockRead reads[] = {
- CreateMockRead(*response_frame_.get(), 2),
- CreateMockRead(*message_frame_.get(), 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6)
- };
-
- InitSession(reads, arraysize(reads), writes, arraysize(writes));
-
- SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
- delegate.SetOnReceivedHeader(
- base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
- base::Unretained(this)));
- delegate.SetOnReceivedData(
- base::Bind(&SpdyWebSocketStreamTest::DoClose,
- base::Unretained(this)));
-
- websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
-
- BoundNetLog net_log;
- GURL url("ws://example.com/echo");
- ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
-
- SendRequest();
-
- completion_callback_.WaitForResult();
-
- // SPDY stream has already been removed from the session by Close().
- EXPECT_FALSE(session_->IsStreamActive(stream_id_));
- websocket_stream_.reset();
-
- const std::vector<SpdyWebSocketStreamEvent>& events =
- delegate.GetSeenEvents();
- ASSERT_EQ(5U, events.size());
-
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
- events[0].event_type);
- EXPECT_EQ(OK, events[0].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
- events[1].event_type);
- EXPECT_EQ(OK, events[1].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- events[2].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- events[3].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, events[4].event_type);
-
- EXPECT_TRUE(
- HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
-}
-
-TEST_P(SpdyWebSocketStreamTest, IOPending) {
- Prepare(1);
- scoped_ptr<SpdyFrame> settings_frame(
- spdy_util_.ConstructSpdySettings(spdy_settings_to_send_));
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
- MockWrite writes[] = {
- CreateMockWrite(*settings_ack, 1),
- CreateMockWrite(*request_frame_.get(), 2),
- CreateMockWrite(*message_frame_.get(), 4),
- CreateMockWrite(*closing_frame_.get(), 6)
- };
-
- MockRead reads[] = {
- CreateMockRead(*settings_frame.get(), 0),
- CreateMockRead(*response_frame_.get(), 3),
- CreateMockRead(*message_frame_.get(), 5),
- CreateMockRead(*closing_frame_.get(), 7),
- MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event.
- };
-
- DeterministicSocketData data(reads, arraysize(reads),
- writes, arraysize(writes));
- session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
- http_session_ =
- SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
-
- session_ = CreateInsecureSpdySession(
- http_session_, spdy_session_key_, BoundNetLog());
-
- // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another
- // WebSocketStream under test.
- SpdyWebSocketStreamEventRecorder block_delegate((CompletionCallback()));
-
- scoped_ptr<SpdyWebSocketStream> block_stream(
- new SpdyWebSocketStream(session_, &block_delegate));
- BoundNetLog block_net_log;
- GURL block_url("ws://example.com/block");
- ASSERT_EQ(OK,
- block_stream->InitializeStream(block_url, HIGHEST, block_net_log));
-
- data.RunFor(1);
-
- // Create a WebSocketStream under test.
- SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
- delegate.SetOnCreated(
- base::Bind(&SpdyWebSocketStreamTest::DoSync,
- base::Unretained(this)));
- delegate.SetOnReceivedHeader(
- base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
- base::Unretained(this)));
- delegate.SetOnReceivedData(
- base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
- base::Unretained(this)));
-
- websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
- BoundNetLog net_log;
- GURL url("ws://example.com/echo");
- ASSERT_EQ(ERR_IO_PENDING, websocket_stream_->InitializeStream(
- url, HIGHEST, net_log));
-
- // Delete the fist stream to allow create the second stream.
- block_stream.reset();
- ASSERT_EQ(OK, sync_callback_.WaitForResult());
-
- SendRequest();
-
- data.RunFor(8);
- completion_callback_.WaitForResult();
-
- websocket_stream_.reset();
-
- const std::vector<SpdyWebSocketStreamEvent>& block_events =
- block_delegate.GetSeenEvents();
- ASSERT_EQ(0U, block_events.size());
-
- const std::vector<SpdyWebSocketStreamEvent>& events =
- delegate.GetSeenEvents();
- ASSERT_EQ(8U, events.size());
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CREATED,
- events[0].event_type);
- EXPECT_EQ(0, events[0].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
- events[1].event_type);
- EXPECT_EQ(OK, events[1].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
- events[2].event_type);
- EXPECT_EQ(OK, events[2].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- events[3].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- events[4].event_type);
- EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[4].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
- events[5].event_type);
- EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
- events[6].event_type);
- EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[6].result);
- EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
- events[7].event_type);
- EXPECT_EQ(OK, events[7].result);
-
- // EOF close SPDY session.
- EXPECT_FALSE(
- HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
- EXPECT_TRUE(data.at_read_eof());
- EXPECT_TRUE(data.at_write_eof());
-}
-
-} // namespace net
diff --git a/net/spdy/spdy_websocket_test_util.cc b/net/spdy/spdy_websocket_test_util.cc
deleted file mode 100644
index b1ef81b..0000000
--- a/net/spdy/spdy_websocket_test_util.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 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 "net/spdy/spdy_websocket_test_util.h"
-
-#include "net/spdy/buffered_spdy_framer.h"
-#include "net/spdy/spdy_http_utils.h"
-
-namespace net {
-
-const bool kDefaultCompressed = false;
-
-SpdyWebSocketTestUtil::SpdyWebSocketTestUtil(
- NextProto protocol) : spdy_util_(protocol) {}
-
-std::string SpdyWebSocketTestUtil::GetHeader(const SpdyHeaderBlock& headers,
- const std::string& key) const {
- SpdyHeaderBlock::const_iterator it = headers.find(GetHeaderKey(key));
- return (it == headers.end()) ? "" : it->second;
-}
-
-void SpdyWebSocketTestUtil::SetHeader(
- const std::string& key,
- const std::string& value,
- SpdyHeaderBlock* headers) const {
- (*headers)[GetHeaderKey(key)] = value;
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketSynStream(
- int stream_id,
- const char* path,
- const char* host,
- const char* origin) {
- scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
- SetHeader("path", path, headers.get());
- SetHeader("host", host, headers.get());
- SetHeader("version", "WebSocket/13", headers.get());
- SetHeader("scheme", "ws", headers.get());
- SetHeader("origin", origin, headers.get());
- return spdy_util_.ConstructSpdySyn(
- stream_id, *headers, HIGHEST, false, false);
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketSynReply(
- int stream_id) {
- SpdyHeaderBlock block;
- SetHeader("status", "101", &block);
- return spdy_util_.ConstructSpdyReply(stream_id, block);
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHandshakeRequestFrame(
- scoped_ptr<SpdyHeaderBlock> headers,
- SpdyStreamId stream_id,
- RequestPriority request_priority) {
- return spdy_util_.ConstructSpdySyn(
- stream_id, *headers, request_priority, kDefaultCompressed, false);
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHandshakeResponseFrame(
- scoped_ptr<SpdyHeaderBlock> headers,
- SpdyStreamId stream_id,
- RequestPriority request_priority) {
- return spdy_util_.ConstructSpdyReply(stream_id, *headers);
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHeadersFrame(
- int stream_id,
- const char* length,
- bool fin) {
- scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
- SetHeader("opcode", "1", headers.get()); // text frame
- SetHeader("length", length, headers.get());
- SetHeader("fin", fin ? "1" : "0", headers.get());
- return spdy_util_.ConstructSpdySyn(stream_id, *headers, LOWEST, false, false);
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketDataFrame(
- const char* data,
- int len,
- SpdyStreamId stream_id,
- bool fin) {
-
- // Construct SPDY data frame.
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
- return framer.CreateDataFrame(
- stream_id,
- data,
- len,
- fin ? DATA_FLAG_FIN : DATA_FLAG_NONE);
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdySettings(
- const SettingsMap& settings) const {
- return spdy_util_.ConstructSpdySettings(settings);
-}
-
-SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdySettingsAck() const {
- return spdy_util_.ConstructSpdySettingsAck();
-}
-
-SpdyMajorVersion SpdyWebSocketTestUtil::spdy_version() const {
- return spdy_util_.spdy_version();
-}
-
-std::string SpdyWebSocketTestUtil::GetHeaderKey(
- const std::string& key) const {
- return (spdy_util_.is_spdy2() ? "" : ":") + key;
-}
-
-} // namespace net
diff --git a/net/spdy/spdy_websocket_test_util.h b/net/spdy/spdy_websocket_test_util.h
deleted file mode 100644
index 14c8c02..0000000
--- a/net/spdy/spdy_websocket_test_util.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 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 NET_SPDY_SPDY_WEBSOCKET_TEST_UTIL_H_
-#define NET_SPDY_SPDY_WEBSOCKET_TEST_UTIL_H_
-
-#include "net/base/request_priority.h"
-#include "net/spdy/spdy_header_block.h"
-#include "net/spdy/spdy_protocol.h"
-#include "net/spdy/spdy_test_util_common.h"
-
-namespace net {
-
-class SpdyWebSocketTestUtil {
- public:
- explicit SpdyWebSocketTestUtil(NextProto protocol);
-
- // Returns the value corresponding to the given key (passed through
- // GetHeaderKey()), or the empty string if none exists.
- std::string GetHeader(const SpdyHeaderBlock& headers,
- const std::string& key) const;
-
- // Adds the given key/value pair to |headers|, passing the key
- // through GetHeaderKey().
- void SetHeader(const std::string& key,
- const std::string& value,
- SpdyHeaderBlock* headers) const;
-
- // Constructs a standard SPDY SYN_STREAM frame for WebSocket over
- // SPDY opening handshake.
- SpdyFrame* ConstructSpdyWebSocketSynStream(int stream_id,
- const char* path,
- const char* host,
- const char* origin);
-
- // Constructs a standard SPDY SYN_REPLY packet to match the
- // WebSocket over SPDY opening handshake.
- SpdyFrame* ConstructSpdyWebSocketSynReply(int stream_id);
-
- // Constructs a WebSocket over SPDY handshake request packet.
- SpdyFrame* ConstructSpdyWebSocketHandshakeRequestFrame(
- scoped_ptr<SpdyHeaderBlock> headers,
- SpdyStreamId stream_id,
- RequestPriority request_priority);
-
- // Constructs a WebSocket over SPDY handshake response packet.
- SpdyFrame* ConstructSpdyWebSocketHandshakeResponseFrame(
- scoped_ptr<SpdyHeaderBlock> headers,
- SpdyStreamId stream_id,
- RequestPriority request_priority);
-
- // Constructs a SPDY HEADERS frame for a WebSocket frame over SPDY.
- SpdyFrame* ConstructSpdyWebSocketHeadersFrame(int stream_id,
- const char* length,
- bool fin);
-
- // Constructs a WebSocket over SPDY data packet.
- SpdyFrame* ConstructSpdyWebSocketDataFrame(const char* data,
- int len,
- SpdyStreamId stream_id,
- bool fin);
-
- // Forwards to |spdy_util_|.
- SpdyFrame* ConstructSpdySettings(const SettingsMap& settings) const;
- SpdyFrame* ConstructSpdySettingsAck() const;
- SpdyMajorVersion spdy_version() const;
-
- private:
- // Modify the header key based on the SPDY version and return it.
- std::string GetHeaderKey(const std::string& key) const;
-
- SpdyTestUtil spdy_util_;
-};
-
-} // namespace net
-
-#endif // NET_SPDY_SPDY_WEBSOCKET_TEST_UTIL_H_
diff --git a/net/websockets/PRESUBMIT.py b/net/websockets/PRESUBMIT.py
deleted file mode 100644
index 1da441c..0000000
--- a/net/websockets/PRESUBMIT.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# 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.
-
-"""Chromium presubmit script for src/net/websockets.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details on the presubmit API built into gcl.
-"""
-
-
-# TODO(ricea): Remove this once the old implementation has been removed and the
-# list of files in the README file is no longer needed.
-def _CheckReadMeComplete(input_api, output_api):
- """Verifies that any new files have been added to the README file.
-
- Checks that if any source files were added in this CL, that they were
- also added to the README file. We do not warn about pre-existing
- errors, as that would be annoying.
-
- Args:
- input_api: The InputApi object provided by the presubmit framework.
- output_api: The OutputApi object provided by the framework.
-
- Returns:
- A list of zero or more PresubmitPromptWarning objects.
- """
- # None passed to AffectedSourceFiles means "use the default filter", which
- # does what we want, ie. returns files in the CL with filenames that look like
- # source code.
- added_source_filenames = set(input_api.basename(af.LocalPath())
- for af in input_api.AffectedSourceFiles(None)
- if af.Action().startswith('A'))
- if not added_source_filenames:
- return []
- readme = input_api.AffectedSourceFiles(
- lambda af: af.LocalPath().endswith('/README'))
- if not readme:
- return [output_api.PresubmitPromptWarning(
- 'One or more files were added to net/websockets without being added\n'
- 'to net/websockets/README.\n', added_source_filenames)]
- readme_added_filenames = set(line.strip() for line in readme[0].NewContents()
- if line.strip() in added_source_filenames)
- if readme_added_filenames < added_source_filenames:
- return [output_api.PresubmitPromptWarning(
- 'One or more files added to net/websockets but not found in the README '
- 'file.\n', added_source_filenames - readme_added_filenames)]
- else:
- return []
-
-
-def CheckChangeOnUpload(input_api, output_api):
- return _CheckReadMeComplete(input_api, output_api)
-
-
-def CheckChangeOnCommit(input_api, output_api):
- return _CheckReadMeComplete(input_api, output_api)
diff --git a/net/websockets/README b/net/websockets/README
deleted file mode 100644
index efe7a59..0000000
--- a/net/websockets/README
+++ /dev/null
@@ -1,91 +0,0 @@
-This directory contains files related to Chromium's WebSocket
-implementation. See http://www.websocket.org/ for an explanation of WebSockets.
-
-As of April 2013, the contents of this directory are in a transitional state,
-and contain parts of two different WebSocket implementations.
-
-The following files are part of the legacy implementation. The legacy
-implementation performs WebSocket framing within Blink and presents a
-low-level socket-like interface to the renderer process. It is described in the
-design doc at
-https://docs.google.com/a/google.com/document/d/1_R6YjCIrm4kikJ3YeapcOU2Keqr3lVUPd-OeaIJ93qQ/preview
-
-websocket_handshake_handler_test.cc
-websocket_handshake_handler_spdy_test.cc
-websocket_job.cc
-websocket_job.h
-websocket_job_test.cc
-websocket_net_log_params.cc
-websocket_net_log_params.h
-websocket_net_log_params_test.cc
-websocket_throttle.cc
-websocket_throttle.h
-websocket_throttle_test.cc
-
-The following files are part of the new implementation. The new implementation
-performs framing and implements protocol semantics in the browser process, and
-presents a high-level interface to the renderer process similar to a
-multiplexing proxy. This is the default implementation from M38.
-
-websocket_basic_handshake_stream.cc
-websocket_basic_handshake_stream.h
-websocket_basic_stream.cc
-websocket_basic_stream.h
-websocket_basic_stream_test.cc
-websocket_channel.cc
-websocket_channel.h
-websocket_channel_test.cc
-websocket_deflate_predictor.h
-websocket_deflate_predictor_impl.cc
-websocket_deflate_predictor_impl.h
-websocket_deflate_predictor_impl_test.cc
-websocket_deflate_stream.cc
-websocket_deflate_stream.h
-websocket_deflate_stream_test.cc
-websocket_deflater.cc
-websocket_deflater.h
-websocket_deflater_test.cc
-websocket_errors.cc
-websocket_errors.h
-websocket_errors_test.cc
-websocket_event_interface.h
-websocket_extension.cc
-websocket_extension.h
-websocket_extension_parser.cc
-websocket_extension_parser.h
-websocket_extension_parser_test.cc
-websocket_frame.cc
-websocket_frame.h
-websocket_frame_parser.cc
-websocket_frame_parser.h
-websocket_frame_parser_test.cc
-websocket_frame_test.cc
-websocket_frame_perftest.cc
-websocket_handshake_stream_base.h
-websocket_handshake_stream_create_helper.cc
-websocket_handshake_stream_create_helper.h
-websocket_handshake_stream_create_helper_test.cc
-websocket_handshake_request_info.cc
-websocket_handshake_request_info.h
-websocket_handshake_response_info.cc
-websocket_handshake_response_info.h
-websocket_inflater.cc
-websocket_inflater.h
-websocket_inflater_test.cc
-websocket_mux.h
-websocket_stream.cc
-websocket_stream.h
-websocket_stream_test.cc
-websocket_test_util.cc
-websocket_test_util.h
-
-These files are shared between the old and new implementations.
-
-websocket_handshake_constants.cc
-websocket_handshake_constants.h
-websocket_handshake_handler.cc
-websocket_handshake_handler.h
-
-A pre-submit check helps us keep this README file up-to-date:
-
-PRESUBMIT.py
diff --git a/net/websockets/websocket_handshake_handler.cc b/net/websockets/websocket_handshake_handler.cc
index 6324710..6bcc230 100644
--- a/net/websockets/websocket_handshake_handler.cc
+++ b/net/websockets/websocket_handshake_handler.cc
@@ -4,346 +4,12 @@
#include "net/websockets/websocket_handshake_handler.h"
-#include <limits>
-
#include "base/base64.h"
+#include "base/logging.h"
#include "base/sha1.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
#include "net/websockets/websocket_handshake_constants.h"
-#include "url/gurl.h"
namespace net {
-namespace {
-
-const int kVersionHeaderValueForRFC6455 = 13;
-
-// Splits |handshake_message| into Status-Line or Request-Line (including CRLF)
-// and headers (excluding 2nd CRLF of double CRLFs at the end of a handshake
-// response).
-void ParseHandshakeHeader(
- const char* handshake_message, int len,
- std::string* request_line,
- std::string* headers) {
- size_t i = base::StringPiece(handshake_message, len).find_first_of("\r\n");
- if (i == base::StringPiece::npos) {
- *request_line = std::string(handshake_message, len);
- *headers = "";
- return;
- }
- // |request_line| includes \r\n.
- *request_line = std::string(handshake_message, i + 2);
-
- int header_len = len - (i + 2) - 2;
- if (header_len > 0) {
- // |handshake_message| includes trailing \r\n\r\n.
- // |headers| doesn't include 2nd \r\n.
- *headers = std::string(handshake_message + i + 2, header_len);
- } else {
- *headers = "";
- }
-}
-
-void FetchHeaders(const std::string& headers,
- const char* const headers_to_get[],
- size_t headers_to_get_len,
- std::vector<std::string>* values) {
- net::HttpUtil::HeadersIterator iter(headers.begin(), headers.end(), "\r\n");
- while (iter.GetNext()) {
- for (size_t i = 0; i < headers_to_get_len; i++) {
- if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(),
- headers_to_get[i])) {
- values->push_back(iter.values());
- }
- }
- }
-}
-
-bool GetHeaderName(std::string::const_iterator line_begin,
- std::string::const_iterator line_end,
- std::string::const_iterator* name_begin,
- std::string::const_iterator* name_end) {
- std::string::const_iterator colon = std::find(line_begin, line_end, ':');
- if (colon == line_end) {
- return false;
- }
- *name_begin = line_begin;
- *name_end = colon;
- if (*name_begin == *name_end || net::HttpUtil::IsLWS(**name_begin))
- return false;
- net::HttpUtil::TrimLWS(name_begin, name_end);
- return true;
-}
-
-// Similar to HttpUtil::StripHeaders, but it preserves malformed headers, that
-// is, lines that are not formatted as "<name>: <value>\r\n".
-std::string FilterHeaders(
- const std::string& headers,
- const char* const headers_to_remove[],
- size_t headers_to_remove_len) {
- std::string filtered_headers;
-
- base::StringTokenizer lines(headers.begin(), headers.end(), "\r\n");
- while (lines.GetNext()) {
- std::string::const_iterator line_begin = lines.token_begin();
- std::string::const_iterator line_end = lines.token_end();
- std::string::const_iterator name_begin;
- std::string::const_iterator name_end;
- bool should_remove = false;
- if (GetHeaderName(line_begin, line_end, &name_begin, &name_end)) {
- for (size_t i = 0; i < headers_to_remove_len; ++i) {
- if (LowerCaseEqualsASCII(name_begin, name_end, headers_to_remove[i])) {
- should_remove = true;
- break;
- }
- }
- }
- if (!should_remove) {
- filtered_headers.append(line_begin, line_end);
- filtered_headers.append("\r\n");
- }
- }
- return filtered_headers;
-}
-
-bool CheckVersionInRequest(const std::string& request_headers) {
- std::vector<std::string> values;
- const char* const headers_to_get[1] = {
- websockets::kSecWebSocketVersionLowercase};
- FetchHeaders(request_headers, headers_to_get, 1, &values);
- DCHECK_LE(values.size(), 1U);
- if (values.empty())
- return false;
-
- int version;
- bool conversion_success = base::StringToInt(values[0], &version);
- if (!conversion_success)
- return false;
-
- return version == kVersionHeaderValueForRFC6455;
-}
-
-// Append a header to a string. Equivalent to
-// response_message += header + ": " + value + "\r\n"
-// but avoids unnecessary allocations and copies.
-void AppendHeader(const base::StringPiece& header,
- const base::StringPiece& value,
- std::string* response_message) {
- static const char kColonSpace[] = ": ";
- const size_t kColonSpaceSize = sizeof(kColonSpace) - 1;
- static const char kCrNl[] = "\r\n";
- const size_t kCrNlSize = sizeof(kCrNl) - 1;
-
- size_t extra_size =
- header.size() + kColonSpaceSize + value.size() + kCrNlSize;
- response_message->reserve(response_message->size() + extra_size);
- response_message->append(header.begin(), header.end());
- response_message->append(kColonSpace, kColonSpace + kColonSpaceSize);
- response_message->append(value.begin(), value.end());
- response_message->append(kCrNl, kCrNl + kCrNlSize);
-}
-
-} // namespace
-
-WebSocketHandshakeRequestHandler::WebSocketHandshakeRequestHandler()
- : original_length_(0),
- raw_length_(0) {}
-
-bool WebSocketHandshakeRequestHandler::ParseRequest(
- const char* data, int length) {
- DCHECK_GT(length, 0);
- std::string input(data, length);
- int input_header_length =
- HttpUtil::LocateEndOfHeaders(input.data(), input.size(), 0);
- if (input_header_length <= 0)
- return false;
-
- ParseHandshakeHeader(input.data(),
- input_header_length,
- &request_line_,
- &headers_);
-
- if (!CheckVersionInRequest(headers_)) {
- NOTREACHED();
- return false;
- }
-
- original_length_ = input_header_length;
- return true;
-}
-
-size_t WebSocketHandshakeRequestHandler::original_length() const {
- return original_length_;
-}
-
-void WebSocketHandshakeRequestHandler::AppendHeaderIfMissing(
- const std::string& name, const std::string& value) {
- DCHECK(!headers_.empty());
- HttpUtil::AppendHeaderIfMissing(name.c_str(), value, &headers_);
-}
-
-void WebSocketHandshakeRequestHandler::RemoveHeaders(
- const char* const headers_to_remove[],
- size_t headers_to_remove_len) {
- DCHECK(!headers_.empty());
- headers_ = FilterHeaders(
- headers_, headers_to_remove, headers_to_remove_len);
-}
-
-HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo(
- const GURL& url, std::string* challenge) {
- HttpRequestInfo request_info;
- request_info.url = url;
- size_t method_end = base::StringPiece(request_line_).find_first_of(" ");
- if (method_end != base::StringPiece::npos)
- request_info.method = std::string(request_line_.data(), method_end);
-
- request_info.extra_headers.Clear();
- request_info.extra_headers.AddHeadersFromString(headers_);
-
- request_info.extra_headers.RemoveHeader(websockets::kUpgrade);
- request_info.extra_headers.RemoveHeader(HttpRequestHeaders::kConnection);
-
- std::string key;
- bool header_present = request_info.extra_headers.GetHeader(
- websockets::kSecWebSocketKey, &key);
- DCHECK(header_present);
- request_info.extra_headers.RemoveHeader(websockets::kSecWebSocketKey);
- *challenge = key;
- return request_info;
-}
-
-bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock(
- const GURL& url,
- SpdyHeaderBlock* headers,
- std::string* challenge,
- int spdy_protocol_version) {
- // Construct opening handshake request headers as a SPDY header block.
- // For details, see WebSocket Layering over SPDY/3 Draft 8.
- if (spdy_protocol_version <= 2) {
- (*headers)["path"] = url.path();
- (*headers)["version"] = "WebSocket/13";
- (*headers)["scheme"] = url.scheme();
- } else {
- (*headers)[":path"] = url.path();
- (*headers)[":version"] = "WebSocket/13";
- (*headers)[":scheme"] = url.scheme();
- }
-
- HttpUtil::HeadersIterator iter(headers_.begin(), headers_.end(), "\r\n");
- while (iter.GetNext()) {
- if (LowerCaseEqualsASCII(iter.name_begin(),
- iter.name_end(),
- websockets::kUpgradeLowercase) ||
- LowerCaseEqualsASCII(
- iter.name_begin(), iter.name_end(), "connection") ||
- LowerCaseEqualsASCII(iter.name_begin(),
- iter.name_end(),
- websockets::kSecWebSocketVersionLowercase)) {
- // These headers must be ignored.
- continue;
- } else if (LowerCaseEqualsASCII(iter.name_begin(),
- iter.name_end(),
- websockets::kSecWebSocketKeyLowercase)) {
- *challenge = iter.values();
- // Sec-WebSocket-Key is not sent to the server.
- continue;
- } else if (LowerCaseEqualsASCII(
- iter.name_begin(), iter.name_end(), "host") ||
- LowerCaseEqualsASCII(
- iter.name_begin(), iter.name_end(), "origin") ||
- LowerCaseEqualsASCII(
- iter.name_begin(),
- iter.name_end(),
- websockets::kSecWebSocketProtocolLowercase) ||
- LowerCaseEqualsASCII(
- iter.name_begin(),
- iter.name_end(),
- websockets::kSecWebSocketExtensionsLowercase)) {
- // TODO(toyoshim): Some WebSocket extensions may not be compatible with
- // SPDY. We should omit them from a Sec-WebSocket-Extension header.
- std::string name;
- if (spdy_protocol_version <= 2)
- name = base::StringToLowerASCII(iter.name());
- else
- name = ":" + base::StringToLowerASCII(iter.name());
- (*headers)[name] = iter.values();
- continue;
- }
- // Others should be sent out to |headers|.
- std::string name = base::StringToLowerASCII(iter.name());
- SpdyHeaderBlock::iterator found = headers->find(name);
- if (found == headers->end()) {
- (*headers)[name] = iter.values();
- } else {
- // For now, websocket doesn't use multiple headers, but follows to http.
- found->second.append(1, '\0'); // +=() doesn't append 0's
- found->second.append(iter.values());
- }
- }
-
- return true;
-}
-
-std::string WebSocketHandshakeRequestHandler::GetRawRequest() {
- DCHECK(!request_line_.empty());
- DCHECK(!headers_.empty());
-
- std::string raw_request = request_line_ + headers_ + "\r\n";
- raw_length_ = raw_request.size();
- return raw_request;
-}
-
-size_t WebSocketHandshakeRequestHandler::raw_length() const {
- DCHECK_GT(raw_length_, 0);
- return raw_length_;
-}
-
-WebSocketHandshakeResponseHandler::WebSocketHandshakeResponseHandler()
- : original_header_length_(0) {}
-
-WebSocketHandshakeResponseHandler::~WebSocketHandshakeResponseHandler() {}
-
-size_t WebSocketHandshakeResponseHandler::ParseRawResponse(
- const char* data, int length) {
- DCHECK_GT(length, 0);
- if (HasResponse()) {
- DCHECK(!status_line_.empty());
- // headers_ might be empty for wrong response from server.
-
- return 0;
- }
-
- size_t old_original_length = original_.size();
-
- original_.append(data, length);
- // TODO(ukai): fail fast when response gives wrong status code.
- original_header_length_ = HttpUtil::LocateEndOfHeaders(
- original_.data(), original_.size(), 0);
- if (!HasResponse())
- return length;
-
- ParseHandshakeHeader(original_.data(),
- original_header_length_,
- &status_line_,
- &headers_);
- int header_size = status_line_.size() + headers_.size();
- DCHECK_GE(original_header_length_, header_size);
- header_separator_ = std::string(original_.data() + header_size,
- original_header_length_ - header_size);
- return original_header_length_ - old_original_length;
-}
-
-bool WebSocketHandshakeResponseHandler::HasResponse() const {
- return original_header_length_ > 0 &&
- static_cast<size_t>(original_header_length_) <= original_.size();
-}
void ComputeSecWebSocketAccept(const std::string& key,
std::string* accept) {
@@ -354,145 +20,4 @@ void ComputeSecWebSocketAccept(const std::string& key,
base::Base64Encode(hash, accept);
}
-bool WebSocketHandshakeResponseHandler::ParseResponseInfo(
- const HttpResponseInfo& response_info,
- const std::string& challenge) {
- if (!response_info.headers.get())
- return false;
-
- // TODO(ricea): Eliminate all the reallocations and string copies.
- std::string response_message;
- response_message = response_info.headers->GetStatusLine();
- response_message += "\r\n";
-
- AppendHeader(websockets::kUpgrade,
- websockets::kWebSocketLowercase,
- &response_message);
-
- AppendHeader(
- HttpRequestHeaders::kConnection, websockets::kUpgrade, &response_message);
-
- std::string websocket_accept;
- ComputeSecWebSocketAccept(challenge, &websocket_accept);
- AppendHeader(
- websockets::kSecWebSocketAccept, websocket_accept, &response_message);
-
- void* iter = NULL;
- std::string name;
- std::string value;
- while (response_info.headers->EnumerateHeaderLines(&iter, &name, &value)) {
- AppendHeader(name, value, &response_message);
- }
- response_message += "\r\n";
-
- return ParseRawResponse(response_message.data(),
- response_message.size()) == response_message.size();
-}
-
-bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock(
- const SpdyHeaderBlock& headers,
- const std::string& challenge,
- int spdy_protocol_version) {
- SpdyHeaderBlock::const_iterator status;
- if (spdy_protocol_version <= 2)
- status = headers.find("status");
- else
- status = headers.find(":status");
- if (status == headers.end())
- return false;
-
- std::string hash =
- base::SHA1HashString(challenge + websockets::kWebSocketGuid);
- std::string websocket_accept;
- base::Base64Encode(hash, &websocket_accept);
-
- std::string response_message = base::StringPrintf(
- "%s %s\r\n", websockets::kHttpProtocolVersion, status->second.c_str());
-
- AppendHeader(
- websockets::kUpgrade, websockets::kWebSocketLowercase, &response_message);
- AppendHeader(
- HttpRequestHeaders::kConnection, websockets::kUpgrade, &response_message);
- AppendHeader(
- websockets::kSecWebSocketAccept, websocket_accept, &response_message);
-
- for (SpdyHeaderBlock::const_iterator iter = headers.begin();
- iter != headers.end();
- ++iter) {
- // For each value, if the server sends a NUL-separated list of values,
- // we separate that back out into individual headers for each value
- // in the list.
- if ((spdy_protocol_version <= 2 &&
- LowerCaseEqualsASCII(iter->first, "status")) ||
- (spdy_protocol_version >= 3 &&
- LowerCaseEqualsASCII(iter->first, ":status"))) {
- // The status value is already handled as the first line of
- // |response_message|. Just skip here.
- continue;
- }
- const std::string& value = iter->second;
- size_t start = 0;
- size_t end = 0;
- do {
- end = value.find('\0', start);
- std::string tval;
- if (end != std::string::npos)
- tval = value.substr(start, (end - start));
- else
- tval = value.substr(start);
- if (spdy_protocol_version >= 3 &&
- (LowerCaseEqualsASCII(iter->first,
- websockets::kSecWebSocketProtocolSpdy3) ||
- LowerCaseEqualsASCII(iter->first,
- websockets::kSecWebSocketExtensionsSpdy3)))
- AppendHeader(iter->first.substr(1), tval, &response_message);
- else
- AppendHeader(iter->first, tval, &response_message);
- start = end + 1;
- } while (end != std::string::npos);
- }
- response_message += "\r\n";
-
- return ParseRawResponse(response_message.data(),
- response_message.size()) == response_message.size();
-}
-
-void WebSocketHandshakeResponseHandler::GetHeaders(
- const char* const headers_to_get[],
- size_t headers_to_get_len,
- std::vector<std::string>* values) {
- DCHECK(HasResponse());
- DCHECK(!status_line_.empty());
- // headers_ might be empty for wrong response from server.
- if (headers_.empty())
- return;
-
- FetchHeaders(headers_, headers_to_get, headers_to_get_len, values);
-}
-
-void WebSocketHandshakeResponseHandler::RemoveHeaders(
- const char* const headers_to_remove[],
- size_t headers_to_remove_len) {
- DCHECK(HasResponse());
- DCHECK(!status_line_.empty());
- // headers_ might be empty for wrong response from server.
- if (headers_.empty())
- return;
-
- headers_ = FilterHeaders(headers_, headers_to_remove, headers_to_remove_len);
-}
-
-std::string WebSocketHandshakeResponseHandler::GetRawResponse() const {
- DCHECK(HasResponse());
- return original_.substr(0, original_header_length_);
-}
-
-std::string WebSocketHandshakeResponseHandler::GetResponse() {
- DCHECK(HasResponse());
- DCHECK(!status_line_.empty());
- // headers_ might be empty for wrong response from server.
-
- return status_line_ + headers_ + header_separator_;
-}
-
} // namespace net
diff --git a/net/websockets/websocket_handshake_handler.h b/net/websockets/websocket_handshake_handler.h
index 73af66d..c65e6d9 100644
--- a/net/websockets/websocket_handshake_handler.h
+++ b/net/websockets/websocket_handshake_handler.h
@@ -1,124 +1,19 @@
// Copyright (c) 2012 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.
-//
-// WebSocketHandshake*Handler handles WebSocket handshake request message
-// from WebKit renderer process, and WebSocket handshake response message
-// from WebSocket server.
-// It modifies messages for the following reason:
-// - We don't trust WebKit renderer process, so we'll not expose HttpOnly
-// cookies to the renderer process, so handles HttpOnly cookies in
-// browser process.
-//
+
#ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
#include <string>
-#include <vector>
-
-#include "net/base/net_export.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_response_info.h"
-#include "net/spdy/spdy_header_block.h"
namespace net {
+// Given a WebSocket handshake challenge, compute the correct response.
+// TODO(ricea): There should probably be a test for this.
void ComputeSecWebSocketAccept(const std::string& key,
std::string* accept);
-class NET_EXPORT_PRIVATE WebSocketHandshakeRequestHandler {
- public:
- WebSocketHandshakeRequestHandler();
- ~WebSocketHandshakeRequestHandler() {}
-
- // Parses WebSocket handshake request from renderer process.
- // It assumes a WebSocket handshake request message is given at once, and
- // no other data is added to the request message.
- bool ParseRequest(const char* data, int length);
-
- size_t original_length() const;
-
- // Appends the header value pair for |name| and |value|, if |name| doesn't
- // exist.
- void AppendHeaderIfMissing(const std::string& name,
- const std::string& value);
- // Removes the headers that matches (case insensitive).
- void RemoveHeaders(const char* const headers_to_remove[],
- size_t headers_to_remove_len);
-
- // Gets request info to open WebSocket connection and fills challenge data in
- // |challenge|.
- HttpRequestInfo GetRequestInfo(const GURL& url, std::string* challenge);
- // Gets request as SpdyHeaderBlock.
- // Also, fills challenge data in |challenge|.
- bool GetRequestHeaderBlock(const GURL& url,
- SpdyHeaderBlock* headers,
- std::string* challenge,
- int spdy_protocol_version);
- // Gets WebSocket handshake raw request message to open WebSocket
- // connection.
- std::string GetRawRequest();
- // Calling raw_length is valid only after GetRawRequest() call.
- size_t raw_length() const;
-
- private:
- std::string request_line_;
- std::string headers_;
- int original_length_;
- int raw_length_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeRequestHandler);
-};
-
-class NET_EXPORT_PRIVATE WebSocketHandshakeResponseHandler {
- public:
- WebSocketHandshakeResponseHandler();
- ~WebSocketHandshakeResponseHandler();
-
- // Parses WebSocket handshake response from WebSocket server.
- // Returns number of bytes in |data| used for WebSocket handshake response
- // message. If it already got whole WebSocket handshake response message,
- // returns zero. In other words, [data + returned value, data + length) will
- // be WebSocket frame data after handshake response message.
- // TODO(ukai): fail fast when response gives wrong status code.
- size_t ParseRawResponse(const char* data, int length);
- // Returns true if it already parses full handshake response message.
- bool HasResponse() const;
- // Parses WebSocket handshake response info given as HttpResponseInfo.
- bool ParseResponseInfo(const HttpResponseInfo& response_info,
- const std::string& challenge);
- // Parses WebSocket handshake response as SpdyHeaderBlock.
- bool ParseResponseHeaderBlock(const SpdyHeaderBlock& headers,
- const std::string& challenge,
- int spdy_protocol_version);
-
- // Gets the headers value.
- void GetHeaders(const char* const headers_to_get[],
- size_t headers_to_get_len,
- std::vector<std::string>* values);
- // Removes the headers that matches (case insensitive).
- void RemoveHeaders(const char* const headers_to_remove[],
- size_t headers_to_remove_len);
-
- // Gets raw WebSocket handshake response received from WebSocket server.
- std::string GetRawResponse() const;
-
- // Gets WebSocket handshake response message sent to renderer process.
- std::string GetResponse();
-
- private:
- // Original bytes input by using ParseRawResponse().
- std::string original_;
- // Number of bytes actually used for the handshake response in |original_|.
- int original_header_length_;
-
- std::string status_line_;
- std::string headers_;
- std::string header_separator_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeResponseHandler);
-};
-
} // namespace net
#endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
diff --git a/net/websockets/websocket_handshake_handler_spdy_test.cc b/net/websockets/websocket_handshake_handler_spdy_test.cc
deleted file mode 100644
index 064bdcf..0000000
--- a/net/websockets/websocket_handshake_handler_spdy_test.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-// 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 "net/websockets/websocket_handshake_handler.h"
-
-#include <string>
-
-#include "net/socket/next_proto.h"
-#include "net/spdy/spdy_header_block.h"
-#include "net/spdy/spdy_websocket_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace net {
-
-namespace {
-
-class WebSocketHandshakeHandlerSpdyTest
- : public ::testing::Test,
- public ::testing::WithParamInterface<NextProto> {
- protected:
- WebSocketHandshakeHandlerSpdyTest() : spdy_util_(GetParam()) {}
-
- SpdyWebSocketTestUtil spdy_util_;
-};
-
-INSTANTIATE_TEST_CASE_P(
- NextProto,
- WebSocketHandshakeHandlerSpdyTest,
- testing::Values(kProtoDeprecatedSPDY2,
- kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
-
-TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponse) {
- WebSocketHandshakeRequestHandler request_handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Extensions: foo\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "\r\n";
-
- EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
-
- GURL url("ws://example.com/demo");
- std::string challenge;
- SpdyHeaderBlock headers;
- ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url,
- &headers,
- &challenge,
- spdy_util_.spdy_version()));
-
- EXPECT_EQ(url.path(), spdy_util_.GetHeader(headers, "path"));
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "upgrade").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Upgrade").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "connection").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Connection").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Key").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-websocket-key").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Version").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-webSocket-version").empty());
- EXPECT_EQ("example.com", spdy_util_.GetHeader(headers, "host"));
- EXPECT_EQ("http://example.com", spdy_util_.GetHeader(headers, "origin"));
- EXPECT_EQ("sample", spdy_util_.GetHeader(headers, "sec-websocket-protocol"));
- EXPECT_EQ("foo", spdy_util_.GetHeader(headers, "sec-websocket-extensions"));
- EXPECT_EQ("ws", spdy_util_.GetHeader(headers, "scheme"));
- EXPECT_EQ("WebSocket/13", spdy_util_.GetHeader(headers, "version"));
-
- static const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
-
- EXPECT_EQ(expected_challenge, challenge);
-
- headers.clear();
-
- spdy_util_.SetHeader("status", "101 Switching Protocols", &headers);
- spdy_util_.SetHeader("sec-websocket-protocol", "sample", &headers);
- spdy_util_.SetHeader("sec-websocket-extensions", "foo", &headers);
-
- WebSocketHandshakeResponseHandler response_handler;
- EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(
- headers, challenge, spdy_util_.spdy_version()));
- EXPECT_TRUE(response_handler.HasResponse());
-
- // Note that order of sec-websocket-* is sensitive with hash_map order.
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "sec-websocket-extensions: foo\r\n"
- "sec-websocket-protocol: sample\r\n"
- "\r\n";
-
- EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
-}
-
-TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponseWithCookies) {
- WebSocketHandshakeRequestHandler request_handler;
-
- // Note that websocket won't use multiple headers in request now.
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Extensions: foo\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
- "\r\n";
-
- EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
-
- GURL url("ws://example.com/demo");
- std::string challenge;
- SpdyHeaderBlock headers;
- ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url,
- &headers,
- &challenge,
- spdy_util_.spdy_version()));
-
- EXPECT_EQ(url.path(), spdy_util_.GetHeader(headers, "path"));
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "upgrade").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Upgrade").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "connection").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Connection").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Key").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-websocket-key").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Version").empty());
- EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-webSocket-version").empty());
- EXPECT_EQ("example.com", spdy_util_.GetHeader(headers, "host"));
- EXPECT_EQ("http://example.com", spdy_util_.GetHeader(headers, "origin"));
- EXPECT_EQ("sample", spdy_util_.GetHeader(headers, "sec-websocket-protocol"));
- EXPECT_EQ("foo", spdy_util_.GetHeader(headers, "sec-websocket-extensions"));
- EXPECT_EQ("ws", spdy_util_.GetHeader(headers, "scheme"));
- EXPECT_EQ("WebSocket/13", spdy_util_.GetHeader(headers, "version"));
- EXPECT_EQ("WK-websocket-test=1; WK-websocket-test-httponly=1",
- headers["cookie"]);
-
- const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
-
- EXPECT_EQ(expected_challenge, challenge);
-
- headers.clear();
-
- spdy_util_.SetHeader("status", "101 Switching Protocols", &headers);
- spdy_util_.SetHeader("sec-websocket-protocol", "sample", &headers);
- spdy_util_.SetHeader("sec-websocket-extensions", "foo", &headers);
- std::string cookie = "WK-websocket-test=1";
- cookie.append(1, '\0');
- cookie += "WK-websocket-test-httponly=1; HttpOnly";
- headers["set-cookie"] = cookie;
-
-
- WebSocketHandshakeResponseHandler response_handler;
- EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(
- headers, challenge, spdy_util_.spdy_version()));
- EXPECT_TRUE(response_handler.HasResponse());
-
- // Note that order of sec-websocket-* is sensitive with hash_map order.
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "sec-websocket-extensions: foo\r\n"
- "sec-websocket-protocol: sample\r\n"
- "set-cookie: WK-websocket-test=1\r\n"
- "set-cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
- "\r\n";
-
- EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
-}
-
-} // namespace
-
-} // namespace net
diff --git a/net/websockets/websocket_handshake_handler_test.cc b/net/websockets/websocket_handshake_handler_test.cc
index e59a982..8eff571 100644
--- a/net/websockets/websocket_handshake_handler_test.cc
+++ b/net/websockets/websocket_handshake_handler_test.cc
@@ -4,238 +4,14 @@
#include "net/websockets/websocket_handshake_handler.h"
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "url/gurl.h"
-
#include "testing/gtest/include/gtest/gtest.h"
-namespace {
-
-const char* const kCookieHeaders[] = {
- "cookie", "cookie2"
-};
-
-const char* const kSetCookieHeaders[] = {
- "set-cookie", "set-cookie2"
-};
-
-} // namespace
-
namespace net {
-TEST(WebSocketHandshakeRequestHandlerTest, SimpleRequest) {
- WebSocketHandshakeRequestHandler handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "\r\n";
-
- EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
-
- handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
-
- EXPECT_EQ(kHandshakeRequestMessage, handler.GetRawRequest());
-}
-
-TEST(WebSocketHandshakeRequestHandlerTest, ReplaceRequestCookies) {
- WebSocketHandshakeRequestHandler handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "Cookie: WK-websocket-test=1\r\n"
- "\r\n";
-
- EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
-
- handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
-
- handler.AppendHeaderIfMissing("Cookie",
- "WK-websocket-test=1; "
- "WK-websocket-test-httponly=1");
-
- static const char kHandshakeRequestExpectedMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
- "\r\n";
-
- EXPECT_EQ(kHandshakeRequestExpectedMessage, handler.GetRawRequest());
-}
-
-TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponse) {
- WebSocketHandshakeResponseHandler handler;
-
- static const char kHandshakeResponseMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n";
-
- EXPECT_EQ(strlen(kHandshakeResponseMessage),
- handler.ParseRawResponse(kHandshakeResponseMessage,
- strlen(kHandshakeResponseMessage)));
- EXPECT_TRUE(handler.HasResponse());
-
- handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
-
- EXPECT_EQ(kHandshakeResponseMessage, handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeResponseHandlerTest, ReplaceResponseCookies) {
- WebSocketHandshakeResponseHandler handler;
-
- static const char kHandshakeResponseMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Set-Cookie: WK-websocket-test-1\r\n"
- "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
- "\r\n";
-
- EXPECT_EQ(strlen(kHandshakeResponseMessage),
- handler.ParseRawResponse(kHandshakeResponseMessage,
- strlen(kHandshakeResponseMessage)));
- EXPECT_TRUE(handler.HasResponse());
- std::vector<std::string> cookies;
- handler.GetHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders), &cookies);
- ASSERT_EQ(2U, cookies.size());
- EXPECT_EQ("WK-websocket-test-1", cookies[0]);
- EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies[1]);
- handler.RemoveHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders));
-
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n";
-
- EXPECT_EQ(kHandshakeResponseExpectedMessage, handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeResponseHandlerTest, BadResponse) {
- WebSocketHandshakeResponseHandler handler;
-
- static const char kBadMessage[] = "\n\n\r\net-Location: w";
- EXPECT_EQ(2U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
- EXPECT_TRUE(handler.HasResponse());
- EXPECT_EQ("\n\n", handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeResponseHandlerTest, BadResponse2) {
- WebSocketHandshakeResponseHandler handler;
-
- static const char kBadMessage[] = "\n\r\n\r\net-Location: w";
- EXPECT_EQ(3U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
- EXPECT_TRUE(handler.HasResponse());
- EXPECT_EQ("\n\r\n", handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeHandlerTest, HttpRequestResponse) {
- WebSocketHandshakeRequestHandler request_handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "\r\n";
-
- EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
-
- GURL url("ws://example.com/demo");
- std::string challenge;
- const HttpRequestInfo& request_info =
- request_handler.GetRequestInfo(url, &challenge);
-
- EXPECT_EQ(url, request_info.url);
- EXPECT_EQ("GET", request_info.method);
- EXPECT_FALSE(request_info.extra_headers.HasHeader("Upgrade"));
- EXPECT_FALSE(request_info.extra_headers.HasHeader("Connection"));
- EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key"));
- std::string value;
- EXPECT_TRUE(request_info.extra_headers.GetHeader("Host", &value));
- EXPECT_EQ("example.com", value);
- EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Origin",
- &value));
- EXPECT_EQ("http://example.com", value);
- EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Protocol",
- &value));
- EXPECT_EQ("sample", value);
-
- EXPECT_EQ("dGhlIHNhbXBsZSBub25jZQ==", challenge);
-
- static const char kHandshakeResponseHeader[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Sec-WebSocket-Protocol: sample\r\n";
-
- std::string raw_headers =
- HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader,
- strlen(kHandshakeResponseHeader));
- HttpResponseInfo response_info;
- response_info.headers = new HttpResponseHeaders(raw_headers);
-
- EXPECT_TRUE(StartsWithASCII(response_info.headers->GetStatusLine(),
- "HTTP/1.1 101 ", false));
- EXPECT_FALSE(response_info.headers->HasHeader("Upgrade"));
- EXPECT_FALSE(response_info.headers->HasHeader("Connection"));
- EXPECT_FALSE(response_info.headers->HasHeader("Sec-WebSocket-Accept"));
- EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Protocol",
- "sample"));
-
- WebSocketHandshakeResponseHandler response_handler;
-
- EXPECT_TRUE(response_handler.ParseResponseInfo(response_info, challenge));
- EXPECT_TRUE(response_handler.HasResponse());
+namespace {
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n";
+// TODO(ricea): Put a test for ComputeSecWebSocketAccept() here.
- EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
-}
+} // namespace
} // namespace net
diff --git a/net/websockets/websocket_job.cc b/net/websockets/websocket_job.cc
deleted file mode 100644
index eb653fa..0000000
--- a/net/websockets/websocket_job.cc
+++ /dev/null
@@ -1,693 +0,0 @@
-// Copyright (c) 2012 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 "net/websockets/websocket_job.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_log.h"
-#include "net/cookies/cookie_store.h"
-#include "net/http/http_network_session.h"
-#include "net/http/http_transaction_factory.h"
-#include "net/http/http_util.h"
-#include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_session_pool.h"
-#include "net/url_request/url_request_context.h"
-#include "net/websockets/websocket_handshake_handler.h"
-#include "net/websockets/websocket_net_log_params.h"
-#include "net/websockets/websocket_throttle.h"
-#include "url/gurl.h"
-
-static const int kMaxPendingSendAllowed = 32768; // 32 kilobytes.
-
-namespace {
-
-// lower-case header names.
-const char* const kCookieHeaders[] = {
- "cookie", "cookie2"
-};
-const char* const kSetCookieHeaders[] = {
- "set-cookie", "set-cookie2"
-};
-
-net::SocketStreamJob* WebSocketJobFactory(
- const GURL& url, net::SocketStream::Delegate* delegate,
- net::URLRequestContext* context, net::CookieStore* cookie_store) {
- net::WebSocketJob* job = new net::WebSocketJob(delegate);
- job->InitSocketStream(new net::SocketStream(url, job, context, cookie_store));
- return job;
-}
-
-class WebSocketJobInitSingleton {
- private:
- friend struct base::DefaultLazyInstanceTraits<WebSocketJobInitSingleton>;
- WebSocketJobInitSingleton() {
- net::SocketStreamJob::RegisterProtocolFactory("ws", WebSocketJobFactory);
- net::SocketStreamJob::RegisterProtocolFactory("wss", WebSocketJobFactory);
- }
-};
-
-static base::LazyInstance<WebSocketJobInitSingleton> g_websocket_job_init =
- LAZY_INSTANCE_INITIALIZER;
-
-} // anonymous namespace
-
-namespace net {
-
-// static
-void WebSocketJob::EnsureInit() {
- g_websocket_job_init.Get();
-}
-
-WebSocketJob::WebSocketJob(SocketStream::Delegate* delegate)
- : delegate_(delegate),
- state_(INITIALIZED),
- waiting_(false),
- handshake_request_(new WebSocketHandshakeRequestHandler),
- handshake_response_(new WebSocketHandshakeResponseHandler),
- started_to_send_handshake_request_(false),
- handshake_request_sent_(0),
- response_cookies_save_index_(0),
- spdy_protocol_version_(0),
- save_next_cookie_running_(false),
- callback_pending_(false),
- weak_ptr_factory_(this),
- weak_ptr_factory_for_send_pending_(this) {
-}
-
-WebSocketJob::~WebSocketJob() {
- DCHECK_EQ(CLOSED, state_);
- DCHECK(!delegate_);
- DCHECK(!socket_.get());
-}
-
-void WebSocketJob::Connect() {
- DCHECK(socket_.get());
- DCHECK_EQ(state_, INITIALIZED);
- state_ = CONNECTING;
- socket_->Connect();
-}
-
-bool WebSocketJob::SendData(const char* data, int len) {
- switch (state_) {
- case INITIALIZED:
- return false;
-
- case CONNECTING:
- return SendHandshakeRequest(data, len);
-
- case OPEN:
- {
- scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(len);
- memcpy(buffer->data(), data, len);
- if (current_send_buffer_.get() || !send_buffer_queue_.empty()) {
- send_buffer_queue_.push_back(buffer);
- return true;
- }
- current_send_buffer_ = new DrainableIOBuffer(buffer.get(), len);
- return SendDataInternal(current_send_buffer_->data(),
- current_send_buffer_->BytesRemaining());
- }
-
- case CLOSING:
- case CLOSED:
- return false;
- }
- return false;
-}
-
-void WebSocketJob::Close() {
- if (state_ == CLOSED)
- return;
-
- state_ = CLOSING;
- if (current_send_buffer_.get()) {
- // Will close in SendPending.
- return;
- }
- state_ = CLOSED;
- CloseInternal();
-}
-
-void WebSocketJob::RestartWithAuth(const AuthCredentials& credentials) {
- state_ = CONNECTING;
- socket_->RestartWithAuth(credentials);
-}
-
-void WebSocketJob::DetachDelegate() {
- state_ = CLOSED;
- WebSocketThrottle::GetInstance()->RemoveFromQueue(this);
-
- scoped_refptr<WebSocketJob> protect(this);
- weak_ptr_factory_.InvalidateWeakPtrs();
- weak_ptr_factory_for_send_pending_.InvalidateWeakPtrs();
-
- delegate_ = NULL;
- if (socket_.get())
- socket_->DetachDelegate();
- socket_ = NULL;
- if (!callback_.is_null()) {
- waiting_ = false;
- callback_.Reset();
- Release(); // Balanced with OnStartOpenConnection().
- }
-}
-
-int WebSocketJob::OnStartOpenConnection(
- SocketStream* socket, const CompletionCallback& callback) {
- DCHECK(callback_.is_null());
- state_ = CONNECTING;
-
- addresses_ = socket->address_list();
- if (!WebSocketThrottle::GetInstance()->PutInQueue(this)) {
- return ERR_WS_THROTTLE_QUEUE_TOO_LARGE;
- }
-
- if (delegate_) {
- int result = delegate_->OnStartOpenConnection(socket, callback);
- DCHECK_EQ(OK, result);
- }
- if (waiting_) {
- // PutInQueue() may set |waiting_| true for throttling. In this case,
- // Wakeup() will be called later.
- callback_ = callback;
- AddRef(); // Balanced when callback_ is cleared.
- return ERR_IO_PENDING;
- }
- return TrySpdyStream();
-}
-
-void WebSocketJob::OnConnected(
- SocketStream* socket, int max_pending_send_allowed) {
- if (state_ == CLOSED)
- return;
- DCHECK_EQ(CONNECTING, state_);
- if (delegate_)
- delegate_->OnConnected(socket, max_pending_send_allowed);
-}
-
-void WebSocketJob::OnSentData(SocketStream* socket, int amount_sent) {
- DCHECK_NE(INITIALIZED, state_);
- DCHECK_GT(amount_sent, 0);
- if (state_ == CLOSED)
- return;
- if (state_ == CONNECTING) {
- OnSentHandshakeRequest(socket, amount_sent);
- return;
- }
- if (delegate_) {
- DCHECK(state_ == OPEN || state_ == CLOSING);
- if (!current_send_buffer_.get()) {
- VLOG(1)
- << "OnSentData current_send_buffer=NULL amount_sent=" << amount_sent;
- return;
- }
- current_send_buffer_->DidConsume(amount_sent);
- if (current_send_buffer_->BytesRemaining() > 0)
- return;
-
- // We need to report amount_sent of original buffer size, instead of
- // amount sent to |socket|.
- amount_sent = current_send_buffer_->size();
- DCHECK_GT(amount_sent, 0);
- current_send_buffer_ = NULL;
- if (!weak_ptr_factory_for_send_pending_.HasWeakPtrs()) {
- base::MessageLoopForIO::current()->PostTask(
- FROM_HERE,
- base::Bind(&WebSocketJob::SendPending,
- weak_ptr_factory_for_send_pending_.GetWeakPtr()));
- }
- delegate_->OnSentData(socket, amount_sent);
- }
-}
-
-void WebSocketJob::OnReceivedData(
- SocketStream* socket, const char* data, int len) {
- DCHECK_NE(INITIALIZED, state_);
- if (state_ == CLOSED)
- return;
- if (state_ == CONNECTING) {
- OnReceivedHandshakeResponse(socket, data, len);
- return;
- }
- DCHECK(state_ == OPEN || state_ == CLOSING);
- if (delegate_ && len > 0)
- delegate_->OnReceivedData(socket, data, len);
-}
-
-void WebSocketJob::OnClose(SocketStream* socket) {
- state_ = CLOSED;
- WebSocketThrottle::GetInstance()->RemoveFromQueue(this);
-
- scoped_refptr<WebSocketJob> protect(this);
- weak_ptr_factory_.InvalidateWeakPtrs();
-
- SocketStream::Delegate* delegate = delegate_;
- delegate_ = NULL;
- socket_ = NULL;
- if (!callback_.is_null()) {
- waiting_ = false;
- callback_.Reset();
- Release(); // Balanced with OnStartOpenConnection().
- }
- if (delegate)
- delegate->OnClose(socket);
-}
-
-void WebSocketJob::OnAuthRequired(
- SocketStream* socket, AuthChallengeInfo* auth_info) {
- if (delegate_)
- delegate_->OnAuthRequired(socket, auth_info);
-}
-
-void WebSocketJob::OnSSLCertificateError(
- SocketStream* socket, const SSLInfo& ssl_info, bool fatal) {
- if (delegate_)
- delegate_->OnSSLCertificateError(socket, ssl_info, fatal);
-}
-
-void WebSocketJob::OnError(const SocketStream* socket, int error) {
- if (delegate_ && error != ERR_PROTOCOL_SWITCHED)
- delegate_->OnError(socket, error);
-}
-
-void WebSocketJob::OnCreatedSpdyStream(int result) {
- DCHECK(spdy_websocket_stream_.get());
- DCHECK(socket_.get());
- DCHECK_NE(ERR_IO_PENDING, result);
-
- if (state_ == CLOSED) {
- result = ERR_ABORTED;
- } else if (result == OK) {
- state_ = CONNECTING;
- result = ERR_PROTOCOL_SWITCHED;
- } else {
- spdy_websocket_stream_.reset();
- }
-
- CompleteIO(result);
-}
-
-void WebSocketJob::OnSentSpdyHeaders() {
- DCHECK_NE(INITIALIZED, state_);
- if (state_ != CONNECTING)
- return;
- size_t original_length = handshake_request_->original_length();
- handshake_request_.reset();
- if (delegate_)
- delegate_->OnSentData(socket_.get(), original_length);
-}
-
-void WebSocketJob::OnSpdyResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) {
- DCHECK_NE(INITIALIZED, state_);
- if (state_ != CONNECTING)
- return;
- // TODO(toyoshim): Fallback to non-spdy connection?
- handshake_response_->ParseResponseHeaderBlock(response_headers,
- challenge_,
- spdy_protocol_version_);
-
- SaveCookiesAndNotifyHeadersComplete();
-}
-
-void WebSocketJob::OnSentSpdyData(size_t bytes_sent) {
- DCHECK_NE(INITIALIZED, state_);
- DCHECK_NE(CONNECTING, state_);
- if (state_ == CLOSED)
- return;
- if (!spdy_websocket_stream_.get())
- return;
- OnSentData(socket_.get(), static_cast<int>(bytes_sent));
-}
-
-void WebSocketJob::OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) {
- DCHECK_NE(INITIALIZED, state_);
- DCHECK_NE(CONNECTING, state_);
- if (state_ == CLOSED)
- return;
- if (!spdy_websocket_stream_.get())
- return;
- if (buffer) {
- OnReceivedData(
- socket_.get(), buffer->GetRemainingData(), buffer->GetRemainingSize());
- } else {
- OnReceivedData(socket_.get(), NULL, 0);
- }
-}
-
-void WebSocketJob::OnCloseSpdyStream() {
- spdy_websocket_stream_.reset();
- OnClose(socket_.get());
-}
-
-bool WebSocketJob::SendHandshakeRequest(const char* data, int len) {
- DCHECK_EQ(state_, CONNECTING);
- if (started_to_send_handshake_request_)
- return false;
- if (!handshake_request_->ParseRequest(data, len))
- return false;
-
- AddCookieHeaderAndSend();
- return true;
-}
-
-void WebSocketJob::AddCookieHeaderAndSend() {
- bool allow = true;
- if (delegate_ && !delegate_->CanGetCookies(socket_.get(), GetURLForCookies()))
- allow = false;
-
- if (socket_.get() && delegate_ && state_ == CONNECTING) {
- handshake_request_->RemoveHeaders(kCookieHeaders,
- arraysize(kCookieHeaders));
- if (allow && socket_->cookie_store()) {
- // Add cookies, including HttpOnly cookies.
- CookieOptions cookie_options;
- cookie_options.set_include_httponly();
- socket_->cookie_store()->GetCookiesWithOptionsAsync(
- GetURLForCookies(), cookie_options,
- base::Bind(&WebSocketJob::LoadCookieCallback,
- weak_ptr_factory_.GetWeakPtr()));
- } else {
- DoSendData();
- }
- }
-}
-
-void WebSocketJob::LoadCookieCallback(const std::string& cookie) {
- if (!cookie.empty())
- // TODO(tyoshino): Sending cookie means that connection doesn't need
- // PRIVACY_MODE_ENABLED as cookies may be server-bound and channel id
- // wouldn't negatively affect privacy anyway. Need to restart connection
- // or refactor to determine cookie status prior to connecting.
- handshake_request_->AppendHeaderIfMissing("Cookie", cookie);
- DoSendData();
-}
-
-void WebSocketJob::DoSendData() {
- if (spdy_websocket_stream_.get()) {
- scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
- handshake_request_->GetRequestHeaderBlock(
- socket_->url(), headers.get(), &challenge_, spdy_protocol_version_);
- spdy_websocket_stream_->SendRequest(headers.Pass());
- } else {
- const std::string& handshake_request =
- handshake_request_->GetRawRequest();
- handshake_request_sent_ = 0;
- socket_->net_log()->AddEvent(
- NetLog::TYPE_WEB_SOCKET_SEND_REQUEST_HEADERS,
- base::Bind(&NetLogWebSocketHandshakeCallback, &handshake_request));
- socket_->SendData(handshake_request.data(),
- handshake_request.size());
- }
- // Just buffered in |handshake_request_|.
- started_to_send_handshake_request_ = true;
-}
-
-void WebSocketJob::OnSentHandshakeRequest(
- SocketStream* socket, int amount_sent) {
- DCHECK_EQ(state_, CONNECTING);
- handshake_request_sent_ += amount_sent;
- DCHECK_LE(handshake_request_sent_, handshake_request_->raw_length());
- if (handshake_request_sent_ >= handshake_request_->raw_length()) {
- // handshake request has been sent.
- // notify original size of handshake request to delegate.
- // Reset the handshake_request_ first in case this object is deleted by the
- // delegate.
- size_t original_length = handshake_request_->original_length();
- handshake_request_.reset();
- if (delegate_)
- delegate_->OnSentData(socket, original_length);
- }
-}
-
-void WebSocketJob::OnReceivedHandshakeResponse(
- SocketStream* socket, const char* data, int len) {
- DCHECK_EQ(state_, CONNECTING);
- if (handshake_response_->HasResponse()) {
- // If we already has handshake response, received data should be frame
- // data, not handshake message.
- received_data_after_handshake_.insert(
- received_data_after_handshake_.end(), data, data + len);
- return;
- }
-
- size_t response_length = handshake_response_->ParseRawResponse(data, len);
- if (!handshake_response_->HasResponse()) {
- // not yet. we need more data.
- return;
- }
- // handshake message is completed.
- std::string raw_response = handshake_response_->GetRawResponse();
- socket_->net_log()->AddEvent(
- NetLog::TYPE_WEB_SOCKET_READ_RESPONSE_HEADERS,
- base::Bind(&NetLogWebSocketHandshakeCallback, &raw_response));
- if (len - response_length > 0) {
- // If we received extra data, it should be frame data.
- DCHECK(received_data_after_handshake_.empty());
- received_data_after_handshake_.assign(data + response_length, data + len);
- }
- SaveCookiesAndNotifyHeadersComplete();
-}
-
-void WebSocketJob::SaveCookiesAndNotifyHeadersComplete() {
- // handshake message is completed.
- DCHECK(handshake_response_->HasResponse());
-
- // Extract cookies from the handshake response into a temporary vector.
- response_cookies_.clear();
- response_cookies_save_index_ = 0;
-
- handshake_response_->GetHeaders(
- kSetCookieHeaders, arraysize(kSetCookieHeaders), &response_cookies_);
-
- // Now, loop over the response cookies, and attempt to persist each.
- SaveNextCookie();
-}
-
-void WebSocketJob::NotifyHeadersComplete() {
- // Remove cookie headers, with malformed headers preserved.
- // Actual handshake should be done in Blink.
- handshake_response_->RemoveHeaders(
- kSetCookieHeaders, arraysize(kSetCookieHeaders));
- std::string handshake_response = handshake_response_->GetResponse();
- handshake_response_.reset();
- std::vector<char> received_data(handshake_response.begin(),
- handshake_response.end());
- received_data.insert(received_data.end(),
- received_data_after_handshake_.begin(),
- received_data_after_handshake_.end());
- received_data_after_handshake_.clear();
-
- state_ = OPEN;
-
- DCHECK(!received_data.empty());
- if (delegate_)
- delegate_->OnReceivedData(
- socket_.get(), &received_data.front(), received_data.size());
-
- WebSocketThrottle::GetInstance()->RemoveFromQueue(this);
-}
-
-void WebSocketJob::SaveNextCookie() {
- if (!socket_.get() || !delegate_ || state_ != CONNECTING)
- return;
-
- callback_pending_ = false;
- save_next_cookie_running_ = true;
-
- if (socket_->cookie_store()) {
- GURL url_for_cookies = GetURLForCookies();
-
- CookieOptions options;
- options.set_include_httponly();
-
- // Loop as long as SetCookieWithOptionsAsync completes synchronously. Since
- // CookieMonster's asynchronous operation APIs queue the callback to run it
- // on the thread where the API was called, there won't be race. I.e. unless
- // the callback is run synchronously, it won't be run in parallel with this
- // method.
- while (!callback_pending_ &&
- response_cookies_save_index_ < response_cookies_.size()) {
- std::string cookie = response_cookies_[response_cookies_save_index_];
- response_cookies_save_index_++;
-
- if (!delegate_->CanSetCookie(
- socket_.get(), url_for_cookies, cookie, &options))
- continue;
-
- callback_pending_ = true;
- socket_->cookie_store()->SetCookieWithOptionsAsync(
- url_for_cookies, cookie, options,
- base::Bind(&WebSocketJob::OnCookieSaved,
- weak_ptr_factory_.GetWeakPtr()));
- }
- }
-
- save_next_cookie_running_ = false;
-
- if (callback_pending_)
- return;
-
- response_cookies_.clear();
- response_cookies_save_index_ = 0;
-
- NotifyHeadersComplete();
-}
-
-void WebSocketJob::OnCookieSaved(bool cookie_status) {
- // Tell the caller of SetCookieWithOptionsAsync() that this completion
- // callback is invoked.
- // - If the caller checks callback_pending earlier than this callback, the
- // caller exits to let this method continue iteration.
- // - Otherwise, the caller continues iteration.
- callback_pending_ = false;
-
- // Resume SaveNextCookie if the caller of SetCookieWithOptionsAsync() exited
- // the loop. Otherwise, return.
- if (save_next_cookie_running_)
- return;
-
- SaveNextCookie();
-}
-
-GURL WebSocketJob::GetURLForCookies() const {
- GURL url = socket_->url();
- std::string scheme = socket_->is_secure() ? "https" : "http";
- url::Replacements<char> replacements;
- replacements.SetScheme(scheme.c_str(), url::Component(0, scheme.length()));
- return url.ReplaceComponents(replacements);
-}
-
-const AddressList& WebSocketJob::address_list() const {
- return addresses_;
-}
-
-int WebSocketJob::TrySpdyStream() {
- if (!socket_.get())
- return ERR_FAILED;
-
- // Check if we have a SPDY session available.
- HttpTransactionFactory* factory =
- socket_->context()->http_transaction_factory();
- if (!factory)
- return OK;
- scoped_refptr<HttpNetworkSession> session = factory->GetSession();
- if (!session.get() || !session->params().enable_websocket_over_spdy)
- return OK;
- SpdySessionPool* spdy_pool = session->spdy_session_pool();
- PrivacyMode privacy_mode = socket_->privacy_mode();
- const SpdySessionKey key(HostPortPair::FromURL(socket_->url()),
- socket_->proxy_server(), privacy_mode);
- // Forbid wss downgrade to SPDY without SSL.
- // TODO(toyoshim): Does it realize the same policy with HTTP?
- base::WeakPtr<SpdySession> spdy_session =
- spdy_pool->FindAvailableSession(key, *socket_->net_log());
- if (!spdy_session)
- return OK;
-
- SSLInfo ssl_info;
- bool was_npn_negotiated;
- NextProto protocol_negotiated = kProtoUnknown;
- bool use_ssl = spdy_session->GetSSLInfo(
- &ssl_info, &was_npn_negotiated, &protocol_negotiated);
- if (socket_->is_secure() && !use_ssl)
- return OK;
-
- // Create SpdyWebSocketStream.
- spdy_protocol_version_ = spdy_session->GetProtocolVersion();
- spdy_websocket_stream_.reset(new SpdyWebSocketStream(spdy_session, this));
-
- int result = spdy_websocket_stream_->InitializeStream(
- socket_->url(), MEDIUM, *socket_->net_log());
- if (result == OK) {
- OnConnected(socket_.get(), kMaxPendingSendAllowed);
- return ERR_PROTOCOL_SWITCHED;
- }
- if (result != ERR_IO_PENDING) {
- spdy_websocket_stream_.reset();
- return OK;
- }
-
- return ERR_IO_PENDING;
-}
-
-void WebSocketJob::SetWaiting() {
- waiting_ = true;
-}
-
-bool WebSocketJob::IsWaiting() const {
- return waiting_;
-}
-
-void WebSocketJob::Wakeup() {
- if (!waiting_)
- return;
- waiting_ = false;
- DCHECK(!callback_.is_null());
- base::MessageLoopForIO::current()->PostTask(
- FROM_HERE,
- base::Bind(&WebSocketJob::RetryPendingIO,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void WebSocketJob::RetryPendingIO() {
- int result = TrySpdyStream();
-
- // In the case of ERR_IO_PENDING, CompleteIO() will be called from
- // OnCreatedSpdyStream().
- if (result != ERR_IO_PENDING)
- CompleteIO(result);
-}
-
-void WebSocketJob::CompleteIO(int result) {
- // |callback_| may be null if OnClose() or DetachDelegate() was called.
- if (!callback_.is_null()) {
- CompletionCallback callback = callback_;
- callback_.Reset();
- callback.Run(result);
- Release(); // Balanced with OnStartOpenConnection().
- }
-}
-
-bool WebSocketJob::SendDataInternal(const char* data, int length) {
- if (spdy_websocket_stream_.get())
- return ERR_IO_PENDING == spdy_websocket_stream_->SendData(data, length);
- if (socket_.get())
- return socket_->SendData(data, length);
- return false;
-}
-
-void WebSocketJob::CloseInternal() {
- if (spdy_websocket_stream_.get())
- spdy_websocket_stream_->Close();
- if (socket_.get())
- socket_->Close();
-}
-
-void WebSocketJob::SendPending() {
- if (current_send_buffer_.get())
- return;
-
- // Current buffer has been sent. Try next if any.
- if (send_buffer_queue_.empty()) {
- // No more data to send.
- if (state_ == CLOSING)
- CloseInternal();
- return;
- }
-
- scoped_refptr<IOBufferWithSize> next_buffer = send_buffer_queue_.front();
- send_buffer_queue_.pop_front();
- current_send_buffer_ =
- new DrainableIOBuffer(next_buffer.get(), next_buffer->size());
- SendDataInternal(current_send_buffer_->data(),
- current_send_buffer_->BytesRemaining());
-}
-
-} // namespace net
diff --git a/net/websockets/websocket_job.h b/net/websockets/websocket_job.h
deleted file mode 100644
index bad06cf..0000000
--- a/net/websockets/websocket_job.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2012 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 NET_WEBSOCKETS_WEBSOCKET_JOB_H_
-#define NET_WEBSOCKETS_WEBSOCKET_JOB_H_
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "base/memory/weak_ptr.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "net/socket_stream/socket_stream_job.h"
-#include "net/spdy/spdy_header_block.h"
-#include "net/spdy/spdy_websocket_stream.h"
-
-class GURL;
-
-namespace net {
-
-class DrainableIOBuffer;
-class SSLInfo;
-class WebSocketHandshakeRequestHandler;
-class WebSocketHandshakeResponseHandler;
-
-// WebSocket protocol specific job on SocketStream.
-// It captures WebSocket handshake message and handles cookie operations.
-// Chrome security policy doesn't allow renderer process (except dev tools)
-// see HttpOnly cookies, so it injects cookie header in handshake request and
-// strips set-cookie headers in handshake response.
-// TODO(ukai): refactor websocket.cc to use this.
-class NET_EXPORT WebSocketJob
- : public SocketStreamJob,
- public SocketStream::Delegate,
- public SpdyWebSocketStream::Delegate {
- public:
- // This is state of WebSocket, not SocketStream.
- enum State {
- INITIALIZED = -1,
- CONNECTING = 0,
- OPEN = 1,
- CLOSING = 2,
- CLOSED = 3,
- };
-
- explicit WebSocketJob(SocketStream::Delegate* delegate);
-
- static void EnsureInit();
-
- State state() const { return state_; }
- void Connect() override;
- bool SendData(const char* data, int len) override;
- void Close() override;
- void RestartWithAuth(const AuthCredentials& credentials) override;
- void DetachDelegate() override;
-
- // SocketStream::Delegate methods.
- int OnStartOpenConnection(SocketStream* socket,
- const CompletionCallback& callback) override;
- void OnConnected(SocketStream* socket, int max_pending_send_allowed) override;
- void OnSentData(SocketStream* socket, int amount_sent) override;
- void OnReceivedData(SocketStream* socket, const char* data, int len) override;
- void OnClose(SocketStream* socket) override;
- void OnAuthRequired(SocketStream* socket,
- AuthChallengeInfo* auth_info) override;
- void OnSSLCertificateError(SocketStream* socket,
- const SSLInfo& ssl_info,
- bool fatal) override;
- void OnError(const SocketStream* socket, int error) override;
-
- // SpdyWebSocketStream::Delegate methods.
- void OnCreatedSpdyStream(int status) override;
- void OnSentSpdyHeaders() override;
- void OnSpdyResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
- void OnSentSpdyData(size_t bytes_sent) override;
- void OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) override;
- void OnCloseSpdyStream() override;
-
- private:
- friend class WebSocketThrottle;
- friend class WebSocketJobTest;
- ~WebSocketJob() override;
-
- bool SendHandshakeRequest(const char* data, int len);
- void AddCookieHeaderAndSend();
- void LoadCookieCallback(const std::string& cookie);
-
- void OnSentHandshakeRequest(SocketStream* socket, int amount_sent);
- // Parses received data into handshake_response_. When finished receiving the
- // response, calls SaveCookiesAndNotifyHeadersComplete().
- void OnReceivedHandshakeResponse(
- SocketStream* socket, const char* data, int len);
- // Saves received cookies to the cookie store, and then notifies the
- // delegate_ of completion of handshake.
- void SaveCookiesAndNotifyHeadersComplete();
- void SaveNextCookie();
- void OnCookieSaved(bool cookie_status);
- // Clears variables for handling cookies, rebuilds handshake string excluding
- // cookies, and then pass the handshake string to delegate_.
- void NotifyHeadersComplete();
- void DoSendData();
-
- GURL GetURLForCookies() const;
-
- const AddressList& address_list() const;
- int TrySpdyStream();
- void SetWaiting();
- bool IsWaiting() const;
- void Wakeup();
- void RetryPendingIO();
- void CompleteIO(int result);
-
- bool SendDataInternal(const char* data, int length);
- void CloseInternal();
- void SendPending();
-
- SocketStream::Delegate* delegate_;
- State state_;
- bool waiting_;
- AddressList addresses_;
- CompletionCallback callback_; // for throttling.
-
- scoped_ptr<WebSocketHandshakeRequestHandler> handshake_request_;
- scoped_ptr<WebSocketHandshakeResponseHandler> handshake_response_;
-
- bool started_to_send_handshake_request_;
- size_t handshake_request_sent_;
-
- std::vector<std::string> response_cookies_;
- size_t response_cookies_save_index_;
-
- std::deque<scoped_refptr<IOBufferWithSize> > send_buffer_queue_;
- scoped_refptr<DrainableIOBuffer> current_send_buffer_;
- std::vector<char> received_data_after_handshake_;
-
- int spdy_protocol_version_;
- scoped_ptr<SpdyWebSocketStream> spdy_websocket_stream_;
- std::string challenge_;
-
- bool save_next_cookie_running_;
- bool callback_pending_;
-
- base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_;
- base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_for_send_pending_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSocketJob);
-};
-
-} // namespace
-
-#endif // NET_WEBSOCKETS_WEBSOCKET_JOB_H_
diff --git a/net/websockets/websocket_job_test.cc b/net/websockets/websocket_job_test.cc
deleted file mode 100644
index c84af8f..0000000
--- a/net/websockets/websocket_job_test.cc
+++ /dev/null
@@ -1,1287 +0,0 @@
-// 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 "net/websockets/websocket_job.h"
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "net/base/completion_callback.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/cookies/cookie_store.h"
-#include "net/cookies/cookie_store_test_helpers.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/http/http_transaction_factory.h"
-#include "net/http/transport_security_state.h"
-#include "net/proxy/proxy_service.h"
-#include "net/socket/next_proto.h"
-#include "net/socket/socket_test_util.h"
-#include "net/socket_stream/socket_stream.h"
-#include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_websocket_test_util.h"
-#include "net/ssl/ssl_config_service.h"
-#include "net/url_request/url_request_context.h"
-#include "net/websockets/websocket_throttle.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "url/gurl.h"
-
-namespace net {
-
-namespace {
-
-class MockSocketStream : public SocketStream {
- public:
- MockSocketStream(const GURL& url, SocketStream::Delegate* delegate,
- URLRequestContext* context, CookieStore* cookie_store)
- : SocketStream(url, delegate, context, cookie_store) {}
-
- void Connect() override {}
- bool SendData(const char* data, int len) override {
- sent_data_ += std::string(data, len);
- return true;
- }
-
- void Close() override {}
- void RestartWithAuth(const AuthCredentials& credentials) override {}
-
- void DetachDelegate() override { delegate_ = NULL; }
-
- const std::string& sent_data() const {
- return sent_data_;
- }
-
- protected:
- ~MockSocketStream() override {}
-
- private:
- std::string sent_data_;
-};
-
-class MockSocketStreamDelegate : public SocketStream::Delegate {
- public:
- MockSocketStreamDelegate()
- : amount_sent_(0), allow_all_cookies_(true) {}
- void set_allow_all_cookies(bool allow_all_cookies) {
- allow_all_cookies_ = allow_all_cookies;
- }
- ~MockSocketStreamDelegate() override {}
-
- void SetOnStartOpenConnection(const base::Closure& callback) {
- on_start_open_connection_ = callback;
- }
- void SetOnConnected(const base::Closure& callback) {
- on_connected_ = callback;
- }
- void SetOnSentData(const base::Closure& callback) {
- on_sent_data_ = callback;
- }
- void SetOnReceivedData(const base::Closure& callback) {
- on_received_data_ = callback;
- }
- void SetOnClose(const base::Closure& callback) {
- on_close_ = callback;
- }
-
- int OnStartOpenConnection(SocketStream* socket,
- const CompletionCallback& callback) override {
- if (!on_start_open_connection_.is_null())
- on_start_open_connection_.Run();
- return OK;
- }
- void OnConnected(SocketStream* socket,
- int max_pending_send_allowed) override {
- if (!on_connected_.is_null())
- on_connected_.Run();
- }
- void OnSentData(SocketStream* socket, int amount_sent) override {
- amount_sent_ += amount_sent;
- if (!on_sent_data_.is_null())
- on_sent_data_.Run();
- }
- void OnReceivedData(SocketStream* socket,
- const char* data,
- int len) override {
- received_data_ += std::string(data, len);
- if (!on_received_data_.is_null())
- on_received_data_.Run();
- }
- void OnClose(SocketStream* socket) override {
- if (!on_close_.is_null())
- on_close_.Run();
- }
- bool CanGetCookies(SocketStream* socket, const GURL& url) override {
- return allow_all_cookies_;
- }
- bool CanSetCookie(SocketStream* request,
- const GURL& url,
- const std::string& cookie_line,
- CookieOptions* options) override {
- return allow_all_cookies_;
- }
-
- size_t amount_sent() const { return amount_sent_; }
- const std::string& received_data() const { return received_data_; }
-
- private:
- int amount_sent_;
- bool allow_all_cookies_;
- std::string received_data_;
- base::Closure on_start_open_connection_;
- base::Closure on_connected_;
- base::Closure on_sent_data_;
- base::Closure on_received_data_;
- base::Closure on_close_;
-};
-
-class MockCookieStore : public CookieStore {
- public:
- struct Entry {
- GURL url;
- std::string cookie_line;
- CookieOptions options;
- };
-
- MockCookieStore() {}
-
- bool SetCookieWithOptions(const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options) {
- Entry entry;
- entry.url = url;
- entry.cookie_line = cookie_line;
- entry.options = options;
- entries_.push_back(entry);
- return true;
- }
-
- std::string GetCookiesWithOptions(const GURL& url,
- const CookieOptions& options) {
- std::string result;
- for (size_t i = 0; i < entries_.size(); i++) {
- Entry& entry = entries_[i];
- if (url == entry.url) {
- if (!result.empty()) {
- result += "; ";
- }
- result += entry.cookie_line;
- }
- }
- return result;
- }
-
- // CookieStore:
- void SetCookieWithOptionsAsync(const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options,
- const SetCookiesCallback& callback) override {
- bool result = SetCookieWithOptions(url, cookie_line, options);
- if (!callback.is_null())
- callback.Run(result);
- }
-
- void GetCookiesWithOptionsAsync(const GURL& url,
- const CookieOptions& options,
- const GetCookiesCallback& callback) override {
- if (!callback.is_null())
- callback.Run(GetCookiesWithOptions(url, options));
- }
-
- void GetAllCookiesForURLAsync(
- const GURL& url,
- const GetCookieListCallback& callback) override {
- ADD_FAILURE();
- }
-
- void DeleteCookieAsync(const GURL& url,
- const std::string& cookie_name,
- const base::Closure& callback) override {
- ADD_FAILURE();
- }
-
- void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
- const base::Time& delete_end,
- const DeleteCallback& callback) override {
- ADD_FAILURE();
- }
-
- void DeleteAllCreatedBetweenForHostAsync(
- const base::Time delete_begin,
- const base::Time delete_end,
- const GURL& url,
- const DeleteCallback& callback) override {
- ADD_FAILURE();
- }
-
- void DeleteSessionCookiesAsync(const DeleteCallback&) override {
- ADD_FAILURE();
- }
-
- CookieMonster* GetCookieMonster() override { return NULL; }
-
- scoped_ptr<CookieStore::CookieChangedSubscription>
- AddCallbackForCookie(const GURL& url, const std::string& name,
- const CookieChangedCallback& callback) override {
- ADD_FAILURE();
- return scoped_ptr<CookieChangedSubscription>();
- }
-
- const std::vector<Entry>& entries() const { return entries_; }
-
- private:
- friend class base::RefCountedThreadSafe<MockCookieStore>;
- ~MockCookieStore() override {}
-
- std::vector<Entry> entries_;
-};
-
-class MockSSLConfigService : public SSLConfigService {
- public:
- void GetSSLConfig(SSLConfig* config) override {}
-
- protected:
- ~MockSSLConfigService() override {}
-};
-
-class MockURLRequestContext : public URLRequestContext {
- public:
- explicit MockURLRequestContext(CookieStore* cookie_store)
- : transport_security_state_() {
- set_cookie_store(cookie_store);
- set_transport_security_state(&transport_security_state_);
- base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
- bool include_subdomains = false;
- transport_security_state_.AddHSTS("upgrademe.com", expiry,
- include_subdomains);
- }
-
- ~MockURLRequestContext() override { AssertNoURLRequests(); }
-
- private:
- TransportSecurityState transport_security_state_;
-};
-
-class MockHttpTransactionFactory : public HttpTransactionFactory {
- public:
- MockHttpTransactionFactory(NextProto next_proto,
- OrderedSocketData* data,
- bool enable_websocket_over_spdy) {
- data_ = data;
- MockConnect connect_data(SYNCHRONOUS, OK);
- data_->set_connect_data(connect_data);
- session_deps_.reset(new SpdySessionDependencies(next_proto));
- session_deps_->enable_websocket_over_spdy = enable_websocket_over_spdy;
- session_deps_->socket_factory->AddSocketDataProvider(data_);
- http_session_ =
- SpdySessionDependencies::SpdyCreateSession(session_deps_.get());
- host_port_pair_.set_host("example.com");
- host_port_pair_.set_port(80);
- spdy_session_key_ = SpdySessionKey(host_port_pair_,
- ProxyServer::Direct(),
- PRIVACY_MODE_DISABLED);
- session_ = CreateInsecureSpdySession(
- http_session_, spdy_session_key_, BoundNetLog());
- }
-
- int CreateTransaction(RequestPriority priority,
- scoped_ptr<HttpTransaction>* trans) override {
- NOTREACHED();
- return ERR_UNEXPECTED;
- }
-
- HttpCache* GetCache() override {
- NOTREACHED();
- return NULL;
- }
-
- HttpNetworkSession* GetSession() override { return http_session_.get(); }
-
- private:
- OrderedSocketData* data_;
- scoped_ptr<SpdySessionDependencies> session_deps_;
- scoped_refptr<HttpNetworkSession> http_session_;
- base::WeakPtr<SpdySession> session_;
- HostPortPair host_port_pair_;
- SpdySessionKey spdy_session_key_;
-};
-
-class DeletingSocketStreamDelegate : public SocketStream::Delegate {
- public:
- DeletingSocketStreamDelegate()
- : delete_next_(false) {}
-
- // Since this class needs to be able to delete |job_|, it must be the only
- // reference holder (except for temporary references). Provide access to the
- // pointer for tests to use.
- WebSocketJob* job() { return job_.get(); }
-
- void set_job(WebSocketJob* job) { job_ = job; }
-
- // After calling this, the next call to a method on this delegate will delete
- // the WebSocketJob object.
- void set_delete_next(bool delete_next) { delete_next_ = delete_next; }
-
- void DeleteJobMaybe() {
- if (delete_next_) {
- job_->DetachContext();
- job_->DetachDelegate();
- job_ = NULL;
- }
- }
-
- // SocketStream::Delegate implementation
-
- // OnStartOpenConnection() is not implemented by SocketStreamDispatcherHost
-
- void OnConnected(SocketStream* socket,
- int max_pending_send_allowed) override {
- DeleteJobMaybe();
- }
-
- void OnSentData(SocketStream* socket, int amount_sent) override {
- DeleteJobMaybe();
- }
-
- void OnReceivedData(SocketStream* socket,
- const char* data,
- int len) override {
- DeleteJobMaybe();
- }
-
- void OnClose(SocketStream* socket) override { DeleteJobMaybe(); }
-
- void OnAuthRequired(SocketStream* socket,
- AuthChallengeInfo* auth_info) override {
- DeleteJobMaybe();
- }
-
- void OnSSLCertificateError(SocketStream* socket,
- const SSLInfo& ssl_info,
- bool fatal) override {
- DeleteJobMaybe();
- }
-
- void OnError(const SocketStream* socket, int error) override {
- DeleteJobMaybe();
- }
-
- // CanGetCookies() and CanSetCookies() do not appear to be able to delete the
- // WebSocketJob object.
-
- private:
- scoped_refptr<WebSocketJob> job_;
- bool delete_next_;
-};
-
-} // namespace
-
-class WebSocketJobTest : public PlatformTest,
- public ::testing::WithParamInterface<NextProto> {
- public:
- WebSocketJobTest()
- : spdy_util_(GetParam()),
- enable_websocket_over_spdy_(false) {}
-
- void SetUp() override {
- stream_type_ = STREAM_INVALID;
- cookie_store_ = new MockCookieStore;
- context_.reset(new MockURLRequestContext(cookie_store_.get()));
- }
- void TearDown() override {
- cookie_store_ = NULL;
- context_.reset();
- websocket_ = NULL;
- socket_ = NULL;
- }
- void DoSendRequest() {
- EXPECT_TRUE(websocket_->SendData(kHandshakeRequestWithoutCookie,
- kHandshakeRequestWithoutCookieLength));
- }
- void DoSendData() {
- if (received_data().size() == kHandshakeResponseWithoutCookieLength)
- websocket_->SendData(kDataHello, kDataHelloLength);
- }
- void DoSync() {
- sync_test_callback_.callback().Run(OK);
- }
- int WaitForResult() {
- return sync_test_callback_.WaitForResult();
- }
-
- protected:
- enum StreamType {
- STREAM_INVALID,
- STREAM_MOCK_SOCKET,
- STREAM_SOCKET,
- STREAM_SPDY_WEBSOCKET,
- };
- enum ThrottlingOption {
- THROTTLING_OFF,
- THROTTLING_ON,
- };
- enum SpdyOption {
- SPDY_OFF,
- SPDY_ON,
- };
- void InitWebSocketJob(const GURL& url,
- MockSocketStreamDelegate* delegate,
- StreamType stream_type) {
- DCHECK_NE(STREAM_INVALID, stream_type);
- stream_type_ = stream_type;
- websocket_ = new WebSocketJob(delegate);
-
- if (stream_type == STREAM_MOCK_SOCKET)
- socket_ = new MockSocketStream(url, websocket_.get(), context_.get(),
- NULL);
-
- if (stream_type == STREAM_SOCKET || stream_type == STREAM_SPDY_WEBSOCKET) {
- if (stream_type == STREAM_SPDY_WEBSOCKET) {
- http_factory_.reset(new MockHttpTransactionFactory(
- GetParam(), data_.get(), enable_websocket_over_spdy_));
- context_->set_http_transaction_factory(http_factory_.get());
- }
-
- ssl_config_service_ = new MockSSLConfigService();
- context_->set_ssl_config_service(ssl_config_service_.get());
- proxy_service_.reset(ProxyService::CreateDirect());
- context_->set_proxy_service(proxy_service_.get());
- host_resolver_.reset(new MockHostResolver);
- context_->set_host_resolver(host_resolver_.get());
-
- socket_ = new SocketStream(url, websocket_.get(), context_.get(), NULL);
- socket_factory_.reset(new MockClientSocketFactory);
- DCHECK(data_.get());
- socket_factory_->AddSocketDataProvider(data_.get());
- socket_->SetClientSocketFactory(socket_factory_.get());
- }
-
- websocket_->InitSocketStream(socket_.get());
- // MockHostResolver resolves all hosts to 127.0.0.1; however, when we create
- // a WebSocketJob purely to block another one in a throttling test, we don't
- // perform a real connect. In that case, the following address is used
- // instead.
- IPAddressNumber ip;
- ParseIPLiteralToNumber("127.0.0.1", &ip);
- websocket_->addresses_ = AddressList::CreateFromIPAddress(ip, 80);
- }
- void SkipToConnecting() {
- websocket_->state_ = WebSocketJob::CONNECTING;
- ASSERT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(websocket_.get()));
- }
- WebSocketJob::State GetWebSocketJobState() {
- return websocket_->state_;
- }
- void CloseWebSocketJob() {
- if (websocket_->socket_.get()) {
- websocket_->socket_->DetachDelegate();
- WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_.get());
- }
- websocket_->state_ = WebSocketJob::CLOSED;
- websocket_->delegate_ = NULL;
- websocket_->socket_ = NULL;
- }
- SocketStream* GetSocket(SocketStreamJob* job) {
- return job->socket_.get();
- }
- const std::string& sent_data() const {
- DCHECK_EQ(STREAM_MOCK_SOCKET, stream_type_);
- MockSocketStream* socket =
- static_cast<MockSocketStream*>(socket_.get());
- DCHECK(socket);
- return socket->sent_data();
- }
- const std::string& received_data() const {
- DCHECK_NE(STREAM_INVALID, stream_type_);
- MockSocketStreamDelegate* delegate =
- static_cast<MockSocketStreamDelegate*>(websocket_->delegate_);
- DCHECK(delegate);
- return delegate->received_data();
- }
-
- void TestSimpleHandshake();
- void TestSlowHandshake();
- void TestHandshakeWithCookie();
- void TestHandshakeWithCookieButNotAllowed();
- void TestHSTSUpgrade();
- void TestInvalidSendData();
- void TestConnectByWebSocket(ThrottlingOption throttling);
- void TestConnectBySpdy(SpdyOption spdy, ThrottlingOption throttling);
- void TestThrottlingLimit();
-
- SpdyWebSocketTestUtil spdy_util_;
- StreamType stream_type_;
- scoped_refptr<MockCookieStore> cookie_store_;
- scoped_ptr<MockURLRequestContext> context_;
- scoped_refptr<WebSocketJob> websocket_;
- scoped_refptr<SocketStream> socket_;
- scoped_ptr<MockClientSocketFactory> socket_factory_;
- scoped_ptr<OrderedSocketData> data_;
- TestCompletionCallback sync_test_callback_;
- scoped_refptr<MockSSLConfigService> ssl_config_service_;
- scoped_ptr<ProxyService> proxy_service_;
- scoped_ptr<MockHostResolver> host_resolver_;
- scoped_ptr<MockHttpTransactionFactory> http_factory_;
-
- // Must be set before call to enable_websocket_over_spdy, defaults to false.
- bool enable_websocket_over_spdy_;
-
- static const char kHandshakeRequestWithoutCookie[];
- static const char kHandshakeRequestWithCookie[];
- static const char kHandshakeRequestWithFilteredCookie[];
- static const char kHandshakeResponseWithoutCookie[];
- static const char kHandshakeResponseWithCookie[];
- static const char kDataHello[];
- static const char kDataWorld[];
- static const char* const kHandshakeRequestForSpdy[];
- static const char* const kHandshakeResponseForSpdy[];
- static const size_t kHandshakeRequestWithoutCookieLength;
- static const size_t kHandshakeRequestWithCookieLength;
- static const size_t kHandshakeRequestWithFilteredCookieLength;
- static const size_t kHandshakeResponseWithoutCookieLength;
- static const size_t kHandshakeResponseWithCookieLength;
- static const size_t kDataHelloLength;
- static const size_t kDataWorldLength;
-};
-
-// Tests using this fixture verify that the WebSocketJob can handle being
-// deleted while calling back to the delegate correctly. These tests need to be
-// run under AddressSanitizer or other systems for detecting use-after-free
-// errors in order to find problems.
-class WebSocketJobDeleteTest : public ::testing::Test {
- protected:
- WebSocketJobDeleteTest()
- : delegate_(new DeletingSocketStreamDelegate),
- cookie_store_(new MockCookieStore),
- context_(new MockURLRequestContext(cookie_store_.get())) {
- WebSocketJob* websocket = new WebSocketJob(delegate_.get());
- delegate_->set_job(websocket);
-
- socket_ = new MockSocketStream(
- GURL("ws://127.0.0.1/"), websocket, context_.get(), NULL);
-
- websocket->InitSocketStream(socket_.get());
- }
-
- void SetDeleteNext() { return delegate_->set_delete_next(true); }
- WebSocketJob* job() { return delegate_->job(); }
-
- scoped_ptr<DeletingSocketStreamDelegate> delegate_;
- scoped_refptr<MockCookieStore> cookie_store_;
- scoped_ptr<MockURLRequestContext> context_;
- scoped_refptr<SocketStream> socket_;
-};
-
-const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "\r\n";
-
-const char WebSocketJobTest::kHandshakeRequestWithCookie[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "Cookie: WK-test=1\r\n"
- "\r\n";
-
-const char WebSocketJobTest::kHandshakeRequestWithFilteredCookie[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "Cookie: CR-test=1; CR-test-httponly=1\r\n"
- "\r\n";
-
-const char WebSocketJobTest::kHandshakeResponseWithoutCookie[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n";
-
-const char WebSocketJobTest::kHandshakeResponseWithCookie[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Set-Cookie: CR-set-test=1\r\n"
- "\r\n";
-
-const char WebSocketJobTest::kDataHello[] = "Hello, ";
-
-const char WebSocketJobTest::kDataWorld[] = "World!\n";
-
-const size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength =
- arraysize(kHandshakeRequestWithoutCookie) - 1;
-const size_t WebSocketJobTest::kHandshakeRequestWithCookieLength =
- arraysize(kHandshakeRequestWithCookie) - 1;
-const size_t WebSocketJobTest::kHandshakeRequestWithFilteredCookieLength =
- arraysize(kHandshakeRequestWithFilteredCookie) - 1;
-const size_t WebSocketJobTest::kHandshakeResponseWithoutCookieLength =
- arraysize(kHandshakeResponseWithoutCookie) - 1;
-const size_t WebSocketJobTest::kHandshakeResponseWithCookieLength =
- arraysize(kHandshakeResponseWithCookie) - 1;
-const size_t WebSocketJobTest::kDataHelloLength =
- arraysize(kDataHello) - 1;
-const size_t WebSocketJobTest::kDataWorldLength =
- arraysize(kDataWorld) - 1;
-
-void WebSocketJobTest::TestSimpleHandshake() {
- GURL url("ws://example.com/demo");
- MockSocketStreamDelegate delegate;
- InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
- SkipToConnecting();
-
- DoSendRequest();
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- websocket_->OnSentData(socket_.get(),
- kHandshakeRequestWithoutCookieLength);
- EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
-
- websocket_->OnReceivedData(socket_.get(),
- kHandshakeResponseWithoutCookie,
- kHandshakeResponseWithoutCookieLength);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
- EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
- CloseWebSocketJob();
-}
-
-void WebSocketJobTest::TestSlowHandshake() {
- GURL url("ws://example.com/demo");
- MockSocketStreamDelegate delegate;
- InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
- SkipToConnecting();
-
- DoSendRequest();
- // We assume request is sent in one data chunk (from WebKit)
- // We don't support streaming request.
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- websocket_->OnSentData(socket_.get(),
- kHandshakeRequestWithoutCookieLength);
- EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
-
- std::vector<std::string> lines;
- base::SplitString(kHandshakeResponseWithoutCookie, '\n', &lines);
- for (size_t i = 0; i < lines.size() - 2; i++) {
- std::string line = lines[i] + "\r\n";
- SCOPED_TRACE("Line: " + line);
- websocket_->OnReceivedData(socket_.get(), line.c_str(), line.size());
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_TRUE(delegate.received_data().empty());
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- }
- websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_FALSE(delegate.received_data().empty());
- EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
- EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
- CloseWebSocketJob();
-}
-
-INSTANTIATE_TEST_CASE_P(
- NextProto,
- WebSocketJobTest,
- testing::Values(kProtoDeprecatedSPDY2,
- kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
-
-TEST_P(WebSocketJobTest, DelayedCookies) {
- enable_websocket_over_spdy_ = true;
- GURL url("ws://example.com/demo");
- GURL cookieUrl("http://example.com/demo");
- CookieOptions cookie_options;
- scoped_refptr<DelayedCookieMonster> cookie_store = new DelayedCookieMonster();
- context_->set_cookie_store(cookie_store.get());
- cookie_store->SetCookieWithOptionsAsync(cookieUrl,
- "CR-test=1",
- cookie_options,
- CookieMonster::SetCookiesCallback());
- cookie_options.set_include_httponly();
- cookie_store->SetCookieWithOptionsAsync(
- cookieUrl, "CR-test-httponly=1", cookie_options,
- CookieMonster::SetCookiesCallback());
-
- MockSocketStreamDelegate delegate;
- InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
- SkipToConnecting();
-
- bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
- kHandshakeRequestWithCookieLength);
- EXPECT_TRUE(sent);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- websocket_->OnSentData(socket_.get(),
- kHandshakeRequestWithFilteredCookieLength);
- EXPECT_EQ(kHandshakeRequestWithCookieLength,
- delegate.amount_sent());
-
- websocket_->OnReceivedData(socket_.get(),
- kHandshakeResponseWithCookie,
- kHandshakeResponseWithCookieLength);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
- EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
-
- CloseWebSocketJob();
-}
-
-void WebSocketJobTest::TestHandshakeWithCookie() {
- GURL url("ws://example.com/demo");
- GURL cookieUrl("http://example.com/demo");
- CookieOptions cookie_options;
- cookie_store_->SetCookieWithOptions(
- cookieUrl, "CR-test=1", cookie_options);
- cookie_options.set_include_httponly();
- cookie_store_->SetCookieWithOptions(
- cookieUrl, "CR-test-httponly=1", cookie_options);
-
- MockSocketStreamDelegate delegate;
- InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
- SkipToConnecting();
-
- bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
- kHandshakeRequestWithCookieLength);
- EXPECT_TRUE(sent);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- websocket_->OnSentData(socket_.get(),
- kHandshakeRequestWithFilteredCookieLength);
- EXPECT_EQ(kHandshakeRequestWithCookieLength,
- delegate.amount_sent());
-
- websocket_->OnReceivedData(socket_.get(),
- kHandshakeResponseWithCookie,
- kHandshakeResponseWithCookieLength);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
- EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
-
- EXPECT_EQ(3U, cookie_store_->entries().size());
- EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
- EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
- EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
- EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
- EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
- EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
-
- CloseWebSocketJob();
-}
-
-void WebSocketJobTest::TestHandshakeWithCookieButNotAllowed() {
- GURL url("ws://example.com/demo");
- GURL cookieUrl("http://example.com/demo");
- CookieOptions cookie_options;
- cookie_store_->SetCookieWithOptions(
- cookieUrl, "CR-test=1", cookie_options);
- cookie_options.set_include_httponly();
- cookie_store_->SetCookieWithOptions(
- cookieUrl, "CR-test-httponly=1", cookie_options);
-
- MockSocketStreamDelegate delegate;
- delegate.set_allow_all_cookies(false);
- InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
- SkipToConnecting();
-
- bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
- kHandshakeRequestWithCookieLength);
- EXPECT_TRUE(sent);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength);
- EXPECT_EQ(kHandshakeRequestWithCookieLength, delegate.amount_sent());
-
- websocket_->OnReceivedData(socket_.get(),
- kHandshakeResponseWithCookie,
- kHandshakeResponseWithCookieLength);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
- EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
-
- EXPECT_EQ(2U, cookie_store_->entries().size());
- EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
- EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
- EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
- EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
-
- CloseWebSocketJob();
-}
-
-void WebSocketJobTest::TestHSTSUpgrade() {
- GURL url("ws://upgrademe.com/");
- MockSocketStreamDelegate delegate;
- scoped_refptr<SocketStreamJob> job =
- SocketStreamJob::CreateSocketStreamJob(
- url, &delegate, context_->transport_security_state(),
- context_->ssl_config_service(), NULL, NULL);
- EXPECT_TRUE(GetSocket(job.get())->is_secure());
- job->DetachDelegate();
-
- url = GURL("ws://donotupgrademe.com/");
- job = SocketStreamJob::CreateSocketStreamJob(
- url, &delegate, context_->transport_security_state(),
- context_->ssl_config_service(), NULL, NULL);
- EXPECT_FALSE(GetSocket(job.get())->is_secure());
- job->DetachDelegate();
-}
-
-void WebSocketJobTest::TestInvalidSendData() {
- GURL url("ws://example.com/demo");
- MockSocketStreamDelegate delegate;
- InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
- SkipToConnecting();
-
- DoSendRequest();
- // We assume request is sent in one data chunk (from WebKit)
- // We don't support streaming request.
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- websocket_->OnSentData(socket_.get(),
- kHandshakeRequestWithoutCookieLength);
- EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
-
- // We could not send any data until connection is established.
- bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie,
- kHandshakeRequestWithoutCookieLength);
- EXPECT_FALSE(sent);
- EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
- CloseWebSocketJob();
-}
-
-// Following tests verify cooperation between WebSocketJob and SocketStream.
-// Other former tests use MockSocketStream as SocketStream, so we could not
-// check SocketStream behavior.
-// OrderedSocketData provide socket level verifiation by checking out-going
-// packets in comparison with the MockWrite array and emulating in-coming
-// packets with MockRead array.
-
-void WebSocketJobTest::TestConnectByWebSocket(
- ThrottlingOption throttling) {
- // This is a test for verifying cooperation between WebSocketJob and
- // SocketStream. If |throttling| was |THROTTLING_OFF|, it test basic
- // situation. If |throttling| was |THROTTLING_ON|, throttling limits the
- // latter connection.
- MockWrite writes[] = {
- MockWrite(ASYNC,
- kHandshakeRequestWithoutCookie,
- kHandshakeRequestWithoutCookieLength,
- 1),
- MockWrite(ASYNC,
- kDataHello,
- kDataHelloLength,
- 3)
- };
- MockRead reads[] = {
- MockRead(ASYNC,
- kHandshakeResponseWithoutCookie,
- kHandshakeResponseWithoutCookieLength,
- 2),
- MockRead(ASYNC,
- kDataWorld,
- kDataWorldLength,
- 4),
- MockRead(SYNCHRONOUS, 0, 5) // EOF
- };
- data_.reset(new OrderedSocketData(
- reads, arraysize(reads), writes, arraysize(writes)));
-
- GURL url("ws://example.com/demo");
- MockSocketStreamDelegate delegate;
- WebSocketJobTest* test = this;
- if (throttling == THROTTLING_ON)
- delegate.SetOnStartOpenConnection(
- base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
- delegate.SetOnConnected(
- base::Bind(&WebSocketJobTest::DoSendRequest,
- base::Unretained(test)));
- delegate.SetOnReceivedData(
- base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
- delegate.SetOnClose(
- base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
- InitWebSocketJob(url, &delegate, STREAM_SOCKET);
-
- scoped_refptr<WebSocketJob> block_websocket;
- if (throttling == THROTTLING_ON) {
- // Create former WebSocket object which obstructs the latter one.
- block_websocket = new WebSocketJob(NULL);
- block_websocket->addresses_ = AddressList(websocket_->address_list());
- ASSERT_TRUE(
- WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
- }
-
- websocket_->Connect();
-
- if (throttling == THROTTLING_ON) {
- EXPECT_EQ(OK, WaitForResult());
- EXPECT_TRUE(websocket_->IsWaiting());
-
- // Remove the former WebSocket object from throttling queue to unblock the
- // latter.
- block_websocket->state_ = WebSocketJob::CLOSED;
- WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
- block_websocket = NULL;
- }
-
- EXPECT_EQ(OK, WaitForResult());
- EXPECT_TRUE(data_->at_read_eof());
- EXPECT_TRUE(data_->at_write_eof());
- EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
-}
-
-void WebSocketJobTest::TestConnectBySpdy(
- SpdyOption spdy, ThrottlingOption throttling) {
- // This is a test for verifying cooperation between WebSocketJob and
- // SocketStream in the situation we have SPDY session to the server. If
- // |throttling| was |THROTTLING_ON|, throttling limits the latter connection.
- // If you enabled spdy, you should specify |spdy| as |SPDY_ON|. Expected
- // results depend on its configuration.
- MockWrite writes_websocket[] = {
- MockWrite(ASYNC,
- kHandshakeRequestWithoutCookie,
- kHandshakeRequestWithoutCookieLength,
- 1),
- MockWrite(ASYNC,
- kDataHello,
- kDataHelloLength,
- 3)
- };
- MockRead reads_websocket[] = {
- MockRead(ASYNC,
- kHandshakeResponseWithoutCookie,
- kHandshakeResponseWithoutCookieLength,
- 2),
- MockRead(ASYNC,
- kDataWorld,
- kDataWorldLength,
- 4),
- MockRead(SYNCHRONOUS, 0, 5) // EOF
- };
-
- scoped_ptr<SpdyHeaderBlock> request_headers(new SpdyHeaderBlock());
- spdy_util_.SetHeader("path", "/demo", request_headers.get());
- spdy_util_.SetHeader("version", "WebSocket/13", request_headers.get());
- spdy_util_.SetHeader("scheme", "ws", request_headers.get());
- spdy_util_.SetHeader("host", "example.com", request_headers.get());
- spdy_util_.SetHeader("origin", "http://example.com", request_headers.get());
- spdy_util_.SetHeader("sec-websocket-protocol", "sample",
- request_headers.get());
-
- scoped_ptr<SpdyHeaderBlock> response_headers(new SpdyHeaderBlock());
- spdy_util_.SetHeader("status", "101 Switching Protocols",
- response_headers.get());
- spdy_util_.SetHeader("sec-websocket-protocol", "sample",
- response_headers.get());
-
- const SpdyStreamId kStreamId = 1;
- scoped_ptr<SpdyFrame> request_frame(
- spdy_util_.ConstructSpdyWebSocketHandshakeRequestFrame(
- request_headers.Pass(),
- kStreamId,
- MEDIUM));
- scoped_ptr<SpdyFrame> response_frame(
- spdy_util_.ConstructSpdyWebSocketHandshakeResponseFrame(
- response_headers.Pass(),
- kStreamId,
- MEDIUM));
- scoped_ptr<SpdyFrame> data_hello_frame(
- spdy_util_.ConstructSpdyWebSocketDataFrame(
- kDataHello,
- kDataHelloLength,
- kStreamId,
- false));
- scoped_ptr<SpdyFrame> data_world_frame(
- spdy_util_.ConstructSpdyWebSocketDataFrame(
- kDataWorld,
- kDataWorldLength,
- kStreamId,
- false));
- MockWrite writes_spdy[] = {
- CreateMockWrite(*request_frame.get(), 1),
- CreateMockWrite(*data_hello_frame.get(), 3),
- };
- MockRead reads_spdy[] = {
- CreateMockRead(*response_frame.get(), 2),
- CreateMockRead(*data_world_frame.get(), 4),
- MockRead(SYNCHRONOUS, 0, 5) // EOF
- };
-
- if (spdy == SPDY_ON)
- data_.reset(new OrderedSocketData(
- reads_spdy, arraysize(reads_spdy),
- writes_spdy, arraysize(writes_spdy)));
- else
- data_.reset(new OrderedSocketData(
- reads_websocket, arraysize(reads_websocket),
- writes_websocket, arraysize(writes_websocket)));
-
- GURL url("ws://example.com/demo");
- MockSocketStreamDelegate delegate;
- WebSocketJobTest* test = this;
- if (throttling == THROTTLING_ON)
- delegate.SetOnStartOpenConnection(
- base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
- delegate.SetOnConnected(
- base::Bind(&WebSocketJobTest::DoSendRequest,
- base::Unretained(test)));
- delegate.SetOnReceivedData(
- base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
- delegate.SetOnClose(
- base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
- InitWebSocketJob(url, &delegate, STREAM_SPDY_WEBSOCKET);
-
- scoped_refptr<WebSocketJob> block_websocket;
- if (throttling == THROTTLING_ON) {
- // Create former WebSocket object which obstructs the latter one.
- block_websocket = new WebSocketJob(NULL);
- block_websocket->addresses_ = AddressList(websocket_->address_list());
- ASSERT_TRUE(
- WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
- }
-
- websocket_->Connect();
-
- if (throttling == THROTTLING_ON) {
- EXPECT_EQ(OK, WaitForResult());
- EXPECT_TRUE(websocket_->IsWaiting());
-
- // Remove the former WebSocket object from throttling queue to unblock the
- // latter.
- block_websocket->state_ = WebSocketJob::CLOSED;
- WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
- block_websocket = NULL;
- }
-
- EXPECT_EQ(OK, WaitForResult());
- EXPECT_TRUE(data_->at_read_eof());
- EXPECT_TRUE(data_->at_write_eof());
- EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
-}
-
-void WebSocketJobTest::TestThrottlingLimit() {
- std::vector<scoped_refptr<WebSocketJob> > jobs;
- const int kMaxWebSocketJobsThrottled = 1024;
- IPAddressNumber ip;
- ParseIPLiteralToNumber("127.0.0.1", &ip);
- for (int i = 0; i < kMaxWebSocketJobsThrottled + 1; ++i) {
- scoped_refptr<WebSocketJob> job = new WebSocketJob(NULL);
- job->addresses_ = AddressList(AddressList::CreateFromIPAddress(ip, 80));
- if (i >= kMaxWebSocketJobsThrottled)
- EXPECT_FALSE(WebSocketThrottle::GetInstance()->PutInQueue(job.get()));
- else
- EXPECT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(job.get()));
- jobs.push_back(job);
- }
-
- // Close the jobs in reverse order. Otherwise, We need to make them prepared
- // for Wakeup call.
- for (std::vector<scoped_refptr<WebSocketJob> >::reverse_iterator iter =
- jobs.rbegin();
- iter != jobs.rend();
- ++iter) {
- WebSocketJob* job = (*iter).get();
- job->state_ = WebSocketJob::CLOSED;
- WebSocketThrottle::GetInstance()->RemoveFromQueue(job);
- }
-}
-
-// Execute tests in both spdy-disabled mode and spdy-enabled mode.
-TEST_P(WebSocketJobTest, SimpleHandshake) {
- TestSimpleHandshake();
-}
-
-TEST_P(WebSocketJobTest, SlowHandshake) {
- TestSlowHandshake();
-}
-
-TEST_P(WebSocketJobTest, HandshakeWithCookie) {
- TestHandshakeWithCookie();
-}
-
-TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
- TestHandshakeWithCookieButNotAllowed();
-}
-
-TEST_P(WebSocketJobTest, HSTSUpgrade) {
- TestHSTSUpgrade();
-}
-
-TEST_P(WebSocketJobTest, InvalidSendData) {
- TestInvalidSendData();
-}
-
-TEST_P(WebSocketJobTest, SimpleHandshakeSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestSimpleHandshake();
-}
-
-TEST_P(WebSocketJobTest, SlowHandshakeSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestSlowHandshake();
-}
-
-TEST_P(WebSocketJobTest, HandshakeWithCookieSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestHandshakeWithCookie();
-}
-
-TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowedSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestHandshakeWithCookieButNotAllowed();
-}
-
-TEST_P(WebSocketJobTest, HSTSUpgradeSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestHSTSUpgrade();
-}
-
-TEST_P(WebSocketJobTest, InvalidSendDataSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestInvalidSendData();
-}
-
-TEST_P(WebSocketJobTest, ConnectByWebSocket) {
- enable_websocket_over_spdy_ = true;
- TestConnectByWebSocket(THROTTLING_OFF);
-}
-
-TEST_P(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestConnectByWebSocket(THROTTLING_OFF);
-}
-
-TEST_P(WebSocketJobTest, ConnectBySpdy) {
- TestConnectBySpdy(SPDY_OFF, THROTTLING_OFF);
-}
-
-TEST_P(WebSocketJobTest, ConnectBySpdySpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestConnectBySpdy(SPDY_ON, THROTTLING_OFF);
-}
-
-TEST_P(WebSocketJobTest, ThrottlingWebSocket) {
- TestConnectByWebSocket(THROTTLING_ON);
-}
-
-TEST_P(WebSocketJobTest, ThrottlingMaxNumberOfThrottledJobLimit) {
- TestThrottlingLimit();
-}
-
-TEST_P(WebSocketJobTest, ThrottlingWebSocketSpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestConnectByWebSocket(THROTTLING_ON);
-}
-
-TEST_P(WebSocketJobTest, ThrottlingSpdy) {
- TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
-}
-
-TEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) {
- enable_websocket_over_spdy_ = true;
- TestConnectBySpdy(SPDY_ON, THROTTLING_ON);
-}
-
-TEST_F(WebSocketJobDeleteTest, OnClose) {
- SetDeleteNext();
- job()->OnClose(socket_.get());
- // OnClose() sets WebSocketJob::_socket to NULL before we can detach it, so
- // socket_->delegate is still set at this point. Clear it to avoid hitting
- // DCHECK(!delegate_) in the SocketStream destructor. SocketStream::Finish()
- // is the only caller of this method in real code, and it also sets delegate_
- // to NULL.
- socket_->DetachDelegate();
- EXPECT_FALSE(job());
-}
-
-TEST_F(WebSocketJobDeleteTest, OnAuthRequired) {
- SetDeleteNext();
- job()->OnAuthRequired(socket_.get(), NULL);
- EXPECT_FALSE(job());
-}
-
-TEST_F(WebSocketJobDeleteTest, OnSSLCertificateError) {
- SSLInfo ssl_info;
- SetDeleteNext();
- job()->OnSSLCertificateError(socket_.get(), ssl_info, true);
- EXPECT_FALSE(job());
-}
-
-TEST_F(WebSocketJobDeleteTest, OnError) {
- SetDeleteNext();
- job()->OnError(socket_.get(), ERR_CONNECTION_RESET);
- EXPECT_FALSE(job());
-}
-
-TEST_F(WebSocketJobDeleteTest, OnSentSpdyHeaders) {
- job()->Connect();
- SetDeleteNext();
- job()->OnSentSpdyHeaders();
- EXPECT_FALSE(job());
-}
-
-TEST_F(WebSocketJobDeleteTest, OnSentHandshakeRequest) {
- static const char kMinimalRequest[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "\r\n";
- const size_t kMinimalRequestSize = arraysize(kMinimalRequest) - 1;
- job()->Connect();
- job()->SendData(kMinimalRequest, kMinimalRequestSize);
- SetDeleteNext();
- job()->OnSentData(socket_.get(), kMinimalRequestSize);
- EXPECT_FALSE(job());
-}
-
-TEST_F(WebSocketJobDeleteTest, NotifyHeadersComplete) {
- static const char kMinimalResponse[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "\r\n";
- job()->Connect();
- SetDeleteNext();
- job()->OnReceivedData(
- socket_.get(), kMinimalResponse, arraysize(kMinimalResponse) - 1);
- EXPECT_FALSE(job());
-}
-
-// TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation.
-// TODO(toyoshim,yutak): Add tests to verify closing handshake.
-} // namespace net
diff --git a/net/websockets/websocket_net_log_params.cc b/net/websockets/websocket_net_log_params.cc
deleted file mode 100644
index dd9bdde..0000000
--- a/net/websockets/websocket_net_log_params.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 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 "net/websockets/websocket_net_log_params.h"
-
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-
-namespace net {
-
-base::Value* NetLogWebSocketHandshakeCallback(
- const std::string* headers,
- NetLog::LogLevel /* log_level */) {
- base::DictionaryValue* dict = new base::DictionaryValue();
- base::ListValue* header_list = new base::ListValue();
-
- size_t last = 0;
- size_t headers_size = headers->size();
- size_t pos = 0;
- while (pos <= headers_size) {
- if (pos == headers_size ||
- ((*headers)[pos] == '\r' &&
- pos + 1 < headers_size && (*headers)[pos + 1] == '\n')) {
- std::string entry = headers->substr(last, pos - last);
- pos += 2;
- last = pos;
-
- header_list->Append(new base::StringValue(entry));
-
- if (entry.empty()) {
- // Dump WebSocket key3.
- std::string key;
- for (; pos < headers_size; ++pos) {
- key += base::StringPrintf("\\x%02x", (*headers)[pos] & 0xff);
- }
- header_list->Append(new base::StringValue(key));
- break;
- }
- } else {
- ++pos;
- }
- }
-
- dict->Set("headers", header_list);
- return dict;
-}
-
-} // namespace net
diff --git a/net/websockets/websocket_net_log_params.h b/net/websockets/websocket_net_log_params.h
deleted file mode 100644
index 45dabb0..0000000
--- a/net/websockets/websocket_net_log_params.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 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 NET_WEBSOCKETS_WEBSOCKET_NET_LOG_PARAMS_H_
-#define NET_WEBSOCKETS_WEBSOCKET_NET_LOG_PARAMS_H_
-
-#include <string>
-
-#include "net/base/net_export.h"
-#include "net/base/net_log.h"
-
-namespace net {
-
-NET_EXPORT_PRIVATE base::Value* NetLogWebSocketHandshakeCallback(
- const std::string* headers,
- NetLog::LogLevel /* log_level */);
-
-} // namespace net
-
-#endif // NET_WEBSOCKETS_WEBSOCKET_NET_LOG_PARAMS_H_
diff --git a/net/websockets/websocket_net_log_params_test.cc b/net/websockets/websocket_net_log_params_test.cc
deleted file mode 100644
index d6d2a0d..0000000
--- a/net/websockets/websocket_net_log_params_test.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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 "net/websockets/websocket_net_log_params.h"
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(NetLogWebSocketHandshakeParameterTest, ToValue) {
- base::ListValue* list = new base::ListValue();
- list->Append(new base::StringValue("GET /demo HTTP/1.1"));
- list->Append(new base::StringValue("Host: example.com"));
- list->Append(new base::StringValue("Connection: Upgrade"));
- list->Append(new base::StringValue("Sec-WebSocket-Key2: 12998 5 Y3 1 .P00"));
- list->Append(new base::StringValue("Sec-WebSocket-Protocol: sample"));
- list->Append(new base::StringValue("Upgrade: WebSocket"));
- list->Append(new base::StringValue(
- "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5"));
- list->Append(new base::StringValue("Origin: http://example.com"));
- list->Append(new base::StringValue(std::string()));
- list->Append(new base::StringValue(
- "\\x00\\x01\\x0a\\x0d\\xff\\xfe\\x0d\\x0a"));
-
- base::DictionaryValue expected;
- expected.Set("headers", list);
-
- const std::string key("\x00\x01\x0a\x0d\xff\xfe\x0d\x0a", 8);
- const std::string testInput =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Upgrade: WebSocket\r\n"
- "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
- "Origin: http://example.com\r\n"
- "\r\n" +
- key;
-
- scoped_ptr<base::Value> actual(
- net::NetLogWebSocketHandshakeCallback(&testInput,
- net::NetLog::LOG_ALL));
-
- EXPECT_TRUE(expected.Equals(actual.get()));
-}
diff --git a/net/websockets/websocket_throttle.cc b/net/websockets/websocket_throttle.cc
deleted file mode 100644
index 59e73fd..0000000
--- a/net/websockets/websocket_throttle.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2012 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 "net/websockets/websocket_throttle.h"
-
-#include <algorithm>
-#include <set>
-#include <string>
-#include <utility>
-
-#include "base/memory/singleton.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/io_buffer.h"
-#include "net/socket_stream/socket_stream.h"
-#include "net/websockets/websocket_job.h"
-
-namespace net {
-
-namespace {
-
-const size_t kMaxWebSocketJobsThrottled = 1024;
-
-} // namespace
-
-WebSocketThrottle::WebSocketThrottle() {
-}
-
-WebSocketThrottle::~WebSocketThrottle() {
- DCHECK(queue_.empty());
- DCHECK(addr_map_.empty());
-}
-
-// static
-WebSocketThrottle* WebSocketThrottle::GetInstance() {
- return Singleton<WebSocketThrottle>::get();
-}
-
-bool WebSocketThrottle::PutInQueue(WebSocketJob* job) {
- if (queue_.size() >= kMaxWebSocketJobsThrottled)
- return false;
-
- queue_.push_back(job);
- const AddressList& address_list = job->address_list();
- std::set<IPEndPoint> address_set;
- for (AddressList::const_iterator addr_iter = address_list.begin();
- addr_iter != address_list.end();
- ++addr_iter) {
- const IPEndPoint& address = *addr_iter;
- // If |address| is already processed, don't do it again.
- if (!address_set.insert(address).second)
- continue;
-
- ConnectingAddressMap::iterator iter = addr_map_.find(address);
- if (iter == addr_map_.end()) {
- ConnectingAddressMap::iterator new_queue =
- addr_map_.insert(make_pair(address, ConnectingQueue())).first;
- new_queue->second.push_back(job);
- } else {
- DCHECK(!iter->second.empty());
- iter->second.push_back(job);
- job->SetWaiting();
- DVLOG(1) << "Waiting on " << address.ToString();
- }
- }
-
- return true;
-}
-
-void WebSocketThrottle::RemoveFromQueue(WebSocketJob* job) {
- ConnectingQueue::iterator queue_iter =
- std::find(queue_.begin(), queue_.end(), job);
- if (queue_iter == queue_.end())
- return;
- queue_.erase(queue_iter);
-
- std::set<WebSocketJob*> wakeup_candidates;
-
- const AddressList& resolved_address_list = job->address_list();
- std::set<IPEndPoint> address_set;
- for (AddressList::const_iterator addr_iter = resolved_address_list.begin();
- addr_iter != resolved_address_list.end();
- ++addr_iter) {
- const IPEndPoint& address = *addr_iter;
- // If |address| is already processed, don't do it again.
- if (!address_set.insert(address).second)
- continue;
-
- ConnectingAddressMap::iterator map_iter = addr_map_.find(address);
- DCHECK(map_iter != addr_map_.end());
-
- ConnectingQueue& per_address_queue = map_iter->second;
- DCHECK(!per_address_queue.empty());
- // Job may not be front of the queue if the socket is closed while waiting.
- ConnectingQueue::iterator per_address_queue_iter =
- std::find(per_address_queue.begin(), per_address_queue.end(), job);
- bool was_front = false;
- if (per_address_queue_iter != per_address_queue.end()) {
- was_front = (per_address_queue_iter == per_address_queue.begin());
- per_address_queue.erase(per_address_queue_iter);
- }
- if (per_address_queue.empty()) {
- addr_map_.erase(map_iter);
- } else if (was_front) {
- // The new front is a wake-up candidate.
- wakeup_candidates.insert(per_address_queue.front());
- }
- }
-
- WakeupSocketIfNecessary(wakeup_candidates);
-}
-
-void WebSocketThrottle::WakeupSocketIfNecessary(
- const std::set<WebSocketJob*>& wakeup_candidates) {
- for (std::set<WebSocketJob*>::const_iterator iter = wakeup_candidates.begin();
- iter != wakeup_candidates.end();
- ++iter) {
- WebSocketJob* job = *iter;
- if (!job->IsWaiting())
- continue;
-
- bool should_wakeup = true;
- const AddressList& resolved_address_list = job->address_list();
- for (AddressList::const_iterator addr_iter = resolved_address_list.begin();
- addr_iter != resolved_address_list.end();
- ++addr_iter) {
- const IPEndPoint& address = *addr_iter;
- ConnectingAddressMap::iterator map_iter = addr_map_.find(address);
- DCHECK(map_iter != addr_map_.end());
- const ConnectingQueue& per_address_queue = map_iter->second;
- if (job != per_address_queue.front()) {
- should_wakeup = false;
- break;
- }
- }
- if (should_wakeup)
- job->Wakeup();
- }
-}
-
-} // namespace net
diff --git a/net/websockets/websocket_throttle.h b/net/websockets/websocket_throttle.h
deleted file mode 100644
index 0b7a39f..0000000
--- a/net/websockets/websocket_throttle.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2011 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 NET_WEBSOCKETS_WEBSOCKET_THROTTLE_H_
-#define NET_WEBSOCKETS_WEBSOCKET_THROTTLE_H_
-
-#include <deque>
-#include <map>
-#include <set>
-#include <string>
-
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
-
-template <typename T> struct DefaultSingletonTraits;
-
-namespace net {
-
-class SocketStream;
-class WebSocketJob;
-
-// SocketStreamThrottle for WebSocket protocol.
-// Implements the client-side requirements in the spec.
-// http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
-// 4.1 Handshake
-// 1. If the user agent already has a Web Socket connection to the
-// remote host (IP address) identified by /host/, even if known by
-// another name, wait until that connection has been established or
-// for that connection to have failed.
-class NET_EXPORT_PRIVATE WebSocketThrottle {
- public:
- // Returns the singleton instance.
- static WebSocketThrottle* GetInstance();
-
- // Puts |job| in |queue_| and queues for the destination addresses
- // of |job|.
- // If other job is using the same destination address, set |job| waiting.
- //
- // Returns true if successful. If the number of pending jobs will exceed
- // the limit, does nothing and returns false.
- bool PutInQueue(WebSocketJob* job);
-
- // Removes |job| from |queue_| and queues for the destination addresses
- // of |job|, and then wakes up jobs that can now resume establishing a
- // connection.
- void RemoveFromQueue(WebSocketJob* job);
-
- private:
- typedef std::deque<WebSocketJob*> ConnectingQueue;
- typedef std::map<IPEndPoint, ConnectingQueue> ConnectingAddressMap;
-
- WebSocketThrottle();
- ~WebSocketThrottle();
- friend struct DefaultSingletonTraits<WebSocketThrottle>;
-
- // Examines if any of the given jobs can resume establishing a connection. If
- // for all per-address queues for each resolved addresses
- // (job->address_list()) of a job, the job is at the front of the queues, the
- // job can resume establishing a connection, so wakes up the job.
- void WakeupSocketIfNecessary(
- const std::set<WebSocketJob*>& wakeup_candidates);
-
- // Key: string of host's address. Value: queue of sockets for the address.
- ConnectingAddressMap addr_map_;
-
- // Queue of sockets for websockets in opening state.
- ConnectingQueue queue_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSocketThrottle);
-};
-
-} // namespace net
-
-#endif // NET_WEBSOCKETS_WEBSOCKET_THROTTLE_H_
diff --git a/net/websockets/websocket_throttle_test.cc b/net/websockets/websocket_throttle_test.cc
deleted file mode 100644
index 4e27c83..0000000
--- a/net/websockets/websocket_throttle_test.cc
+++ /dev/null
@@ -1,359 +0,0 @@
-// 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 "net/websockets/websocket_throttle.h"
-
-#include <string>
-
-#include "base/message_loop/message_loop.h"
-#include "net/base/address_list.h"
-#include "net/base/test_completion_callback.h"
-#include "net/socket_stream/socket_stream.h"
-#include "net/url_request/url_request_test_util.h"
-#include "net/websockets/websocket_job.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "url/gurl.h"
-
-namespace net {
-
-namespace {
-
-class DummySocketStreamDelegate : public SocketStream::Delegate {
- public:
- DummySocketStreamDelegate() {}
- ~DummySocketStreamDelegate() override {}
- void OnConnected(SocketStream* socket,
- int max_pending_send_allowed) override {}
- void OnSentData(SocketStream* socket, int amount_sent) override {}
- void OnReceivedData(SocketStream* socket,
- const char* data,
- int len) override {}
- void OnClose(SocketStream* socket) override {}
-};
-
-class WebSocketThrottleTestContext : public TestURLRequestContext {
- public:
- explicit WebSocketThrottleTestContext(bool enable_websocket_over_spdy)
- : TestURLRequestContext(true) {
- HttpNetworkSession::Params params;
- params.enable_websocket_over_spdy = enable_websocket_over_spdy;
- Init();
- }
-};
-
-} // namespace
-
-class WebSocketThrottleTest : public PlatformTest {
- protected:
- static IPEndPoint MakeAddr(int a1, int a2, int a3, int a4) {
- IPAddressNumber ip;
- ip.push_back(a1);
- ip.push_back(a2);
- ip.push_back(a3);
- ip.push_back(a4);
- return IPEndPoint(ip, 0);
- }
-
- static void MockSocketStreamConnect(
- SocketStream* socket, const AddressList& list) {
- socket->set_addresses(list);
- // TODO(toyoshim): We should introduce additional tests on cases via proxy.
- socket->proxy_info_.UseDirect();
- // In SocketStream::Connect(), it adds reference to socket, which is
- // balanced with SocketStream::Finish() that is finally called from
- // SocketStream::Close() or SocketStream::DetachDelegate(), when
- // next_state_ is not STATE_NONE.
- // If next_state_ is STATE_NONE, SocketStream::Close() or
- // SocketStream::DetachDelegate() won't call SocketStream::Finish(),
- // so Release() won't be called. Thus, we don't need socket->AddRef()
- // here.
- DCHECK_EQ(socket->next_state_, SocketStream::STATE_NONE);
- }
-};
-
-TEST_F(WebSocketThrottleTest, Throttle) {
- // TODO(toyoshim): We need to consider both spdy-enabled and spdy-disabled
- // configuration.
- WebSocketThrottleTestContext context(true);
- DummySocketStreamDelegate delegate;
-
- // For host1: 1.2.3.4, 1.2.3.5, 1.2.3.6
- AddressList addr;
- addr.push_back(MakeAddr(1, 2, 3, 4));
- addr.push_back(MakeAddr(1, 2, 3, 5));
- addr.push_back(MakeAddr(1, 2, 3, 6));
- scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s1(
- new SocketStream(GURL("ws://host1/"), w1.get(), &context, NULL));
- w1->InitSocketStream(s1.get());
- WebSocketThrottleTest::MockSocketStreamConnect(s1.get(), addr);
-
- DVLOG(1) << "socket1";
- TestCompletionCallback callback_s1;
- // Trying to open connection to host1 will start without wait.
- EXPECT_EQ(OK, w1->OnStartOpenConnection(s1.get(), callback_s1.callback()));
-
- // Now connecting to host1, so waiting queue looks like
- // Address | head -> tail
- // 1.2.3.4 | w1
- // 1.2.3.5 | w1
- // 1.2.3.6 | w1
-
- // For host2: 1.2.3.4
- addr.clear();
- addr.push_back(MakeAddr(1, 2, 3, 4));
- scoped_refptr<WebSocketJob> w2(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s2(
- new SocketStream(GURL("ws://host2/"), w2.get(), &context, NULL));
- w2->InitSocketStream(s2.get());
- WebSocketThrottleTest::MockSocketStreamConnect(s2.get(), addr);
-
- DVLOG(1) << "socket2";
- TestCompletionCallback callback_s2;
- // Trying to open connection to host2 will wait for w1.
- EXPECT_EQ(ERR_IO_PENDING,
- w2->OnStartOpenConnection(s2.get(), callback_s2.callback()));
- // Now waiting queue looks like
- // Address | head -> tail
- // 1.2.3.4 | w1 w2
- // 1.2.3.5 | w1
- // 1.2.3.6 | w1
-
- // For host3: 1.2.3.5
- addr.clear();
- addr.push_back(MakeAddr(1, 2, 3, 5));
- scoped_refptr<WebSocketJob> w3(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s3(
- new SocketStream(GURL("ws://host3/"), w3.get(), &context, NULL));
- w3->InitSocketStream(s3.get());
- WebSocketThrottleTest::MockSocketStreamConnect(s3.get(), addr);
-
- DVLOG(1) << "socket3";
- TestCompletionCallback callback_s3;
- // Trying to open connection to host3 will wait for w1.
- EXPECT_EQ(ERR_IO_PENDING,
- w3->OnStartOpenConnection(s3.get(), callback_s3.callback()));
- // Address | head -> tail
- // 1.2.3.4 | w1 w2
- // 1.2.3.5 | w1 w3
- // 1.2.3.6 | w1
-
- // For host4: 1.2.3.4, 1.2.3.6
- addr.clear();
- addr.push_back(MakeAddr(1, 2, 3, 4));
- addr.push_back(MakeAddr(1, 2, 3, 6));
- scoped_refptr<WebSocketJob> w4(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s4(
- new SocketStream(GURL("ws://host4/"), w4.get(), &context, NULL));
- w4->InitSocketStream(s4.get());
- WebSocketThrottleTest::MockSocketStreamConnect(s4.get(), addr);
-
- DVLOG(1) << "socket4";
- TestCompletionCallback callback_s4;
- // Trying to open connection to host4 will wait for w1, w2.
- EXPECT_EQ(ERR_IO_PENDING,
- w4->OnStartOpenConnection(s4.get(), callback_s4.callback()));
- // Address | head -> tail
- // 1.2.3.4 | w1 w2 w4
- // 1.2.3.5 | w1 w3
- // 1.2.3.6 | w1 w4
-
- // For host5: 1.2.3.6
- addr.clear();
- addr.push_back(MakeAddr(1, 2, 3, 6));
- scoped_refptr<WebSocketJob> w5(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s5(
- new SocketStream(GURL("ws://host5/"), w5.get(), &context, NULL));
- w5->InitSocketStream(s5.get());
- WebSocketThrottleTest::MockSocketStreamConnect(s5.get(), addr);
-
- DVLOG(1) << "socket5";
- TestCompletionCallback callback_s5;
- // Trying to open connection to host5 will wait for w1, w4
- EXPECT_EQ(ERR_IO_PENDING,
- w5->OnStartOpenConnection(s5.get(), callback_s5.callback()));
- // Address | head -> tail
- // 1.2.3.4 | w1 w2 w4
- // 1.2.3.5 | w1 w3
- // 1.2.3.6 | w1 w4 w5
-
- // For host6: 1.2.3.6
- addr.clear();
- addr.push_back(MakeAddr(1, 2, 3, 6));
- scoped_refptr<WebSocketJob> w6(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s6(
- new SocketStream(GURL("ws://host6/"), w6.get(), &context, NULL));
- w6->InitSocketStream(s6.get());
- WebSocketThrottleTest::MockSocketStreamConnect(s6.get(), addr);
-
- DVLOG(1) << "socket6";
- TestCompletionCallback callback_s6;
- // Trying to open connection to host6 will wait for w1, w4, w5
- EXPECT_EQ(ERR_IO_PENDING,
- w6->OnStartOpenConnection(s6.get(), callback_s6.callback()));
- // Address | head -> tail
- // 1.2.3.4 | w1 w2 w4
- // 1.2.3.5 | w1 w3
- // 1.2.3.6 | w1 w4 w5 w6
-
- // Receive partial response on w1, still connecting.
- DVLOG(1) << "socket1 1";
- static const char kHeader[] = "HTTP/1.1 101 WebSocket Protocol\r\n";
- w1->OnReceivedData(s1.get(), kHeader, sizeof(kHeader) - 1);
- EXPECT_FALSE(callback_s2.have_result());
- EXPECT_FALSE(callback_s3.have_result());
- EXPECT_FALSE(callback_s4.have_result());
- EXPECT_FALSE(callback_s5.have_result());
- EXPECT_FALSE(callback_s6.have_result());
-
- // Receive rest of handshake response on w1.
- DVLOG(1) << "socket1 2";
- static const char kHeader2[] =
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: http://www.google.com\r\n"
- "Sec-WebSocket-Location: ws://websocket.chromium.org\r\n"
- "\r\n"
- "8jKS'y:G*Co,Wxa-";
- w1->OnReceivedData(s1.get(), kHeader2, sizeof(kHeader2) - 1);
- base::MessageLoopForIO::current()->RunUntilIdle();
- // Now, w1 is open.
- EXPECT_EQ(WebSocketJob::OPEN, w1->state());
- // So, w2 and w3 can start connecting. w4 needs to wait w2 (1.2.3.4)
- EXPECT_TRUE(callback_s2.have_result());
- EXPECT_TRUE(callback_s3.have_result());
- EXPECT_FALSE(callback_s4.have_result());
- // Address | head -> tail
- // 1.2.3.4 | w2 w4
- // 1.2.3.5 | w3
- // 1.2.3.6 | w4 w5 w6
-
- // Closing s1 doesn't change waiting queue.
- DVLOG(1) << "socket1 close";
- w1->OnClose(s1.get());
- base::MessageLoopForIO::current()->RunUntilIdle();
- EXPECT_FALSE(callback_s4.have_result());
- s1->DetachDelegate();
- // Address | head -> tail
- // 1.2.3.4 | w2 w4
- // 1.2.3.5 | w3
- // 1.2.3.6 | w4 w5 w6
-
- // w5 can close while waiting in queue.
- DVLOG(1) << "socket5 close";
- // w5 close() closes SocketStream that change state to STATE_CLOSE, calls
- // DoLoop(), so OnClose() callback will be called.
- w5->OnClose(s5.get());
- base::MessageLoopForIO::current()->RunUntilIdle();
- EXPECT_FALSE(callback_s4.have_result());
- // Address | head -> tail
- // 1.2.3.4 | w2 w4
- // 1.2.3.5 | w3
- // 1.2.3.6 | w4 w6
- s5->DetachDelegate();
-
- // w6 close abnormally (e.g. renderer finishes) while waiting in queue.
- DVLOG(1) << "socket6 close abnormally";
- w6->DetachDelegate();
- base::MessageLoopForIO::current()->RunUntilIdle();
- EXPECT_FALSE(callback_s4.have_result());
- // Address | head -> tail
- // 1.2.3.4 | w2 w4
- // 1.2.3.5 | w3
- // 1.2.3.6 | w4
-
- // Closing s2 kicks w4 to start connecting.
- DVLOG(1) << "socket2 close";
- w2->OnClose(s2.get());
- base::MessageLoopForIO::current()->RunUntilIdle();
- EXPECT_TRUE(callback_s4.have_result());
- // Address | head -> tail
- // 1.2.3.4 | w4
- // 1.2.3.5 | w3
- // 1.2.3.6 | w4
- s2->DetachDelegate();
-
- DVLOG(1) << "socket3 close";
- w3->OnClose(s3.get());
- base::MessageLoopForIO::current()->RunUntilIdle();
- s3->DetachDelegate();
- w4->OnClose(s4.get());
- s4->DetachDelegate();
- DVLOG(1) << "Done";
- base::MessageLoopForIO::current()->RunUntilIdle();
-}
-
-TEST_F(WebSocketThrottleTest, NoThrottleForDuplicateAddress) {
- WebSocketThrottleTestContext context(true);
- DummySocketStreamDelegate delegate;
-
- // For localhost: 127.0.0.1, 127.0.0.1
- AddressList addr;
- addr.push_back(MakeAddr(127, 0, 0, 1));
- addr.push_back(MakeAddr(127, 0, 0, 1));
- scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s1(
- new SocketStream(GURL("ws://localhost/"), w1.get(), &context, NULL));
- w1->InitSocketStream(s1.get());
- WebSocketThrottleTest::MockSocketStreamConnect(s1.get(), addr);
-
- DVLOG(1) << "socket1";
- TestCompletionCallback callback_s1;
- // Trying to open connection to localhost will start without wait.
- EXPECT_EQ(OK, w1->OnStartOpenConnection(s1.get(), callback_s1.callback()));
-
- DVLOG(1) << "socket1 close";
- w1->OnClose(s1.get());
- s1->DetachDelegate();
- DVLOG(1) << "Done";
- base::MessageLoopForIO::current()->RunUntilIdle();
-}
-
-// A connection should not be blocked by another connection to the same IP
-// with a different port.
-TEST_F(WebSocketThrottleTest, NoThrottleForDistinctPort) {
- WebSocketThrottleTestContext context(false);
- DummySocketStreamDelegate delegate;
- IPAddressNumber localhost;
- ParseIPLiteralToNumber("127.0.0.1", &localhost);
-
- // socket1: 127.0.0.1:80
- scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s1(
- new SocketStream(GURL("ws://localhost:80/"), w1.get(), &context, NULL));
- w1->InitSocketStream(s1.get());
- MockSocketStreamConnect(s1.get(),
- AddressList::CreateFromIPAddress(localhost, 80));
-
- DVLOG(1) << "connecting socket1";
- TestCompletionCallback callback_s1;
- // Trying to open connection to localhost:80 will start without waiting.
- EXPECT_EQ(OK, w1->OnStartOpenConnection(s1.get(), callback_s1.callback()));
-
- // socket2: 127.0.0.1:81
- scoped_refptr<WebSocketJob> w2(new WebSocketJob(&delegate));
- scoped_refptr<SocketStream> s2(
- new SocketStream(GURL("ws://localhost:81/"), w2.get(), &context, NULL));
- w2->InitSocketStream(s2.get());
- MockSocketStreamConnect(s2.get(),
- AddressList::CreateFromIPAddress(localhost, 81));
-
- DVLOG(1) << "connecting socket2";
- TestCompletionCallback callback_s2;
- // Trying to open connection to localhost:81 will start without waiting.
- EXPECT_EQ(OK, w2->OnStartOpenConnection(s2.get(), callback_s2.callback()));
-
- DVLOG(1) << "closing socket1";
- w1->OnClose(s1.get());
- s1->DetachDelegate();
-
- DVLOG(1) << "closing socket2";
- w2->OnClose(s2.get());
- s2->DetachDelegate();
- DVLOG(1) << "Done";
- base::MessageLoopForIO::current()->RunUntilIdle();
-}
-
-} // namespace net
diff --git a/storage/common/fileapi/file_system_util.cc b/storage/common/fileapi/file_system_util.cc
index 13ef05a..353225e4 100644
--- a/storage/common/fileapi/file_system_util.cc
+++ b/storage/common/fileapi/file_system_util.cc
@@ -488,8 +488,6 @@ base::File::Error NetErrorToFileError(int error) {
return base::File::FILE_ERROR_NOT_FOUND;
case net::ERR_ACCESS_DENIED:
return base::File::FILE_ERROR_ACCESS_DENIED;
- case net::ERR_TOO_MANY_SOCKET_STREAMS:
- return base::File::FILE_ERROR_TOO_MANY_OPENED;
case net::ERR_OUT_OF_MEMORY:
return base::File::FILE_ERROR_NO_MEMORY;
case net::ERR_FILE_NO_SPACE: