Commit d2ae3b7c authored by Clark DuVall's avatar Clark DuVall Committed by Commit Bot

Keep previously configured DRP servers in network service

This matches the logic in http://crrev.com/c/1045025. A couple of the
most recent configs are kept around in case the config changes in the
middle of a request, which will allow the headers to be correct in that
case.

Also adds a browsertest for basic config changes.

Bug: 721403
Change-Id: I788dcf52efa9a86031fd33cbc77d1be45022b19c
Reviewed-on: https://chromium-review.googlesource.com/c/1292510
Commit-Queue: Clark DuVall <cduvall@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarrajendrant <rajendrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601701}
parent 51006ebf
...@@ -23,13 +23,19 @@ ...@@ -23,13 +23,19 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h" #include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h" #include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h" #include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h" #include "net/test/embedded_test_server/http_response.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h" #include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
namespace data_reduction_proxy { namespace data_reduction_proxy {
...@@ -62,19 +68,36 @@ std::unique_ptr<net::test_server::HttpResponse> IncrementRequestCount( ...@@ -62,19 +68,36 @@ std::unique_ptr<net::test_server::HttpResponse> IncrementRequestCount(
return std::make_unique<net::test_server::BasicHttpResponse>(); return std::make_unique<net::test_server::BasicHttpResponse>();
} }
void SimulateNetworkChange(network::mojom::ConnectionType type) {
if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
!content::IsNetworkServiceRunningInProcess()) {
network::mojom::NetworkServiceTestPtr network_service_test;
content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->BindInterface(content::mojom::kNetworkServiceName,
&network_service_test);
base::RunLoop run_loop;
network_service_test->SimulateNetworkChange(type, run_loop.QuitClosure());
run_loop.Run();
return;
}
net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
net::NetworkChangeNotifier::ConnectionType(type));
}
ClientConfig CreateConfigForServer(const net::EmbeddedTestServer& server) {
net::HostPortPair host_port_pair = server.host_port_pair();
return CreateConfig(
kSessionKey, 1000, 0, ProxyServer_ProxyScheme_HTTP, host_port_pair.host(),
host_port_pair.port(), ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
"fallback.net", 80, ProxyServer::UNSPECIFIED_TYPE, 0.5f, false);
}
} // namespace } // namespace
class DataReductionProxyBrowsertestBase : public InProcessBrowserTest { class DataReductionProxyBrowsertestBase : public InProcessBrowserTest {
public: public:
void SetUpCommandLine(base::CommandLine* command_line) override { void SetUpCommandLine(base::CommandLine* command_line) override {
net::HostPortPair host_port_pair = embedded_test_server()->host_port_pair();
std::string config = EncodeConfig(CreateConfig(
kSessionKey, 1000, 0, ProxyServer_ProxyScheme_HTTP,
host_port_pair.host(), host_port_pair.port(), ProxyServer::CORE,
ProxyServer_ProxyScheme_HTTP, "fallback.net", 80,
ProxyServer::UNSPECIFIED_TYPE, 0.5f, false));
command_line->AppendSwitchASCII(
switches::kDataReductionProxyServerClientConfig, config);
command_line->AppendSwitchASCII( command_line->AppendSwitchASCII(
network::switches::kForceEffectiveConnectionType, "4G"); network::switches::kForceEffectiveConnectionType, "4G");
...@@ -84,6 +107,13 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest { ...@@ -84,6 +107,13 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest {
command_line->AppendSwitchASCII( command_line->AppendSwitchASCII(
switches::kDataReductionProxySecureProxyCheckURL, switches::kDataReductionProxySecureProxyCheckURL,
secure_proxy_check_server_.base_url().spec()); secure_proxy_check_server_.base_url().spec());
config_server_.RegisterRequestHandler(base::BindRepeating(
&DataReductionProxyBrowsertestBase::GetConfigResponse,
base::Unretained(this)));
ASSERT_TRUE(config_server_.Start());
command_line->AppendSwitchASCII(switches::kDataReductionProxyConfigURL,
config_server_.base_url().spec());
} }
void SetUp() override { void SetUp() override {
...@@ -93,7 +123,6 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest { ...@@ -93,7 +123,6 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest {
features::kDataReductionProxyRobustConnection, features::kDataReductionProxyRobustConnection,
{{params::GetMissingViaBypassParamName(), "true"}, {{params::GetMissingViaBypassParamName(), "true"},
{"warmup_fetch_callback_enabled", "true"}}); {"warmup_fetch_callback_enabled", "true"}});
ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
InProcessBrowserTest::SetUp(); InProcessBrowserTest::SetUp();
} }
...@@ -102,10 +131,16 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest { ...@@ -102,10 +131,16 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest {
favicon_catcher_ = favicon_catcher_ =
std::make_unique<net::test_server::ControllableHttpResponse>( std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), "/favicon.ico"); embedded_test_server(), "/favicon.ico");
embedded_test_server()->StartAcceptingConnections(); ASSERT_TRUE(embedded_test_server()->Start());
// Set a default proxy config if one isn't set yet.
if (!config_.has_proxy_config())
SetConfig(CreateConfigForServer(*embedded_test_server()));
host_resolver()->AddRule(kMockHost, "127.0.0.1"); host_resolver()->AddRule(kMockHost, "127.0.0.1");
EnableDataSaver(true); EnableDataSaver(true);
// Make sure initial config has been loaded.
WaitForConfig();
} }
protected: protected:
...@@ -134,10 +169,30 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest { ...@@ -134,10 +169,30 @@ class DataReductionProxyBrowsertestBase : public InProcessBrowserTest {
return base_url.Resolve(relative_url); return base_url.Resolve(relative_url);
} }
void SetConfig(const ClientConfig& config) {
config_run_loop_ = std::make_unique<base::RunLoop>();
config_ = config;
}
void WaitForConfig() { config_run_loop_->Run(); }
private: private:
std::unique_ptr<net::test_server::HttpResponse> GetConfigResponse(
const net::test_server::HttpRequest& request) {
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
response->set_content(config_.SerializeAsString());
response->set_content_type("text/plain");
if (config_run_loop_)
config_run_loop_->Quit();
return response;
}
ClientConfig config_;
std::unique_ptr<base::RunLoop> config_run_loop_;
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
base::test::ScopedFeatureList param_feature_list_; base::test::ScopedFeatureList param_feature_list_;
net::EmbeddedTestServer secure_proxy_check_server_; net::EmbeddedTestServer secure_proxy_check_server_;
net::EmbeddedTestServer config_server_;
std::unique_ptr<net::test_server::ControllableHttpResponse> favicon_catcher_; std::unique_ptr<net::test_server::ControllableHttpResponse> favicon_catcher_;
}; };
...@@ -150,6 +205,36 @@ class DataReductionProxyBrowsertest : public DataReductionProxyBrowsertestBase { ...@@ -150,6 +205,36 @@ class DataReductionProxyBrowsertest : public DataReductionProxyBrowsertestBase {
} }
}; };
IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, UpdateConfig) {
net::EmbeddedTestServer original_server;
original_server.RegisterRequestHandler(
base::BindRepeating(&BasicResponse, kPrimaryResponse));
ASSERT_TRUE(original_server.Start());
SetConfig(CreateConfigForServer(original_server));
// A network change forces the config to be fetched.
SimulateNetworkChange(network::mojom::ConnectionType::CONNECTION_3G);
WaitForConfig();
ui_test_utils::NavigateToURL(browser(), GURL("http://does.not.resolve/foo"));
EXPECT_EQ(GetBody(), kPrimaryResponse);
net::EmbeddedTestServer new_server;
new_server.RegisterRequestHandler(
base::BindRepeating(&BasicResponse, kSecondaryResponse));
ASSERT_TRUE(new_server.Start());
SetConfig(CreateConfigForServer(new_server));
// A network change forces the config to be fetched.
SimulateNetworkChange(network::mojom::ConnectionType::CONNECTION_2G);
WaitForConfig();
ui_test_utils::NavigateToURL(browser(), GURL("http://does.not.resolve/foo"));
EXPECT_EQ(GetBody(), kSecondaryResponse);
}
IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, ChromeProxyHeaderSet) { IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, ChromeProxyHeaderSet) {
// Proxy will be used, so it shouldn't matter if the host cannot be resolved. // Proxy will be used, so it shouldn't matter if the host cannot be resolved.
ui_test_utils::NavigateToURL( ui_test_utils::NavigateToURL(
...@@ -241,9 +326,7 @@ IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, UMAMetricsRecorded) { ...@@ -241,9 +326,7 @@ IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, UMAMetricsRecorded) {
class DataReductionProxyFallbackBrowsertest class DataReductionProxyFallbackBrowsertest
: public DataReductionProxyBrowsertest { : public DataReductionProxyBrowsertest {
public: public:
void SetUpCommandLine(base::CommandLine* command_line) override { void SetUpOnMainThread() override {
DataReductionProxyBrowsertest::SetUpCommandLine(command_line);
// Set up a primary server which will return the Chrome-Proxy header set by // Set up a primary server which will return the Chrome-Proxy header set by
// SetHeader() and status set by SetStatusCode(). Secondary server will just // SetHeader() and status set by SetStatusCode(). Secondary server will just
// return the secondary response. // return the secondary response.
...@@ -259,14 +342,14 @@ class DataReductionProxyFallbackBrowsertest ...@@ -259,14 +342,14 @@ class DataReductionProxyFallbackBrowsertest
net::HostPortPair primary_host_port_pair = primary_server_.host_port_pair(); net::HostPortPair primary_host_port_pair = primary_server_.host_port_pair();
net::HostPortPair secondary_host_port_pair = net::HostPortPair secondary_host_port_pair =
secondary_server_.host_port_pair(); secondary_server_.host_port_pair();
std::string config = EncodeConfig(CreateConfig( SetConfig(CreateConfig(
kSessionKey, 1000, 0, ProxyServer_ProxyScheme_HTTP, kSessionKey, 1000, 0, ProxyServer_ProxyScheme_HTTP,
primary_host_port_pair.host(), primary_host_port_pair.port(), primary_host_port_pair.host(), primary_host_port_pair.port(),
ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP, ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
secondary_host_port_pair.host(), secondary_host_port_pair.port(), secondary_host_port_pair.host(), secondary_host_port_pair.port(),
ProxyServer::CORE, 0.5f, false)); ProxyServer::CORE, 0.5f, false));
command_line->AppendSwitchASCII(
switches::kDataReductionProxyServerClientConfig, config); DataReductionProxyBrowsertest::SetUpOnMainThread();
} }
void SetHeader(const std::string& header) { header_ = header; } void SetHeader(const std::string& header) { header_ = header; }
...@@ -387,9 +470,7 @@ IN_PROC_BROWSER_TEST_F(DataReductionProxyFallbackBrowsertest, ...@@ -387,9 +470,7 @@ IN_PROC_BROWSER_TEST_F(DataReductionProxyFallbackBrowsertest,
class DataReductionProxyResourceTypeBrowsertest class DataReductionProxyResourceTypeBrowsertest
: public DataReductionProxyBrowsertest { : public DataReductionProxyBrowsertest {
public: public:
void SetUpCommandLine(base::CommandLine* command_line) override { void SetUpOnMainThread() override {
DataReductionProxyBrowsertest::SetUpCommandLine(command_line);
// Two proxies are set up here, one with type CORE and one UNSPECIFIED_TYPE. // Two proxies are set up here, one with type CORE and one UNSPECIFIED_TYPE.
// The CORE proxy is the secondary, and should be used for requests from the // The CORE proxy is the secondary, and should be used for requests from the
// <video> tag. // <video> tag.
...@@ -404,14 +485,14 @@ class DataReductionProxyResourceTypeBrowsertest ...@@ -404,14 +485,14 @@ class DataReductionProxyResourceTypeBrowsertest
net::HostPortPair unspecified_host_port_pair = net::HostPortPair unspecified_host_port_pair =
unspecified_server_.host_port_pair(); unspecified_server_.host_port_pair();
net::HostPortPair core_host_port_pair = core_server_.host_port_pair(); net::HostPortPair core_host_port_pair = core_server_.host_port_pair();
std::string config = EncodeConfig(CreateConfig( SetConfig(CreateConfig(
kSessionKey, 1000, 0, ProxyServer_ProxyScheme_HTTP, kSessionKey, 1000, 0, ProxyServer_ProxyScheme_HTTP,
unspecified_host_port_pair.host(), unspecified_host_port_pair.port(), unspecified_host_port_pair.host(), unspecified_host_port_pair.port(),
ProxyServer::UNSPECIFIED_TYPE, ProxyServer_ProxyScheme_HTTP, ProxyServer::UNSPECIFIED_TYPE, ProxyServer_ProxyScheme_HTTP,
core_host_port_pair.host(), core_host_port_pair.port(), core_host_port_pair.host(), core_host_port_pair.port(),
ProxyServer::CORE, 0.5f, false)); ProxyServer::CORE, 0.5f, false));
command_line->AppendSwitchASCII(
switches::kDataReductionProxyServerClientConfig, config); DataReductionProxyBrowsertest::SetUpOnMainThread();
} }
int unspecified_request_count_ = 0; int unspecified_request_count_ = 0;
...@@ -458,23 +539,30 @@ class DataReductionProxyWarmupURLBrowsertest ...@@ -458,23 +539,30 @@ class DataReductionProxyWarmupURLBrowsertest
primary_server_(GetTestServerType()), primary_server_(GetTestServerType()),
secondary_server_(GetTestServerType()) {} secondary_server_(GetTestServerType()) {}
void SetUpCommandLine(base::CommandLine* command_line) override { void SetUpOnMainThread() override {
DataReductionProxyBrowsertestBase::SetUpCommandLine(command_line); primary_server_loop_ = std::make_unique<base::RunLoop>();
primary_server_.RegisterRequestHandler(base::BindRepeating(
&DataReductionProxyWarmupURLBrowsertest::WaitForWarmupRequest,
base::Unretained(this), primary_server_loop_.get()));
ASSERT_TRUE(primary_server_.Start());
ASSERT_TRUE(primary_server_.InitializeAndListen()); secondary_server_loop_ = std::make_unique<base::RunLoop>();
ASSERT_TRUE(secondary_server_.InitializeAndListen()); secondary_server_.RegisterRequestHandler(base::BindRepeating(
&DataReductionProxyWarmupURLBrowsertest::WaitForWarmupRequest,
base::Unretained(this), secondary_server_loop_.get()));
ASSERT_TRUE(secondary_server_.Start());
net::HostPortPair primary_host_port_pair = primary_server_.host_port_pair(); net::HostPortPair primary_host_port_pair = primary_server_.host_port_pair();
net::HostPortPair secondary_host_port_pair = net::HostPortPair secondary_host_port_pair =
secondary_server_.host_port_pair(); secondary_server_.host_port_pair();
std::string config = EncodeConfig(CreateConfig( SetConfig(CreateConfig(
kSessionKey, 1000, 0, std::get<0>(GetParam()), kSessionKey, 1000, 0, std::get<0>(GetParam()),
primary_host_port_pair.host(), primary_host_port_pair.port(), primary_host_port_pair.host(), primary_host_port_pair.port(),
ProxyServer::UNSPECIFIED_TYPE, std::get<0>(GetParam()), ProxyServer::UNSPECIFIED_TYPE, std::get<0>(GetParam()),
secondary_host_port_pair.host(), secondary_host_port_pair.port(), secondary_host_port_pair.host(), secondary_host_port_pair.port(),
ProxyServer::CORE, 0.5f, false)); ProxyServer::CORE, 0.5f, false));
command_line->AppendSwitchASCII(
switches::kDataReductionProxyServerClientConfig, config); DataReductionProxyBrowsertestBase::SetUpOnMainThread();
} }
// Retries fetching |histogram_name| until it contains at least |count| // Retries fetching |histogram_name| until it contains at least |count|
...@@ -498,22 +586,6 @@ class DataReductionProxyWarmupURLBrowsertest ...@@ -498,22 +586,6 @@ class DataReductionProxyWarmupURLBrowsertest
} }
} }
void SetUpOnMainThread() override {
primary_server_loop_ = std::make_unique<base::RunLoop>();
primary_server_.RegisterRequestHandler(base::BindRepeating(
&DataReductionProxyWarmupURLBrowsertest::WaitForWarmupRequest,
base::Unretained(this), primary_server_loop_.get()));
primary_server_.StartAcceptingConnections();
secondary_server_loop_ = std::make_unique<base::RunLoop>();
secondary_server_.RegisterRequestHandler(base::BindRepeating(
&DataReductionProxyWarmupURLBrowsertest::WaitForWarmupRequest,
base::Unretained(this), secondary_server_loop_.get()));
secondary_server_.StartAcceptingConnections();
DataReductionProxyBrowsertestBase::SetUpOnMainThread();
}
std::string GetHistogramName(ProxyServer::ProxyType type) { std::string GetHistogramName(ProxyServer::ProxyType type) {
return base::StrCat( return base::StrCat(
{"DataReductionProxy.WarmupURLFetcherCallback.SuccessfulFetch.", {"DataReductionProxy.WarmupURLFetcherCallback.SuccessfulFetch.",
......
...@@ -16,6 +16,9 @@ namespace { ...@@ -16,6 +16,9 @@ namespace {
// alternate proxy list. // alternate proxy list.
constexpr size_t kMaxCacheSize = 15; constexpr size_t kMaxCacheSize = 15;
// The maximum number of previous configs to keep.
constexpr size_t kMaxPreviousConfigs = 2;
void GetAlternativeProxy(const GURL& url, void GetAlternativeProxy(const GURL& url,
const net::ProxyRetryInfoMap& proxy_retry_info, const net::ProxyRetryInfoMap& proxy_retry_info,
net::ProxyInfo* result) { net::ProxyInfo* result) {
...@@ -55,12 +58,19 @@ bool ApplyProxyConfigToProxyInfo(const net::ProxyConfig::ProxyRules& rules, ...@@ -55,12 +58,19 @@ bool ApplyProxyConfigToProxyInfo(const net::ProxyConfig::ProxyRules& rules,
bool CheckProxyList(const net::ProxyList& proxy_list, bool CheckProxyList(const net::ProxyList& proxy_list,
const net::ProxyServer& target_proxy) { const net::ProxyServer& target_proxy) {
for (const auto& proxy : proxy_list.GetAll()) { for (const auto& proxy : proxy_list.GetAll()) {
if (proxy.host_port_pair().Equals(target_proxy.host_port_pair())) if (!proxy.is_direct() &&
proxy.host_port_pair().Equals(target_proxy.host_port_pair())) {
return true; return true;
}
} }
return false; return false;
} }
// Whether the custom proxy can proxy |url|.
bool IsURLValidForProxy(const GURL& url) {
return url.SchemeIs(url::kHttpScheme) && !net::IsLocalhost(url);
}
} // namespace } // namespace
NetworkServiceProxyDelegate::NetworkServiceProxyDelegate( NetworkServiceProxyDelegate::NetworkServiceProxyDelegate(
...@@ -96,9 +106,7 @@ void NetworkServiceProxyDelegate::OnBeforeSendHeaders( ...@@ -96,9 +106,7 @@ void NetworkServiceProxyDelegate::OnBeforeSendHeaders(
if (url_loader) { if (url_loader) {
headers->MergeFrom(url_loader->custom_proxy_post_cache_headers()); headers->MergeFrom(url_loader->custom_proxy_post_cache_headers());
} }
// TODO(crbug.com/721403): This check may be incorrect if a new proxy config } else if (MayHaveProxiedURL(request->url())) {
// is set between OnBeforeStartTransaction and here.
} else if (MayProxyURL(request->url())) {
for (const auto& kv : proxy_config_->pre_cache_headers.GetHeaderVector()) { for (const auto& kv : proxy_config_->pre_cache_headers.GetHeaderVector()) {
headers->RemoveHeader(kv.key); headers->RemoveHeader(kv.key);
} }
...@@ -138,6 +146,11 @@ void NetworkServiceProxyDelegate::OnCustomProxyConfigUpdated( ...@@ -138,6 +146,11 @@ void NetworkServiceProxyDelegate::OnCustomProxyConfigUpdated(
mojom::CustomProxyConfigPtr proxy_config) { mojom::CustomProxyConfigPtr proxy_config) {
DCHECK(proxy_config->rules.empty() || DCHECK(proxy_config->rules.empty() ||
!proxy_config->rules.proxies_for_http.IsEmpty()); !proxy_config->rules.proxies_for_http.IsEmpty());
if (proxy_config_) {
previous_proxy_configs_.push_front(std::move(proxy_config_));
if (previous_proxy_configs_.size() > kMaxPreviousConfigs)
previous_proxy_configs_.pop_back();
}
proxy_config_ = std::move(proxy_config); proxy_config_ = std::move(proxy_config);
} }
...@@ -146,12 +159,34 @@ bool NetworkServiceProxyDelegate::IsInProxyConfig( ...@@ -146,12 +159,34 @@ bool NetworkServiceProxyDelegate::IsInProxyConfig(
if (!proxy_server.is_valid() || proxy_server.is_direct()) if (!proxy_server.is_valid() || proxy_server.is_direct())
return false; return false;
return CheckProxyList(proxy_config_->rules.proxies_for_http, proxy_server); if (CheckProxyList(proxy_config_->rules.proxies_for_http, proxy_server))
return true;
for (const auto& config : previous_proxy_configs_) {
if (CheckProxyList(config->rules.proxies_for_http, proxy_server))
return true;
}
return false;
} }
bool NetworkServiceProxyDelegate::MayProxyURL(const GURL& url) const { bool NetworkServiceProxyDelegate::MayProxyURL(const GURL& url) const {
return url.SchemeIs(url::kHttpScheme) && !proxy_config_->rules.empty() && return IsURLValidForProxy(url) && !proxy_config_->rules.empty();
!net::IsLocalhost(url); }
bool NetworkServiceProxyDelegate::MayHaveProxiedURL(const GURL& url) const {
if (!IsURLValidForProxy(url))
return false;
if (!proxy_config_->rules.empty())
return true;
for (const auto& config : previous_proxy_configs_) {
if (!config->rules.empty())
return true;
}
return false;
} }
bool NetworkServiceProxyDelegate::EligibleForProxy( bool NetworkServiceProxyDelegate::EligibleForProxy(
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef SERVICES_NETWORK_NETWORK_SERVICE_PROXY_DELEGATE_H_ #ifndef SERVICES_NETWORK_NETWORK_SERVICE_PROXY_DELEGATE_H_
#define SERVICES_NETWORK_NETWORK_SERVICE_PROXY_DELEGATE_H_ #define SERVICES_NETWORK_NETWORK_SERVICE_PROXY_DELEGATE_H_
#include <deque>
#include "base/component_export.h" #include "base/component_export.h"
#include "base/containers/mru_cache.h" #include "base/containers/mru_cache.h"
#include "base/macros.h" #include "base/macros.h"
...@@ -51,6 +53,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceProxyDelegate ...@@ -51,6 +53,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceProxyDelegate
// Whether the current config may proxy |url|. // Whether the current config may proxy |url|.
bool MayProxyURL(const GURL& url) const; bool MayProxyURL(const GURL& url) const;
// Whether the current config may have proxied |url| with the current config
// or a previous config.
bool MayHaveProxiedURL(const GURL& url) const;
// Whether the |url| with current |proxy_info| is eligible to be proxied. // Whether the |url| with current |proxy_info| is eligible to be proxied.
bool EligibleForProxy(const net::ProxyInfo& proxy_info, bool EligibleForProxy(const net::ProxyInfo& proxy_info,
const GURL& url, const GURL& url,
...@@ -68,6 +74,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceProxyDelegate ...@@ -68,6 +74,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceProxyDelegate
base::MRUCache<std::string, bool> should_use_alternate_proxy_list_cache_; base::MRUCache<std::string, bool> should_use_alternate_proxy_list_cache_;
// We keep track of a limited number of previous configs so we can determine
// if a request used a custom proxy if the config happened to change during
// the request.
std::deque<mojom::CustomProxyConfigPtr> previous_proxy_configs_;
DISALLOW_COPY_AND_ASSIGN(NetworkServiceProxyDelegate); DISALLOW_COPY_AND_ASSIGN(NetworkServiceProxyDelegate);
}; };
......
...@@ -29,11 +29,9 @@ class NetworkServiceProxyDelegateTest : public testing::Test { ...@@ -29,11 +29,9 @@ class NetworkServiceProxyDelegateTest : public testing::Test {
protected: protected:
std::unique_ptr<NetworkServiceProxyDelegate> CreateDelegate( std::unique_ptr<NetworkServiceProxyDelegate> CreateDelegate(
mojom::CustomProxyConfigPtr config) { mojom::CustomProxyConfigPtr config) {
mojom::CustomProxyConfigClientPtr client;
auto delegate = std::make_unique<NetworkServiceProxyDelegate>( auto delegate = std::make_unique<NetworkServiceProxyDelegate>(
mojo::MakeRequest(&client)); mojo::MakeRequest(&client_));
client->OnCustomProxyConfigUpdated(std::move(config)); SetConfig(std::move(config));
scoped_task_environment_.RunUntilIdle();
return delegate; return delegate;
} }
...@@ -41,7 +39,13 @@ class NetworkServiceProxyDelegateTest : public testing::Test { ...@@ -41,7 +39,13 @@ class NetworkServiceProxyDelegateTest : public testing::Test {
return context_->CreateRequest(url, net::DEFAULT_PRIORITY, nullptr); return context_->CreateRequest(url, net::DEFAULT_PRIORITY, nullptr);
} }
void SetConfig(mojom::CustomProxyConfigPtr config) {
client_->OnCustomProxyConfigUpdated(std::move(config));
scoped_task_environment_.RunUntilIdle();
}
private: private:
mojom::CustomProxyConfigClientPtr client_;
std::unique_ptr<net::TestURLRequestContext> context_; std::unique_ptr<net::TestURLRequestContext> context_;
base::test::ScopedTaskEnvironment scoped_task_environment_; base::test::ScopedTaskEnvironment scoped_task_environment_;
}; };
...@@ -75,6 +79,19 @@ TEST_F(NetworkServiceProxyDelegateTest, ...@@ -75,6 +79,19 @@ TEST_F(NetworkServiceProxyDelegateTest,
EXPECT_TRUE(headers.IsEmpty()); EXPECT_TRUE(headers.IsEmpty());
} }
TEST_F(NetworkServiceProxyDelegateTest,
DoesNotAddHeadersBeforeCacheWithEmptyConfig) {
auto config = mojom::CustomProxyConfig::New();
config->pre_cache_headers.SetHeader("foo", "bar");
auto delegate = CreateDelegate(std::move(config));
net::HttpRequestHeaders headers;
auto request = CreateRequest(GURL(kHttpUrl));
delegate->OnBeforeStartTransaction(request.get(), &headers);
EXPECT_TRUE(headers.IsEmpty());
}
TEST_F(NetworkServiceProxyDelegateTest, DoesNotAddHeadersBeforeCacheForHttps) { TEST_F(NetworkServiceProxyDelegateTest, DoesNotAddHeadersBeforeCacheForHttps) {
auto config = mojom::CustomProxyConfig::New(); auto config = mojom::CustomProxyConfig::New();
config->rules.ParseFromString("http=proxy"); config->rules.ParseFromString("http=proxy");
...@@ -190,6 +207,49 @@ TEST_F(NetworkServiceProxyDelegateTest, KeepsPreCacheHeadersWhenProxyInConfig) { ...@@ -190,6 +207,49 @@ TEST_F(NetworkServiceProxyDelegateTest, KeepsPreCacheHeadersWhenProxyInConfig) {
EXPECT_EQ(value, "bar"); EXPECT_EQ(value, "bar");
} }
TEST_F(NetworkServiceProxyDelegateTest, KeepsHeadersWhenConfigUpdated) {
auto config = mojom::CustomProxyConfig::New();
config->rules.ParseFromString("http=proxy");
config->pre_cache_headers.SetHeader("foo", "bar");
auto delegate = CreateDelegate(config->Clone());
// Update config with new proxy.
config->rules.ParseFromString("http=other");
SetConfig(std::move(config));
net::HttpRequestHeaders headers;
headers.SetHeader("foo", "bar");
auto request = CreateRequest(GURL(kHttpUrl));
net::ProxyInfo info;
info.UsePacString("PROXY proxy");
delegate->OnBeforeSendHeaders(request.get(), info, &headers);
std::string value;
EXPECT_TRUE(headers.GetHeader("foo", &value));
EXPECT_EQ(value, "bar");
}
TEST_F(NetworkServiceProxyDelegateTest,
RemovesPreCacheHeadersWhenConfigUpdatedToBeEmpty) {
auto config = mojom::CustomProxyConfig::New();
config->rules.ParseFromString("http=proxy");
config->pre_cache_headers.SetHeader("foo", "bar");
auto delegate = CreateDelegate(config->Clone());
// Update config with empty proxy rules.
config->rules = net::ProxyConfig::ProxyRules();
SetConfig(std::move(config));
net::HttpRequestHeaders headers;
headers.SetHeader("foo", "bar");
auto request = CreateRequest(GURL(kHttpUrl));
net::ProxyInfo info;
info.UseDirect();
delegate->OnBeforeSendHeaders(request.get(), info, &headers);
EXPECT_TRUE(headers.IsEmpty());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxySuccessHttpProxy) { TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxySuccessHttpProxy) {
auto config = mojom::CustomProxyConfig::New(); auto config = mojom::CustomProxyConfig::New();
config->rules.ParseFromString("http=foo"); config->rules.ParseFromString("http=foo");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment