Commit c3308d79 authored by tbansal's avatar tbansal Committed by Commit bot

Race TCP connections to proxies with QUIC connections

After the default job finishes proxy resolution, it queries
ProxyDelegate on whether the resolved proxy supports an
alternative proxy server or not. If yes, a new job is
started. This job is provided the alternative proxy server,
and races with the main job.

If the alternative proxy server is found to be broken, the
ProxyDelegate is notified.

Changes to DataReductionProxyDelegate will be in a
subsequent CL.

BUG=343579

Review-Url: https://codereview.chromium.org/2260623002
Cr-Commit-Position: refs/heads/master@{#414884}
parent 390ccf8f
......@@ -95,6 +95,14 @@ void DataReductionProxyDelegate::OnTunnelHeadersReceived(
const net::HttpResponseHeaders& response_headers) {
}
void DataReductionProxyDelegate::GetAlternativeProxy(
const GURL& url,
const net::ProxyServer& resolved_proxy_server,
net::ProxyServer* alternative_proxy_server) const {}
void DataReductionProxyDelegate::OnAlternativeProxyBroken(
const net::ProxyServer& alternative_proxy_server) {}
void OnResolveProxyHandler(const GURL& url,
const std::string& method,
const net::ProxyConfig& data_reduction_proxy_config,
......
......@@ -61,6 +61,12 @@ class DataReductionProxyDelegate : public net::ProxyDelegate {
const net::HostPortPair& origin,
const net::HostPortPair& proxy_server,
const net::HttpResponseHeaders& response_headers) override;
void GetAlternativeProxy(
const GURL& url,
const net::ProxyServer& resolved_proxy_server,
net::ProxyServer* alternative_proxy_server) const override;
void OnAlternativeProxyBroken(
const net::ProxyServer& alternative_proxy_server) override;
private:
const DataReductionProxyConfig* config_;
......
......@@ -68,6 +68,21 @@ class NET_EXPORT ProxyDelegate {
// allowed to push cross-origin resources.
virtual bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) = 0;
// Called after the proxy is resolved but before the connection is
// established. |resolved_proxy_server| is the proxy server resolved by the
// proxy service for fetching |url|. Sets |alternative_proxy_server| to an
// alternative proxy server, if one is available to fetch |url|.
// |alternative_proxy_server| is owned by the caller, and is guaranteed to be
// non-null.
virtual void GetAlternativeProxy(
const GURL& url,
const ProxyServer& resolved_proxy_server,
ProxyServer* alternative_proxy_server) const = 0;
// Notifies the ProxyDelegate that |alternative_proxy_server| is broken.
virtual void OnAlternativeProxyBroken(
const ProxyServer& alternative_proxy_server) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ProxyDelegate);
};
......
......@@ -13,7 +13,8 @@ namespace net {
TestProxyDelegate::TestProxyDelegate()
: on_before_tunnel_request_called_(false),
on_tunnel_request_completed_called_(false),
on_tunnel_headers_received_called_(false) {}
on_tunnel_headers_received_called_(false),
get_alternative_proxy_invocations_(0) {}
TestProxyDelegate::~TestProxyDelegate() {}
......@@ -79,4 +80,21 @@ bool TestProxyDelegate::IsTrustedSpdyProxy(
return proxy_server.is_valid() && trusted_spdy_proxy_ == proxy_server;
}
void TestProxyDelegate::GetAlternativeProxy(
const GURL& url,
const ProxyServer& resolved_proxy_server,
ProxyServer* alternative_proxy_server) const {
EXPECT_TRUE(resolved_proxy_server.is_valid());
EXPECT_FALSE(alternative_proxy_server->is_valid());
*alternative_proxy_server = alternative_proxy_server_;
get_alternative_proxy_invocations_++;
}
void TestProxyDelegate::OnAlternativeProxyBroken(
const ProxyServer& alternative_proxy_server) {
EXPECT_TRUE(alternative_proxy_server.is_valid());
EXPECT_EQ(alternative_proxy_server_, alternative_proxy_server);
alternative_proxy_server_ = ProxyServer();
}
} // namespace net
\ No newline at end of file
......@@ -65,6 +65,24 @@ class TestProxyDelegate : public ProxyDelegate {
const HostPortPair& proxy_server,
const HttpResponseHeaders& response_headers) override;
bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override;
void GetAlternativeProxy(
const GURL& url,
const ProxyServer& resolved_proxy_server,
ProxyServer* alternative_proxy_server) const override;
void OnAlternativeProxyBroken(
const ProxyServer& alternative_proxy_server) override;
void set_alternative_proxy_server(
const ProxyServer& alternative_proxy_server) {
alternative_proxy_server_ = alternative_proxy_server;
}
const ProxyServer& alternative_proxy_server() const {
return alternative_proxy_server_;
}
int get_alternative_proxy_invocations() const {
return get_alternative_proxy_invocations_;
}
private:
bool on_before_tunnel_request_called_;
......@@ -76,6 +94,10 @@ class TestProxyDelegate : public ProxyDelegate {
HostPortPair on_tunnel_headers_received_origin_;
HostPortPair on_tunnel_headers_received_proxy_server_;
std::string on_tunnel_headers_received_status_line_;
ProxyServer alternative_proxy_server_;
// Number of times GetAlternativeProxy() method has been called.
mutable int get_alternative_proxy_invocations_;
};
} // namespace net
......
......@@ -63,7 +63,25 @@ class DefaultJobFactory : public HttpStreamFactoryImpl::JobFactory {
return new HttpStreamFactoryImpl::Job(
delegate, job_type, session, request_info, priority, server_ssl_config,
proxy_ssl_config, destination, origin_url, alternative_service,
net_log);
ProxyServer(), net_log);
}
HttpStreamFactoryImpl::Job* CreateJob(
HttpStreamFactoryImpl::Job::Delegate* delegate,
HttpStreamFactoryImpl::JobType job_type,
HttpNetworkSession* session,
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HostPortPair destination,
GURL origin_url,
const ProxyServer& alternative_proxy_server,
NetLog* net_log) override {
return new HttpStreamFactoryImpl::Job(
delegate, job_type, session, request_info, priority, server_ssl_config,
proxy_ssl_config, destination, origin_url, AlternativeService(),
alternative_proxy_server, net_log);
}
};
} // anonymous namespace
......
......@@ -25,6 +25,7 @@
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/port_util.h"
#include "net/base/proxy_delegate.h"
#include "net/cert/cert_verifier.h"
#include "net/http/bidirectional_stream_impl.h"
#include "net/http/http_basic_stream.h"
......@@ -161,6 +162,7 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
destination,
origin_url,
AlternativeService(),
ProxyServer(),
net_log) {}
HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
......@@ -173,6 +175,7 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
HostPortPair destination,
GURL origin_url,
AlternativeService alternative_service,
const ProxyServer& alternative_proxy_server,
NetLog* net_log)
: request_info_(request_info),
priority_(priority),
......@@ -188,6 +191,7 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
origin_url_(origin_url),
alternative_service_(alternative_service),
delegate_(delegate),
alternative_proxy_server_(alternative_proxy_server),
job_type_(job_type),
using_ssl_(false),
using_spdy_(false),
......@@ -205,6 +209,24 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM),
ptr_factory_(this) {
DCHECK(session);
// The job can't have alternative service and alternative proxy server set at
// the same time since alternative services are used for requests that are
// fetched directly, while the alternative proxy server is used for requests
// that should be fetched using proxy.
DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL ||
!alternative_proxy_server_.is_valid());
DCHECK(!alternative_proxy_server_.is_valid() ||
!(IsSpdyAlternative() || IsQuicAlternative()));
// If either the alternative service protocol is specified or if the
// alternative proxy server is valid, then the job type must be set to
// either ALTERNATIVE or PRECONNECT.
DCHECK((alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL &&
!alternative_proxy_server_.is_valid()) ||
(job_type_ == ALTERNATIVE || job_type_ == PRECONNECT));
// If the alternative proxy server is valid, then the job type must be
// set to ALTERNATIVE.
DCHECK(!alternative_proxy_server_.is_valid() || job_type_ == ALTERNATIVE);
if (IsSpdyAlternative()) {
DCHECK(origin_url_.SchemeIs("https"));
}
......@@ -701,6 +723,12 @@ int HttpStreamFactoryImpl::Job::DoResolveProxy() {
return OK;
}
// If an alternative proxy server was provided, use that.
if (alternative_proxy_server_.is_valid()) {
proxy_info_.UseProxyServer(alternative_proxy_server_);
return OK;
}
return session_->proxy_service()->ResolveProxy(
origin_url_, request_info_.method, &proxy_info_, io_callback_,
&pac_request_, session_->params().proxy_delegate, net_log_);
......@@ -738,6 +766,11 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
}
next_state_ = STATE_WAIT;
delegate_->OnResolveProxyComplete(this, request_info_, priority_,
server_ssl_config_, proxy_ssl_config_,
stream_type_);
return OK;
}
......@@ -1394,6 +1427,14 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
if (request_info_.load_flags & LOAD_BYPASS_PROXY)
return error;
// Alternative proxy server job should not use fallback proxies, and instead
// return. This would resume the main job (if possible) which may try the
// fallback proxies.
if (alternative_proxy_server_.is_valid()) {
DCHECK_EQ(STATE_NONE, next_state_);
return error;
}
if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
session_->ssl_client_auth_cache()->Remove(
proxy_info_.proxy_server().host_port_pair());
......@@ -1474,15 +1515,30 @@ void HttpStreamFactoryImpl::Job::ReportJobSucceededForRequest() {
void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) {
DCHECK_EQ(STATUS_RUNNING, other_job_status_);
DCHECK(!other_job_alternative_proxy_server_.is_valid());
other_job_status_ = job.job_status_;
other_job_alternative_service_ = job.alternative_service_;
other_job_alternative_proxy_server_ = job.alternative_proxy_server_;
// At most one job can have a valid |alternative_proxy_server_|.
DCHECK(!alternative_proxy_server_.is_valid() ||
!other_job_alternative_proxy_server_.is_valid());
MaybeMarkAlternativeServiceBroken();
}
void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() {
// At least one job should not be an alternative job.
DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL ||
other_job_alternative_service_.protocol ==
UNINITIALIZED_ALTERNATE_PROTOCOL);
if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING)
return;
MaybeNotifyAlternativeProxyServerBroken();
if (IsSpdyAlternative() || IsQuicAlternative()) {
if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) {
HistogramBrokenAlternateProtocolLocation(
......@@ -1503,6 +1559,47 @@ void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() {
}
}
void HttpStreamFactoryImpl::Job::MaybeNotifyAlternativeProxyServerBroken()
const {
if (!alternative_proxy_server_.is_valid() &&
!other_job_alternative_proxy_server_.is_valid()) {
// Neither of the two jobs used an alternative proxy server.
return;
}
// Neither this job, nor the other job should have used the alternative
// service.
DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service_.protocol);
DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL,
other_job_alternative_service_.protocol);
ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
if (!proxy_delegate)
return;
if (alternative_proxy_server_.is_valid()) {
// |this| connected to the alternative proxy server.
if ((job_status_ == STATUS_BROKEN || job_status_ == STATUS_FAILED) &&
other_job_status_ == STATUS_SUCCEEDED) {
// Notify ProxyDelegate.
proxy_delegate->OnAlternativeProxyBroken(alternative_proxy_server_);
}
return;
}
if (other_job_alternative_proxy_server_.is_valid()) {
// Other job connected to the alternative proxy server.
if (job_status_ == STATUS_SUCCEEDED &&
(other_job_status_ == STATUS_BROKEN ||
other_job_status_ == STATUS_FAILED)) {
// Notify ProxyDelegate.
proxy_delegate->OnAlternativeProxyBroken(
other_job_alternative_proxy_server_);
}
return;
}
}
ClientSocketPoolManager::SocketGroupType
HttpStreamFactoryImpl::Job::GetSocketGroup() const {
std::string scheme = origin_url_.scheme();
......
......@@ -20,6 +20,7 @@
#include "net/http/http_request_info.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/log/net_log.h"
#include "net/proxy/proxy_server.h"
#include "net/proxy/proxy_service.h"
#include "net/quic/chromium/quic_stream_factory.h"
#include "net/socket/client_socket_handle.h"
......@@ -35,6 +36,7 @@ class HttpAuthController;
class HttpNetworkSession;
class HttpStream;
class SpdySessionPool;
struct SSLConfig;
class QuicHttpStream;
// An HttpStreamRequestImpl exists for each stream which is in progress of being
......@@ -96,6 +98,16 @@ class HttpStreamFactoryImpl::Job {
const ProxyInfo& used_proxy_info,
HttpAuthController* auth_controller) = 0;
// Invoked when |job| has completed proxy resolution. The delegate may
// create an alternative proxy server job to fetch the request.
virtual void OnResolveProxyComplete(
Job* job,
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::StreamType stream_type) = 0;
// Invoked to notify the Request and Factory of the readiness of new
// SPDY session.
virtual void OnNewSpdySessionReady(
......@@ -156,9 +168,14 @@ class HttpStreamFactoryImpl::Job {
GURL origin_url,
NetLog* net_log);
// Constructor for alternative Job.
// Job is owned by |delegate|, hence |delegate| is valid for the
// lifetime of the Job.
// Constructor for the alternative Job. The Job is owned by |delegate|, hence
// |delegate| is valid for the lifetime of the Job. If |alternative_service|
// is initialized, then the Job will use the alternative service. On the
// other hand, if |alternative_proxy_server| is a valid proxy server, then the
// job will use that instead of using ProxyService for proxy resolution.
// Further, if |alternative_proxy_server| is a valid but bad proxy, then
// fallback proxies are not used. It is illegal to call this with an
// initialized |alternative_service|, and a valid |alternative_proxy_server|.
Job(Delegate* delegate,
JobType job_type,
HttpNetworkSession* session,
......@@ -169,6 +186,7 @@ class HttpStreamFactoryImpl::Job {
HostPortPair destination,
GURL origin_url,
AlternativeService alternative_service,
const ProxyServer& alternative_proxy_server,
NetLog* net_log);
virtual ~Job();
......@@ -364,6 +382,11 @@ class HttpStreamFactoryImpl::Job {
void MaybeMarkAlternativeServiceBroken();
// May notify proxy delegate that the alternative proxy server is broken. The
// alternative proxy server is considered as broken if the alternative proxy
// server job failed, but the main job was successful.
void MaybeNotifyAlternativeProxyServerBroken() const;
ClientSocketPoolManager::SocketGroupType GetSocketGroup() const;
void MaybeCopyConnectionAttemptsFromSocketOrHandle();
......@@ -412,7 +435,14 @@ class HttpStreamFactoryImpl::Job {
// Unowned. |this| job is owned by |delegate_|.
Delegate* delegate_;
JobType job_type_;
// Alternative proxy server that should be used by |this| to fetch the
// request.
const ProxyServer alternative_proxy_server_;
// Alternative proxy server for the other job.
ProxyServer other_job_alternative_proxy_server_;
const JobType job_type_;
// True if handling a HTTPS request, or using SPDY with SSL
bool using_ssl_;
......@@ -479,7 +509,7 @@ class HttpStreamFactoryImpl::JobFactory {
public:
virtual ~JobFactory() {}
// Creates an alternative Job.
// Creates an alternative service Job.
virtual HttpStreamFactoryImpl::Job* CreateJob(
HttpStreamFactoryImpl::Job::Delegate* delegate,
HttpStreamFactoryImpl::JobType job_type,
......@@ -493,6 +523,20 @@ class HttpStreamFactoryImpl::JobFactory {
AlternativeService alternative_service,
NetLog* net_log) = 0;
// Creates an alternative proxy server Job.
virtual HttpStreamFactoryImpl::Job* CreateJob(
HttpStreamFactoryImpl::Job::Delegate* delegate,
HttpStreamFactoryImpl::JobType job_type,
HttpNetworkSession* session,
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HostPortPair destination,
GURL origin_url,
const ProxyServer& alternative_proxy_server,
NetLog* net_log) = 0;
// Creates a non-alternative Job.
virtual HttpStreamFactoryImpl::Job* CreateJob(
HttpStreamFactoryImpl::Job::Delegate* delegate,
......
......@@ -9,8 +9,10 @@
#include "base/strings/string_util.h"
#include "base/values.h"
#include "net/base/host_mapping_rules.h"
#include "net/base/proxy_delegate.h"
#include "net/http/bidirectional_stream_impl.h"
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_server.h"
#include "net/spdy/spdy_session.h"
namespace net {
......@@ -38,6 +40,7 @@ HttpStreamFactoryImpl::JobController::JobController(
job_bound_(false),
main_job_is_blocked_(false),
bound_job_(nullptr),
can_start_alternative_proxy_job_(false),
ptr_factory_(this) {
DCHECK(factory);
}
......@@ -355,6 +358,45 @@ void HttpStreamFactoryImpl::JobController::OnNeedsProxyAuth(
auth_controller);
}
void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete(
Job* job,
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::StreamType stream_type) {
DCHECK(job);
ProxyServer alternative_proxy_server;
if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(),
request_info.url,
&alternative_proxy_server)) {
return;
}
DCHECK(main_job_);
DCHECK_EQ(MAIN, job->job_type());
DCHECK(!alternative_job_);
DCHECK(!main_job_is_blocked_);
HostPortPair destination(HostPortPair::FromURL(request_info.url));
GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
alternative_job_.reset(job_factory_->CreateJob(
this, ALTERNATIVE, session_, request_info, priority, server_ssl_config,
proxy_ssl_config, destination, origin_url, alternative_proxy_server,
job->net_log().net_log()));
AttachJob(alternative_job_.get());
can_start_alternative_proxy_job_ = false;
main_job_is_blocked_ = true;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&HttpStreamFactoryImpl::Job::Start,
base::Unretained(alternative_job_.get()),
request_->stream_type()));
}
void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
Job* job,
const base::WeakPtr<SpdySession>& spdy_session,
......@@ -607,6 +649,8 @@ void HttpStreamFactoryImpl::JobController::CreateJobs(
main_job_is_blocked_ = true;
alternative_job_->Start(request_->stream_type());
} else {
can_start_alternative_proxy_job_ = true;
}
// Even if |alternative_job| has already finished, it will not have notified
// the request yet, since we defer that to the next iteration of the
......@@ -895,4 +939,73 @@ HttpStreamFactoryImpl::JobController::GetAlternativeServiceForInternal(
return first_alternative_service;
}
bool HttpStreamFactoryImpl::JobController::
ShouldCreateAlternativeProxyServerJob(
Job* job,
const ProxyInfo& proxy_info,
const GURL& url,
ProxyServer* alternative_proxy_server) const {
DCHECK(!alternative_proxy_server->is_valid());
if (!can_start_alternative_proxy_job_) {
// Either an alternative service job or an alternative proxy server job has
// already been started.
return false;
}
if (job->job_type() == ALTERNATIVE) {
// If |job| is using alternative service, then alternative proxy server
// should not be used.
return false;
}
if (job->job_type() == PRECONNECT) {
// Preconnects should be fetched using only the main job to keep the
// resource utilization down.
return false;
}
if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) {
// Alternative proxy server job can be created only if |job| fetches the
// |request_| through a non-QUIC proxy.
return false;
}
if (!url.SchemeIs(url::kHttpScheme)) {
// Only HTTP URLs can be fetched through alternative proxy server, since the
// alternative proxy server may not support fetching of URLs with other
// schemes.
return false;
}
ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
if (!proxy_delegate)
return false;
proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(),
alternative_proxy_server);
if (!alternative_proxy_server->is_valid())
return false;
DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server()));
if (!alternative_proxy_server->is_https() &&
!alternative_proxy_server->is_quic()) {
// Alternative proxy server should be a secure server.
return false;
}
if (alternative_proxy_server->is_quic()) {
// Check that QUIC is enabled globally, and it is not disabled on
// the specified port.
if (!session_->params().enable_quic ||
session_->quic_stream_factory()->IsQuicDisabled(
alternative_proxy_server->host_port_pair().port())) {
return false;
}
}
return true;
}
}
......@@ -5,6 +5,7 @@
#ifndef NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_CONTROLLER_H_
#define NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_CONTROLLER_H_
#include "net/base/host_port_pair.h"
#include "net/http/http_stream_factory_impl_job.h"
#include "net/http/http_stream_factory_impl_request.h"
......@@ -114,6 +115,14 @@ class HttpStreamFactoryImpl::JobController
const ProxyInfo& used_proxy_info,
HttpAuthController* auth_controller) override;
void OnResolveProxyComplete(
Job* job,
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::StreamType stream_type) override;
// Invoked to notify the Request and Factory of the readiness of new
// SPDY session.
void OnNewSpdySessionReady(Job* job,
......@@ -215,6 +224,16 @@ class HttpStreamFactoryImpl::JobController
// Remove session from the SpdySessionRequestMap.
void RemoveRequestFromSpdySessionRequestMap();
// Returns true if the |request_| can be fetched via an alternative
// proxy server, and sets |alternative_proxy_server| to the available
// alternative proxy server. |alternative_proxy_server| should not be null,
// and is owned by the caller.
bool ShouldCreateAlternativeProxyServerJob(
Job* job,
const ProxyInfo& proxy_info_,
const GURL& url,
ProxyServer* alternative_proxy_server) const;
HttpStreamFactoryImpl* factory_;
HttpNetworkSession* session_;
JobFactory* job_factory_;
......@@ -249,6 +268,9 @@ class HttpStreamFactoryImpl::JobController
// It will be nulled when the |request_| is finished.
Job* bound_job_;
// True if an alternative proxy server job can be started to fetch |request_|.
bool can_start_alternative_proxy_job_;
base::WeakPtrFactory<JobController> ptr_factory_;
};
......
......@@ -46,6 +46,7 @@ MockHttpStreamFactoryImplJob::MockHttpStreamFactoryImplJob(
HostPortPair destination,
GURL origin_url,
AlternativeService alternative_service,
const ProxyServer& alternative_proxy_server,
NetLog* net_log)
: HttpStreamFactoryImpl::Job(delegate,
job_type,
......@@ -57,6 +58,7 @@ MockHttpStreamFactoryImplJob::MockHttpStreamFactoryImplJob(
destination,
origin_url,
alternative_service,
alternative_proxy_server,
net_log) {}
MockHttpStreamFactoryImplJob::~MockHttpStreamFactoryImplJob() {}
......@@ -106,7 +108,29 @@ HttpStreamFactoryImpl::Job* TestJobFactory::CreateJob(
DCHECK(!alternative_job_);
alternative_job_ = new MockHttpStreamFactoryImplJob(
delegate, job_type, session, request_info, priority, SSLConfig(),
SSLConfig(), destination, origin_url, alternative_service, nullptr);
SSLConfig(), destination, origin_url, alternative_service, ProxyServer(),
nullptr);
return alternative_job_;
}
HttpStreamFactoryImpl::Job* TestJobFactory::CreateJob(
HttpStreamFactoryImpl::Job::Delegate* delegate,
HttpStreamFactoryImpl::JobType job_type,
HttpNetworkSession* session,
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HostPortPair destination,
GURL origin_url,
const ProxyServer& alternative_proxy_server,
NetLog* net_log) {
DCHECK(!alternative_job_);
alternative_job_ = new MockHttpStreamFactoryImplJob(
delegate, job_type, session, request_info, priority, SSLConfig(),
SSLConfig(), destination, origin_url, AlternativeService(),
alternative_proxy_server, nullptr);
return alternative_job_;
}
......
......@@ -12,6 +12,7 @@
#include "net/http/http_stream_factory_impl_job.h"
#include "net/http/http_stream_factory_impl_job_controller.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_server.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::_;
......@@ -112,6 +113,7 @@ class MockHttpStreamFactoryImplJob : public HttpStreamFactoryImpl::Job {
HostPortPair destination,
GURL origin_url,
AlternativeService alternative_service,
const ProxyServer& alternative_proxy_server,
NetLog* net_log);
~MockHttpStreamFactoryImplJob() override;
......@@ -154,6 +156,19 @@ class TestJobFactory : public HttpStreamFactoryImpl::JobFactory {
AlternativeService alternative_service,
NetLog* net_log) override;
HttpStreamFactoryImpl::Job* CreateJob(
HttpStreamFactoryImpl::Job::Delegate* delegate,
HttpStreamFactoryImpl::JobType job_type,
HttpNetworkSession* session,
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HostPortPair destination,
GURL origin_url,
const ProxyServer& alternative_proxy_server,
NetLog* net_log) override;
MockHttpStreamFactoryImplJob* main_job() const { return main_job_; }
MockHttpStreamFactoryImplJob* alternative_job() const {
return alternative_job_;
......
......@@ -223,6 +223,12 @@ class TestResolveProxyDelegate : public ProxyDelegate {
bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
return true;
}
void GetAlternativeProxy(
const GURL& url,
const ProxyServer& resolved_proxy_server,
ProxyServer* alternative_proxy_server) const override {}
void OnAlternativeProxyBroken(
const ProxyServer& alternative_proxy_server) override {}
private:
bool on_resolve_proxy_called_;
......@@ -260,6 +266,12 @@ class TestProxyFallbackProxyDelegate : public ProxyDelegate {
bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
return true;
}
void GetAlternativeProxy(
const GURL& url,
const ProxyServer& resolved_proxy_server,
ProxyServer* alternative_proxy_server) const override {}
void OnAlternativeProxyBroken(
const ProxyServer& alternative_proxy_server) override {}
bool on_proxy_fallback_called() const {
return on_proxy_fallback_called_;
......
......@@ -232,6 +232,12 @@ class TestProxyDelegateWithProxyInfo : public ProxyDelegate {
bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
return true;
}
void GetAlternativeProxy(
const GURL& url,
const ProxyServer& resolved_proxy_server,
ProxyServer* alternative_proxy_server) const override {}
void OnAlternativeProxyBroken(
const ProxyServer& alternative_proxy_server) override {}
private:
ResolvedProxyInfo resolved_proxy_info_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment