blob: 4b72a7342d17f6a4fa5529d1df1b8fb58099a2c8 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include <stddef.h>
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "services/network/test/test_network_quality_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_reduction_proxy {
namespace {
std::string CreateEncodedConfig(
const std::vector<DataReductionProxyServer> proxy_servers) {
ClientConfig config;
config.set_session_key("session");
for (const auto& proxy_server : proxy_servers) {
ProxyServer* config_proxy =
config.mutable_proxy_config()->add_http_proxy_servers();
net::HostPortPair host_port_pair =
proxy_server.proxy_server().host_port_pair();
config_proxy->set_scheme(ProxyServer_ProxyScheme_HTTP);
config_proxy->set_host(host_port_pair.host());
config_proxy->set_port(host_port_pair.port());
}
return EncodeConfig(config);
}
} // namespace
class DataReductionProxyIODataTest : public testing::Test {
public:
DataReductionProxyIODataTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
void SetUp() override {
RegisterSimpleProfilePrefs(prefs_.registry());
}
void RequestCallback(int err) {
}
PrefService* prefs() {
return &prefs_;
}
protected:
content::TestBrowserThreadBundle scoped_task_environment_;
private:
TestingPrefServiceSimple prefs_;
};
class TestCustomProxyConfigClient
: public network::mojom::CustomProxyConfigClient {
public:
TestCustomProxyConfigClient(
network::mojom::CustomProxyConfigClientRequest request)
: binding_(this, std::move(request)) {}
// network::mojom::CustomProxyConfigClient implementation:
void OnCustomProxyConfigUpdated(
network::mojom::CustomProxyConfigPtr proxy_config) override {
config = std::move(proxy_config);
}
void MarkProxiesAsBad(base::TimeDelta bypass_duration,
const net::ProxyList& bad_proxies,
MarkProxiesAsBadCallback callback) override {}
void ClearBadProxiesCache() override { num_clear_cache_calls++; }
network::mojom::CustomProxyConfigPtr config;
int num_clear_cache_calls = 0;
private:
mojo::Binding<network::mojom::CustomProxyConfigClient> binding_;
};
TEST_F(DataReductionProxyIODataTest, TestResetBadProxyListOnDisableDataSaver) {
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.SkipSettingsInitialization()
.Build();
drp_test_context->SetDataReductionProxyEnabled(true);
drp_test_context->InitSettings();
network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
drp_test_context->io_data()->SetCustomProxyConfigClient(
std::move(client_ptr_info));
base::RunLoop().RunUntilIdle();
// Turn Data Saver off.
drp_test_context->SetDataReductionProxyEnabled(false);
base::RunLoop().RunUntilIdle();
// Verify that the bad proxy cache was cleared.
EXPECT_EQ(1, client.num_clear_cache_calls);
}
TEST_F(DataReductionProxyIODataTest, HoldbackConfiguresProxies) {
base::FieldTrialList field_trial_list(nullptr);
ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
"DataCompressionProxyHoldback", "Enabled"));
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.SkipSettingsInitialization()
.Build();
EXPECT_TRUE(drp_test_context->test_params()->proxies_for_http().size() > 0);
EXPECT_FALSE(drp_test_context->test_params()
->proxies_for_http()
.front()
.proxy_server()
.is_direct());
}
TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigClient) {
auto proxy_server = net::ProxyServer::FromPacString("PROXY foo");
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kDataReductionProxyHttpProxies, proxy_server.ToURI());
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.Build();
drp_test_context->SetDataReductionProxyEnabled(true);
drp_test_context->test_network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_4G);
DataReductionProxyIOData* io_data = drp_test_context->io_data();
network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
io_data->SetCustomProxyConfigClient(std::move(client_ptr_info));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server);
EXPECT_TRUE(
client.config->post_cache_headers.HasHeader(chrome_proxy_header()));
EXPECT_TRUE(
client.config->pre_cache_headers.HasHeader(chrome_proxy_ect_header()));
}
TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigUpdatedOnECTChange) {
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.Build();
drp_test_context->SetDataReductionProxyEnabled(true);
drp_test_context->test_network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_4G);
DataReductionProxyIOData* io_data = drp_test_context->io_data();
network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
io_data->SetCustomProxyConfigClient(std::move(client_ptr_info));
base::RunLoop().RunUntilIdle();
std::string value;
EXPECT_TRUE(client.config->pre_cache_headers.GetHeader(
chrome_proxy_ect_header(), &value));
EXPECT_EQ(value, "4G");
drp_test_context->test_network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_2G);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client.config->pre_cache_headers.GetHeader(
chrome_proxy_ect_header(), &value));
EXPECT_EQ(value, "2G");
}
TEST_F(DataReductionProxyIODataTest,
TestCustomProxyConfigUpdatedOnHeaderChange) {
DataReductionProxyIOData io_data(
Client::UNKNOWN, prefs(),
network::TestNetworkConnectionTracker::GetInstance(),
scoped_task_environment_.GetMainThreadTaskRunner(),
scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
std::string() /* user_agent */, std::string() /* channel */);
network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
base::RunLoop().RunUntilIdle();
std::string value;
EXPECT_TRUE(client.config->post_cache_headers.GetHeader(chrome_proxy_header(),
&value));
io_data.request_options()->SetSecureSession("session_value");
base::RunLoop().RunUntilIdle();
std::string changed_value;
EXPECT_TRUE(client.config->post_cache_headers.GetHeader(chrome_proxy_header(),
&changed_value));
EXPECT_NE(value, changed_value);
}
TEST_F(DataReductionProxyIODataTest,
TestCustomProxyConfigUpdatedOnProxyChange) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableDataReductionProxyWarmupURLFetch);
DataReductionProxyIOData io_data(
Client::UNKNOWN, prefs(),
network::TestNetworkConnectionTracker::GetInstance(),
scoped_task_environment_.GetMainThreadTaskRunner(),
scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
std::string() /* user_agent */, std::string() /* channel */);
NetworkPropertiesManager network_properties_manager(
base::DefaultClock::GetInstance(), prefs(),
scoped_task_environment_.GetMainThreadTaskRunner());
io_data.config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
io_data.config()->UpdateConfigForTesting(true, true, true);
auto proxy_server1 = net::ProxyServer::FromPacString("PROXY foo");
io_data.config_client()->ApplySerializedConfig(
CreateEncodedConfig({DataReductionProxyServer(proxy_server1)}));
network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server1);
auto proxy_server2 = net::ProxyServer::FromPacString("PROXY bar");
io_data.config_client()->SetRemoteConfigAppliedForTesting(false);
io_data.config_client()->ApplySerializedConfig(
CreateEncodedConfig({DataReductionProxyServer(proxy_server2)}));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server2);
}
TEST_F(DataReductionProxyIODataTest,
TestCustomProxyConfigHasAlternateProxyListOfCoreProxies) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableDataReductionProxyWarmupURLFetch);
DataReductionProxyIOData io_data(
Client::UNKNOWN, prefs(),
network::TestNetworkConnectionTracker::GetInstance(),
scoped_task_environment_.GetMainThreadTaskRunner(),
scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
std::string() /* user_agent */, std::string() /* channel */);
NetworkPropertiesManager network_properties_manager(
base::DefaultClock::GetInstance(), prefs(),
scoped_task_environment_.GetMainThreadTaskRunner());
io_data.config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
io_data.config()->UpdateConfigForTesting(true, true, true);
auto core_proxy_server = net::ProxyServer::FromPacString("PROXY foo");
auto second_proxy_server = net::ProxyServer::FromPacString("PROXY bar");
io_data.config_client()->ApplySerializedConfig(
CreateEncodedConfig({DataReductionProxyServer(core_proxy_server),
DataReductionProxyServer(second_proxy_server)}));
network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
base::RunLoop().RunUntilIdle();
net::ProxyConfig::ProxyRules expected_rules;
expected_rules.type =
net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
expected_rules.proxies_for_http.AddProxyServer(core_proxy_server);
expected_rules.proxies_for_http.AddProxyServer(second_proxy_server);
expected_rules.proxies_for_http.AddProxyServer(net::ProxyServer::Direct());
EXPECT_TRUE(client.config->rules.Equals(expected_rules));
}
TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigProperties) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableDataReductionProxyWarmupURLFetch);
DataReductionProxyIOData io_data(
Client::UNKNOWN, prefs(),
network::TestNetworkConnectionTracker::GetInstance(),
scoped_task_environment_.GetMainThreadTaskRunner(),
scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
std::string() /* user_agent */, std::string() /* channel */);
NetworkPropertiesManager network_properties_manager(
base::DefaultClock::GetInstance(), prefs(),
scoped_task_environment_.GetMainThreadTaskRunner());
io_data.config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
io_data.config()->UpdateConfigForTesting(true, true, true);
network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client.config->assume_https_proxies_support_quic);
EXPECT_FALSE(client.config->can_use_proxy_on_http_url_redirect_cycles);
}
} // namespace data_reduction_proxy