#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include <array>
#include <cstdarg>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "net/base/completion_once_callback.h"
#include "net/base/mock_network_change_notifier.h"
#include "net/base/net_errors.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_isolation_key.h"
#include "net/base/proxy_chain.h"
#include "net/base/proxy_delegate.h"
#include "net/base/proxy_server.h"
#include "net/base/proxy_string_util.h"
#include "net/base/request_priority.h"
#include "net/base/schemeful_site.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_request_headers.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/proxy_resolution/dhcp_pac_file_fetcher.h"
#include "net/proxy_resolution/mock_pac_file_fetcher.h"
#include "net/proxy_resolution/mock_proxy_resolver.h"
#include "net/proxy_resolution/pac_file_fetcher.h"
#include "net/proxy_resolution/proxy_config_service.h"
#include "net/proxy_resolution/proxy_resolution_request.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "net/test/gtest_util.h"
#include "net/test/test_with_task_environment.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using testing::ElementsAre;
using testing::Key;
using net::test::IsError;
using net::test::IsOk;
namespace net {
namespace {
using ProxyOverrideRule = ProxyConfig::ProxyOverrideRule;
constexpr std::string_view kMatchingRule = "https://example.test";
constexpr std::string_view kNonMatchingRule = "https://testing.test";
constexpr std::string_view kMatchingUrl = "https://example.test/some/path";
constexpr std::string_view kSanitizedMatchingUrl = "https://example.test";
constexpr std::string_view kDnsHost1 = "https://host1.test:443";
constexpr std::string_view kDnsHost2 = "https://host2.test:443";
constexpr std::string_view kProxy1 = "HTTPS bar:333";
constexpr std::string_view kProxy2 = "HTTPS foo:333";
class ImmediatePollPolicy
: public ConfiguredProxyResolutionService::PacPollPolicy {
public:
ImmediatePollPolicy() = default;
ImmediatePollPolicy(const ImmediatePollPolicy&) = delete;
ImmediatePollPolicy& operator=(const ImmediatePollPolicy&) = delete;
Mode GetNextDelay(int error,
base::TimeDelta current_delay,
base::TimeDelta* next_delay) const override {
*next_delay = base::Milliseconds(1);
return MODE_USE_TIMER;
}
};
class NeverPollPolicy : public ConfiguredProxyResolutionService::PacPollPolicy {
public:
NeverPollPolicy() = default;
NeverPollPolicy(const NeverPollPolicy&) = delete;
NeverPollPolicy& operator=(const NeverPollPolicy&) = delete;
Mode GetNextDelay(int error,
base::TimeDelta current_delay,
base::TimeDelta* next_delay) const override {
*next_delay = base::Days(60);
return MODE_USE_TIMER;
}
};
class ImmediateAfterActivityPollPolicy
: public ConfiguredProxyResolutionService::PacPollPolicy {
public:
ImmediateAfterActivityPollPolicy() = default;
ImmediateAfterActivityPollPolicy(const ImmediateAfterActivityPollPolicy&) =
delete;
ImmediateAfterActivityPollPolicy& operator=(
const ImmediateAfterActivityPollPolicy&) = delete;
Mode GetNextDelay(int error,
base::TimeDelta current_delay,
base::TimeDelta* next_delay) const override {
*next_delay = base::TimeDelta();
return MODE_START_AFTER_ACTIVITY;
}
};
class ConfiguredProxyResolutionServiceTest : public ::testing::Test,
public WithTaskEnvironment {
protected:
ConfiguredProxyResolutionServiceTest()
: WithTaskEnvironment(
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
testing::Test::SetUp();
previous_policy_ =
ConfiguredProxyResolutionService::set_pac_script_poll_policy(
&never_poll_policy_);
}
void TearDown() override {
ConfiguredProxyResolutionService::set_pac_script_poll_policy(
previous_policy_);
testing::Test::TearDown();
}
void AddDnsEntry(const GURL& dns_host, std::string_view result) {
mock_host_resolver_->rules()->AddRule(dns_host.GetHost(), result);
}
void AddDnsEntry(const GURL& dns_host, Error error) {
mock_host_resolver_->rules()->AddRule(dns_host.GetHost(), error);
}
std::unique_ptr<MockHostResolverBase> mock_host_resolver_{nullptr};
private:
NeverPollPolicy never_poll_policy_;
raw_ptr<const ConfiguredProxyResolutionService::PacPollPolicy>
previous_policy_;
};
const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
const char16_t kValidPacScript116[] = u"pac-script-v1-FindProxyForURL";
const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
const char16_t kValidPacScript216[] = u"pac-script-v2-FindProxyForURL";
class MockProxyConfigService : public ProxyConfigService {
public:
explicit MockProxyConfigService(const ProxyConfig& config)
: config_(
ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS)) {}
explicit MockProxyConfigService(const std::string& pac_url)
: config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url)),
TRAFFIC_ANNOTATION_FOR_TESTS) {}
void AddObserver(Observer* observer) override {
observers_.AddObserver(observer);
}
void RemoveObserver(Observer* observer) override {
observers_.RemoveObserver(observer);
}
ConfigAvailability GetLatestProxyConfig(
ProxyConfigWithAnnotation* results) override {
if (availability_ == CONFIG_VALID)
*results = config_;
return availability_;
}
void SetConfig(const ProxyConfigWithAnnotation& config) {
availability_ = CONFIG_VALID;
config_ = config;
for (auto& observer : observers_)
observer.OnProxyConfigChanged(config_, availability_);
}
void SetPacUrlConfig(std::string_view pac_url) {
SetConfig(ProxyConfigWithAnnotation(
ProxyConfig::CreateFromCustomPacURL(GURL(pac_url)),
TRAFFIC_ANNOTATION_FOR_TESTS));
}
private:
ConfigAvailability availability_ = CONFIG_VALID;
ProxyConfigWithAnnotation config_;
base::ObserverList<Observer, true>::Unchecked observers_;
};
class TestResolveProxyDelegate : public ProxyDelegate {
public:
void OnResolveProxy(const GURL& url,
const NetworkAnonymizationKey& network_anonymization_key,
const std::string& method,
const ProxyRetryInfoMap& proxy_retry_info,
ProxyInfo* result) override {
method_ = method;
num_resolve_proxy_called_++;
network_anonymization_key_ = network_anonymization_key;
proxy_retry_info_ = proxy_retry_info;
DCHECK(!add_proxy_ || !remove_proxy_);
if (add_proxy_) {
result->UseNamedProxy("delegate_proxy.com");
} else if (remove_proxy_) {
result->UseDirect();
}
}
int num_resolve_proxy_called() const { return num_resolve_proxy_called_; }
const std::string& method() const { return method_; }
void set_add_proxy(bool add_proxy) { add_proxy_ = add_proxy; }
void set_remove_proxy(bool remove_proxy) { remove_proxy_ = remove_proxy; }
NetworkAnonymizationKey network_anonymization_key() const {
return network_anonymization_key_;
}
const ProxyRetryInfoMap& proxy_retry_info() const {
return proxy_retry_info_;
}
void OnSuccessfulRequestAfterFailures(
const ProxyRetryInfoMap& proxy_retry_info) override {}
void OnFallback(const ProxyChain& bad_chain, int net_error) override {}
base::expected<HttpRequestHeaders, Error> OnBeforeTunnelRequest(
const ProxyChain& proxy_chain,
size_t proxy_index,
OnBeforeTunnelRequestCallback callback) override {
return HttpRequestHeaders();
}
Error OnTunnelHeadersReceived(const ProxyChain& proxy_chain,
size_t proxy_index,
const HttpResponseHeaders& response_headers,
CompletionOnceCallback callback) override {
return OK;
}
void SetProxyResolutionService(
ProxyResolutionService* proxy_resolution_service) override {}
bool AliasRequiresProxyOverride(
const std::string scheme,
const std::vector<std::string>& dns_aliases,
const net::NetworkAnonymizationKey& network_anonymization_key) override {
return false;
}
#include "arkweb/chromium_ext/net/proxy_resolution/test_resolve_proxy_delegate_for_include.cc"
private:
int num_resolve_proxy_called_ = 0;
bool add_proxy_ = false;
bool remove_proxy_ = false;
std::string method_;
NetworkAnonymizationKey network_anonymization_key_;
ProxyRetryInfoMap proxy_retry_info_;
};
class TestProxyFallbackProxyDelegate : public ProxyDelegate {
public:
void OnResolveProxy(const GURL& url,
const NetworkAnonymizationKey& network_anonymization_key,
const std::string& method,
const ProxyRetryInfoMap& proxy_retry_info,
ProxyInfo* result) override {}
void OnSuccessfulRequestAfterFailures(
const ProxyRetryInfoMap& proxy_retry_info) override {
last_proxy_retry_info_ = proxy_retry_info;
}
void OnFallback(const ProxyChain& bad_chain, int net_error) override {
proxy_chain_ = bad_chain;
last_proxy_fallback_net_error_ = net_error;
num_proxy_fallback_called_++;
}
base::expected<HttpRequestHeaders, Error> OnBeforeTunnelRequest(
const ProxyChain& proxy_chain,
size_t proxy_index,
OnBeforeTunnelRequestCallback callback) override {
return HttpRequestHeaders();
}
Error OnTunnelHeadersReceived(const ProxyChain& proxy_chain,
size_t proxy_index,
const HttpResponseHeaders& response_headers,
CompletionOnceCallback callback) override {
return OK;
}
void SetProxyResolutionService(
ProxyResolutionService* proxy_resolution_service) override {}
bool AliasRequiresProxyOverride(
const std::string scheme,
const std::vector<std::string>& dns_aliases,
const net::NetworkAnonymizationKey& network_anonymization_key) override {
return false;
}
bool num_proxy_fallback_called() const { return num_proxy_fallback_called_; }
const ProxyChain& proxy_chain() const { return proxy_chain_; }
int last_proxy_fallback_net_error() const {
return last_proxy_fallback_net_error_;
}
#include "arkweb/chromium_ext/net/proxy_resolution/test_proxy_fallback_proxy_delegate_for_include.cc"
const ProxyRetryInfoMap& last_proxy_retry_info() const {
return last_proxy_retry_info_;
}
private:
int num_proxy_fallback_called_ = 0;
ProxyChain proxy_chain_;
int last_proxy_fallback_net_error_ = OK;
ProxyRetryInfoMap last_proxy_retry_info_;
};
using JobMap = std::map<GURL, MockAsyncProxyResolver::Job*>;
JobMap GetJobsForURLs(const JobMap& map, const std::vector<GURL>& urls) {
size_t a = urls.size();
size_t b = map.size();
if (a != b) {
ADD_FAILURE() << "map size (" << map.size() << ") != urls size ("
<< urls.size() << ")";
return map;
}
for (const auto& it : urls) {
if (map.count(it) != 1U) {
ADD_FAILURE() << "url not in map: " << it.spec();
break;
}
}
return map;
}
JobMap GetPendingJobsForURLs(const MockAsyncProxyResolver& resolver,
const GURL& url1 = GURL(),
const GURL& url2 = GURL(),
const GURL& url3 = GURL()) {
std::vector<GURL> urls;
if (!url1.is_empty())
urls.push_back(url1);
if (!url2.is_empty())
urls.push_back(url2);
if (!url3.is_empty())
urls.push_back(url3);
JobMap map;
for (MockAsyncProxyResolver::Job* it : resolver.pending_jobs()) {
DCHECK(it);
map[it->url()] = it;
}
return GetJobsForURLs(map, urls);
}
JobMap GetCancelledJobsForURLs(const MockAsyncProxyResolver& resolver,
const GURL& url1 = GURL(),
const GURL& url2 = GURL(),
const GURL& url3 = GURL()) {
std::vector<GURL> urls;
if (!url1.is_empty())
urls.push_back(url1);
if (!url2.is_empty())
urls.push_back(url2);
if (!url3.is_empty())
urls.push_back(url3);
JobMap map;
for (const std::unique_ptr<MockAsyncProxyResolver::Job>& it :
resolver.cancelled_jobs()) {
DCHECK(it);
map[it->url()] = it.get();
}
return GetJobsForURLs(map, urls);
}
ProxyOverrideRule CreateOverrideRule(
std::string_view destination_matcher,
const ProxyList& proxy_list,
std::optional<std::string_view> dns_host = std::nullopt,
ProxyOverrideRule::DnsProbeCondition::Result dns_condition_result =
ProxyOverrideRule::DnsProbeCondition::Result::kResolved,
std::string_view exclude_destination_matcher = "") {
ProxyConfig::ProxyOverrideRule override_rule;
override_rule.destination_matchers.AddRuleFromString(destination_matcher);
override_rule.proxy_list = proxy_list;
if (dns_host) {
override_rule.dns_conditions.emplace_back(
url::SchemeHostPort(GURL(dns_host.value())), dns_condition_result);
}
if (!exclude_destination_matcher.empty()) {
override_rule.exclude_destination_matchers.AddRuleFromString(
exclude_destination_matcher);
}
return override_rule;
}
ProxyList CreateProxyList(std::string_view pac_result_string) {
ProxyList proxy_list;
proxy_list.SetFromPacString(std::string(pac_result_string));
return proxy_list;
}
}
TEST_F(ConfiguredProxyResolutionServiceTest,
PacRuntimeErrorGatesResolver_NonMandatory) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
service.set_enable_pac_runtime_backoff_for_testing(true);
GURL url("http://www.example.com/");
ProxyInfo info;
TestCompletionCallback cb1;
std::unique_ptr<ProxyResolutionRequest> req1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, cb1.callback(), &req1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
EXPECT_THAT(cb1.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
ProxyInfo info2;
TestCompletionCallback cb2;
std::unique_ptr<ProxyResolutionRequest> req2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info2, cb2.callback(), &req2, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info2.is_direct());
EXPECT_TRUE(resolver.pending_jobs().empty());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
PacRuntimeErrorGatesResolver_Mandatory) {
ProxyConfig config(
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
config.set_pac_mandatory(true);
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
service.set_enable_pac_runtime_backoff_for_testing(true);
GURL url("http://www.example.com/");
ProxyInfo info;
TestCompletionCallback cb1;
std::unique_ptr<ProxyResolutionRequest> req1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, cb1.callback(), &req1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, cb1.WaitForResult());
EXPECT_FALSE(info.is_direct());
ProxyInfo info2;
TestCompletionCallback cb2;
std::unique_ptr<ProxyResolutionRequest> req2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info2, cb2.callback(), &req2, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
EXPECT_TRUE(resolver.pending_jobs().empty());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
PacRuntimeErrorBackoffResetsOnSuccess) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
service.set_enable_pac_runtime_backoff_for_testing(true);
GURL url("http://www.example.com/");
ProxyInfo info;
TestCompletionCallback cb1;
std::unique_ptr<ProxyResolutionRequest> req1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, cb1.callback(), &req1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
EXPECT_THAT(cb1.WaitForResult(), IsOk());
FastForwardBy(base::Seconds(9));
ProxyInfo info2;
TestCompletionCallback cb2;
std::unique_ptr<ProxyResolutionRequest> req2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info2, cb2.callback(), &req2, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
resolver.pending_jobs()[0]->results()->UseNamedProxy("ok:8080");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(cb2.WaitForResult(), IsOk());
ProxyInfo info3;
TestCompletionCallback cb3;
std::unique_ptr<ProxyResolutionRequest> req3;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info3, cb3.callback(), &req3, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
PacRuntimeErrorBackoffDelayProgresses) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
service.set_enable_pac_runtime_backoff_for_testing(true);
const GURL url("http://www.example.com/");
ProxyInfo info1;
TestCompletionCallback cb1;
std::unique_ptr<ProxyResolutionRequest> req1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info1, cb1.callback(), &req1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
EXPECT_THAT(cb1.WaitForResult(), IsOk());
EXPECT_TRUE(info1.is_direct());
EXPECT_TRUE(resolver.pending_jobs().empty());
FastForwardBy(base::Seconds(9));
ProxyInfo info2;
TestCompletionCallback cb2;
std::unique_ptr<ProxyResolutionRequest> req2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info2, cb2.callback(), &req2, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
EXPECT_THAT(cb2.WaitForResult(), IsOk());
EXPECT_TRUE(info2.is_direct());
EXPECT_TRUE(resolver.pending_jobs().empty());
ProxyInfo gated_info1;
TestCompletionCallback gated_cb1;
std::unique_ptr<ProxyResolutionRequest> gated_req1;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&gated_info1, gated_cb1.callback(), &gated_req1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(gated_info1.is_direct());
EXPECT_TRUE(resolver.pending_jobs().empty());
FastForwardBy(base::Seconds(31));
ProxyInfo gated_info2;
TestCompletionCallback gated_cb2;
std::unique_ptr<ProxyResolutionRequest> gated_req2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&gated_info2, gated_cb2.callback(), &gated_req2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(gated_info2.is_direct());
EXPECT_TRUE(resolver.pending_jobs().empty());
FastForwardBy(base::Seconds(1));
ProxyInfo info3;
TestCompletionCallback cb3;
std::unique_ptr<ProxyResolutionRequest> req3;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info3, cb3.callback(), &req3, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
resolver.pending_jobs()[0]->results()->UseNamedProxy("ok:8080");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(cb3.WaitForResult(), IsOk());
}
TEST_F(ConfiguredProxyResolutionServiceTest, Direct) {
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(ProxyConfig::CreateDirect()),
std::move(factory), mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
RecordingNetLogObserver net_log_observer;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
EXPECT_TRUE(info.is_direct());
EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
auto entries = net_log_observer.GetEntries();
EXPECT_EQ(3u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsEvent(
entries, 1, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 2,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest, OnResolveProxyCallbackAddProxy) {
ProxyConfig config;
config.proxy_rules().ParseFromString("badproxy:8080,foopy1:8080");
config.set_auto_detect(false);
config.proxy_rules().bypass_rules.ParseFromString("*.org");
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
GURL bypass_url("http://internet.org");
ProxyInfo info;
TestCompletionCallback callback;
NetLogWithSource net_log_with_source =
NetLogWithSource::Make(NetLogSourceType::NONE);
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
net_log_with_source, DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("[badproxy:8080]", info.proxy_chain().ToDebugString());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
service.ReportSuccess(info);
TestResolveProxyDelegate delegate;
service.SetProxyDelegate(&delegate);
rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
callback.callback(), &request, net_log_with_source,
DEFAULT_PRIORITY);
EXPECT_EQ(1, delegate.num_resolve_proxy_called());
EXPECT_THAT(delegate.proxy_retry_info(),
ElementsAre(Key(ProxyChain(ProxyUriToProxyChain(
"badproxy:8080", ProxyServer::SCHEME_HTTP)))));
EXPECT_EQ(delegate.method(), "GET");
delegate.set_add_proxy(true);
rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
callback.callback(), &request, net_log_with_source,
DEFAULT_PRIORITY);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[delegate_proxy.com:80]", info.proxy_chain().ToDebugString());
delegate.set_add_proxy(false);
rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
callback.callback(), &request, net_log_with_source,
DEFAULT_PRIORITY);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
rv = service.ResolveProxy(bypass_url, "GET", NetworkAnonymizationKey(), &info,
callback.callback(), &request, net_log_with_source,
DEFAULT_PRIORITY);
EXPECT_TRUE(info.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OnResolveProxyCallbackRemoveProxy) {
ProxyConfig config;
config.proxy_rules().ParseFromString("foopy1:8080");
config.set_auto_detect(false);
config.proxy_rules().bypass_rules.ParseFromString("*.org");
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
GURL bypass_url("http://internet.org");
ProxyInfo info;
TestCompletionCallback callback;
NetLogWithSource net_log_with_source =
NetLogWithSource::Make(NetLogSourceType::NONE);
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
net_log_with_source, DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
TestResolveProxyDelegate delegate;
service.SetProxyDelegate(&delegate);
delegate.set_remove_proxy(true);
rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
callback.callback(), &request, net_log_with_source,
DEFAULT_PRIORITY);
EXPECT_TRUE(info.is_direct());
delegate.set_remove_proxy(false);
rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
callback.callback(), &request, net_log_with_source,
DEFAULT_PRIORITY);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
rv = service.ResolveProxy(bypass_url, "GET", NetworkAnonymizationKey(), &info,
callback.callback(), &request, net_log_with_source,
DEFAULT_PRIORITY);
EXPECT_TRUE(info.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest, OnResolveProxyHasNak) {
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(ProxyConfig::CreateDirect()),
std::move(factory), mock_host_resolver_.get(), nullptr,
true);
auto proxy_delegate = TestResolveProxyDelegate();
service.SetProxyDelegate(&proxy_delegate);
GURL url("http://www.google.com/");
NetworkAnonymizationKey network_anonymization_key =
NetworkAnonymizationKey::CreateCrossSite(
SchemefulSite(GURL("http://example.com")));
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
service.ResolveProxy(url, std::string(), network_anonymization_key, &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE),
DEFAULT_PRIORITY);
EXPECT_EQ(network_anonymization_key,
proxy_delegate.network_anonymization_key());
}
template <typename T>
class DeletingCallback : public TestCompletionCallbackBase {
public:
explicit DeletingCallback(std::unique_ptr<T>* deletee);
DeletingCallback(const DeletingCallback&) = delete;
DeletingCallback& operator=(const DeletingCallback&) = delete;
~DeletingCallback() override;
CompletionOnceCallback callback() {
return base::BindOnce(&DeletingCallback::DeleteItem,
base::Unretained(this));
}
private:
void DeleteItem(int result) {
deletee_->reset();
SetResult(result);
}
raw_ptr<std::unique_ptr<T>> deletee_;
};
template <typename T>
DeletingCallback<T>::DeletingCallback(std::unique_ptr<T>* deletee)
: deletee_(deletee) {}
template <typename T>
DeletingCallback<T>::~DeletingCallback() = default;
TEST_F(ConfiguredProxyResolutionServiceTest, CallbackDeletesRequest) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
std::unique_ptr<ConfiguredProxyResolutionService> service =
std::make_unique<ConfiguredProxyResolutionService>(
std::move(config_service), std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
GURL url2("http://www.example.com/");
ProxyInfo info;
std::unique_ptr<ProxyResolutionRequest> request, request2;
DeletingCallback<ProxyResolutionRequest> callback(&request2);
net::CompletionOnceCallback callback2 =
base::BindOnce([](int result) { ASSERT_FALSE(true); });
int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = service->ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info, std::move(callback2), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(2u, resolver.pending_jobs().size());
int deleting_job = 2;
for (int i = 0; i < 2; i++) {
if (resolver.pending_jobs()[i]->url() == url) {
deleting_job = i;
break;
}
ASSERT_LE(i, 1);
}
resolver.pending_jobs()[deleting_job]->results()->UseNamedProxy("foopy");
resolver.pending_jobs()[deleting_job]->CompleteNow(OK);
EXPECT_TRUE(callback.have_result());
EXPECT_THAT(callback.WaitForResult(), IsOk());
ASSERT_EQ(0u, resolver.pending_jobs().size());
ASSERT_EQ(1u, resolver.cancelled_jobs().size());
ASSERT_EQ(url2, resolver.cancelled_jobs()[0]->url());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
CallbackDeletesRequestDuringDestructor) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
std::unique_ptr<ConfiguredProxyResolutionService> service =
std::make_unique<ConfiguredProxyResolutionService>(
std::move(config_service), std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
std::unique_ptr<ProxyResolutionRequest> request, request2;
DeletingCallback<ProxyResolutionRequest> callback(&request2),
callback2(&request);
int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
service.reset();
EXPECT_TRUE(callback.have_result() ^ callback2.have_result());
if (callback.have_result()) {
EXPECT_THAT(callback.WaitForResult(),
IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
}
if (callback2.have_result()) {
EXPECT_THAT(callback2.WaitForResult(),
IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
}
}
TEST_F(ConfiguredProxyResolutionServiceTest, CallbackDeletesSelf) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
std::unique_ptr<ConfiguredProxyResolutionService> service =
std::make_unique<ConfiguredProxyResolutionService>(
std::move(config_service), std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
std::unique_ptr<ProxyResolutionRequest> request1;
TestCompletionCallback callback1;
int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
GURL url2("http://www.example.com/");
std::unique_ptr<ProxyResolutionRequest> request2;
DeletingCallback<ProxyResolutionRequest> callback2(&request2);
rv = service->ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
std::unique_ptr<ProxyResolutionRequest> request3;
TestCompletionCallback callback3;
rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback3.callback(), &request3,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(3u, resolver.pending_jobs().size());
int self_deleting_job = 3;
for (int i = 0; i < 3; i++) {
if (resolver.pending_jobs()[i]->url() == url2) {
self_deleting_job = i;
break;
}
ASSERT_LE(i, 2);
}
resolver.pending_jobs()[self_deleting_job]->results()->UseNamedProxy("foopy");
resolver.pending_jobs()[self_deleting_job]->CompleteNow(OK);
ASSERT_EQ(2u, resolver.pending_jobs().size());
ASSERT_EQ(0u, resolver.cancelled_jobs().size());
ASSERT_EQ(url, resolver.pending_jobs()[0]->url());
ASSERT_EQ(url, resolver.pending_jobs()[1]->url());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
CallbackDeletesSelfDuringDestructor) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
std::unique_ptr<ConfiguredProxyResolutionService> service =
std::make_unique<ConfiguredProxyResolutionService>(
std::move(config_service), std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
std::unique_ptr<ProxyResolutionRequest> request1;
TestCompletionCallback callback1;
int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
std::unique_ptr<ProxyResolutionRequest> request2;
DeletingCallback<ProxyResolutionRequest> callback2(&request2);
rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
std::unique_ptr<ProxyResolutionRequest> request3;
TestCompletionCallback callback3;
rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback3.callback(), &request3,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
service.reset();
EXPECT_THAT(callback1.WaitForResult(),
IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
EXPECT_THAT(callback2.WaitForResult(),
IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
EXPECT_THAT(callback3.WaitForResult(),
IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
}
TEST_F(ConfiguredProxyResolutionServiceTest, ProxyServiceDeletedBeforeRequest) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv;
{
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request->GetLoadState());
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
}
ASSERT_EQ(0u, resolver.pending_jobs().size());
EXPECT_THAT(callback.WaitForResult(), IsOk());
}
TEST_F(ConfiguredProxyResolutionServiceTest, CallbackDeletesService) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
auto* config_service_ptr = config_service.get();
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
std::unique_ptr<ConfiguredProxyResolutionService> service =
std::make_unique<ConfiguredProxyResolutionService>(
std::move(config_service), std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
DeletingCallback<ConfiguredProxyResolutionService> callback(&service);
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request1->GetLoadState());
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback3.callback(), &request3,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
config_service_ptr->SetConfig(ProxyConfigWithAnnotation(
ProxyConfig::CreateDirect(), TRAFFIC_ANNOTATION_FOR_TESTS));
ASSERT_EQ(0u, resolver.pending_jobs().size());
ASSERT_THAT(callback.WaitForResult(), IsOk());
ASSERT_THAT(callback2.WaitForResult(), IsOk());
ASSERT_THAT(callback3.WaitForResult(), IsOk());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PAC) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
RecordingNetLogObserver net_log_observer;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request->GetLoadState());
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy:80]", info.proxy_chain().ToDebugString());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
auto entries = net_log_observer.GetEntries();
EXPECT_EQ(5u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 1,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEndEvent(
entries, 2,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEndEvent(entries, 4,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest, PAC_NoIdentityOrHash) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://username:password@www.google.com/?ref#hash#hash");
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://www.google.com/?ref"),
resolver.pending_jobs()[0]->url());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PAC_FailoverWithoutDirect) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy:8080");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy:8080]", info.proxy_chain().ToDebugString());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_TRUE(info.is_empty());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PAC_RuntimeError) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://this-causes-js-error/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PAC_FailoverAfterDirect) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UsePacString(
"DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foobar:10]", info.proxy_chain().ToDebugString());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_TRUE(info.is_direct());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foobar:20]", info.proxy_chain().ToDebugString());
EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_TRUE(info.is_empty());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PAC_ConfigSourcePropagates) {
ProxyConfig config =
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
info.traffic_annotation());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
}
TEST_F(ConfiguredProxyResolutionServiceTest, ProxyResolverFails) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
TestCompletionCallback callback2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy_valid:8080");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
ProxyResolverTerminatedDuringRequest) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
TestCompletionCallback callback2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy_valid:8080");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
ProxyResolverTerminatedDuringRequestWithConcurrentRequest) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url1("http://www.google.com/");
GURL url2("https://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1, request2;
int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
TestCompletionCallback callback2;
rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2);
jobs[url1]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
jobs = GetCancelledJobsForURLs(resolver, url2);
ASSERT_EQ(1u, factory_ptr->pending_requests().size());
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
jobs = GetPendingJobsForURLs(resolver, url2);
jobs[url2]->results()->UseNamedProxy("foopy_valid:8080");
jobs[url2]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
PacFileFetcherFailsDownloadingMandatoryPac) {
ProxyConfig config(
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
config.set_pac_mandatory(true);
auto config_service = std::make_unique<MockProxyConfigService>(config);
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNow(ERR_FAILED, nullptr);
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
callback1.WaitForResult());
EXPECT_FALSE(info.is_direct());
TestCompletionCallback callback2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
EXPECT_FALSE(info.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
ProxyResolverFailsParsingJavaScriptMandatoryPac) {
ProxyConfig config(
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
config.set_pac_mandatory(true);
auto config_service = std::make_unique<MockProxyConfigService>(config);
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, "invalid-script-contents");
EXPECT_FALSE(fetcher_ptr->has_pending_request());
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, callback.WaitForResult());
EXPECT_FALSE(info.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
ProxyResolverFailsInJavaScriptMandatoryPac) {
ProxyConfig config(
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
config.set_pac_mandatory(true);
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
callback1.WaitForResult());
EXPECT_FALSE(info.is_direct());
TestCompletionCallback callback2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback2.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy_valid:8080");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallback) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy(
"foopy1:8080;foopy2:9090");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
TestProxyFallbackProxyDelegate test_delegate;
service.SetProxyDelegate(&test_delegate);
service.ReportSuccess(info);
EXPECT_EQ("[foopy1:8080]", test_delegate.proxy_chain().ToDebugString());
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
test_delegate.last_proxy_fallback_net_error());
service.SetProxyDelegate(nullptr);
EXPECT_EQ(1u, info.proxy_retry_info().size());
EXPECT_TRUE(
info.proxy_retry_info().contains(ProxyChain::FromSchemeHostAndPort(
ProxyServer::SCHEME_HTTP, "foopy1", 8080)));
TestCompletionCallback callback3;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback3.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy(
"foopy3:7070;foopy1:8080;foopy2:9090");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback3.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy3:7070]", info.proxy_chain().ToDebugString());
EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
proxy_resolve_start_time = info.proxy_resolve_start_time();
proxy_resolve_end_time = info.proxy_resolve_end_time();
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_FALSE(info.is_direct());
EXPECT_TRUE(info.is_empty());
EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
TestCompletionCallback callback7;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback7.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy(
"foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback7.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy3:7070]", info.proxy_chain().ToDebugString());
EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
}
TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallbackToDirect) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UsePacString(
"PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_TRUE(info.is_direct());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
}
TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallback_BadConfig) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
TestResolveProxyDelegate delegate;
std::unique_ptr<ProxyResolutionRequest> request;
service.SetProxyDelegate(&delegate);
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy(
"foopy1:8080;foopy2:9090");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
service.ReportSuccess(info);
ProxyInfo info2;
TestCompletionCallback callback2;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info2, callback2.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_TRUE(info2.is_direct());
EXPECT_FALSE(info2.is_empty());
ProxyInfo info3;
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info3, callback3.callback(), &request3,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy(
"foopy1:8080;foopy2:9090");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback3.WaitForResult(), IsOk());
EXPECT_FALSE(info3.is_direct());
EXPECT_EQ("[foopy2:9090]", info3.proxy_chain().ToDebugString());
EXPECT_EQ(2u, info3.proxy_list().size());
EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
EXPECT_EQ(3, delegate.num_resolve_proxy_called());
}
TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallback_BadConfigMandatory) {
ProxyConfig config(
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
config.set_pac_mandatory(true);
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy(
"foopy1:8080;foopy2:9090");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
service.ReportSuccess(info);
ProxyInfo info2;
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info2, callback3.callback(), &request3,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
callback3.WaitForResult());
EXPECT_FALSE(info2.is_direct());
EXPECT_TRUE(info2.is_empty());
ProxyInfo info3;
TestCompletionCallback callback4;
std::unique_ptr<ProxyResolutionRequest> request4;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info3, callback4.callback(), &request4,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy(
"foopy1:8080;foopy2:9090");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback4.WaitForResult(), IsOk());
EXPECT_FALSE(info3.is_direct());
EXPECT_EQ("[foopy2:9090]", info3.proxy_chain().ToDebugString());
EXPECT_EQ(2u, info3.proxy_list().size());
}
TEST_F(ConfiguredProxyResolutionServiceTest, ProxyBypassList) {
std::array<TestCompletionCallback, 2> callback;
std::array<ProxyInfo, 2> info;
ProxyConfig config;
config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
config.set_auto_detect(false);
config.proxy_rules().bypass_rules.ParseFromString("*.org");
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
int rv;
GURL url1("http://www.webkit.org");
GURL url2("http://www.webkit.com");
std::unique_ptr<ProxyResolutionRequest> request1;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
&info[0], callback[0].callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info[0].is_direct());
rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info[1], callback[1].callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("[foopy1:8080]", info[1].proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PerProtocolProxyTests) {
ProxyConfig config;
config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
config.set_auto_detect(false);
std::unique_ptr<ProxyResolutionRequest> request;
{
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("http://www.msn.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
}
{
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("ftp://ftp.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info.is_direct());
EXPECT_EQ("[direct://]", info.proxy_chain().ToDebugString());
}
{
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("https://webbranch.techcu.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy2:8080]", info.proxy_chain().ToDebugString());
}
{
config.proxy_rules().ParseFromString("foopy1:8080");
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("http://www.microsoft.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
}
}
TEST_F(ConfiguredProxyResolutionServiceTest,
ProxyConfigTrafficAnnotationPropagates) {
std::unique_ptr<ProxyResolutionRequest> request;
{
ProxyConfig config;
config.proxy_rules().ParseFromString("https=foopy2:8080");
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("http://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
ASSERT_THAT(rv, IsOk());
EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
info.traffic_annotation());
}
{
ProxyConfig config;
config.proxy_rules().ParseFromString("https=foopy2:8080");
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("https://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
ASSERT_THAT(rv, IsOk());
EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
info.traffic_annotation());
}
{
ProxyConfig config;
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("http://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
ASSERT_THAT(rv, IsOk());
EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
info.traffic_annotation());
}
}
TEST_F(ConfiguredProxyResolutionServiceTest, DefaultProxyFallbackToSOCKS) {
ProxyConfig config;
config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
config.set_auto_detect(false);
EXPECT_EQ(ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
config.proxy_rules().type);
std::unique_ptr<ProxyResolutionRequest> request;
{
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("http://www.msn.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
}
{
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("ftp://ftp.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[socks4://foopy2:1080]", info.proxy_chain().ToDebugString());
}
{
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("https://webbranch.techcu.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[socks4://foopy2:1080]", info.proxy_chain().ToDebugString());
}
{
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(config), nullptr,
mock_host_resolver_.get(), nullptr,
true);
GURL test_url("unknown://www.microsoft.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
test_url, std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("[socks4://foopy2:1080]", info.proxy_chain().ToDebugString());
}
}
TEST_F(ConfiguredProxyResolutionServiceTest, CancelInProgressRequest) {
const GURL url1("http://request1");
const GURL url2("http://request2");
const GURL url3("http://request3");
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
&info1, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
GetPendingJobsForURLs(resolver, url1);
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info2, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
GetPendingJobsForURLs(resolver, url1, url2);
ProxyInfo info3;
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service.ResolveProxy(url3, std::string(), NetworkAnonymizationKey(),
&info3, callback3.callback(), &request3,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
GetPendingJobsForURLs(resolver, url1, url2, url3);
request2.reset();
JobMap jobs = GetPendingJobsForURLs(resolver, url1, url3);
jobs[url3]->results()->UseNamedProxy("request3:80");
jobs[url3]->CompleteNow(OK);
jobs[url1]->results()->UseNamedProxy("request1:80");
jobs[url1]->CompleteNow(OK);
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
EXPECT_FALSE(callback2.have_result());
GetCancelledJobsForURLs(resolver, url2);
EXPECT_THAT(callback3.WaitForResult(), IsOk());
EXPECT_EQ("[request3:80]", info3.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest, InitialPACScriptDownload) {
const GURL url1("http://request1");
const GURL url2("http://request2");
const GURL url3("http://request3");
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
&info1, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info2, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ProxyInfo info3;
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service.ResolveProxy(url3, std::string(), NetworkAnonymizationKey(),
&info3, callback3.callback(), &request3,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(factory_ptr->pending_requests().empty());
EXPECT_EQ(LOAD_STATE_DOWNLOADING_PAC_FILE, request1->GetLoadState());
EXPECT_EQ(LOAD_STATE_DOWNLOADING_PAC_FILE, request2->GetLoadState());
EXPECT_EQ(LOAD_STATE_DOWNLOADING_PAC_FILE, request3->GetLoadState());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2, url3);
EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request1->GetLoadState());
EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request2->GetLoadState());
EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request3->GetLoadState());
jobs[url3]->results()->UseNamedProxy("request3:80");
jobs[url3]->CompleteNow(OK);
jobs[url1]->results()->UseNamedProxy("request1:80");
jobs[url1]->CompleteNow(OK);
jobs[url2]->results()->UseNamedProxy("request2:80");
jobs[url2]->CompleteNow(OK);
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
EXPECT_THAT(callback3.WaitForResult(), IsOk());
EXPECT_EQ("[request3:80]", info3.proxy_chain().ToDebugString());
EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
ChangeScriptFetcherWhilePACDownloadInProgress) {
const GURL url1("http://request1");
const GURL url2("http://request2");
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
&info1, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info2, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fetcher = std::make_unique<MockPacFileFetcher>();
fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
GetPendingJobsForURLs(resolver, url1, url2);
}
TEST_F(ConfiguredProxyResolutionServiceTest, CancelWhilePACFetching) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
RecordingNetLogObserver net_log_observer;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ProxyInfo info3;
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service.ResolveProxy(
GURL("http://request3"), std::string(), NetworkAnonymizationKey(), &info3,
callback3.callback(), &request3, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(factory_ptr->pending_requests().empty());
request1.reset();
request2.reset();
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request3"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request3:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback3.WaitForResult(), IsOk());
EXPECT_EQ("[request3:80]", info3.proxy_chain().ToDebugString());
EXPECT_TRUE(resolver.cancelled_jobs().empty());
EXPECT_FALSE(callback1.have_result());
EXPECT_FALSE(callback2.have_result());
auto entries1 = net_log_observer.GetEntries();
EXPECT_EQ(4u, entries1.size());
EXPECT_TRUE(LogContainsBeginEvent(entries1, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries1, 1,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEvent(entries1, 2, NetLogEventType::CANCELLED,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries1, 3,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
FallbackFromAutodetectToCustomPac) {
const GURL url1("http://request1");
const GURL url2("http://request2");
ProxyConfig config;
config.set_auto_detect(true);
config.set_pac_url(GURL("http://foopy/proxy.pac"));
config.proxy_rules().ParseFromString("http=foopy:80");
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
&info1, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info2, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2);
jobs[url2]->results()->UseNamedProxy("request2:80");
jobs[url2]->CompleteNow(OK);
jobs[url1]->results()->UseNamedProxy("request1:80");
jobs[url1]->CompleteNow(OK);
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
FallbackFromAutodetectToCustomPac2) {
const GURL url1("http://request1");
const GURL url2("http://request2");
ProxyConfig config;
config.set_auto_detect(true);
config.set_pac_url(GURL("http://foopy/proxy.pac"));
config.proxy_rules().ParseFromString("http=foopy:80");
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
&info1, callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
&info2, callback2.callback(), &request2,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, "invalid-script-contents");
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2);
jobs[url2]->results()->UseNamedProxy("request2:80");
jobs[url2]->CompleteNow(OK);
jobs[url1]->results()->UseNamedProxy("request1:80");
jobs[url1]->CompleteNow(OK);
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
FallbackFromAutodetectToCustomToManual) {
ProxyConfig config;
config.set_auto_detect(true);
config.set_pac_url(GURL("http://foopy/proxy.pac"));
config.proxy_rules().ParseFromString("http=foopy:80");
auto config_service = std::make_unique<MockProxyConfigService>(config);
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[foopy:80]", info1.proxy_chain().ToDebugString());
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[foopy:80]", info2.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest, BypassDoesntApplyToPac) {
ProxyConfig config;
config.set_auto_detect(true);
config.set_pac_url(GURL("http://foopy/proxy.pac"));
config.proxy_rules().ParseFromString("http=foopy:80");
config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://www.google.com"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://www.google.com"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
DeleteWhileInitProxyResolverHasOutstandingFetch) {
ProxyConfig config =
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
auto config_service = std::make_unique<MockProxyConfigService>(config);
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
DeleteWhileInitProxyResolverHasOutstandingSet) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
}
TEST_F(ConfiguredProxyResolutionServiceTest, UpdateConfigFromPACToDirect) {
ProxyConfig config = ProxyConfig::CreateAutoDetect();
auto config_service = std::make_unique<MockProxyConfigService>(config);
auto* config_service_ptr = config_service.get();
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(PacFileData::TYPE_AUTO_DETECT,
factory_ptr->pending_requests()[0]->script_data()->type());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
config_service_ptr->SetConfig(ProxyConfigWithAnnotation::CreateDirect());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info2.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest, NetworkChangeTriggersPacRefetch) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
RecordingNetLogObserver observer;
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
net::NetLog::Get(),
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
service.set_stall_proxy_auto_config_delay(base::TimeDelta());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
base::RunLoop().RunUntilIdle();
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
EXPECT_EQ(kValidPacScript216,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
auto entries = observer.GetEntries();
EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
NetLogEventType::PROXY_CONFIG_CHANGED));
ASSERT_EQ(9u, entries.size());
for (size_t i = 1; i < entries.size(); ++i)
EXPECT_NE(NetLogEventType::PROXY_CONFIG_CHANGED, entries[i].type);
}
TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptRefetchAfterFailure) {
ImmediatePollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
ASSERT_TRUE(factory_ptr->pending_requests().empty());
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info1.is_direct());
fetcher_ptr->WaitUntilFetch();
ASSERT_TRUE(factory_ptr->pending_requests().empty());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
PACScriptRefetchAfterContentChange) {
ImmediatePollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
fetcher_ptr->WaitUntilFetch();
ASSERT_TRUE(factory_ptr->pending_requests().empty());
ASSERT_TRUE(resolver.pending_jobs().empty());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(kValidPacScript216,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
PACScriptRefetchAfterContentUnchanged) {
ImmediatePollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
fetcher_ptr->WaitUntilFetch();
ASSERT_TRUE(factory_ptr->pending_requests().empty());
ASSERT_TRUE(resolver.pending_jobs().empty());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(factory_ptr->pending_requests().empty());
ASSERT_TRUE(resolver.pending_jobs().empty());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptRefetchAfterSuccess) {
ImmediatePollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
fetcher_ptr->WaitUntilFetch();
ASSERT_TRUE(factory_ptr->pending_requests().empty());
ASSERT_TRUE(resolver.pending_jobs().empty());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
base::RunLoop().RunUntilIdle();
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info2.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptPollingPolicy) {
std::unique_ptr<ConfiguredProxyResolutionService::PacPollPolicy> policy =
ConfiguredProxyResolutionService::CreateDefaultPacPollPolicy();
int error;
ConfiguredProxyResolutionService::PacPollPolicy::Mode mode;
const base::TimeDelta initial_delay = base::Milliseconds(-1);
base::TimeDelta delay = initial_delay;
error = ERR_NAME_NOT_RESOLVED;
mode = policy->GetNextDelay(error, initial_delay, &delay);
EXPECT_EQ(8, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::MODE_USE_TIMER,
mode);
mode = policy->GetNextDelay(error, delay, &delay);
EXPECT_EQ(32, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
MODE_START_AFTER_ACTIVITY,
mode);
mode = policy->GetNextDelay(error, delay, &delay);
EXPECT_EQ(120, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
MODE_START_AFTER_ACTIVITY,
mode);
mode = policy->GetNextDelay(error, delay, &delay);
EXPECT_EQ(14400, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
MODE_START_AFTER_ACTIVITY,
mode);
mode = policy->GetNextDelay(error, delay, &delay);
EXPECT_EQ(14400, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
MODE_START_AFTER_ACTIVITY,
mode);
error = OK;
mode = policy->GetNextDelay(error, initial_delay, &delay);
EXPECT_EQ(43200, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
MODE_START_AFTER_ACTIVITY,
mode);
mode = policy->GetNextDelay(error, delay, &delay);
EXPECT_EQ(43200, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
MODE_START_AFTER_ACTIVITY,
mode);
mode = policy->GetNextDelay(error, delay, &delay);
EXPECT_EQ(43200, delay.InSeconds());
EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
MODE_START_AFTER_ACTIVITY,
mode);
}
TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptRefetchAfterActivity) {
ImmediateAfterActivityPollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
EXPECT_TRUE(factory_ptr->pending_requests().empty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
ASSERT_FALSE(fetcher_ptr->has_pending_request());
ASSERT_TRUE(factory_ptr->pending_requests().empty());
ASSERT_TRUE(resolver.pending_jobs().empty());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
base::RunLoop().RunUntilIdle();
ProxyInfo info3;
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service.ResolveProxy(
GURL("http://request3"), std::string(), NetworkAnonymizationKey(), &info3,
callback3.callback(), &request3, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info3.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest, IpAddressChangeResetsProxy) {
NeverPollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(
true);
MockAsyncProxyResolverFactory* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(ProxyConfig::CreateAutoDetect()),
std::move(factory), mock_host_resolver_.get(),
nullptr, true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
MockPacFileFetcher* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
const base::TimeDelta kConfigDelay = base::Seconds(5);
service.set_stall_proxy_auto_config_delay(kConfigDelay);
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_TRUE(fetcher_ptr->has_pending_request());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
resolver.pending_jobs()[0]->CompleteNow(OK);
ASSERT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_FALSE(fetcher_ptr->has_pending_request());
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
FastForwardBy(kConfigDelay - base::Milliseconds(2));
EXPECT_FALSE(fetcher_ptr->has_pending_request());
FastForwardBy(base::Milliseconds(2));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_THAT(resolver.pending_jobs(), testing::IsEmpty());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
EXPECT_EQ(kValidPacScript216,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_FALSE(fetcher_ptr->has_pending_request());
}
TEST_F(ConfiguredProxyResolutionServiceTest, DnsChangeTriggersPoll) {
ImmediateAfterActivityPollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(
true);
MockAsyncProxyResolverFactory* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(ProxyConfig::CreateAutoDetect()),
std::move(factory), mock_host_resolver_.get(),
nullptr, true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
MockPacFileFetcher* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(
GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1, NetLogWithSource(), DEFAULT_PRIORITY);
ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_TRUE(fetcher_ptr->has_pending_request());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
resolver.pending_jobs()[0]->CompleteNow(OK);
ASSERT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_FALSE(fetcher_ptr->has_pending_request());
NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests();
fetcher_ptr->WaitUntilFetch();
EXPECT_TRUE(fetcher_ptr->has_pending_request());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(
GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
callback2.callback(), &request2, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
RunUntilIdle();
ProxyInfo info3;
TestCompletionCallback callback3;
std::unique_ptr<ProxyResolutionRequest> request3;
rv = service.ResolveProxy(
GURL("http://request3"), std::string(), NetworkAnonymizationKey(), &info3,
callback3.callback(), &request3, NetLogWithSource(), DEFAULT_PRIORITY);
ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
EXPECT_EQ(kValidPacScript216,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
resolver.pending_jobs()[0]->CompleteNow(OK);
ASSERT_THAT(callback3.WaitForResult(), IsOk());
EXPECT_FALSE(fetcher_ptr->has_pending_request());
}
TEST_F(ConfiguredProxyResolutionServiceTest, DnsChangeNoopWithoutResolver) {
ImmediateAfterActivityPollPolicy poll_policy;
ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
MockAsyncProxyResolver resolver;
ConfiguredProxyResolutionService service(
std::make_unique<MockProxyConfigService>(ProxyConfig::CreateAutoDetect()),
std::make_unique<MockAsyncProxyResolverFactory>(
true),
mock_host_resolver_.get(),
nullptr, true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
MockPacFileFetcher* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests();
RunUntilIdle();
EXPECT_FALSE(fetcher_ptr->has_pending_request());
}
class SanitizeUrlHelper {
public:
SanitizeUrlHelper() {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* factory_ptr = factory.get();
service_ = std::make_unique<ConfiguredProxyResolutionService>(
std::move(config_service), std::move(factory), nullptr, nullptr,
true);
GURL url("http://example.com");
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv =
service_->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), net::DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
factory_ptr->pending_requests()[0]->script_data()->url());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
EXPECT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UsePacString("DIRECT");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
}
GURL SanitizeUrl(const GURL& raw_url) {
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service_->ResolveProxy(raw_url, std::string(),
NetworkAnonymizationKey(), &info,
callback.callback(), &request1,
NetLogWithSource(), net::DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_EQ(1u, resolver.pending_jobs().size());
GURL sanitized_url = resolver.pending_jobs()[0]->url();
resolver.pending_jobs()[0]->results()->UsePacString("DIRECT");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
return sanitized_url;
}
private:
MockAsyncProxyResolver resolver;
std::unique_ptr<ConfiguredProxyResolutionService> service_;
};
TEST_F(ConfiguredProxyResolutionServiceTest, SanitizeUrlForPacScript) {
const struct {
const char* raw_url;
const char* sanitized_url;
} kTests[] = {
{
"https://foo:bar@example.com/",
"https://example.com/",
},
{
"https://example.com/blah#hello",
"https://example.com/",
},
{
"https://example.com/?hello",
"https://example.com/",
},
{
"https://foo:bar@example.com/foo/bar/baz?hello#sigh",
"https://example.com/",
},
{
"https://example.com:88/hi",
"https://example.com:88/",
},
{
"wss://example.com:88/hi",
"wss://example.com:88/",
},
{
"http://foo:bar@example.com/",
"http://example.com/",
},
{
"ftp://foo:bar@example.com/",
"ftp://example.com/",
},
{
"ftp://example.com/some/path/here",
"ftp://example.com/some/path/here",
},
{
"http://example.com/blah#hello",
"http://example.com/blah",
},
{
"http://example.com/foo/bar/baz?hello",
"http://example.com/foo/bar/baz?hello",
},
{
"http://foo:bar@example.com/foo/bar/baz?hello#sigh",
"http://example.com/foo/bar/baz?hello",
},
{
"http://example.com:88/hi",
"http://example.com:88/hi",
},
};
SanitizeUrlHelper helper;
for (const auto& test : kTests) {
GURL raw_url(test.raw_url);
ASSERT_TRUE(raw_url.is_valid());
EXPECT_EQ(GURL(test.sanitized_url), helper.SanitizeUrl(raw_url));
}
}
TEST_F(ConfiguredProxyResolutionServiceTest, OnShutdownWithLiveRequest) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL("http://request/"), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
service.OnShutdown();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback.have_result());
EXPECT_FALSE(fetcher_ptr->has_pending_request());
}
TEST_F(ConfiguredProxyResolutionServiceTest, OnShutdownFollowedByRequest) {
auto config_service =
std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
service.OnShutdown();
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL("http://request/"), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(fetcher_ptr->has_pending_request());
EXPECT_TRUE(info.is_direct());
}
constexpr const char* kImplicityBypassedHosts[] = {
"localhost", "localhost.", "foo.localhost", "127.0.0.1", "127.100.0.2",
"[::1]", "169.254.3.2", "169.254.100.1", "[FE80::8]", "[feb8::1]",
};
constexpr const char* kUrlSchemes[] = {"http://", "https://", "ftp://"};
TEST_F(ConfiguredProxyResolutionServiceTest,
ImplicitlyBypassWithManualSettings) {
ProxyConfig config;
config.proxy_rules().ParseFromString("foopy1:8080");
config.set_auto_detect(false);
auto service = ConfiguredProxyResolutionService::CreateFixedForTest(
ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS));
std::unique_ptr<ProxyResolutionRequest> request1;
ProxyInfo info1;
TestCompletionCallback callback1;
int rv = service->ResolveProxy(GURL("http://www.example.com"), std::string(),
NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("[foopy1:8080]", info1.proxy_chain().ToDebugString());
for (auto* host : kImplicityBypassedHosts) {
for (auto* scheme : kUrlSchemes) {
auto url = GURL(std::string(scheme) + std::string(host));
std::unique_ptr<ProxyResolutionRequest> request;
ProxyInfo info;
TestCompletionCallback callback;
rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info.is_direct());
}
}
}
TEST_F(ConfiguredProxyResolutionServiceTest, ImplicitlyBypassWithPac) {
ProxyConfig config;
config.set_auto_detect(true);
auto config_service = std::make_unique<MockProxyConfigService>(config);
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(std::move(config_service),
std::move(factory),
mock_host_resolver_.get(), nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
int rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
NetworkAnonymizationKey(), &info1,
callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, factory_ptr->pending_requests().size());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_jobs().size());
EXPECT_EQ(GURL("http://www.google.com"), resolver.pending_jobs()[0]->url());
resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
resolver.pending_jobs()[0]->CompleteNow(OK);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
for (auto* host : kImplicityBypassedHosts) {
for (auto* scheme : kUrlSchemes) {
auto url = GURL(std::string(scheme) + std::string(host));
std::unique_ptr<ProxyResolutionRequest> request;
ProxyInfo info;
TestCompletionCallback callback;
rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
&info, callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_TRUE(info.is_direct());
}
}
}
TEST_F(ConfiguredProxyResolutionServiceTest,
CastToConfiguredProxyResolutionService) {
auto config_service =
std::make_unique<MockProxyConfigService>(ProxyConfig::CreateDirect());
ConfiguredProxyResolutionService service(
std::move(config_service),
std::make_unique<MockAsyncProxyResolverFactory>(false),
mock_host_resolver_.get(), nullptr,
true);
ConfiguredProxyResolutionService* casted_service = nullptr;
EXPECT_TRUE(service.CastToConfiguredProxyResolutionService(&casted_service));
EXPECT_EQ(&service, casted_service);
}
TEST_F(ConfiguredProxyResolutionServiceTest, NoMatchingOverrideRule) {
auto config = ProxyConfig::CreateDirect();
auto override_rule =
CreateOverrideRule(kNonMatchingRule, CreateProxyList(kProxy1));
config.set_proxy_override_rules({override_rule});
mock_host_resolver_ = std::make_unique<MockCachingHostResolver>();
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
RecordingNetLogObserver net_log_observer;
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(request);
EXPECT_FALSE(callback.have_result());
EXPECT_TRUE(info.is_direct());
const auto& entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 3U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsEvent(
entries, 1, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 2,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest, NoMatchingOverrideRuleWithPac) {
auto config = ProxyConfig::CreateAutoDetect();
auto override_rule =
CreateOverrideRule(kNonMatchingRule, CreateProxyList(kProxy1));
config.set_proxy_override_rules({override_rule});
mock_host_resolver_ = std::make_unique<MockCachingHostResolver>();
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
RecordingNetLogObserver net_log_observer;
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
GURL sanitized_matching_url(kSanitizedMatchingUrl);
JobMap jobs = GetPendingJobsForURLs(resolver, sanitized_matching_url);
jobs[sanitized_matching_url]->results()->UseNamedProxy("request1:80");
jobs[sanitized_matching_url]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[request1:80]");
const auto& entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 7U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 1,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEndEvent(
entries, 2,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 3, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEndEvent(
entries, 4, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(
entries, 5, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 6,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest, ExcludedOverrideRuleWithPac) {
auto config = ProxyConfig::CreateAutoDetect();
auto override_rule = CreateOverrideRule(
kMatchingRule, CreateProxyList(kProxy1), std::nullopt,
ProxyOverrideRule::DnsProbeCondition::Result::kResolved,
"*.test");
config.set_proxy_override_rules({override_rule});
mock_host_resolver_ = std::make_unique<MockCachingHostResolver>();
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
RecordingNetLogObserver net_log_observer;
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
GURL sanitized_matching_url(kSanitizedMatchingUrl);
JobMap jobs = GetPendingJobsForURLs(resolver, sanitized_matching_url);
jobs[sanitized_matching_url]->results()->UseNamedProxy("request1:80");
jobs[sanitized_matching_url]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[request1:80]");
const auto& entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 7U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 1,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEndEvent(
entries, 2,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 3, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEndEvent(
entries, 4, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(
entries, 5, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 6,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
MatchingOverrideRuleWithHostNotApplyingSync) {
auto config = ProxyConfig::CreateDirect();
auto override_rule = CreateOverrideRule(
kMatchingRule, CreateProxyList(kProxy1), kDnsHost1,
ProxyOverrideRule::DnsProbeCondition::Result::kNotFound);
override_rule.dns_conditions.push_back(
ProxyConfig::ProxyOverrideRule::DnsProbeCondition{
.host = url::SchemeHostPort(GURL(kDnsHost2)),
.result = ProxyOverrideRule::DnsProbeCondition::Result::kNotFound});
config.set_proxy_override_rules({override_rule});
mock_host_resolver_ = std::make_unique<MockCachingHostResolver>();
mock_host_resolver_->set_synchronous_mode(true);
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
RecordingNetLogObserver net_log_observer;
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(request);
EXPECT_FALSE(callback.have_result());
EXPECT_TRUE(info.is_direct());
const auto& entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 8U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 1, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(entries, 2,
NetLogEventType::PROXY_OVERRIDE_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEvent(
entries, 3, NetLogEventType::PROXY_OVERRIDE_BEGIN_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEvent(
entries, 4, NetLogEventType::PROXY_OVERRIDE_END_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(
entries, 5, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(
entries, 6, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 7,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithoutHostAppliedSync) {
auto proxy_list = CreateProxyList(kProxy1);
auto config = ProxyConfig::CreateDirect();
auto override_rule = CreateOverrideRule(kMatchingRule, proxy_list);
config.set_proxy_override_rules({override_rule});
mock_host_resolver_ = std::make_unique<MockCachingHostResolver>();
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
RecordingNetLogObserver net_log_observer;
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(request);
EXPECT_FALSE(callback.have_result());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list));
const auto& entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 4U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsEvent(
entries, 1, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULE_APPLIED,
NetLogEventPhase::NONE));
EXPECT_EQ(entries[1].params, override_rule.ToDict());
EXPECT_TRUE(LogContainsEvent(
entries, 2, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 3,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostAppliedSyncWhenHostIsCached) {
auto proxy_list = CreateProxyList(kProxy1);
auto config = ProxyConfig::CreateDirect();
auto override_rule = CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1);
config.set_proxy_override_rules({override_rule});
mock_host_resolver_ = std::make_unique<MockCachingHostResolver>();
mock_host_resolver_->set_synchronous_mode(true);
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
RecordingNetLogObserver net_log_observer;
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(request);
EXPECT_FALSE(callback.have_result());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list));
const auto& entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 9U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 1, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(entries, 2,
NetLogEventType::PROXY_OVERRIDE_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEvent(
entries, 3, NetLogEventType::PROXY_OVERRIDE_BEGIN_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEvent(
entries, 4, NetLogEventType::PROXY_OVERRIDE_END_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_EQ(GetStringValueFromParams(entries[4], "host"), "https://host1.test");
EXPECT_EQ(GetBooleanValueFromParams(entries[4], "was_resolved_sync"), true);
EXPECT_EQ(GetIntegerValueFromParams(entries[4], "net_error"), 0);
EXPECT_EQ(GetBooleanValueFromParams(entries[4], "is_address_list_empty"),
false);
EXPECT_TRUE(LogContainsEvent(
entries, 5, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULE_APPLIED,
NetLogEventPhase::NONE));
EXPECT_EQ(entries[5].params, override_rule.ToDict());
EXPECT_TRUE(LogContainsEndEvent(
entries, 6, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(
entries, 7, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 8,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
MultipleOverrideRuleWithHostSecondResolutionCompletedAfterRequest) {
auto config = ProxyConfig::CreateDirect();
auto proxy_list1 = CreateProxyList(kProxy1);
auto override_rule1 =
CreateOverrideRule(kMatchingRule, proxy_list1, kDnsHost1);
auto override_rule2 =
CreateOverrideRule(kMatchingRule, CreateProxyList(kProxy2), kDnsHost2);
config.set_proxy_override_rules({override_rule1, override_rule2});
mock_host_resolver_ = std::make_unique<MockCachingHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 2U);
ASSERT_EQ(mock_host_resolver_->request_host(1U), "host1.test");
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
mock_host_resolver_->ResolveNow(1U);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list1));
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
AddDnsEntry(GURL(kDnsHost2), "2.3.4.5");
mock_host_resolver_->ResolveOnlyRequestNow();
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithSecureAndInsecureHostsSeparateDnsRequests) {
ProxyConfig config = ProxyConfig::CreateDirect();
auto proxy_list = CreateProxyList(kProxy1);
auto override_rule = CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1);
constexpr std::string_view kInsecureHost1 = "http://insecure.test:80";
override_rule.dns_conditions.push_back(
ProxyConfig::ProxyOverrideRule::DnsProbeCondition{
.host = url::SchemeHostPort(GURL(kInsecureHost1)),
.result = ProxyOverrideRule::DnsProbeCondition::Result::kResolved});
constexpr std::string_view kInsecureHost2 = "http://host1.test:80";
override_rule.dns_conditions.push_back(
ProxyConfig::ProxyOverrideRule::DnsProbeCondition{
.host = url::SchemeHostPort(GURL(kInsecureHost2)),
.result = ProxyOverrideRule::DnsProbeCondition::Result::kResolved});
config.set_proxy_override_rules({std::move(override_rule)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
auto nak = NetworkAnonymizationKey::CreateSameSite(
net::SchemefulSite(GURL(kMatchingUrl)));
int rv = service.ResolveProxy(GURL(kMatchingUrl), std::string(), nak, &info,
callback.callback(), &request,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 3U);
const auto& request_host_1 = mock_host_resolver_->request_full_host(1U);
ASSERT_TRUE(request_host_1.HasScheme());
EXPECT_EQ(request_host_1.GetScheme(), "https");
EXPECT_EQ(request_host_1.GetHostnameWithoutBrackets(), "host1.test");
EXPECT_EQ(request_host_1.GetPort(), 443);
const auto& request_host_2 = mock_host_resolver_->request_full_host(2U);
ASSERT_FALSE(request_host_2.HasScheme());
EXPECT_EQ(request_host_2.GetHostnameWithoutBrackets(), "insecure.test");
EXPECT_EQ(request_host_2.GetPort(), 80);
const auto& request_host_3 = mock_host_resolver_->request_full_host(3U);
ASSERT_FALSE(request_host_3.HasScheme());
EXPECT_EQ(request_host_3.GetHostnameWithoutBrackets(), "host1.test");
EXPECT_EQ(request_host_3.GetPort(), 80);
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
AddDnsEntry(GURL(kInsecureHost1), "2.3.4.5");
mock_host_resolver_->ResolveAllPending();
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostTwoRequestsSameNak) {
ProxyConfig config = ProxyConfig::CreateDirect();
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
auto nak = NetworkAnonymizationKey::CreateSameSite(
net::SchemefulSite(GURL(kMatchingUrl)));
int rv = service.ResolveProxy(GURL(kMatchingUrl), std::string(), nak, &info1,
callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request1);
ASSERT_FALSE(callback1.have_result());
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
EXPECT_EQ(mock_host_resolver_->request_priority(1U), DEFAULT_PRIORITY);
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
rv = service.ResolveProxy(GURL(kMatchingUrl), std::string(), nak, &info2,
callback2.callback(), &request2, NetLogWithSource(),
HIGHEST);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request2);
ASSERT_FALSE(callback2.have_result());
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
EXPECT_EQ(mock_host_resolver_->request_priority(1U), HIGHEST);
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
mock_host_resolver_->ResolveOnlyRequestNow();
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info1.proxy_list().Equals(proxy_list));
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_TRUE(info2.proxy_list().Equals(proxy_list));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostTwoRequestsDifferentNak) {
ProxyConfig config = ProxyConfig::CreateDirect();
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info1;
TestCompletionCallback callback1;
std::unique_ptr<ProxyResolutionRequest> request1;
auto nak1 = NetworkAnonymizationKey::CreateSameSite(
net::SchemefulSite(GURL(kMatchingUrl)));
int rv = service.ResolveProxy(GURL(kMatchingUrl), std::string(), nak1, &info1,
callback1.callback(), &request1,
NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request1);
ASSERT_FALSE(callback1.have_result());
ProxyInfo info2;
TestCompletionCallback callback2;
std::unique_ptr<ProxyResolutionRequest> request2;
auto nak2 = NetworkAnonymizationKey::CreateCrossSite(
net::SchemefulSite(GURL(kMatchingUrl)));
rv = service.ResolveProxy(GURL(kMatchingUrl), std::string(), nak2, &info2,
callback2.callback(), &request2, NetLogWithSource(),
DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request2);
ASSERT_FALSE(callback2.have_result());
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 2U);
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
mock_host_resolver_->ResolveNow(2U);
EXPECT_THAT(callback2.WaitForResult(), IsOk());
EXPECT_TRUE(info2.proxy_list().Equals(proxy_list));
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
mock_host_resolver_->ResolveNow(1U);
EXPECT_THAT(callback1.WaitForResult(), IsOk());
EXPECT_TRUE(info1.proxy_list().Equals(proxy_list));
EXPECT_FALSE(mock_host_resolver_->has_pending_requests());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleAppliedFixedServerFallbackSync) {
ProxyConfig config;
config.proxy_rules().ParseFromString("http=foopy1:8080");
config.set_auto_detect(false);
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list)});
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
mock_host_resolver_ = std::make_unique<MockHostResolver>();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(request);
EXPECT_FALSE(callback.have_result());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleNotAppliedFallbackFixedServerSync) {
ProxyConfig config;
config.proxy_rules().ParseFromString("https=foopy1:8080");
config.set_auto_detect(false);
config.set_proxy_override_rules(
{CreateOverrideRule(kNonMatchingRule, CreateProxyList(kProxy1))});
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
mock_host_resolver_ = std::make_unique<MockHostResolver>();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsOk());
EXPECT_FALSE(request);
EXPECT_FALSE(callback.have_result());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[foopy1:8080]");
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostNotAppliedFixedServerFallbackSync) {
ProxyConfig config;
config.proxy_rules().ParseFromString("https=foopy1:8080");
config.set_auto_detect(false);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, CreateProxyList(kProxy1), kDnsHost1)});
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
mock_host_resolver_ = std::make_unique<MockHostResolver>();
AddDnsEntry(GURL(kDnsHost1), ERR_NAME_NOT_RESOLVED);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[foopy1:8080]");
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostMatchWithAutoConfig) {
ProxyConfig config = ProxyConfig::CreateAutoDetect();
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostNoMatchWithAutoConfig) {
ProxyConfig config = ProxyConfig::CreateAutoDetect();
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kNonMatchingRule, proxy_list, kDnsHost1)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
GURL sanitized_matching_url(kSanitizedMatchingUrl);
JobMap jobs = GetPendingJobsForURLs(resolver, sanitized_matching_url);
jobs[sanitized_matching_url]->results()->UseNamedProxy("request1:80");
jobs[sanitized_matching_url]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[request1:80]");
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostNoApplyWithPacInBackoffWindow) {
GURL pac_url("http://foopy/proxy.pac");
ProxyConfig config = ProxyConfig::CreateFromCustomPacURL(pac_url);
config.set_pac_mandatory(true);
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
AddDnsEntry(GURL(kDnsHost1), ERR_NAME_NOT_RESOLVED);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
service.set_enable_pac_runtime_backoff_for_testing(true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_EQ(callback.WaitForResult(), ERR_MANDATORY_PROXY_CONFIGURATION_FAILED);
EXPECT_FALSE(info.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest, OverrideRuleWithHostCancelled) {
auto config = ProxyConfig::CreateDirect();
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, CreateProxyList(kProxy1), kDnsHost1)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
RecordingNetLogObserver net_log_observer;
auto nak = net::NetworkAnonymizationKey::CreateCrossSite(
net::SchemefulSite(GURL("https://top.test")));
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), nak, &info, callback.callback(),
&request, NetLogWithSource::Make(NetLogSourceType::NONE), MEDIUM);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
size_t request_id = mock_host_resolver_->last_id();
EXPECT_EQ(mock_host_resolver_->request_network_anonymization_key(request_id),
nak);
EXPECT_EQ(mock_host_resolver_->request_priority(request_id), MEDIUM);
request.reset();
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
mock_host_resolver_->ResolveOnlyRequestNow();
auto entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 7U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 1, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(entries, 2,
NetLogEventType::PROXY_OVERRIDE_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEvent(
entries, 3, NetLogEventType::PROXY_OVERRIDE_BEGIN_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEvent(entries, 4, NetLogEventType::CANCELLED,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(
entries, 5, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEndEvent(entries, 6,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(
ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostConfigChangedToDifferentOverrideRuleWithHostDuringDnsResolution) {
ProxyConfig config = ProxyConfig::CreateDirect();
auto proxy_list1 = CreateProxyList(kProxy1);
auto override_rule1 =
CreateOverrideRule(kMatchingRule, proxy_list1, kDnsHost1);
config.set_proxy_override_rules({override_rule1});
ProxyConfig new_config = ProxyConfig::CreateDirect();
auto proxy_list2 = CreateProxyList(kProxy2);
auto override_rule2 =
CreateOverrideRule(kMatchingRule, proxy_list2, kDnsHost2);
new_config.set_proxy_override_rules({override_rule2});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
auto* config_service_ptr = config_service.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
RecordingNetLogObserver net_log_observer;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request,
NetLogWithSource::Make(NetLogSourceType::NONE), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
config_service_ptr->SetConfig(
ProxyConfigWithAnnotation(new_config, TRAFFIC_ANNOTATION_FOR_TESTS));
AddDnsEntry(GURL(kDnsHost2), "2.3.4.5");
ASSERT_EQ(mock_host_resolver_->last_id(), 2U);
mock_host_resolver_->ResolveOnlyRequestNow();
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list2));
auto entries = net_log_observer.GetEntries();
EXPECT_EQ(entries.size(), 16U);
EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 1, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(entries, 2,
NetLogEventType::PROXY_OVERRIDE_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(entries[2].params.contains("source_dependency"));
EXPECT_TRUE(LogContainsEvent(
entries, 3, NetLogEventType::PROXY_OVERRIDE_BEGIN_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(entries[3].params.contains("source_dependency"));
auto* dns_condition_params = entries[3].params.FindDict("dns_condition");
ASSERT_TRUE(dns_condition_params);
EXPECT_EQ(*dns_condition_params, override_rule1.dns_conditions[0].ToDict());
EXPECT_TRUE(LogContainsEvent(entries, 4, NetLogEventType::CANCELLED,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(
entries, 5, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 6,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEndEvent(
entries, 7,
NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsBeginEvent(
entries, 8, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(entries, 9,
NetLogEventType::PROXY_OVERRIDE_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(entries[9].params.contains("source_dependency"));
EXPECT_TRUE(LogContainsEvent(
entries, 10, NetLogEventType::PROXY_OVERRIDE_BEGIN_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_TRUE(entries[10].params.contains("source_dependency"));
dns_condition_params = entries[10].params.FindDict("dns_condition");
ASSERT_TRUE(dns_condition_params);
EXPECT_EQ(*dns_condition_params, override_rule2.dns_conditions[0].ToDict());
EXPECT_TRUE(LogContainsEvent(
entries, 11, NetLogEventType::PROXY_OVERRIDE_END_HOST_RESOLUTION,
NetLogEventPhase::NONE));
EXPECT_EQ(GetStringValueFromParams(entries[11], "host"),
"https://host2.test");
EXPECT_EQ(GetBooleanValueFromParams(entries[11], "was_resolved_sync"), false);
EXPECT_EQ(GetIntegerValueFromParams(entries[11], "net_error"), 0);
EXPECT_EQ(GetBooleanValueFromParams(entries[11], "is_address_list_empty"),
false);
EXPECT_TRUE(LogContainsEvent(
entries, 12, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULE_APPLIED,
NetLogEventPhase::NONE));
EXPECT_EQ(entries[12].params, override_rule2.ToDict());
EXPECT_TRUE(LogContainsEndEvent(
entries, 13, NetLogEventType::PROXY_RESOLUTION_OVERRIDE_RULES));
EXPECT_TRUE(LogContainsEvent(
entries, 14,
NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
NetLogEventPhase::NONE));
EXPECT_TRUE(LogContainsEndEvent(entries, 15,
NetLogEventType::PROXY_RESOLUTION_SERVICE));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
ThreeOverrideRulesWithPartiallySharedDnsHosts) {
auto proxy_list1 = CreateProxyList(kProxy1);
auto override_rule1 = CreateOverrideRule(kMatchingRule, proxy_list1);
override_rule1.dns_conditions.emplace_back(
url::SchemeHostPort(GURL(kDnsHost1)),
ProxyOverrideRule::DnsProbeCondition::Result::kNotFound);
auto override_rule2 = CreateOverrideRule(kMatchingRule, proxy_list1);
override_rule2.dns_conditions.emplace_back(
url::SchemeHostPort(GURL(kDnsHost2)),
ProxyOverrideRule::DnsProbeCondition::Result::kResolved);
auto proxy_list2 = CreateProxyList(kProxy2);
auto override_rule3 = CreateOverrideRule(kMatchingRule, proxy_list2);
override_rule2.dns_conditions.emplace_back(
url::SchemeHostPort(GURL(kDnsHost1)),
ProxyOverrideRule::DnsProbeCondition::Result::kResolved);
auto config = ProxyConfig::CreateDirect();
config.set_proxy_override_rules({std::move(override_rule1),
std::move(override_rule2),
std::move(override_rule3)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
AddDnsEntry(GURL(kDnsHost2), ERR_NAME_NOT_RESOLVED);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list2));
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostAndPacFallbackConfigChangedToDirectDuringExecution) {
ProxyConfig config = ProxyConfig::CreateAutoDetect();
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
ProxyConfig new_config = ProxyConfig::CreateDirect();
new_config.set_proxy_override_rules(config.proxy_override_rules());
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto* config_service_ptr = config_service.get();
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
config_service_ptr->SetConfig(
ProxyConfigWithAnnotation(new_config, TRAFFIC_ANNOTATION_FOR_TESTS));
AddDnsEntry(GURL(kDnsHost1), ERR_NAME_NOT_RESOLVED);
ASSERT_EQ(mock_host_resolver_->last_id(), 2U);
mock_host_resolver_->ResolveOnlyRequestNow();
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.is_direct());
}
TEST_F(ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostAndPacFallbackConfigChangedToMatchingOverrideRule) {
ProxyConfig config = ProxyConfig::CreateAutoDetect();
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kNonMatchingRule, proxy_list, kDnsHost1)});
ProxyConfig new_config = ProxyConfig::CreateAutoDetect();
new_config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto* config_service_ptr = config_service.get();
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_FALSE(mock_host_resolver_->has_pending_requests());
GURL sanitized_matching_url(kSanitizedMatchingUrl);
JobMap jobs = GetPendingJobsForURLs(resolver, sanitized_matching_url);
ASSERT_EQ(jobs.size(), 1U);
config_service_ptr->SetConfig(
ProxyConfigWithAnnotation(new_config, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_TRUE(resolver.pending_jobs().empty());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
mock_host_resolver_->ResolveOnlyRequestNow();
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_TRUE(info.proxy_list().Equals(proxy_list));
}
TEST_F(
ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostConfigChangedToAdditionalPacFallbackDuringExecution) {
ProxyConfig config = ProxyConfig::CreateDirect();
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
ProxyConfig new_config = ProxyConfig::CreateAutoDetect();
new_config.set_proxy_override_rules(config.proxy_override_rules());
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto* config_service_ptr = config_service.get();
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
config_service_ptr->SetConfig(
ProxyConfigWithAnnotation(new_config, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
AddDnsEntry(GURL(kDnsHost1), ERR_NAME_NOT_RESOLVED);
ASSERT_EQ(mock_host_resolver_->last_id(), 2U);
mock_host_resolver_->ResolveOnlyRequestNow();
GURL sanitized_matching_url(kSanitizedMatchingUrl);
JobMap jobs = GetPendingJobsForURLs(resolver, sanitized_matching_url);
jobs[sanitized_matching_url]->results()->UseNamedProxy("request1:80");
jobs[sanitized_matching_url]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[request1:80]");
}
TEST_F(
ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostAndPacFallbackConfigChangedToDifferentPacFallbackDuringExecution) {
GURL pac_url("http://foopy/proxy.pac");
ProxyConfig config = ProxyConfig::CreateFromCustomPacURL(pac_url);
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
ProxyConfig new_config = ProxyConfig::CreateAutoDetect();
new_config.set_proxy_override_rules(config.proxy_override_rules());
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto* config_service_ptr = config_service.get();
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
config_service_ptr->SetConfig(
ProxyConfigWithAnnotation(new_config, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
EXPECT_EQ(kValidPacScript216,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
AddDnsEntry(GURL(kDnsHost1), ERR_NAME_NOT_RESOLVED);
ASSERT_EQ(mock_host_resolver_->last_id(), 2U);
mock_host_resolver_->ResolveOnlyRequestNow();
GURL sanitized_matching_url(kSanitizedMatchingUrl);
JobMap jobs = GetPendingJobsForURLs(resolver, sanitized_matching_url);
jobs[sanitized_matching_url]->results()->UseNamedProxy("request1:80");
jobs[sanitized_matching_url]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[request1:80]");
}
TEST_F(
ConfiguredProxyResolutionServiceTest,
OverrideRuleWithHostAndPacFallbackConfigChangedToDifferentPacFallbackWithDelayDuringExecution) {
GURL pac_url("http://foopy/proxy.pac");
ProxyConfig config = ProxyConfig::CreateFromCustomPacURL(pac_url);
auto proxy_list = CreateProxyList(kProxy1);
config.set_proxy_override_rules(
{CreateOverrideRule(kMatchingRule, proxy_list, kDnsHost1)});
ProxyConfig new_config = ProxyConfig::CreateAutoDetect();
new_config.set_proxy_override_rules(config.proxy_override_rules());
mock_host_resolver_ = std::make_unique<MockHostResolver>();
mock_host_resolver_->set_ondemand_mode(true);
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto* config_service_ptr = config_service.get();
MockAsyncProxyResolver resolver;
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
auto* factory_ptr = factory.get();
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
auto fetcher = std::make_unique<MockPacFileFetcher>();
auto* fetcher_ptr = fetcher.get();
service.SetPacFileFetchers(std::move(fetcher),
std::make_unique<DoNothingDhcpPacFileFetcher>());
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_TRUE(fetcher_ptr->has_pending_request());
EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
EXPECT_EQ(kValidPacScript116,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 1U);
config_service_ptr->SetConfig(
ProxyConfigWithAnnotation(new_config, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_TRUE(fetcher_ptr->has_pending_request());
ASSERT_FALSE(mock_host_resolver_->has_pending_requests());
ASSERT_FALSE(callback.have_result());
EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
EXPECT_EQ(kValidPacScript216,
factory_ptr->pending_requests()[0]->script_data()->utf16());
factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_TRUE(mock_host_resolver_->has_pending_requests());
ASSERT_EQ(mock_host_resolver_->last_id(), 2U);
AddDnsEntry(GURL(kDnsHost1), ERR_NAME_NOT_RESOLVED);
mock_host_resolver_->ResolveOnlyRequestNow();
GURL sanitized_matching_url(kSanitizedMatchingUrl);
JobMap jobs = GetPendingJobsForURLs(resolver, sanitized_matching_url);
jobs[sanitized_matching_url]->results()->UseNamedProxy("request1:80");
jobs[sanitized_matching_url]->CompleteNow(OK);
EXPECT_THAT(callback.WaitForResult(), IsOk());
EXPECT_EQ(info.proxy_chain().ToDebugString(), "[request1:80]");
}
struct TwoDnsConditionsTestCase {
bool first_condition_resolves;
bool first_host_found;
bool second_condition_resolves;
bool second_host_found;
bool resolution_completed_in_order = true;
bool is_resolution_sync = false;
bool is_rule_applied = false;
};
class TwoDnsConditionsConfiguredProxyResolutionServiceTest
: public ConfiguredProxyResolutionServiceTest,
public testing::WithParamInterface<TwoDnsConditionsTestCase> {
protected:
TwoDnsConditionsConfiguredProxyResolutionServiceTest() = default;
~TwoDnsConditionsConfiguredProxyResolutionServiceTest() override = default;
};
TEST_P(TwoDnsConditionsConfiguredProxyResolutionServiceTest,
OverrideRuleWithTwoDnsConditionsParameterizedTest) {
auto params = GetParam();
auto proxy_list = CreateProxyList(kProxy1);
auto config = ProxyConfig::CreateDirect();
auto override_rule = CreateOverrideRule(
kMatchingRule, proxy_list, kDnsHost1,
params.first_condition_resolves
? ProxyOverrideRule::DnsProbeCondition::Result::kResolved
: ProxyOverrideRule::DnsProbeCondition::Result::kNotFound);
override_rule.dns_conditions.push_back(
ProxyConfig::ProxyOverrideRule::DnsProbeCondition{
.host = url::SchemeHostPort(GURL(kDnsHost2)),
.result =
params.second_condition_resolves
? ProxyOverrideRule::DnsProbeCondition::Result::kResolved
: ProxyOverrideRule::DnsProbeCondition::Result::kNotFound});
config.set_proxy_override_rules({std::move(override_rule)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
if (params.is_resolution_sync) {
mock_host_resolver_->set_synchronous_mode(true);
} else {
mock_host_resolver_->set_ondemand_mode(true);
}
if (params.first_host_found) {
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
} else {
AddDnsEntry(GURL(kDnsHost1), ERR_NAME_NOT_RESOLVED);
}
if (params.second_host_found) {
AddDnsEntry(GURL(kDnsHost2), "2.3.4.5");
} else {
AddDnsEntry(GURL(kDnsHost2), ERR_NAME_NOT_RESOLVED);
}
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
if (params.is_resolution_sync) {
EXPECT_THAT(rv, IsOk());
} else {
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
ASSERT_EQ(mock_host_resolver_->last_id(), 2u);
if (params.resolution_completed_in_order) {
mock_host_resolver_->ResolveNow(1u);
mock_host_resolver_->ResolveNow(2u);
} else {
mock_host_resolver_->ResolveNow(2u);
mock_host_resolver_->ResolveNow(1u);
}
EXPECT_THAT(callback.WaitForResult(), IsOk());
}
if (params.is_rule_applied) {
EXPECT_TRUE(info.proxy_list().Equals(proxy_list));
} else {
EXPECT_TRUE(info.is_direct());
}
}
INSTANTIATE_TEST_SUITE_P(
,
TwoDnsConditionsConfiguredProxyResolutionServiceTest,
::testing::ValuesIn({
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = true,
.is_rule_applied = true},
TwoDnsConditionsTestCase{.first_condition_resolves = false,
.first_host_found = false,
.second_condition_resolves = true,
.second_host_found = true,
.is_rule_applied = true},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = false,
.second_host_found = false,
.is_rule_applied = true},
TwoDnsConditionsTestCase{.first_condition_resolves = false,
.first_host_found = false,
.second_condition_resolves = false,
.second_host_found = false,
.is_rule_applied = true},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = false,
.second_condition_resolves = true,
.second_host_found = true,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = false,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = true,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = false,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = false,
.second_host_found = true,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = false,
.first_host_found = true,
.second_condition_resolves = false,
.second_host_found = true,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = true,
.is_resolution_sync = true,
.is_rule_applied = true},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = false,
.is_resolution_sync = true,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = false,
.second_condition_resolves = true,
.second_host_found = true,
.is_resolution_sync = true,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = true,
.resolution_completed_in_order = true,
.is_rule_applied = true},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = false,
.resolution_completed_in_order = true,
.is_rule_applied = false},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = true,
.resolution_completed_in_order = false,
.is_rule_applied = true},
TwoDnsConditionsTestCase{.first_condition_resolves = true,
.first_host_found = true,
.second_condition_resolves = true,
.second_host_found = false,
.resolution_completed_in_order = false,
.is_rule_applied = false},
}));
struct TwoRulesTestCase {
bool first_rule_matches;
bool first_rule_has_host;
bool first_dns_host_resolves = false;
bool result_is_first_rule = false;
bool second_rule_matches;
bool second_rule_has_host;
bool second_dns_host_resolves = false;
bool result_is_second_rule = false;
bool completes_synchronously = false;
};
class TwoRulesConfiguredProxyResolutionServiceTest
: public ConfiguredProxyResolutionServiceTest,
public testing::WithParamInterface<TwoRulesTestCase> {
protected:
TwoRulesConfiguredProxyResolutionServiceTest() = default;
~TwoRulesConfiguredProxyResolutionServiceTest() override = default;
};
TEST_P(TwoRulesConfiguredProxyResolutionServiceTest,
TwoOverrideRulesParameterizedTest) {
auto params = GetParam();
auto proxy_list1 = CreateProxyList(kProxy1);
auto override_rule1 = CreateOverrideRule(
params.first_rule_matches ? kMatchingRule : kNonMatchingRule,
proxy_list1);
if (params.first_rule_has_host) {
override_rule1.dns_conditions.emplace_back(
url::SchemeHostPort(GURL(kDnsHost1)),
params.first_dns_host_resolves
? ProxyOverrideRule::DnsProbeCondition::Result::kResolved
: ProxyOverrideRule::DnsProbeCondition::Result::kNotFound);
}
auto proxy_list2 = CreateProxyList(kProxy2);
auto override_rule2 = CreateOverrideRule(
params.second_rule_matches ? kMatchingRule : kNonMatchingRule,
proxy_list2);
if (params.second_rule_has_host) {
override_rule2.dns_conditions.emplace_back(
url::SchemeHostPort(GURL(kDnsHost2)),
params.second_dns_host_resolves
? ProxyOverrideRule::DnsProbeCondition::Result::kResolved
: ProxyOverrideRule::DnsProbeCondition::Result::kNotFound);
}
auto config = ProxyConfig::CreateDirect();
config.set_proxy_override_rules(
{std::move(override_rule1), std::move(override_rule2)});
mock_host_resolver_ = std::make_unique<MockHostResolver>();
AddDnsEntry(GURL(kDnsHost1), "1.2.3.4");
AddDnsEntry(GURL(kDnsHost2), "2.3.4.5");
auto config_service =
std::make_unique<MockProxyConfigService>(std::move(config));
auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
ConfiguredProxyResolutionService service(
std::move(config_service), std::move(factory), mock_host_resolver_.get(),
nullptr,
true);
ProxyInfo info;
TestCompletionCallback callback;
std::unique_ptr<ProxyResolutionRequest> request;
int rv = service.ResolveProxy(
GURL(kMatchingUrl), std::string(), NetworkAnonymizationKey(), &info,
callback.callback(), &request, NetLogWithSource(), DEFAULT_PRIORITY);
if (params.completes_synchronously) {
EXPECT_THAT(rv, IsOk());
} else {
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_TRUE(request);
ASSERT_FALSE(callback.have_result());
EXPECT_THAT(callback.WaitForResult(), IsOk());
}
if (params.result_is_first_rule) {
EXPECT_TRUE(info.proxy_list().Equals(proxy_list1));
} else if (params.result_is_second_rule) {
EXPECT_TRUE(info.proxy_list().Equals(proxy_list2));
} else {
EXPECT_TRUE(info.is_direct());
}
}
INSTANTIATE_TEST_SUITE_P(,
TwoRulesConfiguredProxyResolutionServiceTest,
::testing::ValuesIn({
TwoRulesTestCase{.first_rule_matches = true,
.first_rule_has_host = false,
.result_is_first_rule = true,
.second_rule_matches = true,
.second_rule_has_host = false,
.result_is_second_rule = false,
.completes_synchronously = true},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = false,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = false,
.result_is_second_rule = true,
.completes_synchronously = true},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = false,
.result_is_first_rule = false,
.second_rule_matches = false,
.second_rule_has_host = false,
.result_is_second_rule = false,
.completes_synchronously = true},
TwoRulesTestCase{.first_rule_matches = true,
.first_rule_has_host = true,
.first_dns_host_resolves = true,
.result_is_first_rule = true,
.second_rule_matches = true,
.second_rule_has_host = false,
.result_is_second_rule = false},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = true,
.first_dns_host_resolves = true,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = false,
.result_is_second_rule = true,
.completes_synchronously = true},
TwoRulesTestCase{.first_rule_matches = true,
.first_rule_has_host = true,
.first_dns_host_resolves = false,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = false,
.result_is_second_rule = true},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = true,
.first_dns_host_resolves = false,
.result_is_first_rule = false,
.second_rule_matches = false,
.second_rule_has_host = false,
.result_is_second_rule = false,
.completes_synchronously = true},
TwoRulesTestCase{.first_rule_matches = true,
.first_rule_has_host = false,
.result_is_first_rule = true,
.second_rule_matches = true,
.second_rule_has_host = true,
.second_dns_host_resolves = true,
.result_is_second_rule = false,
.completes_synchronously = true},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = false,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = true,
.second_dns_host_resolves = true,
.result_is_second_rule = true},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = false,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = true,
.second_dns_host_resolves = false,
.result_is_second_rule = false},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = false,
.result_is_first_rule = false,
.second_rule_matches = false,
.second_rule_has_host = true,
.second_dns_host_resolves = true,
.result_is_second_rule = false,
.completes_synchronously = true},
TwoRulesTestCase{.first_rule_matches = true,
.first_rule_has_host = true,
.first_dns_host_resolves = true,
.result_is_first_rule = true,
.second_rule_matches = true,
.second_rule_has_host = true,
.second_dns_host_resolves = true,
.result_is_second_rule = false},
TwoRulesTestCase{.first_rule_matches = true,
.first_rule_has_host = true,
.first_dns_host_resolves = false,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = true,
.second_dns_host_resolves = true,
.result_is_second_rule = true},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = true,
.first_dns_host_resolves = true,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = true,
.second_dns_host_resolves = true,
.result_is_second_rule = true},
TwoRulesTestCase{.first_rule_matches = true,
.first_rule_has_host = true,
.first_dns_host_resolves = false,
.result_is_first_rule = false,
.second_rule_matches = true,
.second_rule_has_host = true,
.second_dns_host_resolves = false,
.result_is_second_rule = false},
TwoRulesTestCase{.first_rule_matches = false,
.first_rule_has_host = true,
.first_dns_host_resolves = true,
.result_is_first_rule = false,
.second_rule_matches = false,
.second_rule_has_host = true,
.second_dns_host_resolves = true,
.result_is_second_rule = false,
.completes_synchronously = true},
}));
}