summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
Diffstat (limited to 'net/http')
-rw-r--r--net/http/http_network_session.cc14
-rw-r--r--net/http/http_network_session.h4
-rw-r--r--net/http/http_network_transaction.cc14
-rw-r--r--net/http/http_network_transaction_unittest.cc290
-rw-r--r--net/http/http_proxy_client_socket_pool.cc121
-rw-r--r--net/http/http_proxy_client_socket_pool.h40
-rw-r--r--net/http/http_proxy_client_socket_pool_unittest.cc96
-rw-r--r--net/http/http_stream_request.cc88
-rw-r--r--net/http/http_stream_request.h13
9 files changed, 578 insertions, 102 deletions
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index d85a4ef..93340ef 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -46,6 +46,10 @@ HttpNetworkSession::HttpNetworkSession(
tcp_for_http_proxy_pool_histograms_(
new ClientSocketPoolHistograms("TCPforHTTPProxy")),
http_proxy_pool_histograms_(new ClientSocketPoolHistograms("HTTPProxy")),
+ tcp_for_https_proxy_pool_histograms_(
+ new ClientSocketPoolHistograms("TCPforHTTPSProxy")),
+ ssl_for_https_proxy_pool_histograms_(
+ new ClientSocketPoolHistograms("SSLforHTTPSProxy")),
tcp_for_socks_pool_histograms_(
new ClientSocketPoolHistograms("TCPforSOCKS")),
socks_pool_histograms_(new ClientSocketPoolHistograms("SOCK")),
@@ -91,6 +95,16 @@ HttpNetworkSession::GetSocketPoolForHTTPProxy(const HostPortPair& http_proxy) {
g_max_sockets_per_proxy_server, g_max_sockets_per_group,
tcp_for_http_proxy_pool_histograms_, host_resolver_,
socket_factory_, net_log_),
+ new SSLClientSocketPool(
+ g_max_sockets_per_proxy_server, g_max_sockets_per_group,
+ ssl_for_https_proxy_pool_histograms_, host_resolver_,
+ socket_factory_,
+ new TCPClientSocketPool(
+ g_max_sockets_per_proxy_server,
+ g_max_sockets_per_group,
+ tcp_for_https_proxy_pool_histograms_, host_resolver_,
+ socket_factory_, net_log_),
+ NULL, NULL, net_log_),
net_log_)));
return ret.first->second;
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index ae1738e..9efcb9f 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -156,6 +156,10 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
scoped_refptr<ClientSocketPoolHistograms> tcp_pool_histograms_;
scoped_refptr<ClientSocketPoolHistograms> tcp_for_http_proxy_pool_histograms_;
scoped_refptr<ClientSocketPoolHistograms> http_proxy_pool_histograms_;
+ scoped_refptr<ClientSocketPoolHistograms>
+ tcp_for_https_proxy_pool_histograms_;
+ scoped_refptr<ClientSocketPoolHistograms>
+ ssl_for_https_proxy_pool_histograms_;
scoped_refptr<ClientSocketPoolHistograms> tcp_for_socks_pool_histograms_;
scoped_refptr<ClientSocketPoolHistograms> socks_pool_histograms_;
scoped_refptr<ClientSocketPoolHistograms> ssl_pool_histograms_;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 1ff166c..bf3c4b9 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -322,7 +322,7 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
// because an active network attacker can already control HTTP sessions.
// We reach this case when the user cancels a 407 proxy auth prompt.
// See http://crbug.com/8473.
- DCHECK(proxy_info_.is_http());
+ DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
DCHECK_EQ(headers->response_code(), 407);
LOG(WARNING) << "Blocked proxy response with status "
<< headers->response_code() << " to CONNECT request for "
@@ -658,7 +658,8 @@ int HttpNetworkTransaction::DoSendRequest() {
HttpRequestHeaders request_headers;
BuildRequestHeaders(request_, authorization_headers, request_body,
- !is_https_request() && proxy_info_.is_http(),
+ !is_https_request() && (proxy_info_.is_http() ||
+ proxy_info_.is_https()),
&request_line, &request_headers);
if (session_->network_delegate())
@@ -1093,7 +1094,8 @@ void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
}
bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
- return !is_https_request() && proxy_info_.is_http();
+ return !is_https_request() &&
+ (proxy_info_.is_https() || proxy_info_.is_http());
}
bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
@@ -1134,13 +1136,15 @@ bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
switch (target) {
- case HttpAuth::AUTH_PROXY:
+ case HttpAuth::AUTH_PROXY: {
if (!proxy_info_.proxy_server().is_valid() ||
proxy_info_.proxy_server().is_direct()) {
return GURL(); // There is no proxy server.
}
- return GURL("http://" +
+ const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
+ return GURL(scheme +
proxy_info_.proxy_server().host_port_pair().ToString());
+ }
case HttpAuth::AUTH_SERVER:
return request_->url;
default:
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 5e07b88..81c26fa 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -327,6 +327,12 @@ CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
: ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
template<>
+CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
+ HttpNetworkSession* session)
+ : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
+ NULL, NULL) {}
+
+template<>
CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
HttpNetworkSession* session)
: SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
@@ -1661,6 +1667,153 @@ TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
}
+
+// Test a simple get through an HTTPS Proxy.
+TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
+ // Configure against https proxy server "proxy:70".
+ SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
+ CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+ session_deps.net_log = log.bound().net_log();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+
+ // Since we have proxy, should use full url
+ MockWrite data_writes1[] = {
+ MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ };
+
+ MockRead data_reads1[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
+ MockRead("Content-Length: 100\r\n\r\n"),
+ MockRead(false, OK),
+ };
+
+ StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
+ data_writes1, arraysize(data_writes1));
+ session_deps.socket_factory.AddSocketDataProvider(&data1);
+ SSLSocketDataProvider ssl(true, OK);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+
+ TestCompletionCallback callback1;
+
+ int rv = trans->Start(&request, &callback1, log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback1.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_TRUE(response->headers->IsKeepAlive());
+ EXPECT_EQ(200, response->headers->response_code());
+ EXPECT_EQ(100, response->headers->GetContentLength());
+ EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
+
+ // The password prompt info should not be set.
+ EXPECT_TRUE(response->auth_challenge.get() == NULL);
+}
+
+// Test the challenge-response-retry sequence through an HTTPS Proxy
+TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
+ // Configure against https proxy server "proxy:70".
+ SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
+ CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+ session_deps.net_log = log.bound().net_log();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ // when the no authentication data flag is set.
+ request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
+
+ // Since we have proxy, should use full url
+ MockWrite data_writes1[] = {
+ MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+
+ // After calling trans->RestartWithAuth(), this is the request we should
+ // be issuing -- the final header line contains the credentials.
+ MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n"
+ "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+ };
+
+ // The proxy responds to the GET with a 407, using a persistent
+ // connection.
+ MockRead data_reads1[] = {
+ // No credentials.
+ MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
+ MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
+ MockRead("Proxy-Connection: keep-alive\r\n"),
+ MockRead("Content-Length: 0\r\n\r\n"),
+
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
+ MockRead("Content-Length: 100\r\n\r\n"),
+ MockRead(false, OK),
+ };
+
+ StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
+ data_writes1, arraysize(data_writes1));
+ session_deps.socket_factory.AddSocketDataProvider(&data1);
+ SSLSocketDataProvider ssl(true, OK);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+
+ TestCompletionCallback callback1;
+
+ int rv = trans->Start(&request, &callback1, log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback1.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_EQ(407, response->headers->response_code());
+ EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
+
+ // The password prompt info should have been set in response->auth_challenge.
+ ASSERT_FALSE(response->auth_challenge.get() == NULL);
+
+ EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
+ EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
+ EXPECT_EQ(L"basic", response->auth_challenge->scheme);
+
+ TestCompletionCallback callback2;
+
+ rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback2.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ response = trans->GetResponseInfo();
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_TRUE(response->headers->IsKeepAlive());
+ EXPECT_EQ(200, response->headers->response_code());
+ EXPECT_EQ(100, response->headers->GetContentLength());
+ EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
+
+ // The password prompt info should not be set.
+ EXPECT_TRUE(response->auth_challenge.get() == NULL);
+}
+
void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
const MockRead& status, int expected_status) {
// Configure against proxy server "myproxy:70".
@@ -3691,6 +3844,143 @@ TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
}
}
+
+// Test HTTPS connections to a site, going through an HTTPS proxy
+TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
+ SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
+ MockWrite data_writes[] = {
+ MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ MockWrite("GET / HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Connection: keep-alive\r\n\r\n"),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
+ MockRead("Content-Length: 100\r\n\r\n"),
+ MockRead(false, OK),
+ };
+
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads),
+ data_writes, arraysize(data_writes));
+ SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
+ SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
+
+ session_deps.socket_factory.AddSocketDataProvider(&data);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
+
+ TestCompletionCallback callback;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
+ int rv = trans->Start(&request, &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_TRUE(response->headers->IsKeepAlive());
+ EXPECT_EQ(200, response->headers->response_code());
+ EXPECT_EQ(100, response->headers->GetContentLength());
+ EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
+}
+
+// Test HTTPS connections to a site with a bad certificate, going through an
+// HTTPS proxy
+TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
+ SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
+ // Attempt to fetch the URL from a server with a bad cert
+ MockWrite bad_cert_writes[] = {
+ MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ };
+
+ MockRead bad_cert_reads[] = {
+ MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
+ MockRead(false, OK)
+ };
+
+ // Attempt to fetch the URL with a good cert
+ MockWrite good_data_writes[] = {
+ MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ MockWrite("GET / HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Connection: keep-alive\r\n\r\n"),
+ };
+
+ MockRead good_cert_reads[] = {
+ MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
+ MockRead("HTTP/1.0 200 OK\r\n"),
+ MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
+ MockRead("Content-Length: 100\r\n\r\n"),
+ MockRead(false, OK),
+ };
+
+ StaticSocketDataProvider ssl_bad_certificate(
+ bad_cert_reads, arraysize(bad_cert_reads),
+ bad_cert_writes, arraysize(bad_cert_writes));
+ StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
+ good_data_writes, arraysize(good_data_writes));
+ SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
+ SSLSocketDataProvider ssl(true, OK);
+
+ // SSL to the proxy, then CONNECT request, then SSL with bad certificate
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+ session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
+
+ // SSL to the proxy, then CONNECT request, then valid SSL certificate
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+ session_deps.socket_factory.AddSocketDataProvider(&data);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+
+ TestCompletionCallback callback;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
+ int rv = trans->Start(&request, &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
+
+ rv = trans->RestartIgnoringLastError(&callback);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+
+ EXPECT_FALSE(response == NULL);
+ EXPECT_EQ(100, response->headers->GetContentLength());
+}
+
TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
SessionDependencies session_deps;
scoped_ptr<HttpTransaction> trans(
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index ef2a640..23654d3 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -4,6 +4,8 @@
#include "net/http/http_proxy_client_socket_pool.h"
+#include <algorithm>
+
#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_errors.h"
@@ -17,18 +19,29 @@
namespace net {
HttpProxySocketParams::HttpProxySocketParams(
- const scoped_refptr<TCPSocketParams>& proxy_server,
+ const scoped_refptr<TCPSocketParams>& tcp_params,
+ const scoped_refptr<SSLSocketParams>& ssl_params,
const GURL& request_url,
const std::string& user_agent,
HostPortPair endpoint,
scoped_refptr<HttpNetworkSession> session,
bool tunnel)
- : tcp_params_(proxy_server),
+ : tcp_params_(tcp_params),
+ ssl_params_(ssl_params),
request_url_(request_url),
user_agent_(user_agent),
endpoint_(endpoint),
session_(tunnel ? session : NULL),
tunnel_(tunnel) {
+ DCHECK((tcp_params == NULL && ssl_params != NULL) ||
+ (tcp_params != NULL && ssl_params == NULL));
+}
+
+const HostResolver::RequestInfo& HttpProxySocketParams::destination() const {
+ if (tcp_params_ == NULL)
+ return ssl_params_->tcp_params()->destination();
+ else
+ return tcp_params_->destination();
}
HttpProxySocketParams::~HttpProxySocketParams() {}
@@ -42,6 +55,7 @@ HttpProxyConnectJob::HttpProxyConnectJob(
const scoped_refptr<HttpProxySocketParams>& params,
const base::TimeDelta& timeout_duration,
const scoped_refptr<TCPClientSocketPool>& tcp_pool,
+ const scoped_refptr<SSLClientSocketPool>& ssl_pool,
const scoped_refptr<HostResolver>& host_resolver,
Delegate* delegate,
NetLog* net_log)
@@ -49,6 +63,7 @@ HttpProxyConnectJob::HttpProxyConnectJob(
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
params_(params),
tcp_pool_(tcp_pool),
+ ssl_pool_(ssl_pool),
resolver_(host_resolver),
ALLOW_THIS_IN_INITIALIZER_LIST(
callback_(this, &HttpProxyConnectJob::OnIOComplete)) {
@@ -60,7 +75,9 @@ LoadState HttpProxyConnectJob::GetLoadState() const {
switch (next_state_) {
case kStateTCPConnect:
case kStateTCPConnectComplete:
- return tcp_socket_handle_->GetLoadState();
+ case kStateSSLConnect:
+ case kStateSSLConnectComplete:
+ return transport_socket_handle_->GetLoadState();
case kStateHttpProxyConnect:
case kStateHttpProxyConnectComplete:
return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
@@ -71,7 +88,10 @@ LoadState HttpProxyConnectJob::GetLoadState() const {
}
int HttpProxyConnectJob::ConnectInternal() {
- next_state_ = kStateTCPConnect;
+ if (params_->tcp_params())
+ next_state_ = kStateTCPConnect;
+ else
+ next_state_ = kStateSSLConnect;
return DoLoop(OK);
}
@@ -96,6 +116,13 @@ int HttpProxyConnectJob::DoLoop(int result) {
case kStateTCPConnectComplete:
rv = DoTCPConnectComplete(rv);
break;
+ case kStateSSLConnect:
+ DCHECK_EQ(OK, rv);
+ rv = DoSSLConnect();
+ break;
+ case kStateSSLConnectComplete:
+ rv = DoSSLConnectComplete(rv);
+ break;
case kStateHttpProxyConnect:
DCHECK_EQ(OK, rv);
rv = DoHttpProxyConnect();
@@ -115,8 +142,8 @@ int HttpProxyConnectJob::DoLoop(int result) {
int HttpProxyConnectJob::DoTCPConnect() {
next_state_ = kStateTCPConnectComplete;
- tcp_socket_handle_.reset(new ClientSocketHandle());
- return tcp_socket_handle_->Init(
+ transport_socket_handle_.reset(new ClientSocketHandle());
+ return transport_socket_handle_->Init(
group_name(), params_->tcp_params(),
params_->tcp_params()->destination().priority(), &callback_, tcp_pool_,
net_log());
@@ -135,22 +162,46 @@ int HttpProxyConnectJob::DoTCPConnectComplete(int result) {
return result;
}
+int HttpProxyConnectJob::DoSSLConnect() {
+ next_state_ = kStateSSLConnectComplete;
+ transport_socket_handle_.reset(new ClientSocketHandle());
+ return transport_socket_handle_->Init(
+ group_name(), params_->ssl_params(),
+ params_->ssl_params()->tcp_params()->destination().priority(),
+ &callback_, ssl_pool_, net_log());
+}
+
+int HttpProxyConnectJob::DoSSLConnectComplete(int result) {
+ if (result < 0) {
+ if (transport_socket_handle_->socket())
+ transport_socket_handle_->socket()->Disconnect();
+ return result;
+ }
+
+ // Reset the timer to just the length of time allowed for HttpProxy handshake
+ // so that a fast SSL connection plus a slow HttpProxy failure doesn't take
+ // longer to timeout than it should.
+ ResetTimer(base::TimeDelta::FromSeconds(
+ kHttpProxyConnectJobTimeoutInSeconds));
+ next_state_ = kStateHttpProxyConnect;
+ return result;
+}
+
int HttpProxyConnectJob::DoHttpProxyConnect() {
next_state_ = kStateHttpProxyConnectComplete;
- const HostResolver::RequestInfo& tcp_destination =
- params_->tcp_params()->destination();
+ const HostResolver::RequestInfo& tcp_destination = params_->destination();
HostPortPair proxy_server(tcp_destination.hostname(),
tcp_destination.port());
// Add a HttpProxy connection on top of the tcp socket.
- socket_.reset(new HttpProxyClientSocket(tcp_socket_handle_.release(),
- params_->request_url(),
- params_->user_agent(),
- params_->endpoint(),
- proxy_server,
- params_->session(),
- params_->tunnel()));
- int result = socket_->Connect(&callback_);
+ transport_socket_.reset(
+ new HttpProxyClientSocket(transport_socket_handle_.release(),
+ params_->request_url(),
+ params_->user_agent(),
+ params_->endpoint(),
+ proxy_server, params_->session(),
+ params_->tunnel()));
+ int result = transport_socket_->Connect(&callback_);
// Clear the circular reference to HttpNetworkSession (|params_| reference
// HttpNetworkSession, which reference HttpProxyClientSocketPool, which
@@ -162,26 +213,40 @@ int HttpProxyConnectJob::DoHttpProxyConnect() {
int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
if (result == OK || result == ERR_PROXY_AUTH_REQUESTED)
- set_socket(socket_.release());
+ set_socket(transport_socket_.release());
return result;
}
+HttpProxyClientSocketPool::
+HttpProxyConnectJobFactory::HttpProxyConnectJobFactory(
+ const scoped_refptr<TCPClientSocketPool>& tcp_pool,
+ const scoped_refptr<SSLClientSocketPool>& ssl_pool,
+ HostResolver* host_resolver,
+ NetLog* net_log)
+ : tcp_pool_(tcp_pool),
+ ssl_pool_(ssl_pool),
+ host_resolver_(host_resolver),
+ net_log_(net_log) {
+ base::TimeDelta max_pool_timeout = base::TimeDelta();
+ if (tcp_pool_)
+ max_pool_timeout = tcp_pool_->ConnectionTimeout();
+ if (ssl_pool_)
+ max_pool_timeout = std::max(max_pool_timeout,
+ ssl_pool_->ConnectionTimeout());
+ timeout_ = max_pool_timeout +
+ base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds);
+}
+
+
ConnectJob*
HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob(
const std::string& group_name,
const PoolBase::Request& request,
ConnectJob::Delegate* delegate) const {
return new HttpProxyConnectJob(group_name, request.params(),
- ConnectionTimeout(), tcp_pool_, host_resolver_,
- delegate, net_log_);
-}
-
-base::TimeDelta
-HttpProxyClientSocketPool::HttpProxyConnectJobFactory::ConnectionTimeout()
-const {
- return tcp_pool_->ConnectionTimeout() +
- base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds);
+ ConnectionTimeout(), tcp_pool_, ssl_pool_,
+ host_resolver_, delegate, net_log_);
}
HttpProxyClientSocketPool::HttpProxyClientSocketPool(
@@ -190,12 +255,14 @@ HttpProxyClientSocketPool::HttpProxyClientSocketPool(
const scoped_refptr<ClientSocketPoolHistograms>& histograms,
const scoped_refptr<HostResolver>& host_resolver,
const scoped_refptr<TCPClientSocketPool>& tcp_pool,
+ const scoped_refptr<SSLClientSocketPool>& ssl_pool,
NetLog* net_log)
: base_(max_sockets, max_sockets_per_group, histograms,
base::TimeDelta::FromSeconds(
ClientSocketPool::unused_idle_socket_timeout()),
base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout),
- new HttpProxyConnectJobFactory(tcp_pool, host_resolver, net_log)) {}
+ new HttpProxyConnectJobFactory(tcp_pool, ssl_pool, host_resolver,
+ net_log)) {}
HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {}
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h
index 3e3df7c..c992cf0 100644
--- a/net/http/http_proxy_client_socket_pool.h
+++ b/net/http/http_proxy_client_socket_pool.h
@@ -22,12 +22,19 @@ namespace net {
class HostResolver;
class HttpNetworkSession;
+class SSLClientSocketPool;
+class SSLSocketParams;
class TCPClientSocketPool;
class TCPSocketParams;
+// HttpProxySocketParams only needs the socket params for one of the proxy
+// types. The other param must be NULL. When using an HTTP Proxy,
+// |tcp_params| must be set. When using an HTTPS Proxy, |ssl_params|
+// must be set.
class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> {
public:
- HttpProxySocketParams(const scoped_refptr<TCPSocketParams>& proxy_server,
+ HttpProxySocketParams(const scoped_refptr<TCPSocketParams>& tcp_params,
+ const scoped_refptr<SSLSocketParams>& ssl_params,
const GURL& request_url,
const std::string& user_agent,
HostPortPair endpoint,
@@ -37,12 +44,16 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> {
const scoped_refptr<TCPSocketParams>& tcp_params() const {
return tcp_params_;
}
+ const scoped_refptr<SSLSocketParams>& ssl_params() const {
+ return ssl_params_;
+ }
const GURL& request_url() const { return request_url_; }
const std::string& user_agent() const { return user_agent_; }
const HostPortPair& endpoint() const { return endpoint_; }
const scoped_refptr<HttpNetworkSession>& session() {
return session_;
}
+ const HostResolver::RequestInfo& destination() const;
bool tunnel() const { return tunnel_; }
private:
@@ -50,6 +61,7 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> {
~HttpProxySocketParams();
const scoped_refptr<TCPSocketParams> tcp_params_;
+ const scoped_refptr<SSLSocketParams> ssl_params_;
const GURL request_url_;
const std::string user_agent_;
const HostPortPair endpoint_;
@@ -67,6 +79,7 @@ class HttpProxyConnectJob : public ConnectJob {
const scoped_refptr<HttpProxySocketParams>& params,
const base::TimeDelta& timeout_duration,
const scoped_refptr<TCPClientSocketPool>& tcp_pool,
+ const scoped_refptr<SSLClientSocketPool>& ssl_pool,
const scoped_refptr<HostResolver> &host_resolver,
Delegate* delegate,
NetLog* net_log);
@@ -79,6 +92,8 @@ class HttpProxyConnectJob : public ConnectJob {
enum State {
kStateTCPConnect,
kStateTCPConnectComplete,
+ kStateSSLConnect,
+ kStateSSLConnectComplete,
kStateHttpProxyConnect,
kStateHttpProxyConnectComplete,
kStateNone,
@@ -98,19 +113,25 @@ class HttpProxyConnectJob : public ConnectJob {
// Runs the state transition loop.
int DoLoop(int result);
+ // Connecting to HTTP Proxy
int DoTCPConnect();
int DoTCPConnectComplete(int result);
+ // Connecting to HTTPS Proxy
+ int DoSSLConnect();
+ int DoSSLConnectComplete(int result);
+
int DoHttpProxyConnect();
int DoHttpProxyConnectComplete(int result);
scoped_refptr<HttpProxySocketParams> params_;
const scoped_refptr<TCPClientSocketPool> tcp_pool_;
+ const scoped_refptr<SSLClientSocketPool> ssl_pool_;
const scoped_refptr<HostResolver> resolver_;
State next_state_;
CompletionCallbackImpl<HttpProxyConnectJob> callback_;
- scoped_ptr<ClientSocketHandle> tcp_socket_handle_;
- scoped_ptr<ClientSocket> socket_;
+ scoped_ptr<ClientSocketHandle> transport_socket_handle_;
+ scoped_ptr<ClientSocket> transport_socket_;
DISALLOW_COPY_AND_ASSIGN(HttpProxyConnectJob);
};
@@ -123,6 +144,7 @@ class HttpProxyClientSocketPool : public ClientSocketPool {
const scoped_refptr<ClientSocketPoolHistograms>& histograms,
const scoped_refptr<HostResolver>& host_resolver,
const scoped_refptr<TCPClientSocketPool>& tcp_pool,
+ const scoped_refptr<SSLClientSocketPool>& ssl_pool,
NetLog* net_log);
// ClientSocketPool methods:
@@ -171,25 +193,23 @@ class HttpProxyClientSocketPool : public ClientSocketPool {
public:
HttpProxyConnectJobFactory(
const scoped_refptr<TCPClientSocketPool>& tcp_pool,
+ const scoped_refptr<SSLClientSocketPool>& ssl_pool,
HostResolver* host_resolver,
- NetLog* net_log)
- : tcp_pool_(tcp_pool),
- host_resolver_(host_resolver),
- net_log_(net_log) {}
-
- virtual ~HttpProxyConnectJobFactory() {}
+ NetLog* net_log);
// ClientSocketPoolBase::ConnectJobFactory methods.
virtual ConnectJob* NewConnectJob(const std::string& group_name,
const PoolBase::Request& request,
ConnectJob::Delegate* delegate) const;
- virtual base::TimeDelta ConnectionTimeout() const;
+ virtual base::TimeDelta ConnectionTimeout() const { return timeout_; }
private:
const scoped_refptr<TCPClientSocketPool> tcp_pool_;
+ const scoped_refptr<SSLClientSocketPool> ssl_pool_;
const scoped_refptr<HostResolver> host_resolver_;
NetLog* net_log_;
+ base::TimeDelta timeout_;
DISALLOW_COPY_AND_ASSIGN(HttpProxyConnectJobFactory);
};
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 2324b0d..761360b 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -29,14 +29,27 @@ namespace {
const int kMaxSockets = 32;
const int kMaxSocketsPerGroup = 6;
-class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest {
+enum HttpProxyType {
+ HTTP,
+ HTTPS
+};
+
+typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam;
+
+class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
protected:
HttpProxyClientSocketPoolTest()
- : ignored_tcp_socket_params_(new TCPSocketParams(
+ : ssl_config_(),
+ ignored_tcp_socket_params_(new TCPSocketParams(
HostPortPair("proxy", 80), MEDIUM, GURL(), false)),
+ ignored_ssl_socket_params_(new SSLSocketParams(
+ ignored_tcp_socket_params_, NULL, NULL, ProxyServer::SCHEME_DIRECT,
+ "host", ssl_config_, 0, false, false)),
tcp_histograms_(new ClientSocketPoolHistograms("MockTCP")),
tcp_socket_pool_(new MockTCPClientSocketPool(kMaxSockets,
kMaxSocketsPerGroup, tcp_histograms_, &tcp_client_socket_factory_)),
+ ssl_socket_pool_(new MockSSLClientSocketPool(kMaxSockets,
+ kMaxSocketsPerGroup, tcp_histograms_, &tcp_client_socket_factory_)),
http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
session_(new HttpNetworkSession(new MockHostResolver,
ProxyService::CreateNull(),
@@ -46,16 +59,11 @@ class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest {
http_auth_handler_factory_.get(),
NULL,
NULL)),
- notunnel_socket_params_(new HttpProxySocketParams(
- ignored_tcp_socket_params_, GURL("http://host"), "",
- HostPortPair("host", 80), NULL, false)),
- tunnel_socket_params_(new HttpProxySocketParams(
- ignored_tcp_socket_params_, GURL("http://host"), "",
- HostPortPair("host", 80), session_, true)),
http_proxy_histograms_(
new ClientSocketPoolHistograms("HttpProxyUnitTest")),
pool_(new HttpProxyClientSocketPool(kMaxSockets, kMaxSocketsPerGroup,
- http_proxy_histograms_, NULL, tcp_socket_pool_, NULL)) {
+ http_proxy_histograms_, NULL, tcp_socket_pool_, ssl_socket_pool_,
+ NULL)) {
}
void AddAuthToCache() {
@@ -65,32 +73,64 @@ class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest {
"Basic realm=MyRealm1", kFoo, kBar, "/");
}
- int StartRequest(const std::string& group_name, RequestPriority priority) {
- return StartRequestUsingPool(
- pool_, group_name, priority, tunnel_socket_params_);
+ scoped_refptr<TCPSocketParams> GetTcpParams() {
+ if (GetParam() == HTTPS)
+ return scoped_refptr<TCPSocketParams>();
+ return ignored_tcp_socket_params_;
+ }
+
+ scoped_refptr<SSLSocketParams> GetSslParams() {
+ if (GetParam() == HTTP)
+ return scoped_refptr<SSLSocketParams>();
+ return ignored_ssl_socket_params_;
+ }
+
+ // Returns the a correctly constructed HttpProxyParms
+ // for the HTTP or HTTPS proxy.
+ scoped_refptr<HttpProxySocketParams> GetParams(bool tunnel) {
+ return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams(
+ GetTcpParams(), GetSslParams(), GURL("http://host/"), "",
+ HostPortPair("host", 80), session_, tunnel));
+ }
+
+ scoped_refptr<HttpProxySocketParams> GetTunnelParams() {
+ return GetParams(true);
}
+ scoped_refptr<HttpProxySocketParams> GetNoTunnelParams() {
+ return GetParams(false);
+ }
+
+ SSLConfig ssl_config_;
+
scoped_refptr<TCPSocketParams> ignored_tcp_socket_params_;
+ scoped_refptr<SSLSocketParams> ignored_ssl_socket_params_;
scoped_refptr<ClientSocketPoolHistograms> tcp_histograms_;
MockClientSocketFactory tcp_client_socket_factory_;
scoped_refptr<MockTCPClientSocketPool> tcp_socket_pool_;
+ scoped_refptr<MockSSLClientSocketPool> ssl_socket_pool_;
MockClientSocketFactory socket_factory_;
scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
scoped_refptr<HttpNetworkSession> session_;
- scoped_refptr<HttpProxySocketParams> notunnel_socket_params_;
- scoped_refptr<HttpProxySocketParams> tunnel_socket_params_;
scoped_refptr<ClientSocketPoolHistograms> http_proxy_histograms_;
scoped_refptr<HttpProxyClientSocketPool> pool_;
};
-TEST_F(HttpProxyClientSocketPoolTest, NoTunnel) {
+//-----------------------------------------------------------------------------
+// All tests are run with three different connection types: SPDY after NPN
+// negotiation, SPDY without SSL, and SPDY with SSL.
+INSTANTIATE_TEST_CASE_P(HttpProxyClientSocketPoolTests,
+ HttpProxyClientSocketPoolTest,
+ ::testing::Values(HTTP, HTTPS));
+
+TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
StaticSocketDataProvider data;
data.set_connect_data(MockConnect(false, 0));
tcp_client_socket_factory_.AddSocketDataProvider(&data);
ClientSocketHandle handle;
- int rv = handle.Init("a", notunnel_socket_params_, LOW, NULL, pool_,
+ int rv = handle.Init("a", GetNoTunnelParams(), LOW, NULL, pool_,
BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_initialized());
@@ -100,7 +140,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NoTunnel) {
EXPECT_TRUE(tunnel_socket->IsConnected());
}
-TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) {
+TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
MockWrite writes[] = {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
@@ -120,7 +160,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_,
+ int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
@@ -134,7 +174,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) {
EXPECT_FALSE(tunnel_socket->IsConnected());
}
-TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) {
+TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
MockWrite writes[] = {
MockWrite(false,
"CONNECT host:80 HTTP/1.1\r\n"
@@ -154,7 +194,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_,
+ int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_,
BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_initialized());
@@ -164,7 +204,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) {
EXPECT_TRUE(tunnel_socket->IsConnected());
}
-TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
+TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
MockWrite writes[] = {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
@@ -182,7 +222,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_,
+ int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
@@ -196,7 +236,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
EXPECT_TRUE(tunnel_socket->IsConnected());
}
-TEST_F(HttpProxyClientSocketPoolTest, TCPError) {
+TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
StaticSocketDataProvider data;
data.set_connect_data(MockConnect(true, ERR_CONNECTION_CLOSED));
@@ -204,7 +244,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TCPError) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_,
+ int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
@@ -215,7 +255,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TCPError) {
EXPECT_FALSE(handle.socket());
}
-TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
+TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
MockWrite writes[] = {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
@@ -234,7 +274,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_,
+ int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
@@ -245,7 +285,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
EXPECT_FALSE(handle.socket());
}
-TEST_F(HttpProxyClientSocketPoolTest, TunnelSetupError) {
+TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
MockWrite writes[] = {
MockWrite("CONNECT host:80 HTTP/1.1\r\n"
"Host: host\r\n"
@@ -263,7 +303,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelSetupError) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_,
+ int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc
index 8ca375b..567e353 100644
--- a/net/http/http_stream_request.cc
+++ b/net/http/http_stream_request.cc
@@ -395,7 +395,8 @@ int HttpStreamRequest::DoResolveProxyComplete(int result) {
// Remove unsupported proxies from the list.
proxy_info()->RemoveProxiesWithoutScheme(
- ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP |
+ ProxyServer::SCHEME_DIRECT |
+ ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
if (proxy_info()->is_empty()) {
@@ -461,7 +462,7 @@ int HttpStreamRequest::DoInitConnection() {
new TCPSocketParams(*proxy_host_port, request_info().priority,
request_info().referrer, disable_resolver_cache);
- if (proxy_info()->is_http()) {
+ if (proxy_info()->is_http() || proxy_info()->is_https()) {
GURL authentication_url = request_info().url;
if (using_ssl_ && !authentication_url.SchemeIs("https")) {
// If a proxy tunnel connection needs to be established due to
@@ -479,7 +480,15 @@ int HttpStreamRequest::DoInitConnection() {
std::string user_agent;
request_info().extra_headers.GetHeader(HttpRequestHeaders::kUserAgent,
&user_agent);
+ scoped_refptr<SSLSocketParams> ssl_params;
+ if (proxy_info()->is_https())
+ // Set ssl_params, and unset proxy_tcp_params
+ ssl_params = GenerateSslParams(proxy_tcp_params.release(), NULL, NULL,
+ ProxyServer::SCHEME_DIRECT,
+ want_spdy_over_npn);
+
http_proxy_params = new HttpProxySocketParams(proxy_tcp_params,
+ ssl_params,
authentication_url,
user_agent,
endpoint_,
@@ -504,35 +513,10 @@ int HttpStreamRequest::DoInitConnection() {
// Deal with SSL - which layers on top of any given proxy.
if (using_ssl_) {
- if (factory_->IsTLSIntolerantServer(request_info().url)) {
- LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
- << GetHostAndPort(request_info().url);
- ssl_config()->ssl3_fallback = true;
- ssl_config()->tls1_enabled = false;
- }
-
- UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
- static_cast<int>(ssl_config()->ssl3_fallback), 2);
-
- int load_flags = request_info().load_flags;
- if (factory_->ignore_certificate_errors())
- load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
- if (request_info().load_flags & LOAD_VERIFY_EV_CERT)
- ssl_config()->verify_ev_cert = true;
-
- if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP ||
- proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) {
- ssl_config()->mitm_proxies_allowed = true;
- }
-
scoped_refptr<SSLSocketParams> ssl_params =
- new SSLSocketParams(tcp_params, http_proxy_params, socks_params,
- proxy_info()->proxy_server().scheme(),
- request_info().url.HostNoBrackets(), *ssl_config(),
- load_flags,
- force_spdy_always_ && force_spdy_over_ssl_,
- want_spdy_over_npn);
-
+ GenerateSslParams(tcp_params, http_proxy_params, socks_params,
+ proxy_info()->proxy_server().scheme(),
+ want_spdy_over_npn);
scoped_refptr<SSLClientSocketPool> ssl_pool;
if (proxy_info()->is_direct())
ssl_pool = session_->ssl_socket_pool();
@@ -545,7 +529,7 @@ int HttpStreamRequest::DoInitConnection() {
}
// Finally, get the connection started.
- if (proxy_info()->is_http()) {
+ if (proxy_info()->is_http() || proxy_info()->is_https()) {
return connection_->Init(
connection_group, http_proxy_params, request_info().priority,
&io_callback_, session_->GetSocketPoolForHTTPProxy(*proxy_host_port),
@@ -743,6 +727,47 @@ int HttpStreamRequest::DoRestartTunnelAuthComplete(int result) {
return ReconsiderProxyAfterError(result);
}
+// Returns a newly create SSLSocketParams, and sets several
+// fields of ssl_config_.
+scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSslParams(
+ scoped_refptr<TCPSocketParams> tcp_params,
+ scoped_refptr<HttpProxySocketParams> http_proxy_params,
+ scoped_refptr<SOCKSSocketParams> socks_params,
+ ProxyServer::Scheme proxy_scheme,
+ bool want_spdy_over_npn) {
+
+ if (factory_->IsTLSIntolerantServer(request_info().url)) {
+ LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
+ << GetHostAndPort(request_info().url);
+ ssl_config()->ssl3_fallback = true;
+ ssl_config()->tls1_enabled = false;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
+ static_cast<int>(ssl_config()->ssl3_fallback), 2);
+
+ int load_flags = request_info().load_flags;
+ if (factory_->ignore_certificate_errors())
+ load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
+ if (request_info().load_flags & LOAD_VERIFY_EV_CERT)
+ ssl_config()->verify_ev_cert = true;
+
+ if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP ||
+ proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) {
+ ssl_config()->mitm_proxies_allowed = true;
+ }
+
+ scoped_refptr<SSLSocketParams> ssl_params =
+ new SSLSocketParams(tcp_params, http_proxy_params, socks_params,
+ proxy_scheme, request_info().url.HostNoBrackets(),
+ *ssl_config(), load_flags,
+ force_spdy_always_ && force_spdy_over_ssl_,
+ want_spdy_over_npn);
+
+ return ssl_params;
+}
+
+
void HttpStreamRequest::MarkBrokenAlternateProtocolAndFallback() {
// We have to:
// * Reset the endpoint to be the unmodified URL specified destination.
@@ -915,4 +940,3 @@ void HttpStreamRequest::LogHttpConnectedMetrics(
}
} // namespace net
-
diff --git a/net/http/http_stream_request.h b/net/http/http_stream_request.h
index 3039839..cd1551e 100644
--- a/net/http/http_stream_request.h
+++ b/net/http/http_stream_request.h
@@ -22,8 +22,12 @@ namespace net {
class ClientSocketHandle;
class HttpAuthController;
class HttpNetworkSession;
+class HttpProxySocketParams;
class HttpStreamFactory;
+class SOCKSSocketParams;
+class SSLSocketParams;
class StreamRequestDelegate;
+class TCPSocketParams;
// An HttpStreamRequest exists for each stream which is in progress of being
// created for the StreamFactory.
@@ -106,6 +110,15 @@ class HttpStreamRequest : public StreamFactory::StreamRequestJob {
int DoRestartTunnelAuth();
int DoRestartTunnelAuthComplete(int result);
+ // Returns a newly create SSLSocketParams, and sets several
+ // fields of ssl_config_.
+ scoped_refptr<SSLSocketParams> GenerateSslParams(
+ scoped_refptr<TCPSocketParams> tcp_params,
+ scoped_refptr<HttpProxySocketParams> http_proxy_params,
+ scoped_refptr<SOCKSSocketParams> socks_params,
+ ProxyServer::Scheme proxy_scheme,
+ bool want_spdy_over_npn);
+
// AlternateProtocol API
void MarkBrokenAlternateProtocolAndFallback();