Switch gcm connection_factory_impl.cc to using services/network/proxy_resolving_client_socket.h
This CL migrates gcm to using proxy_resolving_client_socket.h/cc. As a part of network servicification, we are reducing the //net's API surface. connection_factory_impl.cc calls into static net::InitSocketHandleForTlsConnect(), which will not be exposed by network service. This CL migrates gcm off that static function. Bug: 817094 Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo Change-Id: If5a6df107603c676412b971a3d74284a1d01cfc0 Reviewed-on: https://chromium-review.googlesource.com/952333 Reviewed-by: Asanka Herath <asanka@chromium.org> Reviewed-by: Sergey Ulanov <sergeyu@chromium.org> Reviewed-by: Ilya Sherman <isherman@chromium.org> Reviewed-by: Steven Valdez <svaldez@chromium.org> Reviewed-by: Nicolas Zea (slow) <zea@chromium.org> Commit-Queue: Helen Li <xunjieli@chromium.org> Cr-Commit-Position: refs/heads/master@{#544537}
This commit is contained in:
content/browser/renderer_host/p2p
google_apis/gcm
jingle/glue
net/socket
remoting/signaling
services/network
proxy_resolving_client_socket.ccproxy_resolving_client_socket.hproxy_resolving_client_socket_factory.ccproxy_resolving_client_socket_factory.hproxy_resolving_client_socket_unittest.cc
tools/metrics/histograms
@@ -126,7 +126,8 @@ bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
|
|||||||
// The default SSLConfig is good enough for us for now.
|
// The default SSLConfig is good enough for us for now.
|
||||||
const net::SSLConfig ssl_config;
|
const net::SSLConfig ssl_config;
|
||||||
socket_ = proxy_resolving_socket_factory_->CreateSocket(
|
socket_ = proxy_resolving_socket_factory_->CreateSocket(
|
||||||
ssl_config, GURL("https://" + dest_host_port_pair.ToString()));
|
ssl_config, GURL("https://" + dest_host_port_pair.ToString()),
|
||||||
|
false /*use_tls*/);
|
||||||
|
|
||||||
int status = socket_->Connect(
|
int status = socket_->Connect(
|
||||||
base::Bind(&P2PSocketHostTcpBase::OnConnected,
|
base::Bind(&P2PSocketHostTcpBase::OnConnected,
|
||||||
|
@@ -67,6 +67,7 @@ component("gcm") {
|
|||||||
"//base",
|
"//base",
|
||||||
"//base/third_party/dynamic_annotations",
|
"//base/third_party/dynamic_annotations",
|
||||||
"//net",
|
"//net",
|
||||||
|
"//services/network:network_service",
|
||||||
"//third_party/leveldatabase",
|
"//third_party/leveldatabase",
|
||||||
"//url",
|
"//url",
|
||||||
]
|
]
|
||||||
|
@@ -10,4 +10,5 @@ include_rules = [
|
|||||||
"+google", # For third_party/protobuf/src.
|
"+google", # For third_party/protobuf/src.
|
||||||
"+net",
|
"+net",
|
||||||
"+third_party/leveldatabase",
|
"+third_party/leveldatabase",
|
||||||
|
"+services/network",
|
||||||
]
|
]
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include "net/socket/client_socket_handle.h"
|
#include "net/socket/client_socket_handle.h"
|
||||||
#include "net/socket/client_socket_pool_manager.h"
|
#include "net/socket/client_socket_pool_manager.h"
|
||||||
#include "net/ssl/ssl_config_service.h"
|
#include "net/ssl/ssl_config_service.h"
|
||||||
|
#include "services/network/proxy_resolving_client_socket.h"
|
||||||
|
|
||||||
namespace gcm {
|
namespace gcm {
|
||||||
|
|
||||||
@@ -61,9 +62,6 @@ ConnectionFactoryImpl::ConnectionFactoryImpl(
|
|||||||
backoff_policy_(backoff_policy),
|
backoff_policy_(backoff_policy),
|
||||||
gcm_network_session_(gcm_network_session),
|
gcm_network_session_(gcm_network_session),
|
||||||
http_network_session_(http_network_session),
|
http_network_session_(http_network_session),
|
||||||
net_log_(
|
|
||||||
net::NetLogWithSource::Make(net_log, net::NetLogSourceType::SOCKET)),
|
|
||||||
proxy_resolve_request_(NULL),
|
|
||||||
connecting_(false),
|
connecting_(false),
|
||||||
waiting_for_backoff_(false),
|
waiting_for_backoff_(false),
|
||||||
waiting_for_network_online_(false),
|
waiting_for_network_online_(false),
|
||||||
@@ -79,11 +77,6 @@ ConnectionFactoryImpl::ConnectionFactoryImpl(
|
|||||||
ConnectionFactoryImpl::~ConnectionFactoryImpl() {
|
ConnectionFactoryImpl::~ConnectionFactoryImpl() {
|
||||||
CloseSocket();
|
CloseSocket();
|
||||||
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
|
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
|
||||||
if (proxy_resolve_request_) {
|
|
||||||
gcm_network_session_->proxy_resolution_service()->CancelRequest(
|
|
||||||
proxy_resolve_request_);
|
|
||||||
proxy_resolve_request_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFactoryImpl::Initialize(
|
void ConnectionFactoryImpl::Initialize(
|
||||||
@@ -299,11 +292,11 @@ GURL ConnectionFactoryImpl::GetCurrentEndpoint() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() {
|
net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() {
|
||||||
if (!socket_handle_.socket())
|
if (!socket_)
|
||||||
return net::IPEndPoint();
|
return net::IPEndPoint();
|
||||||
|
|
||||||
net::IPEndPoint ip_endpoint;
|
net::IPEndPoint ip_endpoint;
|
||||||
int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint);
|
int result = socket_->GetPeerAddress(&ip_endpoint);
|
||||||
if (result != net::OK)
|
if (result != net::OK)
|
||||||
return net::IPEndPoint();
|
return net::IPEndPoint();
|
||||||
|
|
||||||
@@ -318,7 +311,7 @@ void ConnectionFactoryImpl::ConnectImpl() {
|
|||||||
void ConnectionFactoryImpl::StartConnection() {
|
void ConnectionFactoryImpl::StartConnection() {
|
||||||
DCHECK(!IsEndpointReachable());
|
DCHECK(!IsEndpointReachable());
|
||||||
// TODO(zea): Make this a dcheck again. crbug.com/462319
|
// TODO(zea): Make this a dcheck again. crbug.com/462319
|
||||||
CHECK(!socket_handle_.socket());
|
CHECK(!socket_);
|
||||||
|
|
||||||
// TODO(zea): if the network is offline, don't attempt to connect.
|
// TODO(zea): if the network is offline, don't attempt to connect.
|
||||||
// See crbug.com/396687
|
// See crbug.com/396687
|
||||||
@@ -327,13 +320,14 @@ void ConnectionFactoryImpl::StartConnection() {
|
|||||||
GURL current_endpoint = GetCurrentEndpoint();
|
GURL current_endpoint = GetCurrentEndpoint();
|
||||||
recorder_->RecordConnectionInitiated(current_endpoint.host());
|
recorder_->RecordConnectionInitiated(current_endpoint.host());
|
||||||
UpdateFromHttpNetworkSession();
|
UpdateFromHttpNetworkSession();
|
||||||
int status = gcm_network_session_->proxy_resolution_service()->ResolveProxy(
|
net::SSLConfig ssl_config;
|
||||||
current_endpoint, std::string(), &proxy_info_,
|
gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config);
|
||||||
base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
|
socket_ = std::make_unique<network::ProxyResolvingClientSocket>(
|
||||||
weak_ptr_factory_.GetWeakPtr()),
|
gcm_network_session_, ssl_config, current_endpoint, true /*use_tls*/);
|
||||||
&proxy_resolve_request_, NULL, net_log_);
|
int status = socket_->Connect(base::BindRepeating(
|
||||||
|
&ConnectionFactoryImpl::OnConnectDone, weak_ptr_factory_.GetWeakPtr()));
|
||||||
if (status != net::ERR_IO_PENDING)
|
if (status != net::ERR_IO_PENDING)
|
||||||
OnProxyResolveDone(status);
|
OnConnectDone(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFactoryImpl::InitHandler() {
|
void ConnectionFactoryImpl::InitHandler() {
|
||||||
@@ -381,8 +375,7 @@ void ConnectionFactoryImpl::InitHandler() {
|
|||||||
"but does not have any effect on other Google Cloud messages."
|
"but does not have any effect on other Google Cloud messages."
|
||||||
)");
|
)");
|
||||||
|
|
||||||
connection_handler_->Init(login_request, traffic_annotation,
|
connection_handler_->Init(login_request, traffic_annotation, socket_.get());
|
||||||
socket_handle_.socket());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<net::BackoffEntry> ConnectionFactoryImpl::CreateBackoffEntry(
|
std::unique_ptr<net::BackoffEntry> ConnectionFactoryImpl::CreateBackoffEntry(
|
||||||
@@ -405,15 +398,8 @@ base::TimeTicks ConnectionFactoryImpl::NowTicks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFactoryImpl::OnConnectDone(int result) {
|
void ConnectionFactoryImpl::OnConnectDone(int result) {
|
||||||
|
DCHECK_NE(net::ERR_IO_PENDING, result);
|
||||||
if (result != net::OK) {
|
if (result != net::OK) {
|
||||||
// If the connection fails, try another proxy.
|
|
||||||
result = ReconsiderProxyAfterError(result);
|
|
||||||
// ReconsiderProxyAfterError either returns an error (in which case it is
|
|
||||||
// not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering
|
|
||||||
// another proxy.
|
|
||||||
DCHECK_NE(result, net::OK);
|
|
||||||
if (result == net::ERR_IO_PENDING)
|
|
||||||
return; // Proxy reconsideration pending. Return.
|
|
||||||
LOG(ERROR) << "Failed to connect to MCS endpoint with error " << result;
|
LOG(ERROR) << "Failed to connect to MCS endpoint with error " << result;
|
||||||
UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", false);
|
UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", false);
|
||||||
recorder_->RecordConnectionFailure(result);
|
recorder_->RecordConnectionFailure(result);
|
||||||
@@ -436,9 +422,6 @@ void ConnectionFactoryImpl::OnConnectDone(int result) {
|
|||||||
|
|
||||||
UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true);
|
UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true);
|
||||||
UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_);
|
UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_);
|
||||||
UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy",
|
|
||||||
!(proxy_info_.is_empty() || proxy_info_.is_direct()));
|
|
||||||
ReportSuccessfulProxyConnection();
|
|
||||||
recorder_->RecordConnectionSuccess();
|
recorder_->RecordConnectionSuccess();
|
||||||
|
|
||||||
// Reset the endpoint back to the default.
|
// Reset the endpoint back to the default.
|
||||||
@@ -478,106 +461,15 @@ void ConnectionFactoryImpl::ConnectionHandlerCallback(int result) {
|
|||||||
listener_->OnConnected(GetCurrentEndpoint(), GetPeerIP());
|
listener_->OnConnected(GetCurrentEndpoint(), GetPeerIP());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This has largely been copied from
|
|
||||||
// HttpStreamFactoryImpl::Job::DoResolveProxyComplete. This should be
|
|
||||||
// refactored into some common place.
|
|
||||||
void ConnectionFactoryImpl::OnProxyResolveDone(int status) {
|
|
||||||
proxy_resolve_request_ = NULL;
|
|
||||||
DVLOG(1) << "Proxy resolution status: " << status;
|
|
||||||
|
|
||||||
DCHECK_NE(status, net::ERR_IO_PENDING);
|
|
||||||
if (status == net::OK) {
|
|
||||||
// Remove unsupported proxies from the list.
|
|
||||||
proxy_info_.RemoveProxiesWithoutScheme(
|
|
||||||
net::ProxyServer::SCHEME_DIRECT |
|
|
||||||
net::ProxyServer::SCHEME_HTTP | net::ProxyServer::SCHEME_HTTPS |
|
|
||||||
net::ProxyServer::SCHEME_SOCKS4 | net::ProxyServer::SCHEME_SOCKS5);
|
|
||||||
|
|
||||||
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.
|
|
||||||
status = net::ERR_NO_SUPPORTED_PROXIES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != net::OK) {
|
|
||||||
// Failed to resolve proxy. Retry later.
|
|
||||||
OnConnectDone(status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DVLOG(1) << "Resolved proxy with PAC:" << proxy_info_.ToPacString();
|
|
||||||
|
|
||||||
net::SSLConfig ssl_config;
|
|
||||||
gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config);
|
|
||||||
status = net::InitSocketHandleForTlsConnect(
|
|
||||||
net::HostPortPair::FromURL(GetCurrentEndpoint()),
|
|
||||||
gcm_network_session_,
|
|
||||||
proxy_info_,
|
|
||||||
ssl_config,
|
|
||||||
ssl_config,
|
|
||||||
net::PRIVACY_MODE_DISABLED,
|
|
||||||
net_log_,
|
|
||||||
&socket_handle_,
|
|
||||||
base::Bind(&ConnectionFactoryImpl::OnConnectDone,
|
|
||||||
weak_ptr_factory_.GetWeakPtr()));
|
|
||||||
if (status != net::ERR_IO_PENDING)
|
|
||||||
OnConnectDone(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This has largely been copied from
|
|
||||||
// HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError. This should be
|
|
||||||
// refactored into some common place.
|
|
||||||
// This method reconsiders the proxy on certain errors. If it does reconsider
|
|
||||||
// a proxy it always returns ERR_IO_PENDING and posts a call to
|
|
||||||
// OnProxyResolveDone with the result of the reconsideration.
|
|
||||||
int ConnectionFactoryImpl::ReconsiderProxyAfterError(int error) {
|
|
||||||
DCHECK(!proxy_resolve_request_);
|
|
||||||
DCHECK_NE(error, net::OK);
|
|
||||||
DCHECK_NE(error, net::ERR_IO_PENDING);
|
|
||||||
|
|
||||||
// Check if the error was a proxy failure.
|
|
||||||
if (!net::CanFalloverToNextProxy(&error))
|
|
||||||
return error;
|
|
||||||
|
|
||||||
net::SSLConfig ssl_config;
|
|
||||||
gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config);
|
|
||||||
if (proxy_info_.is_https() && ssl_config.send_client_cert) {
|
|
||||||
gcm_network_session_->ssl_client_auth_cache()->Remove(
|
|
||||||
proxy_info_.proxy_server().host_port_pair());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!proxy_info_.Fallback(error, net_log_)) {
|
|
||||||
// There was nothing left to fall-back to, so fail the transaction
|
|
||||||
// with the last connection error we got.
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseSocket();
|
|
||||||
|
|
||||||
// If there is new proxy info, post OnProxyResolveDone to retry it.
|
|
||||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
|
||||||
FROM_HERE, base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
|
|
||||||
weak_ptr_factory_.GetWeakPtr(), net::OK));
|
|
||||||
|
|
||||||
return net::ERR_IO_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionFactoryImpl::ReportSuccessfulProxyConnection() {
|
|
||||||
if (gcm_network_session_ && gcm_network_session_->proxy_resolution_service())
|
|
||||||
gcm_network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionFactoryImpl::CloseSocket() {
|
void ConnectionFactoryImpl::CloseSocket() {
|
||||||
// The connection handler needs to be reset, else it'll attempt to keep using
|
// The connection handler needs to be reset, else it'll attempt to keep using
|
||||||
// the destroyed socket.
|
// the destroyed socket.
|
||||||
if (connection_handler_)
|
if (connection_handler_)
|
||||||
connection_handler_->Reset();
|
connection_handler_->Reset();
|
||||||
|
|
||||||
if (socket_handle_.socket() && socket_handle_.socket()->IsConnected())
|
if (socket_)
|
||||||
socket_handle_.socket()->Disconnect();
|
socket_->Disconnect();
|
||||||
socket_handle_.Reset();
|
socket_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFactoryImpl::UpdateFromHttpNetworkSession() {
|
void ConnectionFactoryImpl::UpdateFromHttpNetworkSession() {
|
||||||
|
@@ -18,11 +18,12 @@
|
|||||||
#include "net/base/backoff_entry.h"
|
#include "net/base/backoff_entry.h"
|
||||||
#include "net/base/network_change_notifier.h"
|
#include "net/base/network_change_notifier.h"
|
||||||
#include "net/log/net_log_with_source.h"
|
#include "net/log/net_log_with_source.h"
|
||||||
#include "net/proxy_resolution/proxy_info.h"
|
|
||||||
#include "net/proxy_resolution/proxy_resolution_service.h"
|
|
||||||
#include "net/socket/client_socket_handle.h"
|
|
||||||
#include "url/gurl.h"
|
#include "url/gurl.h"
|
||||||
|
|
||||||
|
namespace network {
|
||||||
|
class ProxyResolvingClientSocket;
|
||||||
|
}
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
class HttpNetworkSession;
|
class HttpNetworkSession;
|
||||||
class NetLog;
|
class NetLog;
|
||||||
@@ -123,12 +124,6 @@ class GCM_EXPORT ConnectionFactoryImpl :
|
|||||||
// handshake. On connection/handshake failure, goes into backoff.
|
// handshake. On connection/handshake failure, goes into backoff.
|
||||||
void ConnectImpl();
|
void ConnectImpl();
|
||||||
|
|
||||||
// Proxy resolution and connection functions.
|
|
||||||
void OnProxyResolveDone(int status);
|
|
||||||
void OnProxyConnectDone(int status);
|
|
||||||
int ReconsiderProxyAfterError(int error);
|
|
||||||
void ReportSuccessfulProxyConnection();
|
|
||||||
|
|
||||||
// Closes the local socket if one is present, and resets connection handler.
|
// Closes the local socket if one is present, and resets connection handler.
|
||||||
void CloseSocket();
|
void CloseSocket();
|
||||||
|
|
||||||
@@ -157,15 +152,8 @@ class GCM_EXPORT ConnectionFactoryImpl :
|
|||||||
// HTTP Network session. If set, is used for extracting proxy auth
|
// HTTP Network session. If set, is used for extracting proxy auth
|
||||||
// credentials. If nullptr, is ignored.
|
// credentials. If nullptr, is ignored.
|
||||||
net::HttpNetworkSession* http_network_session_;
|
net::HttpNetworkSession* http_network_session_;
|
||||||
// Net log to use in connection attempts.
|
|
||||||
net::NetLogWithSource net_log_;
|
|
||||||
// The current proxy resolution request, if one exists. Owned by the proxy
|
|
||||||
// service.
|
|
||||||
net::ProxyResolutionService::Request* proxy_resolve_request_;
|
|
||||||
// The current proxy info.
|
|
||||||
net::ProxyInfo proxy_info_;
|
|
||||||
// The handle to the socket for the current connection, if one exists.
|
// The handle to the socket for the current connection, if one exists.
|
||||||
net::ClientSocketHandle socket_handle_;
|
std::unique_ptr<network::ProxyResolvingClientSocket> socket_;
|
||||||
// Current backoff entry.
|
// Current backoff entry.
|
||||||
std::unique_ptr<net::BackoffEntry> backoff_entry_;
|
std::unique_ptr<net::BackoffEntry> backoff_entry_;
|
||||||
// Backoff entry from previous connection attempt. Updated on each login
|
// Backoff entry from previous connection attempt. Updated on each login
|
||||||
|
@@ -39,7 +39,8 @@ XmppClientSocketFactory::CreateTransportClientSocket(
|
|||||||
const net::HostPortPair& host_and_port) {
|
const net::HostPortPair& host_and_port) {
|
||||||
// TODO(akalin): Use socket pools.
|
// TODO(akalin): Use socket pools.
|
||||||
auto transport_socket = proxy_resolving_socket_factory_.CreateSocket(
|
auto transport_socket = proxy_resolving_socket_factory_.CreateSocket(
|
||||||
ssl_config_, GURL("https://" + host_and_port.ToString()));
|
ssl_config_, GURL("https://" + host_and_port.ToString()),
|
||||||
|
false /*use_tls*/);
|
||||||
return (use_fake_ssl_client_socket_
|
return (use_fake_ssl_client_socket_
|
||||||
? std::unique_ptr<net::StreamSocket>(
|
? std::unique_ptr<net::StreamSocket>(
|
||||||
new FakeSSLClientSocket(std::move(transport_socket)))
|
new FakeSSLClientSocket(std::move(transport_socket)))
|
||||||
|
@@ -427,6 +427,8 @@ int InitSocketHandleForRawConnect(const HostPortPair& host_port_pair,
|
|||||||
|
|
||||||
int InitSocketHandleForTlsConnect(const HostPortPair& endpoint,
|
int InitSocketHandleForTlsConnect(const HostPortPair& endpoint,
|
||||||
HttpNetworkSession* session,
|
HttpNetworkSession* session,
|
||||||
|
int request_load_flags,
|
||||||
|
RequestPriority request_priority,
|
||||||
const ProxyInfo& proxy_info,
|
const ProxyInfo& proxy_info,
|
||||||
const SSLConfig& ssl_config_for_origin,
|
const SSLConfig& ssl_config_for_origin,
|
||||||
const SSLConfig& ssl_config_for_proxy,
|
const SSLConfig& ssl_config_for_proxy,
|
||||||
@@ -436,8 +438,6 @@ int InitSocketHandleForTlsConnect(const HostPortPair& endpoint,
|
|||||||
const CompletionCallback& callback) {
|
const CompletionCallback& callback) {
|
||||||
DCHECK(socket_handle);
|
DCHECK(socket_handle);
|
||||||
HttpRequestHeaders request_extra_headers;
|
HttpRequestHeaders request_extra_headers;
|
||||||
int request_load_flags = 0;
|
|
||||||
RequestPriority request_priority = MEDIUM;
|
|
||||||
return InitSocketPoolHelper(
|
return InitSocketPoolHelper(
|
||||||
ClientSocketPoolManager::SSL_GROUP, endpoint, request_extra_headers,
|
ClientSocketPoolManager::SSL_GROUP, endpoint, request_extra_headers,
|
||||||
request_load_flags, request_priority, session, proxy_info,
|
request_load_flags, request_priority, session, proxy_info,
|
||||||
|
@@ -146,6 +146,7 @@ int InitSocketHandleForWebSocketRequest(
|
|||||||
const OnHostResolutionCallback& resolution_callback,
|
const OnHostResolutionCallback& resolution_callback,
|
||||||
const CompletionCallback& callback);
|
const CompletionCallback& callback);
|
||||||
|
|
||||||
|
// Deprecated: Please do not use this outside of //net and //services/network.
|
||||||
// A helper method that uses the passed in proxy information to initialize a
|
// A helper method that uses the passed in proxy information to initialize a
|
||||||
// ClientSocketHandle with the relevant socket pool. Use this method for
|
// ClientSocketHandle with the relevant socket pool. Use this method for
|
||||||
// a raw socket connection to a host-port pair (that needs to tunnel through
|
// a raw socket connection to a host-port pair (that needs to tunnel through
|
||||||
@@ -163,6 +164,7 @@ NET_EXPORT int InitSocketHandleForRawConnect(
|
|||||||
ClientSocketHandle* socket_handle,
|
ClientSocketHandle* socket_handle,
|
||||||
const CompletionCallback& callback);
|
const CompletionCallback& callback);
|
||||||
|
|
||||||
|
// Deprecated: Please do not use this outside of //net and //services/network.
|
||||||
// A helper method that uses the passed in proxy information to initialize a
|
// A helper method that uses the passed in proxy information to initialize a
|
||||||
// ClientSocketHandle with the relevant socket pool. Use this method for
|
// ClientSocketHandle with the relevant socket pool. Use this method for
|
||||||
// a raw socket connection with TLS negotiation to a host-port pair (that needs
|
// a raw socket connection with TLS negotiation to a host-port pair (that needs
|
||||||
@@ -170,6 +172,8 @@ NET_EXPORT int InitSocketHandleForRawConnect(
|
|||||||
NET_EXPORT int InitSocketHandleForTlsConnect(
|
NET_EXPORT int InitSocketHandleForTlsConnect(
|
||||||
const HostPortPair& host_port_pair,
|
const HostPortPair& host_port_pair,
|
||||||
HttpNetworkSession* session,
|
HttpNetworkSession* session,
|
||||||
|
int request_load_flags,
|
||||||
|
RequestPriority request_priority,
|
||||||
const ProxyInfo& proxy_info,
|
const ProxyInfo& proxy_info,
|
||||||
const SSLConfig& ssl_config_for_origin,
|
const SSLConfig& ssl_config_for_origin,
|
||||||
const SSLConfig& ssl_config_for_proxy,
|
const SSLConfig& ssl_config_for_proxy,
|
||||||
|
@@ -1212,6 +1212,7 @@ int MockSSLClientSocket::Write(
|
|||||||
|
|
||||||
int MockSSLClientSocket::Connect(const CompletionCallback& callback) {
|
int MockSSLClientSocket::Connect(const CompletionCallback& callback) {
|
||||||
DCHECK(transport_->socket()->IsConnected());
|
DCHECK(transport_->socket()->IsConnected());
|
||||||
|
data_->is_connect_data_consumed = true;
|
||||||
if (data_->connect.result == OK)
|
if (data_->connect.result == OK)
|
||||||
connected_ = true;
|
connected_ = true;
|
||||||
if (data_->connect.mode == ASYNC) {
|
if (data_->connect.mode == ASYNC) {
|
||||||
|
@@ -360,6 +360,9 @@ struct SSLSocketDataProvider {
|
|||||||
SSLSocketDataProvider(const SSLSocketDataProvider& other);
|
SSLSocketDataProvider(const SSLSocketDataProvider& other);
|
||||||
~SSLSocketDataProvider();
|
~SSLSocketDataProvider();
|
||||||
|
|
||||||
|
// Returns whether MockConnect data has been consumed.
|
||||||
|
bool ConnectDataConsumed() const { return is_connect_data_consumed; }
|
||||||
|
|
||||||
// Result for Connect().
|
// Result for Connect().
|
||||||
MockConnect connect;
|
MockConnect connect;
|
||||||
|
|
||||||
@@ -374,6 +377,8 @@ struct SSLSocketDataProvider {
|
|||||||
|
|
||||||
ChannelIDService* channel_id_service;
|
ChannelIDService* channel_id_service;
|
||||||
base::Optional<NextProtoVector> next_protos_expected_in_ssl_config;
|
base::Optional<NextProtoVector> next_protos_expected_in_ssl_config;
|
||||||
|
|
||||||
|
bool is_connect_data_consumed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Uses the sequence_number field in the mock reads and writes to
|
// Uses the sequence_number field in the mock reads and writes to
|
||||||
|
@@ -190,7 +190,8 @@ void XmppSignalStrategy::Core::Connect() {
|
|||||||
net::SSLConfig(),
|
net::SSLConfig(),
|
||||||
GURL("https://" +
|
GURL("https://" +
|
||||||
net::HostPortPair(xmpp_server_config_.host, xmpp_server_config_.port)
|
net::HostPortPair(xmpp_server_config_.host, xmpp_server_config_.port)
|
||||||
.ToString()));
|
.ToString()),
|
||||||
|
false /*use_tls*/);
|
||||||
|
|
||||||
int result = socket_->Connect(base::Bind(
|
int result = socket_->Connect(base::Bind(
|
||||||
&Core::OnSocketConnected, base::Unretained(this)));
|
&Core::OnSocketConnected, base::Unretained(this)));
|
||||||
|
@@ -31,13 +31,17 @@ namespace network {
|
|||||||
ProxyResolvingClientSocket::ProxyResolvingClientSocket(
|
ProxyResolvingClientSocket::ProxyResolvingClientSocket(
|
||||||
net::HttpNetworkSession* network_session,
|
net::HttpNetworkSession* network_session,
|
||||||
const net::SSLConfig& ssl_config,
|
const net::SSLConfig& ssl_config,
|
||||||
const GURL& url)
|
const GURL& url,
|
||||||
|
bool use_tls)
|
||||||
: network_session_(network_session),
|
: network_session_(network_session),
|
||||||
|
socket_handle_(std::make_unique<net::ClientSocketHandle>()),
|
||||||
ssl_config_(ssl_config),
|
ssl_config_(ssl_config),
|
||||||
proxy_resolve_request_(nullptr),
|
proxy_resolve_request_(nullptr),
|
||||||
url_(url),
|
url_(url),
|
||||||
|
use_tls_(use_tls),
|
||||||
net_log_(net::NetLogWithSource::Make(network_session_->net_log(),
|
net_log_(net::NetLogWithSource::Make(network_session_->net_log(),
|
||||||
net::NetLogSourceType::SOCKET)),
|
net::NetLogSourceType::SOCKET)),
|
||||||
|
next_state_(STATE_NONE),
|
||||||
weak_factory_(this) {
|
weak_factory_(this) {
|
||||||
// TODO(xunjieli): Handle invalid URLs more gracefully (at mojo API layer
|
// TODO(xunjieli): Handle invalid URLs more gracefully (at mojo API layer
|
||||||
// or when the request is created).
|
// or when the request is created).
|
||||||
@@ -51,8 +55,8 @@ ProxyResolvingClientSocket::~ProxyResolvingClientSocket() {
|
|||||||
int ProxyResolvingClientSocket::Read(net::IOBuffer* buf,
|
int ProxyResolvingClientSocket::Read(net::IOBuffer* buf,
|
||||||
int buf_len,
|
int buf_len,
|
||||||
const net::CompletionCallback& callback) {
|
const net::CompletionCallback& callback) {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->Read(buf, buf_len, callback);
|
return socket_handle_->socket()->Read(buf, buf_len, callback);
|
||||||
return net::ERR_SOCKET_NOT_CONNECTED;
|
return net::ERR_SOCKET_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,21 +65,21 @@ int ProxyResolvingClientSocket::Write(
|
|||||||
int buf_len,
|
int buf_len,
|
||||||
const net::CompletionCallback& callback,
|
const net::CompletionCallback& callback,
|
||||||
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
|
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->Write(buf, buf_len, callback,
|
return socket_handle_->socket()->Write(buf, buf_len, callback,
|
||||||
traffic_annotation);
|
traffic_annotation);
|
||||||
return net::ERR_SOCKET_NOT_CONNECTED;
|
return net::ERR_SOCKET_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProxyResolvingClientSocket::SetReceiveBufferSize(int32_t size) {
|
int ProxyResolvingClientSocket::SetReceiveBufferSize(int32_t size) {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->SetReceiveBufferSize(size);
|
return socket_handle_->socket()->SetReceiveBufferSize(size);
|
||||||
return net::ERR_SOCKET_NOT_CONNECTED;
|
return net::ERR_SOCKET_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProxyResolvingClientSocket::SetSendBufferSize(int32_t size) {
|
int ProxyResolvingClientSocket::SetSendBufferSize(int32_t size) {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->SetSendBufferSize(size);
|
return socket_handle_->socket()->SetSendBufferSize(size);
|
||||||
return net::ERR_SOCKET_NOT_CONNECTED;
|
return net::ERR_SOCKET_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,29 +87,16 @@ int ProxyResolvingClientSocket::Connect(
|
|||||||
const net::CompletionCallback& callback) {
|
const net::CompletionCallback& callback) {
|
||||||
DCHECK(user_connect_callback_.is_null());
|
DCHECK(user_connect_callback_.is_null());
|
||||||
|
|
||||||
// First try to resolve the proxy.
|
next_state_ = STATE_PROXY_RESOLVE;
|
||||||
// TODO(xunjieli): Having a null ProxyDelegate is bad. Figure out how to
|
int result = DoLoop(net::OK);
|
||||||
// interact with the new interface for proxy delegate.
|
if (result == net::ERR_IO_PENDING) {
|
||||||
// https://crbug.com/793071.
|
user_connect_callback_ = callback;
|
||||||
int net_error = network_session_->proxy_resolution_service()->ResolveProxy(
|
|
||||||
url_, "POST", &proxy_info_,
|
|
||||||
base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxy,
|
|
||||||
base::Unretained(this)),
|
|
||||||
&proxy_resolve_request_, nullptr /*proxy_delegate*/, net_log_);
|
|
||||||
if (net_error != net::ERR_IO_PENDING) {
|
|
||||||
// Defer execution of ConnectToProxy instead of calling it
|
|
||||||
// directly here for simplicity. From the caller's point of view,
|
|
||||||
// the connect always happens asynchronously.
|
|
||||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
|
||||||
FROM_HERE, base::BindOnce(&ProxyResolvingClientSocket::ConnectToProxy,
|
|
||||||
weak_factory_.GetWeakPtr(), net_error));
|
|
||||||
}
|
}
|
||||||
user_connect_callback_ = callback;
|
return result;
|
||||||
return net::ERR_IO_PENDING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyResolvingClientSocket::Disconnect() {
|
void ProxyResolvingClientSocket::Disconnect() {
|
||||||
CloseTransportSocket();
|
CloseSocket(true /*close_connection*/);
|
||||||
if (proxy_resolve_request_) {
|
if (proxy_resolve_request_) {
|
||||||
network_session_->proxy_resolution_service()->CancelRequest(
|
network_session_->proxy_resolution_service()->CancelRequest(
|
||||||
proxy_resolve_request_);
|
proxy_resolve_request_);
|
||||||
@@ -115,24 +106,24 @@ void ProxyResolvingClientSocket::Disconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ProxyResolvingClientSocket::IsConnected() const {
|
bool ProxyResolvingClientSocket::IsConnected() const {
|
||||||
if (!transport_.get() || !transport_->socket())
|
if (!socket_handle_->socket())
|
||||||
return false;
|
return false;
|
||||||
return transport_->socket()->IsConnected();
|
return socket_handle_->socket()->IsConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProxyResolvingClientSocket::IsConnectedAndIdle() const {
|
bool ProxyResolvingClientSocket::IsConnectedAndIdle() const {
|
||||||
if (!transport_.get() || !transport_->socket())
|
if (!socket_handle_->socket())
|
||||||
return false;
|
return false;
|
||||||
return transport_->socket()->IsConnectedAndIdle();
|
return socket_handle_->socket()->IsConnectedAndIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProxyResolvingClientSocket::GetPeerAddress(net::IPEndPoint* address) const {
|
int ProxyResolvingClientSocket::GetPeerAddress(net::IPEndPoint* address) const {
|
||||||
if (!transport_.get() || !transport_->socket()) {
|
if (!socket_handle_->socket()) {
|
||||||
return net::ERR_SOCKET_NOT_CONNECTED;
|
return net::ERR_SOCKET_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy_info_.is_direct())
|
if (proxy_info_.is_direct())
|
||||||
return transport_->socket()->GetPeerAddress(address);
|
return socket_handle_->socket()->GetPeerAddress(address);
|
||||||
|
|
||||||
net::IPAddress ip_address;
|
net::IPAddress ip_address;
|
||||||
if (!ip_address.AssignFromIPLiteral(url_.HostNoBrackets())) {
|
if (!ip_address.AssignFromIPLiteral(url_.HostNoBrackets())) {
|
||||||
@@ -146,44 +137,48 @@ int ProxyResolvingClientSocket::GetPeerAddress(net::IPEndPoint* address) const {
|
|||||||
|
|
||||||
int ProxyResolvingClientSocket::GetLocalAddress(
|
int ProxyResolvingClientSocket::GetLocalAddress(
|
||||||
net::IPEndPoint* address) const {
|
net::IPEndPoint* address) const {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->GetLocalAddress(address);
|
return socket_handle_->socket()->GetLocalAddress(address);
|
||||||
return net::ERR_SOCKET_NOT_CONNECTED;
|
return net::ERR_SOCKET_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const net::NetLogWithSource& ProxyResolvingClientSocket::NetLog() const {
|
const net::NetLogWithSource& ProxyResolvingClientSocket::NetLog() const {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->NetLog();
|
return socket_handle_->socket()->NetLog();
|
||||||
return net_log_;
|
return net_log_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyResolvingClientSocket::SetSubresourceSpeculation() {
|
void ProxyResolvingClientSocket::SetSubresourceSpeculation() {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
transport_->socket()->SetSubresourceSpeculation();
|
socket_handle_->socket()->SetSubresourceSpeculation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyResolvingClientSocket::SetOmniboxSpeculation() {
|
void ProxyResolvingClientSocket::SetOmniboxSpeculation() {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
transport_->socket()->SetOmniboxSpeculation();
|
socket_handle_->socket()->SetOmniboxSpeculation();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProxyResolvingClientSocket::WasEverUsed() const {
|
bool ProxyResolvingClientSocket::WasEverUsed() const {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->WasEverUsed();
|
return socket_handle_->socket()->WasEverUsed();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProxyResolvingClientSocket::WasAlpnNegotiated() const {
|
bool ProxyResolvingClientSocket::WasAlpnNegotiated() const {
|
||||||
|
if (socket_handle_->socket())
|
||||||
|
return socket_handle_->socket()->WasAlpnNegotiated();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
net::NextProto ProxyResolvingClientSocket::GetNegotiatedProtocol() const {
|
net::NextProto ProxyResolvingClientSocket::GetNegotiatedProtocol() const {
|
||||||
if (transport_.get() && transport_->socket())
|
if (socket_handle_->socket())
|
||||||
return transport_->socket()->GetNegotiatedProtocol();
|
return socket_handle_->socket()->GetNegotiatedProtocol();
|
||||||
return net::kProtoUnknown;
|
return net::kProtoUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProxyResolvingClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
|
bool ProxyResolvingClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
|
||||||
|
if (socket_handle_->socket())
|
||||||
|
return socket_handle_->socket()->GetSSLInfo(ssl_info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,11 +196,67 @@ void ProxyResolvingClientSocket::ApplySocketTag(const net::SocketTag& tag) {
|
|||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyResolvingClientSocket::ConnectToProxy(int net_error) {
|
void ProxyResolvingClientSocket::OnIOComplete(int result) {
|
||||||
proxy_resolve_request_ = nullptr;
|
DCHECK_NE(net::ERR_IO_PENDING, result);
|
||||||
|
int net_error = DoLoop(result);
|
||||||
|
if (net_error != net::ERR_IO_PENDING)
|
||||||
|
base::ResetAndReturn(&user_connect_callback_).Run(net_error);
|
||||||
|
}
|
||||||
|
|
||||||
DCHECK_NE(net_error, net::ERR_IO_PENDING);
|
int ProxyResolvingClientSocket::DoLoop(int result) {
|
||||||
if (net_error == net::OK) {
|
DCHECK_NE(next_state_, STATE_NONE);
|
||||||
|
int rv = result;
|
||||||
|
do {
|
||||||
|
State state = next_state_;
|
||||||
|
next_state_ = STATE_NONE;
|
||||||
|
switch (state) {
|
||||||
|
case STATE_PROXY_RESOLVE:
|
||||||
|
DCHECK_EQ(net::OK, rv);
|
||||||
|
rv = DoProxyResolve();
|
||||||
|
break;
|
||||||
|
case STATE_PROXY_RESOLVE_COMPLETE:
|
||||||
|
rv = DoProxyResolveComplete(rv);
|
||||||
|
break;
|
||||||
|
case STATE_INIT_CONNECTION:
|
||||||
|
DCHECK_EQ(net::OK, rv);
|
||||||
|
rv = DoInitConnection();
|
||||||
|
break;
|
||||||
|
case STATE_INIT_CONNECTION_COMPLETE:
|
||||||
|
rv = DoInitConnectionComplete(rv);
|
||||||
|
break;
|
||||||
|
case STATE_RESTART_TUNNEL_AUTH:
|
||||||
|
rv = DoRestartTunnelAuth(rv);
|
||||||
|
break;
|
||||||
|
case STATE_RESTART_TUNNEL_AUTH_COMPLETE:
|
||||||
|
rv = DoRestartTunnelAuthComplete(rv);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED() << "bad state";
|
||||||
|
rv = net::ERR_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (rv != net::ERR_IO_PENDING && next_state_ != STATE_NONE);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProxyResolvingClientSocket::DoProxyResolve() {
|
||||||
|
next_state_ = STATE_PROXY_RESOLVE_COMPLETE;
|
||||||
|
// TODO(xunjieli): Having a null ProxyDelegate is bad. Figure out how to
|
||||||
|
// interact with the new interface for proxy delegate.
|
||||||
|
// https://crbug.com/793071.
|
||||||
|
// base::Unretained(this) is safe because resolution request is canceled when
|
||||||
|
// |proxy_resolve_request_| is destroyed.
|
||||||
|
return network_session_->proxy_resolution_service()->ResolveProxy(
|
||||||
|
url_, "POST", &proxy_info_,
|
||||||
|
base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
|
||||||
|
base::Unretained(this)),
|
||||||
|
&proxy_resolve_request_, nullptr /*proxy_delegate*/, net_log_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProxyResolvingClientSocket::DoProxyResolveComplete(int result) {
|
||||||
|
proxy_resolve_request_ = nullptr;
|
||||||
|
if (result == net::OK) {
|
||||||
|
next_state_ = STATE_INIT_CONNECTION;
|
||||||
// Removes unsupported proxies from the list. Currently, this removes
|
// Removes unsupported proxies from the list. Currently, this removes
|
||||||
// just the SCHEME_QUIC proxy, which doesn't yet support tunneling.
|
// just the SCHEME_QUIC proxy, which doesn't yet support tunneling.
|
||||||
// TODO(xunjieli): Allow QUIC proxy once it supports tunneling.
|
// TODO(xunjieli): Allow QUIC proxy once it supports tunneling.
|
||||||
@@ -217,82 +268,119 @@ void ProxyResolvingClientSocket::ConnectToProxy(int net_error) {
|
|||||||
if (proxy_info_.is_empty()) {
|
if (proxy_info_.is_empty()) {
|
||||||
// No proxies/direct to choose from. This happens when we don't support
|
// No proxies/direct to choose from. This happens when we don't support
|
||||||
// any of the proxies in the returned list.
|
// any of the proxies in the returned list.
|
||||||
net_error = net::ERR_NO_SUPPORTED_PROXIES;
|
result = net::ERR_NO_SUPPORTED_PROXIES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (net_error != net::OK) {
|
int ProxyResolvingClientSocket::DoInitConnection() {
|
||||||
CloseTransportSocket();
|
DCHECK(!socket_handle_->socket());
|
||||||
base::ResetAndReturn(&user_connect_callback_).Run(net_error);
|
|
||||||
return;
|
next_state_ = STATE_INIT_CONNECTION_COMPLETE;
|
||||||
}
|
|
||||||
|
|
||||||
transport_.reset(new net::ClientSocketHandle);
|
|
||||||
// Now that the proxy is resolved, issue a socket connect.
|
// Now that the proxy is resolved, issue a socket connect.
|
||||||
net::HostPortPair host_port_pair = net::HostPortPair::FromURL(url_);
|
net::HostPortPair host_port_pair = net::HostPortPair::FromURL(url_);
|
||||||
// Ignore socket limit set by socket pool for this type of socket.
|
// Ignore socket limit set by socket pool for this type of socket.
|
||||||
int request_load_flags = net::LOAD_IGNORE_LIMITS;
|
int request_load_flags = net::LOAD_IGNORE_LIMITS;
|
||||||
net::RequestPriority request_priority = net::MAXIMUM_PRIORITY;
|
net::RequestPriority request_priority = net::MAXIMUM_PRIORITY;
|
||||||
|
|
||||||
net_error = net::InitSocketHandleForRawConnect(
|
// base::Unretained(this) is safe because request is canceled when
|
||||||
|
// |socket_handle_| is destroyed.
|
||||||
|
if (use_tls_) {
|
||||||
|
return net::InitSocketHandleForTlsConnect(
|
||||||
|
host_port_pair, network_session_, request_load_flags, request_priority,
|
||||||
|
proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED,
|
||||||
|
net_log_, socket_handle_.get(),
|
||||||
|
base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
|
||||||
|
base::Unretained(this)));
|
||||||
|
}
|
||||||
|
return net::InitSocketHandleForRawConnect(
|
||||||
host_port_pair, network_session_, request_load_flags, request_priority,
|
host_port_pair, network_session_, request_load_flags, request_priority,
|
||||||
proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED,
|
proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED,
|
||||||
net_log_, transport_.get(),
|
net_log_, socket_handle_.get(),
|
||||||
base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxyDone,
|
base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
|
||||||
base::Unretained(this)));
|
base::Unretained(this)));
|
||||||
if (net_error != net::ERR_IO_PENDING) {
|
|
||||||
// Since this method is always called asynchronously. it is OK to call
|
|
||||||
// ConnectToProxyDone synchronously.
|
|
||||||
ConnectToProxyDone(net_error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyResolvingClientSocket::ConnectToProxyDone(int net_error) {
|
int ProxyResolvingClientSocket::DoInitConnectionComplete(int result) {
|
||||||
if (net_error != net::OK) {
|
if (result == net::ERR_PROXY_AUTH_REQUESTED) {
|
||||||
// If the connection fails, try another proxy.
|
if (use_tls_) {
|
||||||
net_error = ReconsiderProxyAfterError(net_error);
|
// Put the in-progress HttpProxyClientSocket into |socket_handle_| to
|
||||||
|
// do tunnel auth. After auth completes, it's important to reset
|
||||||
|
// |socket_handle_|, so it doesn't have a HttpProxyClientSocket when the
|
||||||
|
// code expects an SSLClientSocket. The tunnel restart code is careful to
|
||||||
|
// put it back to the socket pool before returning control to the rest of
|
||||||
|
// this class.
|
||||||
|
socket_handle_.reset(
|
||||||
|
socket_handle_->release_pending_http_proxy_connection());
|
||||||
|
}
|
||||||
|
next_state_ = STATE_RESTART_TUNNEL_AUTH;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != net::OK) {
|
||||||
// ReconsiderProxyAfterError either returns an error (in which case it is
|
// ReconsiderProxyAfterError either returns an error (in which case it is
|
||||||
// not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering
|
// not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering
|
||||||
// another proxy.
|
// another proxy.
|
||||||
DCHECK_NE(net_error, net::OK);
|
return ReconsiderProxyAfterError(result);
|
||||||
if (net_error == net::ERR_IO_PENDING) {
|
|
||||||
// Proxy reconsideration pending. Return.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CloseTransportSocket();
|
|
||||||
} else {
|
|
||||||
network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_,
|
|
||||||
nullptr);
|
|
||||||
}
|
}
|
||||||
base::ResetAndReturn(&user_connect_callback_).Run(net_error);
|
|
||||||
|
network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_,
|
||||||
|
nullptr);
|
||||||
|
return net::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyResolvingClientSocket::CloseTransportSocket() {
|
int ProxyResolvingClientSocket::DoRestartTunnelAuth(int result) {
|
||||||
if (transport_.get() && transport_->socket())
|
DCHECK_EQ(net::ERR_PROXY_AUTH_REQUESTED, result);
|
||||||
transport_->socket()->Disconnect();
|
|
||||||
transport_.reset();
|
net::ProxyClientSocket* proxy_socket =
|
||||||
|
static_cast<net::ProxyClientSocket*>(socket_handle_->socket());
|
||||||
|
|
||||||
|
if (proxy_socket->GetAuthController() &&
|
||||||
|
proxy_socket->GetAuthController()->HaveAuth()) {
|
||||||
|
next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
|
||||||
|
// base::Unretained(this) is safe because |proxy_socket| is owned by this.
|
||||||
|
return proxy_socket->RestartWithAuth(base::BindRepeating(
|
||||||
|
&ProxyResolvingClientSocket::OnIOComplete, base::Unretained(this)));
|
||||||
|
}
|
||||||
|
// This socket is unusable if the underlying authentication handler doesn't
|
||||||
|
// already have credentials. It is possible to overcome this hurdle and
|
||||||
|
// finish the handshake if this class exposes an interface for an embedder to
|
||||||
|
// supply credentials.
|
||||||
|
CloseSocket(true /*close_connection*/);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProxyResolvingClientSocket::DoRestartTunnelAuthComplete(int result) {
|
||||||
|
if (result == net::ERR_PROXY_AUTH_REQUESTED) {
|
||||||
|
// Handle multi-round auth challenge.
|
||||||
|
next_state_ = STATE_RESTART_TUNNEL_AUTH;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (result == net::OK) {
|
||||||
|
CloseSocket(false /*close_connection*/);
|
||||||
|
// Now that the HttpProxyClientSocket is connected, release it as an idle
|
||||||
|
// socket into the pool and start the connection process from the beginning.
|
||||||
|
next_state_ = STATE_INIT_CONNECTION;
|
||||||
|
return net::OK;
|
||||||
|
}
|
||||||
|
CloseSocket(true /*close_connection*/);
|
||||||
|
return ReconsiderProxyAfterError(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyResolvingClientSocket::CloseSocket(bool close_connection) {
|
||||||
|
if (close_connection && socket_handle_->socket())
|
||||||
|
socket_handle_->socket()->Disconnect();
|
||||||
|
socket_handle_->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method reconsiders the proxy on certain errors. If it does
|
|
||||||
// reconsider a proxy it always returns ERR_IO_PENDING and posts a call to
|
|
||||||
// ConnectToProxy with the result of the reconsideration.
|
|
||||||
int ProxyResolvingClientSocket::ReconsiderProxyAfterError(int error) {
|
int ProxyResolvingClientSocket::ReconsiderProxyAfterError(int error) {
|
||||||
|
DCHECK(!socket_handle_->socket());
|
||||||
DCHECK(!proxy_resolve_request_);
|
DCHECK(!proxy_resolve_request_);
|
||||||
DCHECK_NE(error, net::OK);
|
DCHECK_NE(error, net::OK);
|
||||||
DCHECK_NE(error, net::ERR_IO_PENDING);
|
DCHECK_NE(error, net::ERR_IO_PENDING);
|
||||||
|
|
||||||
if (error == net::ERR_PROXY_AUTH_REQUESTED) {
|
|
||||||
net::ProxyClientSocket* proxy_socket =
|
|
||||||
static_cast<net::ProxyClientSocket*>(transport_->socket());
|
|
||||||
|
|
||||||
if (proxy_socket->GetAuthController()->HaveAuth()) {
|
|
||||||
return proxy_socket->RestartWithAuth(
|
|
||||||
base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxyDone,
|
|
||||||
base::Unretained(this)));
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the error was a proxy failure.
|
// Check if the error was a proxy failure.
|
||||||
if (!net::CanFalloverToNextProxy(&error))
|
if (!net::CanFalloverToNextProxy(&error))
|
||||||
return error;
|
return error;
|
||||||
@@ -307,14 +395,8 @@ int ProxyResolvingClientSocket::ReconsiderProxyAfterError(int error) {
|
|||||||
if (!proxy_info_.Fallback(error, net_log_))
|
if (!proxy_info_.Fallback(error, net_log_))
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
CloseTransportSocket();
|
next_state_ = STATE_INIT_CONNECTION;
|
||||||
|
return net::OK;
|
||||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
|
||||||
FROM_HERE, base::BindOnce(&ProxyResolvingClientSocket::ConnectToProxy,
|
|
||||||
weak_factory_.GetWeakPtr(), net::OK));
|
|
||||||
// Since we potentially have another try to go, set the return code code to
|
|
||||||
// ERR_IO_PENDING.
|
|
||||||
return net::ERR_IO_PENDING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace network
|
} // namespace network
|
||||||
|
@@ -50,10 +50,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocket
|
|||||||
// any sensitive data (like embedded usernames and passwords), and local data
|
// any sensitive data (like embedded usernames and passwords), and local data
|
||||||
// (i.e. reference fragment) will be sanitized by
|
// (i.e. reference fragment) will be sanitized by
|
||||||
// net::ProxyResolutionService::ResolveProxyHelper() before the url is
|
// net::ProxyResolutionService::ResolveProxyHelper() before the url is
|
||||||
// disclosed to the proxy. |network_session| must outlive |this|.
|
// disclosed to the proxy. If |use_tls|, this will try to do a tls connect
|
||||||
|
// instead of a regular tcp connect. |network_session| must outlive |this|.
|
||||||
ProxyResolvingClientSocket(net::HttpNetworkSession* network_session,
|
ProxyResolvingClientSocket(net::HttpNetworkSession* network_session,
|
||||||
const net::SSLConfig& ssl_config,
|
const net::SSLConfig& ssl_config,
|
||||||
const GURL& url);
|
const GURL& url,
|
||||||
|
bool use_tls);
|
||||||
~ProxyResolvingClientSocket() override;
|
~ProxyResolvingClientSocket() override;
|
||||||
|
|
||||||
// net::StreamSocket implementation.
|
// net::StreamSocket implementation.
|
||||||
@@ -88,29 +90,53 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocket
|
|||||||
void ApplySocketTag(const net::SocketTag& tag) override;
|
void ApplySocketTag(const net::SocketTag& tag) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum State {
|
||||||
|
STATE_PROXY_RESOLVE,
|
||||||
|
STATE_PROXY_RESOLVE_COMPLETE,
|
||||||
|
STATE_INIT_CONNECTION,
|
||||||
|
STATE_INIT_CONNECTION_COMPLETE,
|
||||||
|
STATE_RESTART_TUNNEL_AUTH,
|
||||||
|
STATE_RESTART_TUNNEL_AUTH_COMPLETE,
|
||||||
|
STATE_DONE,
|
||||||
|
STATE_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ConnectToProxy);
|
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ConnectToProxy);
|
||||||
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ReadWriteErrors);
|
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ReadWriteErrors);
|
||||||
|
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest,
|
||||||
|
ResetSocketAfterTunnelAuth);
|
||||||
|
|
||||||
void ConnectToProxy(int net_error);
|
void OnIOComplete(int result);
|
||||||
void ConnectToProxyDone(int net_error);
|
|
||||||
|
int DoLoop(int result);
|
||||||
|
int DoProxyResolve();
|
||||||
|
int DoProxyResolveComplete(int result);
|
||||||
|
int DoInitConnection();
|
||||||
|
int DoInitConnectionComplete(int result);
|
||||||
|
int DoRestartTunnelAuth(int result);
|
||||||
|
int DoRestartTunnelAuthComplete(int result);
|
||||||
|
|
||||||
|
void CloseSocket(bool close_connection);
|
||||||
|
|
||||||
void CloseTransportSocket();
|
|
||||||
int ReconsiderProxyAfterError(int error);
|
int ReconsiderProxyAfterError(int error);
|
||||||
|
|
||||||
net::HttpNetworkSession* network_session_;
|
net::HttpNetworkSession* network_session_;
|
||||||
|
|
||||||
// The transport socket.
|
std::unique_ptr<net::ClientSocketHandle> socket_handle_;
|
||||||
std::unique_ptr<net::ClientSocketHandle> transport_;
|
|
||||||
|
|
||||||
const net::SSLConfig ssl_config_;
|
const net::SSLConfig ssl_config_;
|
||||||
net::ProxyResolutionService::Request* proxy_resolve_request_;
|
net::ProxyResolutionService::Request* proxy_resolve_request_;
|
||||||
net::ProxyInfo proxy_info_;
|
net::ProxyInfo proxy_info_;
|
||||||
const GURL url_;
|
const GURL url_;
|
||||||
|
const bool use_tls_;
|
||||||
|
|
||||||
net::NetLogWithSource net_log_;
|
net::NetLogWithSource net_log_;
|
||||||
|
|
||||||
// The callback passed to Connect().
|
// The callback passed to Connect().
|
||||||
net::CompletionCallback user_connect_callback_;
|
net::CompletionCallback user_connect_callback_;
|
||||||
|
|
||||||
|
State next_state_;
|
||||||
|
|
||||||
base::WeakPtrFactory<ProxyResolvingClientSocket> weak_factory_;
|
base::WeakPtrFactory<ProxyResolvingClientSocket> weak_factory_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ProxyResolvingClientSocket);
|
DISALLOW_COPY_AND_ASSIGN(ProxyResolvingClientSocket);
|
||||||
|
@@ -70,7 +70,8 @@ ProxyResolvingClientSocketFactory::~ProxyResolvingClientSocketFactory() {}
|
|||||||
std::unique_ptr<ProxyResolvingClientSocket>
|
std::unique_ptr<ProxyResolvingClientSocket>
|
||||||
ProxyResolvingClientSocketFactory::CreateSocket(
|
ProxyResolvingClientSocketFactory::CreateSocket(
|
||||||
const net::SSLConfig& ssl_config,
|
const net::SSLConfig& ssl_config,
|
||||||
const GURL& url) {
|
const GURL& url,
|
||||||
|
bool use_tls) {
|
||||||
// |request_context|'s HttpAuthCache might have updates. For example, a user
|
// |request_context|'s HttpAuthCache might have updates. For example, a user
|
||||||
// might have since entered proxy credentials. Clear the http auth of
|
// might have since entered proxy credentials. Clear the http auth of
|
||||||
// |network_session_| and copy over the data from |request_context|'s auth
|
// |network_session_| and copy over the data from |request_context|'s auth
|
||||||
@@ -83,7 +84,7 @@ ProxyResolvingClientSocketFactory::CreateSocket(
|
|||||||
->http_auth_cache();
|
->http_auth_cache();
|
||||||
network_session_->http_auth_cache()->UpdateAllFrom(*other_auth_cache);
|
network_session_->http_auth_cache()->UpdateAllFrom(*other_auth_cache);
|
||||||
return std::make_unique<ProxyResolvingClientSocket>(network_session_.get(),
|
return std::make_unique<ProxyResolvingClientSocket>(network_session_.get(),
|
||||||
ssl_config, url);
|
ssl_config, url, use_tls);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace network
|
} // namespace network
|
||||||
|
@@ -39,10 +39,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocketFactory {
|
|||||||
// doesn't need to explicitly sanitize the url, any sensitive data (like
|
// doesn't need to explicitly sanitize the url, any sensitive data (like
|
||||||
// embedded usernames and passwords), and local data (i.e. reference fragment)
|
// embedded usernames and passwords), and local data (i.e. reference fragment)
|
||||||
// will be sanitized by net::ProxyService::ResolveProxyHelper() before the url
|
// will be sanitized by net::ProxyService::ResolveProxyHelper() before the url
|
||||||
// is disclosed to the proxy.
|
// is disclosed to the proxy. If |use_tls|, tls connect will be used in
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> CreateSocket(
|
// addition to tcp connect.
|
||||||
const net::SSLConfig& ssl_config,
|
std::unique_ptr<ProxyResolvingClientSocket>
|
||||||
const GURL& url);
|
CreateSocket(const net::SSLConfig& ssl_config, const GURL& url, bool use_tls);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<net::HttpNetworkSession> network_session_;
|
std::unique_ptr<net::HttpNetworkSession> network_session_;
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include "net/dns/mock_host_resolver.h"
|
#include "net/dns/mock_host_resolver.h"
|
||||||
#include "net/proxy_resolution/mock_proxy_resolver.h"
|
#include "net/proxy_resolution/mock_proxy_resolver.h"
|
||||||
#include "net/proxy_resolution/proxy_config_service_fixed.h"
|
#include "net/proxy_resolution/proxy_config_service_fixed.h"
|
||||||
|
#include "net/proxy_resolution/proxy_config_with_annotation.h"
|
||||||
#include "net/proxy_resolution/proxy_resolution_service.h"
|
#include "net/proxy_resolution/proxy_resolution_service.h"
|
||||||
#include "net/socket/client_socket_pool_manager.h"
|
#include "net/socket/client_socket_pool_manager.h"
|
||||||
#include "net/socket/socket_test_util.h"
|
#include "net/socket/socket_test_util.h"
|
||||||
@@ -50,10 +51,13 @@ class TestURLRequestContextWithProxy : public net::TestURLRequestContext {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class ProxyResolvingClientSocketTest : public testing::Test {
|
class ProxyResolvingClientSocketTest
|
||||||
|
: public testing::Test,
|
||||||
|
public testing::WithParamInterface<bool> {
|
||||||
protected:
|
protected:
|
||||||
ProxyResolvingClientSocketTest()
|
ProxyResolvingClientSocketTest()
|
||||||
: context_with_proxy_("PROXY bad:99; PROXY maybe:80; DIRECT") {}
|
: context_with_proxy_("PROXY bad:99; PROXY maybe:80; DIRECT"),
|
||||||
|
use_tls_(GetParam()) {}
|
||||||
|
|
||||||
~ProxyResolvingClientSocketTest() override {}
|
~ProxyResolvingClientSocketTest() override {}
|
||||||
|
|
||||||
@@ -65,12 +69,17 @@ class ProxyResolvingClientSocketTest : public testing::Test {
|
|||||||
|
|
||||||
base::test::ScopedTaskEnvironment scoped_task_environment_;
|
base::test::ScopedTaskEnvironment scoped_task_environment_;
|
||||||
TestURLRequestContextWithProxy context_with_proxy_;
|
TestURLRequestContextWithProxy context_with_proxy_;
|
||||||
|
const bool use_tls_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(/* no prefix */,
|
||||||
|
ProxyResolvingClientSocketTest,
|
||||||
|
::testing::Bool());
|
||||||
|
|
||||||
// Tests that the global socket pool limit
|
// Tests that the global socket pool limit
|
||||||
// (ClientSocketPoolManager::max_sockets_per_group) doesn't apply to this
|
// (ClientSocketPoolManager::max_sockets_per_group) doesn't apply to this
|
||||||
// type of sockets.
|
// type of sockets.
|
||||||
TEST_F(ProxyResolvingClientSocketTest, SocketLimitNotApply) {
|
TEST_P(ProxyResolvingClientSocketTest, SocketLimitNotApply) {
|
||||||
const int kNumSockets = net::ClientSocketPoolManager::max_sockets_per_group(
|
const int kNumSockets = net::ClientSocketPoolManager::max_sockets_per_group(
|
||||||
net::HttpNetworkSession::NORMAL_SOCKET_POOL) +
|
net::HttpNetworkSession::NORMAL_SOCKET_POOL) +
|
||||||
10;
|
10;
|
||||||
@@ -82,11 +91,15 @@ TEST_F(ProxyResolvingClientSocketTest, SocketLimitNotApply) {
|
|||||||
"Proxy-Connection: keep-alive\r\n\r\n")};
|
"Proxy-Connection: keep-alive\r\n\r\n")};
|
||||||
net::MockRead reads[] = {net::MockRead("HTTP/1.1 200 Success\r\n\r\n")};
|
net::MockRead reads[] = {net::MockRead("HTTP/1.1 200 Success\r\n\r\n")};
|
||||||
std::vector<std::unique_ptr<net::StaticSocketDataProvider>> socket_data;
|
std::vector<std::unique_ptr<net::StaticSocketDataProvider>> socket_data;
|
||||||
|
std::vector<std::unique_ptr<net::SSLSocketDataProvider>> ssl_data;
|
||||||
for (int i = 0; i < kNumSockets; ++i) {
|
for (int i = 0; i < kNumSockets; ++i) {
|
||||||
socket_data.push_back(std::make_unique<net::StaticSocketDataProvider>(
|
socket_data.push_back(std::make_unique<net::StaticSocketDataProvider>(
|
||||||
reads, arraysize(reads), writes, arraysize(writes)));
|
reads, arraysize(reads), writes, arraysize(writes)));
|
||||||
socket_data[i]->set_connect_data(net::MockConnect(net::ASYNC, net::OK));
|
socket_data[i]->set_connect_data(net::MockConnect(net::ASYNC, net::OK));
|
||||||
socket_factory.AddSocketDataProvider(socket_data[i].get());
|
socket_factory.AddSocketDataProvider(socket_data[i].get());
|
||||||
|
ssl_data.push_back(
|
||||||
|
std::make_unique<net::SSLSocketDataProvider>(net::ASYNC, net::OK));
|
||||||
|
socket_factory.AddSSLSocketDataProvider(ssl_data[i].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
@@ -95,7 +108,7 @@ TEST_F(ProxyResolvingClientSocketTest, SocketLimitNotApply) {
|
|||||||
for (int i = 0; i < kNumSockets; ++i) {
|
for (int i = 0; i < kNumSockets; ++i) {
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
||||||
@@ -104,10 +117,11 @@ TEST_F(ProxyResolvingClientSocketTest, SocketLimitNotApply) {
|
|||||||
for (int i = 0; i < kNumSockets; ++i) {
|
for (int i = 0; i < kNumSockets; ++i) {
|
||||||
EXPECT_TRUE(socket_data[i]->AllReadDataConsumed());
|
EXPECT_TRUE(socket_data[i]->AllReadDataConsumed());
|
||||||
EXPECT_TRUE(socket_data[i]->AllWriteDataConsumed());
|
EXPECT_TRUE(socket_data[i]->AllWriteDataConsumed());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_data[i]->ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ProxyResolvingClientSocketTest, ConnectError) {
|
TEST_P(ProxyResolvingClientSocketTest, ConnectError) {
|
||||||
const struct TestData {
|
const struct TestData {
|
||||||
// Whether the error is encountered synchronously as opposed to
|
// Whether the error is encountered synchronously as opposed to
|
||||||
// asynchronously.
|
// asynchronously.
|
||||||
@@ -136,7 +150,7 @@ TEST_F(ProxyResolvingClientSocketTest, ConnectError) {
|
|||||||
&socket_factory, context.get());
|
&socket_factory, context.get());
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
||||||
@@ -152,7 +166,7 @@ TEST_F(ProxyResolvingClientSocketTest, ConnectError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the connection is established to the proxy.
|
// Tests that the connection is established to the proxy.
|
||||||
TEST_F(ProxyResolvingClientSocketTest, ConnectToProxy) {
|
TEST_P(ProxyResolvingClientSocketTest, ConnectToProxy) {
|
||||||
const GURL kDestination("https://example.com:443");
|
const GURL kDestination("https://example.com:443");
|
||||||
// Use a different port than that of |kDestination|.
|
// Use a different port than that of |kDestination|.
|
||||||
const int kProxyPort = 8009;
|
const int kProxyPort = 8009;
|
||||||
@@ -171,6 +185,9 @@ TEST_F(ProxyResolvingClientSocketTest, ConnectToProxy) {
|
|||||||
net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
|
net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
|
||||||
"Host: example.com:443\r\n"
|
"Host: example.com:443\r\n"
|
||||||
"Proxy-Connection: keep-alive\r\n\r\n")};
|
"Proxy-Connection: keep-alive\r\n\r\n")};
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
net::StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
|
net::StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
|
||||||
arraysize(writes));
|
arraysize(writes));
|
||||||
net::IPEndPoint remote_addr(net::IPAddress(127, 0, 0, 1),
|
net::IPEndPoint remote_addr(net::IPAddress(127, 0, 0, 1),
|
||||||
@@ -183,7 +200,7 @@ TEST_F(ProxyResolvingClientSocketTest, ConnectToProxy) {
|
|||||||
&socket_factory, context.get());
|
&socket_factory, context.get());
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
||||||
@@ -196,16 +213,42 @@ TEST_F(ProxyResolvingClientSocketTest, ConnectToProxy) {
|
|||||||
// proxy, so call private member to make sure address is correct.
|
// proxy, so call private member to make sure address is correct.
|
||||||
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, status);
|
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, status);
|
||||||
status =
|
status =
|
||||||
socket->transport_->socket()->GetPeerAddress(&actual_remote_addr);
|
socket->socket_handle_->socket()->GetPeerAddress(&actual_remote_addr);
|
||||||
}
|
}
|
||||||
EXPECT_EQ(net::OK, status);
|
EXPECT_EQ(net::OK, status);
|
||||||
EXPECT_EQ(remote_addr.ToString(), actual_remote_addr.ToString());
|
EXPECT_EQ(remote_addr.ToString(), actual_remote_addr.ToString());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(ProxyResolvingClientSocketTest, SocketDestroyedBeforeConnectComplete) {
|
||||||
|
const GURL kDestination("https://example.com:443");
|
||||||
|
net::StaticSocketDataProvider socket_data;
|
||||||
|
socket_data.set_connect_data(net::MockConnect(net::ASYNC, net::OK));
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
|
||||||
|
net::MockClientSocketFactory socket_factory;
|
||||||
|
socket_factory.AddSocketDataProvider(&socket_data);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
|
auto context = std::make_unique<TestURLRequestContextWithProxy>("DIRECT");
|
||||||
|
|
||||||
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
|
&socket_factory, context.get());
|
||||||
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
|
kDestination, use_tls_);
|
||||||
|
net::TestCompletionCallback callback;
|
||||||
|
int status = socket->Connect(callback.callback());
|
||||||
|
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
||||||
|
socket.reset();
|
||||||
|
// Makes sure there is no UAF and socket request is canceled properly.
|
||||||
|
base::RunLoop().RunUntilIdle();
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that connection itself is successful but an error occurred during
|
// Tests that connection itself is successful but an error occurred during
|
||||||
// Read()/Write().
|
// Read()/Write().
|
||||||
TEST_F(ProxyResolvingClientSocketTest, ReadWriteErrors) {
|
TEST_P(ProxyResolvingClientSocketTest, ReadWriteErrors) {
|
||||||
const GURL kDestination("http://example.com:80");
|
const GURL kDestination("http://example.com:80");
|
||||||
const struct TestData {
|
const struct TestData {
|
||||||
// Whether there is a read error as opposed to a write error.
|
// Whether there is a read error as opposed to a write error.
|
||||||
@@ -254,12 +297,14 @@ TEST_F(ProxyResolvingClientSocketTest, ReadWriteErrors) {
|
|||||||
socket_data.set_connect_data(
|
socket_data.set_connect_data(
|
||||||
net::MockConnect(net::ASYNC, net::OK, remote_addr));
|
net::MockConnect(net::ASYNC, net::OK, remote_addr));
|
||||||
net::MockClientSocketFactory socket_factory;
|
net::MockClientSocketFactory socket_factory;
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
socket_factory.AddSocketDataProvider(&socket_data);
|
socket_factory.AddSocketDataProvider(&socket_data);
|
||||||
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
&socket_factory, context.get());
|
&socket_factory, context.get());
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
||||||
@@ -272,7 +317,7 @@ TEST_F(ProxyResolvingClientSocketTest, ReadWriteErrors) {
|
|||||||
// proxy, so call private member to make sure address is correct.
|
// proxy, so call private member to make sure address is correct.
|
||||||
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, status);
|
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, status);
|
||||||
status =
|
status =
|
||||||
socket->transport_->socket()->GetPeerAddress(&actual_remote_addr);
|
socket->socket_handle_->socket()->GetPeerAddress(&actual_remote_addr);
|
||||||
}
|
}
|
||||||
EXPECT_EQ(net::OK, status);
|
EXPECT_EQ(net::OK, status);
|
||||||
EXPECT_EQ(remote_addr.ToString(), actual_remote_addr.ToString());
|
EXPECT_EQ(remote_addr.ToString(), actual_remote_addr.ToString());
|
||||||
@@ -298,10 +343,11 @@ TEST_F(ProxyResolvingClientSocketTest, ReadWriteErrors) {
|
|||||||
EXPECT_EQ(net::ERR_FAILED, read_write_result);
|
EXPECT_EQ(net::ERR_FAILED, read_write_result);
|
||||||
EXPECT_TRUE(socket_data.AllReadDataConsumed());
|
EXPECT_TRUE(socket_data.AllReadDataConsumed());
|
||||||
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
|
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ProxyResolvingClientSocketTest, ReportsBadProxies) {
|
TEST_P(ProxyResolvingClientSocketTest, ReportsBadProxies) {
|
||||||
const GURL kDestination("https://example.com:443");
|
const GURL kDestination("https://example.com:443");
|
||||||
net::MockClientSocketFactory socket_factory;
|
net::MockClientSocketFactory socket_factory;
|
||||||
|
|
||||||
@@ -319,12 +365,14 @@ TEST_F(ProxyResolvingClientSocketTest, ReportsBadProxies) {
|
|||||||
arraysize(writes));
|
arraysize(writes));
|
||||||
socket_data2.set_connect_data(net::MockConnect(net::ASYNC, net::OK));
|
socket_data2.set_connect_data(net::MockConnect(net::ASYNC, net::OK));
|
||||||
socket_factory.AddSocketDataProvider(&socket_data2);
|
socket_factory.AddSocketDataProvider(&socket_data2);
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
&socket_factory, &context_with_proxy_);
|
&socket_factory, &context_with_proxy_);
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
||||||
@@ -337,9 +385,127 @@ TEST_F(ProxyResolvingClientSocketTest, ReportsBadProxies) {
|
|||||||
EXPECT_EQ(1u, retry_info.size());
|
EXPECT_EQ(1u, retry_info.size());
|
||||||
net::ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99");
|
net::ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99");
|
||||||
EXPECT_TRUE(iter != retry_info.end());
|
EXPECT_TRUE(iter != retry_info.end());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) {
|
TEST_P(ProxyResolvingClientSocketTest, ResetSocketAfterTunnelAuth) {
|
||||||
|
net::MockClientSocketFactory socket_factory;
|
||||||
|
const GURL kDestination("https://example.com:443");
|
||||||
|
|
||||||
|
// Initial connect without credentials. The server responds with a 407.
|
||||||
|
net::MockWrite kConnectWrites1[] = {
|
||||||
|
net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
|
||||||
|
"Host: example.com:443\r\n"
|
||||||
|
"Proxy-Connection: keep-alive\r\n"
|
||||||
|
"\r\n")};
|
||||||
|
net::MockRead kConnectReads1[] = {
|
||||||
|
net::MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
|
||||||
|
"Proxy-Authenticate: Basic realm=\"test_realm\"\r\n"
|
||||||
|
"\r\n")};
|
||||||
|
|
||||||
|
net::StaticSocketDataProvider kSocketData1(
|
||||||
|
kConnectReads1, arraysize(kConnectReads1), kConnectWrites1,
|
||||||
|
arraysize(kConnectWrites1));
|
||||||
|
socket_factory.AddSocketDataProvider(&kSocketData1);
|
||||||
|
|
||||||
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
|
&socket_factory, &context_with_proxy_);
|
||||||
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
|
kDestination, use_tls_);
|
||||||
|
net::TestCompletionCallback callback;
|
||||||
|
int status = socket->Connect(callback.callback());
|
||||||
|
EXPECT_THAT(callback.GetResult(status),
|
||||||
|
net::test::IsError(net::ERR_PROXY_AUTH_REQUESTED));
|
||||||
|
// Make sure |socket_handle_| is closed appropriately.
|
||||||
|
EXPECT_FALSE(socket->socket_handle_->socket());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(ProxyResolvingClientSocketTest, MultiroundAuth) {
|
||||||
|
net::MockClientSocketFactory socket_factory;
|
||||||
|
const GURL kDestination("https://example.com:443");
|
||||||
|
|
||||||
|
// Initial connect without credentials. The server responds with a 407.
|
||||||
|
net::MockWrite kConnectWrites1[] = {
|
||||||
|
net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
|
||||||
|
"Host: example.com:443\r\n"
|
||||||
|
"Proxy-Connection: keep-alive\r\n"
|
||||||
|
"\r\n")};
|
||||||
|
net::MockRead kConnectReads1[] = {
|
||||||
|
net::MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
|
||||||
|
"Proxy-Authenticate: Basic realm=\"test_realm\"\r\n"
|
||||||
|
"\r\n")};
|
||||||
|
|
||||||
|
// Second connect attempt includes credentials for test_realm.
|
||||||
|
net::MockWrite kConnectWrites2[] = {
|
||||||
|
net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
|
||||||
|
"Host: example.com:443\r\n"
|
||||||
|
"Proxy-Connection: keep-alive\r\n"
|
||||||
|
"Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==\r\n"
|
||||||
|
"\r\n")};
|
||||||
|
net::MockRead kConnectReads2[] = {
|
||||||
|
net::MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
|
||||||
|
"Proxy-Authenticate: Basic realm=\"test_realm2\"\r\n"
|
||||||
|
"\r\n")};
|
||||||
|
|
||||||
|
// Third connect attempt include credentials for test_realm2.
|
||||||
|
net::MockWrite kConnectWrites3[] = {
|
||||||
|
net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
|
||||||
|
"Host: example.com:443\r\n"
|
||||||
|
"Proxy-Connection: keep-alive\r\n"
|
||||||
|
"Proxy-Authorization: Basic dXNlcjI6cGFzc3dvcmQy\r\n"
|
||||||
|
"\r\n")};
|
||||||
|
net::MockRead kConnectReads3[] = {
|
||||||
|
net::MockRead("HTTP/1.1 200 Success\r\n\r\n")};
|
||||||
|
|
||||||
|
net::StaticSocketDataProvider kSocketData1(
|
||||||
|
kConnectReads1, arraysize(kConnectReads1), kConnectWrites1,
|
||||||
|
arraysize(kConnectWrites1));
|
||||||
|
socket_factory.AddSocketDataProvider(&kSocketData1);
|
||||||
|
|
||||||
|
net::StaticSocketDataProvider kSocketData2(
|
||||||
|
kConnectReads2, arraysize(kConnectReads2), kConnectWrites2,
|
||||||
|
arraysize(kConnectWrites2));
|
||||||
|
socket_factory.AddSocketDataProvider(&kSocketData2);
|
||||||
|
net::StaticSocketDataProvider kSocketData3(
|
||||||
|
kConnectReads3, arraysize(kConnectReads3), kConnectWrites3,
|
||||||
|
arraysize(kConnectWrites3));
|
||||||
|
socket_factory.AddSocketDataProvider(&kSocketData3);
|
||||||
|
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
|
net::HttpAuthCache* auth_cache =
|
||||||
|
context_with_proxy_.http_transaction_factory()
|
||||||
|
->GetSession()
|
||||||
|
->http_auth_cache();
|
||||||
|
|
||||||
|
auth_cache->Add(GURL("http://bad:99"), "test_realm",
|
||||||
|
net::HttpAuth::AUTH_SCHEME_BASIC,
|
||||||
|
"Basic realm=\"test_realm\"",
|
||||||
|
net::AuthCredentials(base::ASCIIToUTF16("user"),
|
||||||
|
base::ASCIIToUTF16("password")),
|
||||||
|
std::string());
|
||||||
|
|
||||||
|
auth_cache->Add(GURL("http://bad:99"), "test_realm2",
|
||||||
|
net::HttpAuth::AUTH_SCHEME_BASIC,
|
||||||
|
"Basic realm=\"test_realm2\"",
|
||||||
|
net::AuthCredentials(base::ASCIIToUTF16("user2"),
|
||||||
|
base::ASCIIToUTF16("password2")),
|
||||||
|
std::string());
|
||||||
|
|
||||||
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
|
&socket_factory, &context_with_proxy_);
|
||||||
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
|
kDestination, use_tls_);
|
||||||
|
net::TestCompletionCallback callback;
|
||||||
|
int status = socket->Connect(callback.callback());
|
||||||
|
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) {
|
||||||
net::MockClientSocketFactory socket_factory;
|
net::MockClientSocketFactory socket_factory;
|
||||||
const GURL kDestination("https://example.com:443");
|
const GURL kDestination("https://example.com:443");
|
||||||
|
|
||||||
@@ -373,6 +539,8 @@ TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) {
|
|||||||
kConnectReads2, arraysize(kConnectReads2), kConnectWrites2,
|
kConnectReads2, arraysize(kConnectReads2), kConnectWrites2,
|
||||||
arraysize(kConnectWrites2));
|
arraysize(kConnectWrites2));
|
||||||
socket_factory.AddSocketDataProvider(&kSocketData2);
|
socket_factory.AddSocketDataProvider(&kSocketData2);
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
net::HttpAuthCache* auth_cache =
|
net::HttpAuthCache* auth_cache =
|
||||||
context_with_proxy_.http_transaction_factory()
|
context_with_proxy_.http_transaction_factory()
|
||||||
@@ -393,16 +561,17 @@ TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) {
|
|||||||
&socket_factory, &context_with_proxy_);
|
&socket_factory, &context_with_proxy_);
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that if HttpAuthCache is updated e.g through normal URLRequests,
|
// Make sure that if HttpAuthCache is updated e.g through normal URLRequests,
|
||||||
// ProxyResolvingClientSocketFactory uses the latest cache for creating new
|
// ProxyResolvingClientSocketFactory uses the latest cache for creating new
|
||||||
// sockets.
|
// sockets.
|
||||||
TEST_F(ProxyResolvingClientSocketTest, FactoryUsesLatestHTTPAuthCache) {
|
TEST_P(ProxyResolvingClientSocketTest, FactoryUsesLatestHTTPAuthCache) {
|
||||||
net::MockClientSocketFactory socket_factory;
|
net::MockClientSocketFactory socket_factory;
|
||||||
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
&socket_factory, &context_with_proxy_);
|
&socket_factory, &context_with_proxy_);
|
||||||
@@ -449,16 +618,19 @@ TEST_F(ProxyResolvingClientSocketTest, FactoryUsesLatestHTTPAuthCache) {
|
|||||||
kConnectReads, arraysize(kConnectReads), kConnectWrites,
|
kConnectReads, arraysize(kConnectReads), kConnectWrites,
|
||||||
arraysize(kConnectWrites));
|
arraysize(kConnectWrites));
|
||||||
socket_factory.AddSocketDataProvider(&kSocketData);
|
socket_factory.AddSocketDataProvider(&kSocketData);
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) {
|
TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) {
|
||||||
net::MockClientSocketFactory socket_factory;
|
net::MockClientSocketFactory socket_factory;
|
||||||
const GURL kDestination("https://example.com:443");
|
const GURL kDestination("https://example.com:443");
|
||||||
|
|
||||||
@@ -476,6 +648,8 @@ TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) {
|
|||||||
kConnectReads, arraysize(kConnectReads), kConnectWrites,
|
kConnectReads, arraysize(kConnectReads), kConnectWrites,
|
||||||
arraysize(kConnectWrites));
|
arraysize(kConnectWrites));
|
||||||
socket_factory.AddSocketDataProvider(&kSocketData);
|
socket_factory.AddSocketDataProvider(&kSocketData);
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
net::HttpAuthCache* auth_cache =
|
net::HttpAuthCache* auth_cache =
|
||||||
context_with_proxy_.http_transaction_factory()
|
context_with_proxy_.http_transaction_factory()
|
||||||
@@ -493,14 +667,15 @@ TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) {
|
|||||||
&socket_factory, &context_with_proxy_);
|
&socket_factory, &context_with_proxy_);
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
|
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_NoCredentials) {
|
TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_NoCredentials) {
|
||||||
net::MockClientSocketFactory socket_factory;
|
net::MockClientSocketFactory socket_factory;
|
||||||
const GURL kDestination("https://example.com:443");
|
const GURL kDestination("https://example.com:443");
|
||||||
|
|
||||||
@@ -524,7 +699,7 @@ TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_NoCredentials) {
|
|||||||
&socket_factory, &context_with_proxy_);
|
&socket_factory, &context_with_proxy_);
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
|
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
@@ -532,7 +707,7 @@ TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_NoCredentials) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that url is sanitized before it is disclosed to the proxy.
|
// Make sure that url is sanitized before it is disclosed to the proxy.
|
||||||
TEST_F(ProxyResolvingClientSocketTest, URLSanitized) {
|
TEST_P(ProxyResolvingClientSocketTest, URLSanitized) {
|
||||||
GURL url("http://username:password@www.example.com:79/?ref#hash#hash");
|
GURL url("http://username:password@www.example.com:79/?ref#hash#hash");
|
||||||
|
|
||||||
auto context = std::make_unique<net::TestURLRequestContext>(true);
|
auto context = std::make_unique<net::TestURLRequestContext>(true);
|
||||||
@@ -555,7 +730,8 @@ TEST_F(ProxyResolvingClientSocketTest, URLSanitized) {
|
|||||||
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
nullptr, context.get());
|
nullptr, context.get());
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), url);
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), url,
|
||||||
|
use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
||||||
@@ -572,18 +748,57 @@ TEST_F(ProxyResolvingClientSocketTest, URLSanitized) {
|
|||||||
resolver.pending_jobs()[0]->url());
|
resolver.pending_jobs()[0]->url());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that socket is destroyed before proxy resolution can complete
|
||||||
|
// asynchronously.
|
||||||
|
TEST_P(ProxyResolvingClientSocketTest,
|
||||||
|
SocketDestroyedBeforeProxyResolutionCompletes) {
|
||||||
|
GURL url("http://www.example.com:79");
|
||||||
|
|
||||||
|
auto context = std::make_unique<net::TestURLRequestContext>(true);
|
||||||
|
net::ProxyConfig proxy_config;
|
||||||
|
proxy_config.set_pac_url(GURL("http://foopy/proxy.pac"));
|
||||||
|
proxy_config.set_pac_mandatory(true);
|
||||||
|
net::MockAsyncProxyResolver resolver;
|
||||||
|
auto proxy_resolver_factory =
|
||||||
|
std::make_unique<net::MockAsyncProxyResolverFactory>(false);
|
||||||
|
net::MockAsyncProxyResolverFactory* proxy_resolver_factory_raw =
|
||||||
|
proxy_resolver_factory.get();
|
||||||
|
net::ProxyResolutionService service(
|
||||||
|
std::make_unique<net::ProxyConfigServiceFixed>(
|
||||||
|
net::ProxyConfigWithAnnotation(proxy_config,
|
||||||
|
TRAFFIC_ANNOTATION_FOR_TESTS)),
|
||||||
|
std::move(proxy_resolver_factory), nullptr);
|
||||||
|
context->set_proxy_resolution_service(&service);
|
||||||
|
context->Init();
|
||||||
|
|
||||||
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
|
nullptr, context.get());
|
||||||
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), url,
|
||||||
|
use_tls_);
|
||||||
|
net::TestCompletionCallback callback;
|
||||||
|
EXPECT_EQ(net::ERR_IO_PENDING, socket->Connect(callback.callback()));
|
||||||
|
socket.reset();
|
||||||
|
ASSERT_EQ(1u, proxy_resolver_factory_raw->pending_requests().size());
|
||||||
|
proxy_resolver_factory_raw->pending_requests()[0]->CompleteNowWithForwarder(
|
||||||
|
net::OK, &resolver);
|
||||||
|
base::RunLoop().RunUntilIdle();
|
||||||
|
}
|
||||||
|
|
||||||
class ReconsiderProxyAfterErrorTest
|
class ReconsiderProxyAfterErrorTest
|
||||||
: public testing::Test,
|
: public testing::Test,
|
||||||
public testing::WithParamInterface<::testing::tuple<bool, int>> {
|
public testing::WithParamInterface<::testing::tuple<bool, bool, int>> {
|
||||||
public:
|
public:
|
||||||
ReconsiderProxyAfterErrorTest()
|
ReconsiderProxyAfterErrorTest()
|
||||||
: context_with_proxy_(
|
: context_with_proxy_(
|
||||||
"HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT") {}
|
"HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT"),
|
||||||
|
use_tls_(::testing::get<0>(GetParam())) {}
|
||||||
|
|
||||||
~ReconsiderProxyAfterErrorTest() override {}
|
~ReconsiderProxyAfterErrorTest() override {}
|
||||||
|
|
||||||
base::test::ScopedTaskEnvironment scoped_task_environment_;
|
base::test::ScopedTaskEnvironment scoped_task_environment_;
|
||||||
TestURLRequestContextWithProxy context_with_proxy_;
|
TestURLRequestContextWithProxy context_with_proxy_;
|
||||||
|
const bool use_tls_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// List of errors that are used in the proxy resolution tests.
|
// List of errors that are used in the proxy resolution tests.
|
||||||
@@ -600,12 +815,14 @@ const int kProxyTestMockErrors[] = {
|
|||||||
INSTANTIATE_TEST_CASE_P(
|
INSTANTIATE_TEST_CASE_P(
|
||||||
/* no prefix */,
|
/* no prefix */,
|
||||||
ReconsiderProxyAfterErrorTest,
|
ReconsiderProxyAfterErrorTest,
|
||||||
testing::Combine(testing::Bool(), testing::ValuesIn(kProxyTestMockErrors)));
|
testing::Combine(testing::Bool(),
|
||||||
|
testing::Bool(),
|
||||||
|
testing::ValuesIn(kProxyTestMockErrors)));
|
||||||
|
|
||||||
TEST_P(ReconsiderProxyAfterErrorTest, ReconsiderProxyAfterError) {
|
TEST_P(ReconsiderProxyAfterErrorTest, ReconsiderProxyAfterError) {
|
||||||
net::IoMode io_mode =
|
net::IoMode io_mode =
|
||||||
::testing::get<0>(GetParam()) ? net::SYNCHRONOUS : net::ASYNC;
|
::testing::get<1>(GetParam()) ? net::SYNCHRONOUS : net::ASYNC;
|
||||||
const int mock_error = ::testing::get<1>(GetParam());
|
const int mock_error = ::testing::get<2>(GetParam());
|
||||||
|
|
||||||
// Before starting the test, verify that there are no proxies marked as bad.
|
// Before starting the test, verify that there are no proxies marked as bad.
|
||||||
ASSERT_TRUE(context_with_proxy_.proxy_resolution_service()
|
ASSERT_TRUE(context_with_proxy_.proxy_resolution_service()
|
||||||
@@ -628,13 +845,15 @@ TEST_P(ReconsiderProxyAfterErrorTest, ReconsiderProxyAfterError) {
|
|||||||
net::StaticSocketDataProvider data3;
|
net::StaticSocketDataProvider data3;
|
||||||
data3.set_connect_data(net::MockConnect(io_mode, net::OK));
|
data3.set_connect_data(net::MockConnect(io_mode, net::OK));
|
||||||
socket_factory.AddSocketDataProvider(&data3);
|
socket_factory.AddSocketDataProvider(&data3);
|
||||||
|
net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
|
||||||
|
socket_factory.AddSSLSocketDataProvider(&ssl_socket);
|
||||||
|
|
||||||
const GURL kDestination("https://example.com:443");
|
const GURL kDestination("https://example.com:443");
|
||||||
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
|
||||||
&socket_factory, &context_with_proxy_);
|
&socket_factory, &context_with_proxy_);
|
||||||
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
std::unique_ptr<ProxyResolvingClientSocket> socket =
|
||||||
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(),
|
||||||
kDestination);
|
kDestination, use_tls_);
|
||||||
net::TestCompletionCallback callback;
|
net::TestCompletionCallback callback;
|
||||||
int status = socket->Connect(callback.callback());
|
int status = socket->Connect(callback.callback());
|
||||||
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
EXPECT_EQ(net::ERR_IO_PENDING, status);
|
||||||
@@ -646,6 +865,7 @@ TEST_P(ReconsiderProxyAfterErrorTest, ReconsiderProxyAfterError) {
|
|||||||
EXPECT_EQ(2u, retry_info.size()) << mock_error;
|
EXPECT_EQ(2u, retry_info.size()) << mock_error;
|
||||||
EXPECT_NE(retry_info.end(), retry_info.find("https://badproxy:99"));
|
EXPECT_NE(retry_info.end(), retry_info.find("https://badproxy:99"));
|
||||||
EXPECT_NE(retry_info.end(), retry_info.find("https://badfallbackproxy:98"));
|
EXPECT_NE(retry_info.end(), retry_info.find("https://badfallbackproxy:98"));
|
||||||
|
EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace network
|
} // namespace network
|
||||||
|
@@ -27250,6 +27250,9 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
|
|||||||
</histogram>
|
</histogram>
|
||||||
|
|
||||||
<histogram name="GCM.ConnectedViaProxy" enum="Boolean">
|
<histogram name="GCM.ConnectedViaProxy" enum="Boolean">
|
||||||
|
<obsolete>
|
||||||
|
Deprecated as of 03/2018 (M67).
|
||||||
|
</obsolete>
|
||||||
<owner>zea@chromium.org</owner>
|
<owner>zea@chromium.org</owner>
|
||||||
<summary>Whether the GCM connection was made via a proxy or not.</summary>
|
<summary>Whether the GCM connection was made via a proxy or not.</summary>
|
||||||
</histogram>
|
</histogram>
|
||||||
|
Reference in New Issue
Block a user