summaryrefslogtreecommitdiffstats
path: root/net/socket_stream
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 /net/socket_stream
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}
Diffstat (limited to 'net/socket_stream')
-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
10 files changed, 0 insertions, 3475 deletions
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