Commit c558244d authored by jeremyim's avatar jeremyim Committed by Commit bot

Add the ability to use DataReductionProxyParams from DataReductionProxyConfigServiceClient.

- Permit DRP RequestOptions to take auth credentials instead of always internally
  generating them.
- Permit DRP Config to perform a reload of the configuration
- Create a new DRP MutableConfigValues class which can have its underlying values
  updated.
- Add a configuration refresh timer to DRP ConfigServiceClient, along with
  backoff logic.

BUG=466753

Review URL: https://codereview.chromium.org/1024553009

Cr-Commit-Position: refs/heads/master@{#322217}
parent bc0b05bd
...@@ -108,6 +108,8 @@ ...@@ -108,6 +108,8 @@
'data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc',
......
...@@ -21,6 +21,8 @@ static_library("browser") { ...@@ -21,6 +21,8 @@ static_library("browser") {
"data_reduction_proxy_io_data.h", "data_reduction_proxy_io_data.h",
"data_reduction_proxy_metrics.cc", "data_reduction_proxy_metrics.cc",
"data_reduction_proxy_metrics.h", "data_reduction_proxy_metrics.h",
"data_reduction_proxy_mutable_config_values.cc",
"data_reduction_proxy_mutable_config_values.h",
"data_reduction_proxy_network_delegate.cc", "data_reduction_proxy_network_delegate.cc",
"data_reduction_proxy_network_delegate.h", "data_reduction_proxy_network_delegate.h",
"data_reduction_proxy_prefs.cc", "data_reduction_proxy_prefs.cc",
......
...@@ -90,6 +90,12 @@ void DataReductionProxyConfig::SetProxyPrefs(bool enabled, ...@@ -90,6 +90,12 @@ void DataReductionProxyConfig::SetProxyPrefs(bool enabled,
alternative_enabled, at_startup)); alternative_enabled, at_startup));
} }
void DataReductionProxyConfig::ReloadConfig() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
UpdateConfigurator(enabled_by_user_, alternative_enabled_by_user_,
restricted_by_carrier_, false /* at_startup */);
}
bool DataReductionProxyConfig::WasDataReductionProxyUsed( bool DataReductionProxyConfig::WasDataReductionProxyUsed(
const net::URLRequest* request, const net::URLRequest* request,
DataReductionProxyTypeInfo* proxy_info) const { DataReductionProxyTypeInfo* proxy_info) const {
...@@ -276,18 +282,31 @@ void DataReductionProxyConfig::UpdateConfigurator(bool enabled, ...@@ -276,18 +282,31 @@ void DataReductionProxyConfig::UpdateConfigurator(bool enabled,
LogProxyState(enabled, restricted, at_startup); LogProxyState(enabled, restricted, at_startup);
// The alternative is only configured if the standard configuration is // The alternative is only configured if the standard configuration is
// is enabled. // is enabled.
if (enabled & !config_values_->holdback()) { std::string origin;
std::string fallback_origin;
std::string ssl_origin;
bool fallback_allowed = false;
if (enabled && !disabled_on_vpn_ && !config_values_->holdback()) {
if (alternative_enabled) { if (alternative_enabled) {
configurator_->Enable(restricted, fallback_allowed = config_values_->alternative_fallback_allowed();
!config_values_->alternative_fallback_allowed(), if (config_values_->alt_origin().is_valid())
config_values_->alt_origin().ToURI(), std::string(), origin = config_values_->alt_origin().ToURI();
config_values_->ssl_origin().ToURI()); if (config_values_->ssl_origin().is_valid())
ssl_origin = config_values_->ssl_origin().ToURI();
} else { } else {
configurator_->Enable(restricted, !config_values_->fallback_allowed(), fallback_allowed = config_values_->fallback_allowed();
config_values_->origin().ToURI(), if (config_values_->origin().is_valid())
config_values_->fallback_origin().ToURI(), origin = config_values_->origin().ToURI();
std::string()); if (config_values_->fallback_origin().is_valid())
fallback_origin = config_values_->fallback_origin().ToURI();
} }
}
// TODO(jeremyim): Enable should take std::vector<net::ProxyServer> as its
// parameters.
if (!origin.empty() || !fallback_origin.empty() || !ssl_origin.empty()) {
configurator_->Enable(restricted, !fallback_allowed, origin,
fallback_origin, ssl_origin);
} else { } else {
configurator_->Disable(); configurator_->Disable();
} }
...@@ -475,17 +494,18 @@ bool DataReductionProxyConfig::DisableIfVPN() { ...@@ -475,17 +494,18 @@ bool DataReductionProxyConfig::DisableIfVPN() {
interface_name.begin(), interface_name.begin(),
interface_name.begin() + vpn_interface_name_prefix.size(), interface_name.begin() + vpn_interface_name_prefix.size(),
vpn_interface_name_prefix.c_str())) { vpn_interface_name_prefix.c_str())) {
UpdateConfigurator(false, alternative_enabled_by_user_, false, false);
disabled_on_vpn_ = true; disabled_on_vpn_ = true;
UpdateConfigurator(enabled_by_user_, alternative_enabled_by_user_,
restricted_by_carrier_, false);
RecordNetworkChangeEvent(DISABLED_ON_VPN); RecordNetworkChangeEvent(DISABLED_ON_VPN);
return true; return true;
} }
} }
if (disabled_on_vpn_) { if (disabled_on_vpn_) {
disabled_on_vpn_ = false;
UpdateConfigurator(enabled_by_user_, alternative_enabled_by_user_, UpdateConfigurator(enabled_by_user_, alternative_enabled_by_user_,
restricted_by_carrier_, false); restricted_by_carrier_, false);
} }
disabled_on_vpn_ = false;
return false; return false;
} }
......
...@@ -90,6 +90,11 @@ class DataReductionProxyConfig ...@@ -90,6 +90,11 @@ class DataReductionProxyConfig
bool alternative_enabled, bool alternative_enabled,
bool at_startup); bool at_startup);
// Provides a mechanism for an external object to force |this| to refresh
// the Data Reduction Proxy configuration from |config_values_| and apply to
// |configurator_|. Used by the Data Reduction Proxy config service client.
void ReloadConfig();
// Returns true if a Data Reduction Proxy was used for the given |request|. // Returns true if a Data Reduction Proxy was used for the given |request|.
// If true, |proxy_info.proxy_servers.first| will contain the name of the // If true, |proxy_info.proxy_servers.first| will contain the name of the
// proxy that was used. |proxy_info.proxy_servers.second| will contain the // proxy that was used. |proxy_info.proxy_servers.second| will contain the
......
...@@ -4,27 +4,169 @@ ...@@ -4,27 +4,169 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/values.h" #include "base/values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.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_request_options.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "net/base/host_port_pair.h"
#include "net/proxy/proxy_server.h"
namespace data_reduction_proxy { namespace data_reduction_proxy {
namespace {
// This is the default backoff policy used to communicate with the Data
// Reduction Proxy configuration service.
const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
0, // num_errors_to_ignore
1 * 1000, // initial_delay_ms
4, // multiply_factor
0.10, // jitter_factor,
30 * 60 * 1000, // maximum_backoff_ms
-1, // entry_lifetime_ms
true, // always_use_initial_delay
};
// Extracts the list of Data Reduction Proxy servers to use for HTTP requests.
std::vector<net::ProxyServer> GetProxiesForHTTP(
const data_reduction_proxy::ProxyConfig& proxy_config) {
std::vector<net::ProxyServer> proxies;
for (const auto& server : proxy_config.http_proxy_servers()) {
if (server.scheme() != ProxyServer_ProxyScheme_UNSPECIFIED) {
proxies.push_back(net::ProxyServer(
config_parser::SchemeFromProxyScheme(server.scheme()),
net::HostPortPair(server.host(), server.port())));
}
}
return proxies;
}
// Calculate the next time at which the Data Reduction Proxy configuration
// should be retrieved, based on response success, configuration expiration,
// and the backoff delay. |backoff_delay| must be non-negative. Note that it is
// possible for |config_expiration| to be prior to |now|, but on a successful
// config refresh, |backoff_delay| will be returned.
base::TimeDelta CalculateNextConfigRefreshTime(
bool fetch_succeeded,
const base::Time& config_expiration,
const base::Time& now,
const base::TimeDelta& backoff_delay) {
DCHECK(backoff_delay >= base::TimeDelta());
if (fetch_succeeded) {
base::TimeDelta success_delay = config_expiration - now;
if (success_delay > backoff_delay)
return success_delay;
}
return backoff_delay;
}
} // namespace
const net::BackoffEntry::Policy& GetBackoffPolicy() {
return kDefaultBackoffPolicy;
}
DataReductionProxyConfigServiceClient::DataReductionProxyConfigServiceClient( DataReductionProxyConfigServiceClient::DataReductionProxyConfigServiceClient(
DataReductionProxyParams* params, scoped_ptr<DataReductionProxyParams> params,
DataReductionProxyRequestOptions* request_options) const net::BackoffEntry::Policy& backoff_policy,
: params_(params), DataReductionProxyRequestOptions* request_options,
request_options_(request_options) { DataReductionProxyMutableConfigValues* config_values,
DCHECK(params); DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: params_(params.Pass()),
request_options_(request_options),
config_values_(config_values),
config_(config),
io_task_runner_(io_task_runner),
backoff_entry_(&backoff_policy) {
DCHECK(request_options); DCHECK(request_options);
DCHECK(config_values);
DCHECK(config);
DCHECK(io_task_runner.get());
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DataReductionProxyConfigServiceClient::RetrieveConfig,
base::Unretained(this)));
} }
DataReductionProxyConfigServiceClient:: DataReductionProxyConfigServiceClient::
~DataReductionProxyConfigServiceClient() { ~DataReductionProxyConfigServiceClient() {
} }
void DataReductionProxyConfigServiceClient::RetrieveConfig() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
std::string static_response = ConstructStaticResponse();
ClientConfig config;
bool succeeded = false;
if (config_parser::ParseClientConfig(static_response, &config)) {
if (config.has_proxy_config()) {
net::ProxyServer origin;
net::ProxyServer fallback_origin;
std::vector<net::ProxyServer> proxies =
GetProxiesForHTTP(config.proxy_config());
if (proxies.size() > 0) {
origin = proxies[0];
if (proxies.size() > 1)
fallback_origin = proxies[1];
std::string session;
std::string credentials;
if (DataReductionProxyRequestOptions::ParseLocalSessionKey(
config.session_key(), &session, &credentials)) {
request_options_->SetCredentials(session, credentials);
config_values_->UpdateValues(origin, fallback_origin);
config_->ReloadConfig();
succeeded = true;
}
}
}
}
base::Time expiration_time;
if (succeeded) {
expiration_time = config_parser::TimestampToTime(config.expire_time());
}
GetBackoffEntry()->InformOfRequest(succeeded);
base::TimeDelta next_config_refresh_time =
CalculateNextConfigRefreshTime(succeeded, expiration_time, Now(),
GetBackoffEntry()->GetTimeUntilRelease());
SetConfigRefreshTimer(next_config_refresh_time);
}
net::BackoffEntry* DataReductionProxyConfigServiceClient::GetBackoffEntry() {
return &backoff_entry_;
}
void DataReductionProxyConfigServiceClient::SetConfigRefreshTimer(
const base::TimeDelta& delay) {
DCHECK(delay >= base::TimeDelta());
config_refresh_timer_.Stop();
config_refresh_timer_.Start(
FROM_HERE, delay, this,
&DataReductionProxyConfigServiceClient::RetrieveConfig);
}
base::Time DataReductionProxyConfigServiceClient::Now() const {
return base::Time::Now();
}
std::string std::string
DataReductionProxyConfigServiceClient::ConstructStaticResponse() const { DataReductionProxyConfigServiceClient::ConstructStaticResponse() const {
std::string response; std::string response;
......
...@@ -9,38 +9,95 @@ ...@@ -9,38 +9,95 @@
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "net/base/backoff_entry.h"
namespace base {
class SingleThreadTaskRunner;
class Time;
class TimeDelta;
}
namespace data_reduction_proxy { namespace data_reduction_proxy {
class DataReductionProxyConfig;
class DataReductionProxyMutableConfigValues;
class DataReductionProxyParams; class DataReductionProxyParams;
class DataReductionProxyRequestOptions; class DataReductionProxyRequestOptions;
// Retrieves the default net::BackoffEntry::Policy for the Data Reduction Proxy
// configuration service client.
const net::BackoffEntry::Policy& GetBackoffPolicy();
// Retrieves the Data Reduction Proxy configuration from a remote service. This // Retrieves the Data Reduction Proxy configuration from a remote service. This
// object lives on the IO thread. // object lives on the IO thread.
class DataReductionProxyConfigServiceClient { class DataReductionProxyConfigServiceClient {
public: public:
// The caller must ensure that all parameters remain alive for the lifetime of // The caller must ensure that all parameters remain alive for the lifetime of
// the |DataReductionProxyConfigClient|. // the |DataReductionProxyConfigClient|, with the exception of |params|
// which this instance will own.
DataReductionProxyConfigServiceClient( DataReductionProxyConfigServiceClient(
DataReductionProxyParams* params, scoped_ptr<DataReductionProxyParams> params,
DataReductionProxyRequestOptions* request_options); const net::BackoffEntry::Policy& backoff_policy,
DataReductionProxyRequestOptions* request_options,
DataReductionProxyMutableConfigValues* config_values,
DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~DataReductionProxyConfigServiceClient(); virtual ~DataReductionProxyConfigServiceClient();
private: // Request the retrieval of the Data Reduction Proxy configuration.
FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigClientTest, void RetrieveConfig();
TestConstructStaticResponse);
protected:
// Retrieves the backoff entry object being used to throttle request failures.
// Virtual for testing.
virtual net::BackoffEntry* GetBackoffEntry();
// Sets a timer to determine when to next refresh the Data Reduction Proxy
// configuration.
// Virtual for testing.
virtual void SetConfigRefreshTimer(const base::TimeDelta& delay);
// Returns the current time.
// Virtual for testing.
virtual base::Time Now() const;
// Constructs a synthetic response based on |params_|. // Constructs a synthetic response based on |params_|.
std::string ConstructStaticResponse() const; // Virtual for testing.
virtual std::string ConstructStaticResponse() const;
// The caller must ensure that the |params_| outlives this instance. private:
DataReductionProxyParams* params_; FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigServiceClientTest,
TestConstructStaticResponse);
friend class TestDataReductionProxyConfigServiceClient;
// Contains the static configuration data to use.
scoped_ptr<DataReductionProxyParams> params_;
// The caller must ensure that the |request_options_| outlives this instance. // The caller must ensure that the |request_options_| outlives this instance.
DataReductionProxyRequestOptions* request_options_; DataReductionProxyRequestOptions* request_options_;
// The caller must ensure that the |config_values_| outlives this instance.
DataReductionProxyMutableConfigValues* config_values_;
// The caller must ensure that the |config_| outlives this instance.
DataReductionProxyConfig* config_;
// |io_task_runner_| should be the task runner for running operations on the
// IO thread.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// Used to calculate the backoff time on request failures.
net::BackoffEntry backoff_entry_;
// An event that fires when it is time to refresh the Data Reduction Proxy
// configuration.
base::OneShotTimer<DataReductionProxyConfigServiceClient>
config_refresh_timer_;
DISALLOW_COPY_AND_ASSIGN(DataReductionProxyConfigServiceClient); DISALLOW_COPY_AND_ASSIGN(DataReductionProxyConfigServiceClient);
}; };
......
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
#include <string> #include <string>
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/time/tick_clock.h"
#include "base/values.h" #include "base/values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
...@@ -19,7 +21,34 @@ ...@@ -19,7 +21,34 @@
namespace data_reduction_proxy { namespace data_reduction_proxy {
class DataReductionProxyConfigClientTest : public testing::Test { namespace {
class RequestOptionsPopulator {
public:
RequestOptionsPopulator(const base::Time& expiration_time,
const base::TimeDelta& increment)
: expiration_time_(expiration_time),
increment_(increment) {
}
void PopulateResponse(base::DictionaryValue* response) {
response->SetString("sessionKey", "abcdef|1234-5678-12345678");
response->SetString("expireTime",
config_parser::TimeToISO8601(expiration_time_));
expiration_time_ += increment_;
}
private:
base::Time expiration_time_;
base::TimeDelta increment_;
};
void PopulateResponseFailure(base::DictionaryValue* response) {
}
} // namespace
class DataReductionProxyConfigServiceClientTest : public testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
test_context_ = test_context_ =
...@@ -28,20 +57,62 @@ class DataReductionProxyConfigClientTest : public testing::Test { ...@@ -28,20 +57,62 @@ class DataReductionProxyConfigClientTest : public testing::Test {
DataReductionProxyParams::kFallbackAllowed | DataReductionProxyParams::kFallbackAllowed |
DataReductionProxyParams::kPromoAllowed) DataReductionProxyParams::kPromoAllowed)
.WithParamsDefinitions(TestDataReductionProxyParams::HAS_EVERYTHING) .WithParamsDefinitions(TestDataReductionProxyParams::HAS_EVERYTHING)
.WithTestConfigurator()
.WithMockRequestOptions()
.WithTestConfigClient()
.Build(); .Build();
test_context_->test_config_client()->SetCustomReleaseTime(
base::TimeTicks::UnixEpoch());
test_context_->test_config_client()->SetNow(base::Time::UnixEpoch());
}
void SetDataReductionProxyEnabled(bool enabled) {
test_context_->config()->SetStateForTest(enabled, false, false);
} }
scoped_ptr<DataReductionProxyConfigServiceClient> BuildConfigClient() { scoped_ptr<DataReductionProxyConfigServiceClient> BuildConfigClient() {
return make_scoped_ptr(new DataReductionProxyConfigServiceClient( scoped_ptr<DataReductionProxyParams> params(new DataReductionProxyParams(
test_context_->config()->test_params(), DataReductionProxyParams::kAllowed |
test_context_->io_data()->request_options())); DataReductionProxyParams::kFallbackAllowed |
DataReductionProxyParams::kPromoAllowed));
request_options_.reset(
new DataReductionProxyRequestOptions(Client::UNKNOWN,
test_context_->io_data()->config(),
test_context_->task_runner()));
return scoped_ptr<DataReductionProxyConfigServiceClient>(
new DataReductionProxyConfigServiceClient(
params.Pass(), GetBackoffPolicy(),
request_options_.get(),
test_context_->mutable_config_values(),
test_context_->io_data()->config(), test_context_->task_runner()));
}
DataReductionProxyParams* params() {
return test_context_->test_params();
}
TestDataReductionProxyConfigServiceClient* config_client() {
return test_context_->test_config_client();
}
TestDataReductionProxyConfigurator* configurator() {
return test_context_->test_configurator();
}
MockDataReductionProxyRequestOptions* request_options() {
return test_context_->mock_request_options();
}
void RunUntilIdle() {
test_context_->RunUntilIdle();
} }
private: private:
scoped_ptr<DataReductionProxyTestContext> test_context_; scoped_ptr<DataReductionProxyTestContext> test_context_;
scoped_ptr<DataReductionProxyRequestOptions> request_options_;
}; };
TEST_F(DataReductionProxyConfigClientTest, TestConstructStaticResponse) { TEST_F(DataReductionProxyConfigServiceClientTest, TestConstructStaticResponse) {
scoped_ptr<DataReductionProxyConfigServiceClient> config_client = scoped_ptr<DataReductionProxyConfigServiceClient> config_client =
BuildConfigClient(); BuildConfigClient();
std::string config_data = config_client->ConstructStaticResponse(); std::string config_data = config_client->ConstructStaticResponse();
...@@ -49,4 +120,93 @@ TEST_F(DataReductionProxyConfigClientTest, TestConstructStaticResponse) { ...@@ -49,4 +120,93 @@ TEST_F(DataReductionProxyConfigClientTest, TestConstructStaticResponse) {
EXPECT_TRUE(config_parser::ParseClientConfig(config_data, &config)); EXPECT_TRUE(config_parser::ParseClientConfig(config_data, &config));
} }
TEST_F(DataReductionProxyConfigServiceClientTest, SuccessfulLoop) {
RequestOptionsPopulator populator(
base::Time::UnixEpoch() + base::TimeDelta::FromDays(1),
base::TimeDelta::FromDays(1));
SetDataReductionProxyEnabled(true);
EXPECT_TRUE(configurator()->origin().empty());
EXPECT_TRUE(configurator()->fallback_origin().empty());
EXPECT_TRUE(configurator()->ssl_origin().empty());
EXPECT_CALL(*request_options(), PopulateConfigResponse(testing::_))
.Times(2)
.WillRepeatedly(
testing::Invoke(&populator,
&RequestOptionsPopulator::PopulateResponse));
RunUntilIdle();
EXPECT_EQ(base::TimeDelta::FromDays(1), config_client()->GetDelay());
EXPECT_EQ(params()->origin().ToURI(), configurator()->origin());
EXPECT_EQ(params()->fallback_origin().ToURI(),
configurator()->fallback_origin());
EXPECT_TRUE(configurator()->ssl_origin().empty());
config_client()->SetNow(base::Time::UnixEpoch() + base::TimeDelta::FromDays(1)
+ base::TimeDelta::FromSeconds(5));
config_client()->RetrieveConfig();
EXPECT_EQ(base::TimeDelta::FromDays(1) - base::TimeDelta::FromSeconds(5),
config_client()->GetDelay());
EXPECT_EQ(params()->origin().ToURI(), configurator()->origin());
EXPECT_EQ(params()->fallback_origin().ToURI(),
configurator()->fallback_origin());
EXPECT_TRUE(configurator()->ssl_origin().empty());
}
TEST_F(DataReductionProxyConfigServiceClientTest, SuccessfulLoopShortDuration) {
RequestOptionsPopulator populator(
base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1),
base::TimeDelta::FromSeconds(1));
SetDataReductionProxyEnabled(true);
EXPECT_TRUE(configurator()->origin().empty());
EXPECT_TRUE(configurator()->fallback_origin().empty());
EXPECT_TRUE(configurator()->ssl_origin().empty());
EXPECT_CALL(*request_options(), PopulateConfigResponse(testing::_))
.Times(1)
.WillOnce(testing::Invoke(&populator,
&RequestOptionsPopulator::PopulateResponse));
RunUntilIdle();
EXPECT_EQ(base::TimeDelta::FromSeconds(10), config_client()->GetDelay());
EXPECT_EQ(params()->origin().ToURI(), configurator()->origin());
EXPECT_EQ(params()->fallback_origin().ToURI(),
configurator()->fallback_origin());
EXPECT_TRUE(configurator()->ssl_origin().empty());
}
TEST_F(DataReductionProxyConfigServiceClientTest, EnsureBackoff) {
SetDataReductionProxyEnabled(true);
EXPECT_TRUE(configurator()->origin().empty());
EXPECT_TRUE(configurator()->fallback_origin().empty());
EXPECT_TRUE(configurator()->ssl_origin().empty());
EXPECT_CALL(*request_options(), PopulateConfigResponse(testing::_))
.Times(2)
.WillRepeatedly(testing::Invoke(&PopulateResponseFailure));
config_client()->RetrieveConfig();
EXPECT_TRUE(configurator()->origin().empty());
EXPECT_TRUE(configurator()->fallback_origin().empty());
EXPECT_TRUE(configurator()->ssl_origin().empty());
EXPECT_EQ(base::TimeDelta::FromSeconds(20), config_client()->GetDelay());
config_client()->RetrieveConfig();
EXPECT_TRUE(configurator()->origin().empty());
EXPECT_TRUE(configurator()->fallback_origin().empty());
EXPECT_TRUE(configurator()->ssl_origin().empty());
EXPECT_EQ(base::TimeDelta::FromSeconds(40), config_client()->GetDelay());
}
TEST_F(DataReductionProxyConfigServiceClientTest, ConfigDisabled) {
RequestOptionsPopulator populator(
base::Time::UnixEpoch() + base::TimeDelta::FromDays(1),
base::TimeDelta::FromDays(1));
SetDataReductionProxyEnabled(false);
EXPECT_TRUE(configurator()->origin().empty());
EXPECT_TRUE(configurator()->fallback_origin().empty());
EXPECT_TRUE(configurator()->ssl_origin().empty());
EXPECT_CALL(*request_options(), PopulateConfigResponse(testing::_))
.Times(1)
.WillOnce(testing::Invoke(&populator,
&RequestOptionsPopulator::PopulateResponse));
RunUntilIdle();
EXPECT_TRUE(configurator()->origin().empty());
EXPECT_TRUE(configurator()->fallback_origin().empty());
EXPECT_TRUE(configurator()->ssl_origin().empty());
EXPECT_EQ(base::TimeDelta::FromDays(1), config_client()->GetDelay());
}
} // namespace data_reduction_proxy } // namespace data_reduction_proxy
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.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_params_test_utils.h"
#include "net/base/net_util.h" #include "net/base/net_util.h"
#include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/test_url_fetcher_factory.h"
...@@ -21,12 +22,28 @@ TestDataReductionProxyConfig::TestDataReductionProxyConfig( ...@@ -21,12 +22,28 @@ TestDataReductionProxyConfig::TestDataReductionProxyConfig(
net::NetLog* net_log, net::NetLog* net_log,
DataReductionProxyConfigurator* configurator, DataReductionProxyConfigurator* configurator,
DataReductionProxyEventStore* event_store) DataReductionProxyEventStore* event_store)
: DataReductionProxyConfig( : TestDataReductionProxyConfig(
task_runner, task_runner, net_log, make_scoped_ptr(
make_scoped_ptr( new TestDataReductionProxyParams(params_flags,
new TestDataReductionProxyParams(params_flags, params_definitions)) params_definitions)).Pass(),
.Pass(), task_runner,
configurator, event_store) { net_log,
configurator,
event_store) {
}
TestDataReductionProxyConfig::TestDataReductionProxyConfig(
scoped_ptr<DataReductionProxyConfigValues> config_values,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
net::NetLog* net_log,
DataReductionProxyConfigurator* configurator,
DataReductionProxyEventStore* event_store)
: DataReductionProxyConfig(task_runner,
task_runner,
net_log,
config_values.Pass(),
configurator,
event_store) {
network_interfaces_.reset(new net::NetworkInterfaceList()); network_interfaces_.reset(new net::NetworkInterfaceList());
} }
...@@ -58,28 +75,30 @@ TestDataReductionProxyParams* TestDataReductionProxyConfig::test_params() { ...@@ -58,28 +75,30 @@ TestDataReductionProxyParams* TestDataReductionProxyConfig::test_params() {
return static_cast<TestDataReductionProxyParams*>(config_values_.get()); return static_cast<TestDataReductionProxyParams*>(config_values_.get());
} }
DataReductionProxyConfigValues* TestDataReductionProxyConfig::config_values() {
return config_values_.get();
}
void TestDataReductionProxyConfig::SetStateForTest( void TestDataReductionProxyConfig::SetStateForTest(
bool enabled_by_user, bool enabled_by_user,
bool alternative_enabled_by_user, bool alternative_enabled_by_user,
bool restricted_by_carrier, bool restricted_by_carrier) {
bool at_startup) {
enabled_by_user_ = enabled_by_user; enabled_by_user_ = enabled_by_user;
alternative_enabled_by_user_ = alternative_enabled_by_user; alternative_enabled_by_user_ = alternative_enabled_by_user;
restricted_by_carrier_ = restricted_by_carrier; restricted_by_carrier_ = restricted_by_carrier;
UpdateConfigurator(enabled_by_user_, alternative_enabled_by_user_,
restricted_by_carrier_, at_startup);
} }
MockDataReductionProxyConfig::MockDataReductionProxyConfig( MockDataReductionProxyConfig::MockDataReductionProxyConfig(
int params_flags, scoped_ptr<DataReductionProxyConfigValues> config_values,
unsigned int params_definitions,
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
net::NetLog* net_log, net::NetLog* net_log,
DataReductionProxyConfigurator* configurator, DataReductionProxyConfigurator* configurator,
DataReductionProxyEventStore* event_store) DataReductionProxyEventStore* event_store)
: TestDataReductionProxyConfig( : TestDataReductionProxyConfig(config_values.Pass(),
params_flags, params_definitions, task_runner, net_log, configurator, task_runner,
event_store) { net_log,
configurator,
event_store) {
} }
MockDataReductionProxyConfig::~MockDataReductionProxyConfig() { MockDataReductionProxyConfig::~MockDataReductionProxyConfig() {
......
...@@ -23,6 +23,7 @@ namespace data_reduction_proxy { ...@@ -23,6 +23,7 @@ namespace data_reduction_proxy {
class DataReductionProxyConfigurator; class DataReductionProxyConfigurator;
class DataReductionProxyEventStore; class DataReductionProxyEventStore;
class DataReductionProxyMutableConfigValues;
class TestDataReductionProxyParams; class TestDataReductionProxyParams;
// Test version of |DataReductionProxyConfig|, which uses an underlying // Test version of |DataReductionProxyConfig|, which uses an underlying
...@@ -39,6 +40,17 @@ class TestDataReductionProxyConfig : public DataReductionProxyConfig { ...@@ -39,6 +40,17 @@ class TestDataReductionProxyConfig : public DataReductionProxyConfig {
net::NetLog* net_log, net::NetLog* net_log,
DataReductionProxyConfigurator* configurator, DataReductionProxyConfigurator* configurator,
DataReductionProxyEventStore* event_store); DataReductionProxyEventStore* event_store);
// Creates a |TestDataReductionProxyConfig| with the provided |config_values|.
// This permits any DataReductionProxyConfigValues to be used (such as
// DataReductionProxyParams or DataReductionProxyMutableConfigValues).
TestDataReductionProxyConfig(
scoped_ptr<DataReductionProxyConfigValues> config_values,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
net::NetLog* net_log,
DataReductionProxyConfigurator* configurator,
DataReductionProxyEventStore* event_store);
~TestDataReductionProxyConfig() override; ~TestDataReductionProxyConfig() override;
void GetNetworkList(net::NetworkInterfaceList* interfaces, void GetNetworkList(net::NetworkInterfaceList* interfaces,
...@@ -53,11 +65,14 @@ class TestDataReductionProxyConfig : public DataReductionProxyConfig { ...@@ -53,11 +65,14 @@ class TestDataReductionProxyConfig : public DataReductionProxyConfig {
// Retrieves the test params being used for the configuration. // Retrieves the test params being used for the configuration.
TestDataReductionProxyParams* test_params(); TestDataReductionProxyParams* test_params();
// Retrieves the underlying config values.
// TODO(jeremyim): Rationalize with test_params().
DataReductionProxyConfigValues* config_values();
// Allows tests to set the internal state. // Allows tests to set the internal state.
void SetStateForTest(bool enabled_by_user, void SetStateForTest(bool enabled_by_user,
bool alternative_enabled_by_user, bool alternative_enabled_by_user,
bool restricted_by_carrier, bool restricted_by_carrier);
bool at_startup);
net::NetworkInterfaceList* interfaces() { net::NetworkInterfaceList* interfaces() {
return network_interfaces_.get(); return network_interfaces_.get();
...@@ -71,10 +86,9 @@ class TestDataReductionProxyConfig : public DataReductionProxyConfig { ...@@ -71,10 +86,9 @@ class TestDataReductionProxyConfig : public DataReductionProxyConfig {
// testing. // testing.
class MockDataReductionProxyConfig : public TestDataReductionProxyConfig { class MockDataReductionProxyConfig : public TestDataReductionProxyConfig {
public: public:
// Creates a |MockDataReductionProxyConfig| with the provided |params_flags|. // Creates a |MockDataReductionProxyConfig|.
MockDataReductionProxyConfig( MockDataReductionProxyConfig(
int params_flags, scoped_ptr<DataReductionProxyConfigValues> config_values,
unsigned int params_definitions,
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
net::NetLog* net_log, net::NetLog* net_log,
DataReductionProxyConfigurator* configurator, DataReductionProxyConfigurator* configurator,
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.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.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.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_network_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
...@@ -46,12 +48,32 @@ DataReductionProxyIOData::DataReductionProxyIOData( ...@@ -46,12 +48,32 @@ DataReductionProxyIOData::DataReductionProxyIOData(
event_store_.reset(new DataReductionProxyEventStore(ui_task_runner)); event_store_.reset(new DataReductionProxyEventStore(ui_task_runner));
configurator_.reset(new DataReductionProxyConfigurator( configurator_.reset(new DataReductionProxyConfigurator(
io_task_runner, net_log, event_store_.get())); io_task_runner, net_log, event_store_.get()));
config_.reset(new DataReductionProxyConfig( bool use_config_client = DataReductionProxyParams::IsConfigClientEnabled();
io_task_runner_, ui_task_runner_, net_log, params.Pass(), DataReductionProxyMutableConfigValues* raw_mutable_config = nullptr;
configurator_.get(), event_store_.get())); if (use_config_client) {
scoped_ptr<DataReductionProxyMutableConfigValues> mutable_config =
DataReductionProxyMutableConfigValues::CreateFromParams(io_task_runner_,
params.get());
raw_mutable_config = mutable_config.get();
config_.reset(new DataReductionProxyConfig(
io_task_runner_, ui_task_runner_, net_log, mutable_config.Pass(),
configurator_.get(), event_store_.get()));
} else {
config_.reset(new DataReductionProxyConfig(
io_task_runner_, ui_task_runner_, net_log, params.Pass(),
configurator_.get(), event_store_.get()));
}
request_options_.reset(new DataReductionProxyRequestOptions( request_options_.reset(new DataReductionProxyRequestOptions(
client_, config_.get(), io_task_runner_)); client_, config_.get(), io_task_runner_));
request_options_->Init(); request_options_->Init();
if (use_config_client) {
config_client_.reset(new DataReductionProxyConfigServiceClient(
params.Pass(), GetBackoffPolicy(), request_options_.get(),
raw_mutable_config, config_.get(), io_task_runner_));
}
proxy_delegate_.reset( proxy_delegate_.reset(
new DataReductionProxyDelegate(request_options_.get(), config_.get())); new DataReductionProxyDelegate(request_options_.get(), config_.get()));
} }
......
...@@ -21,6 +21,7 @@ class URLRequestInterceptor; ...@@ -21,6 +21,7 @@ class URLRequestInterceptor;
namespace data_reduction_proxy { namespace data_reduction_proxy {
class DataReductionProxyConfig; class DataReductionProxyConfig;
class DataReductionProxyConfigServiceClient;
class DataReductionProxyConfigurator; class DataReductionProxyConfigurator;
class DataReductionProxyEventStore; class DataReductionProxyEventStore;
class DataReductionProxyService; class DataReductionProxyService;
...@@ -150,6 +151,9 @@ class DataReductionProxyIOData { ...@@ -150,6 +151,9 @@ class DataReductionProxyIOData {
// Constructs credentials suitable for authenticating the client. // Constructs credentials suitable for authenticating the client.
scoped_ptr<DataReductionProxyRequestOptions> request_options_; scoped_ptr<DataReductionProxyRequestOptions> request_options_;
// Requests new Data Reduction Proxy configurations from a remote service.
scoped_ptr<DataReductionProxyConfigServiceClient> config_client_;
// A net log. // A net log.
net::NetLog* net_log_; net::NetLog* net_log_;
......
// 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_mutable_config_values.h"
#include "base/single_thread_task_runner.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
namespace data_reduction_proxy {
scoped_ptr<DataReductionProxyMutableConfigValues>
DataReductionProxyMutableConfigValues::CreateFromParams(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const DataReductionProxyParams* params) {
scoped_ptr<DataReductionProxyMutableConfigValues> config_values(
new DataReductionProxyMutableConfigValues(io_task_runner));
config_values->promo_allowed_ = params->promo_allowed();
config_values->holdback_ = params->holdback();
config_values->allowed_ = params->allowed();
config_values->fallback_allowed_ = params->fallback_allowed();
config_values->secure_proxy_check_url_ = params->secure_proxy_check_url();
return config_values.Pass();
}
DataReductionProxyMutableConfigValues::DataReductionProxyMutableConfigValues(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: empty_origin_(),
promo_allowed_(false),
holdback_(false),
allowed_(false),
fallback_allowed_(false),
origin_(empty_origin_),
fallback_origin_(empty_origin_),
io_task_runner_(io_task_runner) {
DCHECK(io_task_runner.get());
}
DataReductionProxyMutableConfigValues::
~DataReductionProxyMutableConfigValues() {
}
bool DataReductionProxyMutableConfigValues::promo_allowed() const {
return promo_allowed_;
}
bool DataReductionProxyMutableConfigValues::holdback() const {
return holdback_;
}
bool DataReductionProxyMutableConfigValues::allowed() const {
return allowed_;
}
bool DataReductionProxyMutableConfigValues::fallback_allowed() const {
return fallback_allowed_;
}
bool DataReductionProxyMutableConfigValues::alternative_allowed() const {
return false;
}
bool DataReductionProxyMutableConfigValues::alternative_fallback_allowed()
const {
return false;
}
bool DataReductionProxyMutableConfigValues::UsingHTTPTunnel(
const net::HostPortPair& proxy_server) const {
return false;
}
bool DataReductionProxyMutableConfigValues::IsDataReductionProxy(
const net::HostPortPair& host_port_pair,
DataReductionProxyTypeInfo* proxy_info) const {
// TODO(jeremyim): Rework as part of ConfigValues interface changes.
if (allowed() && origin().is_valid() &&
origin().host_port_pair().Equals(host_port_pair)) {
if (proxy_info) {
proxy_info->proxy_servers.first = origin();
if (fallback_allowed())
proxy_info->proxy_servers.second = fallback_origin();
}
return true;
}
if (!fallback_allowed() || !fallback_origin().is_valid() ||
!fallback_origin().host_port_pair().Equals(host_port_pair))
return false;
if (proxy_info) {
proxy_info->proxy_servers.first = fallback_origin();
proxy_info->proxy_servers.second = net::ProxyServer::FromURI(
std::string(), net::ProxyServer::SCHEME_HTTP);
proxy_info->is_fallback = true;
}
return true;
}
const net::ProxyServer& DataReductionProxyMutableConfigValues::origin() const {
DCHECK(io_task_runner_->BelongsToCurrentThread());
return origin_;
}
const net::ProxyServer& DataReductionProxyMutableConfigValues::fallback_origin()
const {
DCHECK(io_task_runner_->BelongsToCurrentThread());
return fallback_origin_;
}
const net::ProxyServer& DataReductionProxyMutableConfigValues::alt_origin()
const {
return empty_origin_;
}
const net::ProxyServer&
DataReductionProxyMutableConfigValues::alt_fallback_origin() const {
return empty_origin_;
}
const net::ProxyServer& DataReductionProxyMutableConfigValues::ssl_origin()
const {
return empty_origin_;
}
const GURL& DataReductionProxyMutableConfigValues::secure_proxy_check_url()
const {
return secure_proxy_check_url_;
}
void DataReductionProxyMutableConfigValues::UpdateValues(
const net::ProxyServer& origin,
const net::ProxyServer& fallback_origin) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
origin_ = origin;
fallback_origin_ = fallback_origin;
}
} // namespace data_reduction_proxy
// 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.
#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_MUTABLE_CONFIG_VALUES_H_
#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_MUTABLE_CONFIG_VALUES_H_
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h"
#include "net/proxy/proxy_server.h"
#include "url/gurl.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace data_reduction_proxy {
class DataReductionProxyParams;
// A |DataReductionProxyConfigValues| which is permitted to change its
// underlying values via the UpdateValues method.
class DataReductionProxyMutableConfigValues
: public DataReductionProxyConfigValues {
public:
// Creates a new |DataReductionProxyMutableConfigValues| using |params| as
// the basis for its initial values.
static scoped_ptr<DataReductionProxyMutableConfigValues> CreateFromParams(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const DataReductionProxyParams* params);
~DataReductionProxyMutableConfigValues() override;
// Updates |origin_| and |fallback_origin_| with the provided values.
// Virtual for testing.
virtual void UpdateValues(const net::ProxyServer& origin,
const net::ProxyServer& fallback_origin);
// Overrides of |DataReductionProxyConfigValues|
bool promo_allowed() const override;
bool holdback() const override;
bool allowed() const override;
bool fallback_allowed() const override;
bool alternative_allowed() const override;
bool alternative_fallback_allowed() const override;
bool UsingHTTPTunnel(const net::HostPortPair& proxy_server) const override;
bool IsDataReductionProxy(
const net::HostPortPair& host_port_pair,
DataReductionProxyTypeInfo* proxy_info) const override;
const net::ProxyServer& origin() const override;
const net::ProxyServer& fallback_origin() const override;
const net::ProxyServer& alt_origin() const override;
const net::ProxyServer& alt_fallback_origin() const override;
const net::ProxyServer& ssl_origin() const override;
const GURL& secure_proxy_check_url() const override;
protected:
DataReductionProxyMutableConfigValues(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
private:
net::ProxyServer empty_origin_;
bool promo_allowed_;
bool holdback_;
bool allowed_;
bool fallback_allowed_;
net::ProxyServer origin_;
net::ProxyServer fallback_origin_;
GURL secure_proxy_check_url_;
// |io_task_runner_| should be the task runner for running operations on the
// IO thread.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
DISALLOW_COPY_AND_ASSIGN(DataReductionProxyMutableConfigValues);
};
} // namespace data_reduction_proxy
#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_MUTABLE_CONFIG_VALUES_H_
...@@ -99,6 +99,7 @@ DataReductionProxyRequestOptions::DataReductionProxyRequestOptions( ...@@ -99,6 +99,7 @@ DataReductionProxyRequestOptions::DataReductionProxyRequestOptions(
DataReductionProxyConfig* config, DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner) scoped_refptr<base::SingleThreadTaskRunner> network_task_runner)
: client_(GetString(client)), : client_(GetString(client)),
use_assigned_credentials_(false),
data_reduction_proxy_config_(config), data_reduction_proxy_config_(config),
network_task_runner_(network_task_runner) { network_task_runner_(network_task_runner) {
GetChromiumBuildAndPatch(ChromiumVersion(), &build_, &patch_); GetChromiumBuildAndPatch(ChromiumVersion(), &build_, &patch_);
...@@ -110,6 +111,7 @@ DataReductionProxyRequestOptions::DataReductionProxyRequestOptions( ...@@ -110,6 +111,7 @@ DataReductionProxyRequestOptions::DataReductionProxyRequestOptions(
DataReductionProxyConfig* config, DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner) scoped_refptr<base::SingleThreadTaskRunner> network_task_runner)
: client_(GetString(client)), : client_(GetString(client)),
use_assigned_credentials_(false),
data_reduction_proxy_config_(config), data_reduction_proxy_config_(config),
network_task_runner_(network_task_runner) { network_task_runner_(network_task_runner) {
GetChromiumBuildAndPatch(version, &build_, &patch_); GetChromiumBuildAndPatch(version, &build_, &patch_);
...@@ -227,7 +229,7 @@ void DataReductionProxyRequestOptions::SetHeader( ...@@ -227,7 +229,7 @@ void DataReductionProxyRequestOptions::SetHeader(
net::HttpRequestHeaders* headers) { net::HttpRequestHeaders* headers) {
base::Time now = Now(); base::Time now = Now();
// Authorization credentials must be regenerated if they are expired. // Authorization credentials must be regenerated if they are expired.
if (now > credentials_expiration_time_) if (!use_assigned_credentials_ && (now > credentials_expiration_time_))
UpdateCredentials(); UpdateCredentials();
UpdateLoFi(); UpdateLoFi();
const char kChromeProxyHeader[] = "Chrome-Proxy"; const char kChromeProxyHeader[] = "Chrome-Proxy";
...@@ -264,8 +266,6 @@ void DataReductionProxyRequestOptions::ComputeCredentials( ...@@ -264,8 +266,6 @@ void DataReductionProxyRequestOptions::ComputeCredentials(
} }
void DataReductionProxyRequestOptions::UpdateCredentials() { void DataReductionProxyRequestOptions::UpdateCredentials() {
std::string session;
std::string credentials;
base::Time now = Now(); base::Time now = Now();
ComputeCredentials(now, &session_, &credentials_); ComputeCredentials(now, &session_, &credentials_);
credentials_expiration_time_ = now + base::TimeDelta::FromHours(24); credentials_expiration_time_ = now + base::TimeDelta::FromHours(24);
...@@ -293,6 +293,18 @@ void DataReductionProxyRequestOptions::PopulateConfigResponse( ...@@ -293,6 +293,18 @@ void DataReductionProxyRequestOptions::PopulateConfigResponse(
config_parser::TimeToISO8601(expiration_time)); config_parser::TimeToISO8601(expiration_time));
} }
void DataReductionProxyRequestOptions::SetCredentials(
const std::string& session,
const std::string& credentials) {
DCHECK(network_task_runner_->BelongsToCurrentThread());
session_ = session;
credentials_ = credentials;
// Force skipping of credential regeneration. It should be handled by the
// caller.
use_assigned_credentials_ = true;
RegenerateRequestHeaderValue();
}
std::string DataReductionProxyRequestOptions::GetDefaultKey() const { std::string DataReductionProxyRequestOptions::GetDefaultKey() const {
const base::CommandLine& command_line = const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess(); *base::CommandLine::ForCurrentProcess();
......
...@@ -125,6 +125,10 @@ class DataReductionProxyRequestOptions { ...@@ -125,6 +125,10 @@ class DataReductionProxyRequestOptions {
// Virtualized for testing. // Virtualized for testing.
virtual void PopulateConfigResponse(base::DictionaryValue* response) const; virtual void PopulateConfigResponse(base::DictionaryValue* response) const;
// Sets the credentials for sending to the Data Reduction Proxy.
void SetCredentials(const std::string& session,
const std::string& credentials);
protected: protected:
void SetHeader(net::HttpRequestHeaders* headers); void SetHeader(net::HttpRequestHeaders* headers);
...@@ -211,6 +215,10 @@ class DataReductionProxyRequestOptions { ...@@ -211,6 +215,10 @@ class DataReductionProxyRequestOptions {
// never used for more than twenty-four hours. // never used for more than twenty-four hours.
base::Time credentials_expiration_time_; base::Time credentials_expiration_time_;
// Whether the authentication headers are sourced by |this| or injected via
// |SetCredentials|.
bool use_assigned_credentials_;
DataReductionProxyConfig* data_reduction_proxy_config_; DataReductionProxyConfig* data_reduction_proxy_config_;
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
......
...@@ -45,7 +45,7 @@ class DataReductionProxySettingsTest ...@@ -45,7 +45,7 @@ class DataReductionProxySettingsTest
test_context_->pref_service()->SetBoolean(prefs::kDataReductionProxyEnabled, test_context_->pref_service()->SetBoolean(prefs::kDataReductionProxyEnabled,
initially_enabled); initially_enabled);
test_context_->config()->SetStateForTest(initially_enabled, false, test_context_->config()->SetStateForTest(initially_enabled, false,
!request_succeeded, false); !request_succeeded);
ExpectSetProxyPrefs(expected_enabled, false, false); ExpectSetProxyPrefs(expected_enabled, false, false);
settings_->MaybeActivateDataReductionProxy(false); settings_->MaybeActivateDataReductionProxy(false);
test_context_->RunUntilIdle(); test_context_->RunUntilIdle();
...@@ -55,7 +55,7 @@ class DataReductionProxySettingsTest ...@@ -55,7 +55,7 @@ class DataReductionProxySettingsTest
TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) { TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) {
settings_->InitPrefMembers(); settings_->InitPrefMembers();
// The proxy is disabled initially. // The proxy is disabled initially.
test_context_->config()->SetStateForTest(false, false, false, false); test_context_->config()->SetStateForTest(false, false, false);
EXPECT_FALSE(settings_->IsDataReductionProxyEnabled()); EXPECT_FALSE(settings_->IsDataReductionProxyEnabled());
EXPECT_FALSE(settings_->IsDataReductionProxyManaged()); EXPECT_FALSE(settings_->IsDataReductionProxyManaged());
...@@ -74,7 +74,7 @@ TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) { ...@@ -74,7 +74,7 @@ TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) {
TEST_F(DataReductionProxySettingsTest, TestCanUseDataReductionProxy) { TEST_F(DataReductionProxySettingsTest, TestCanUseDataReductionProxy) {
settings_->InitPrefMembers(); settings_->InitPrefMembers();
// The proxy is disabled initially. // The proxy is disabled initially.
test_context_->config()->SetStateForTest(false, false, false, false); test_context_->config()->SetStateForTest(false, false, false);
GURL http_gurl("http://url.com/"); GURL http_gurl("http://url.com/");
EXPECT_FALSE(settings_->CanUseDataReductionProxy(http_gurl)); EXPECT_FALSE(settings_->CanUseDataReductionProxy(http_gurl));
...@@ -240,7 +240,7 @@ TEST(DataReductionProxySettingsStandaloneTest, TestOnProxyEnabledPrefChange) { ...@@ -240,7 +240,7 @@ TEST(DataReductionProxySettingsStandaloneTest, TestOnProxyEnabledPrefChange) {
.Build(); .Build();
// The proxy is enabled initially. // The proxy is enabled initially.
drp_test_context->config()->SetStateForTest(true, false, false, true); drp_test_context->config()->SetStateForTest(true, false, false);
drp_test_context->InitSettings(); drp_test_context->InitSettings();
// The pref is disabled, so correspondingly should be the proxy. // The pref is disabled, so correspondingly should be the proxy.
...@@ -269,7 +269,7 @@ TEST_F(DataReductionProxySettingsTest, TestMaybeActivateDataReductionProxy) { ...@@ -269,7 +269,7 @@ TEST_F(DataReductionProxySettingsTest, TestMaybeActivateDataReductionProxy) {
// TODO(bengr): Test enabling/disabling while a secure proxy check is // TODO(bengr): Test enabling/disabling while a secure proxy check is
// outstanding. // outstanding.
// The proxy is enabled and unrestructed initially. // The proxy is enabled and unrestricted initially.
// Request succeeded but with bad response, expect proxy to be restricted. // Request succeeded but with bad response, expect proxy to be restricted.
CheckMaybeActivateDataReductionProxy(true, true, true, true, false); CheckMaybeActivateDataReductionProxy(true, true, true, true, false);
// Request succeeded with valid response, expect proxy to be unrestricted. // Request succeeded with valid response, expect proxy to be unrestricted.
......
...@@ -12,11 +12,13 @@ ...@@ -12,11 +12,13 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h"
#include "net/base/backoff_entry.h"
#include "net/base/capturing_net_log.h" #include "net/base/capturing_net_log.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -38,12 +40,14 @@ namespace data_reduction_proxy { ...@@ -38,12 +40,14 @@ namespace data_reduction_proxy {
class DataReductionProxyConfigurator; class DataReductionProxyConfigurator;
class DataReductionProxyEventStore; class DataReductionProxyEventStore;
class DataReductionProxyMutableConfigValues;
class DataReductionProxyRequestOptions; class DataReductionProxyRequestOptions;
class DataReductionProxySettings; class DataReductionProxySettings;
class DataReductionProxyStatisticsPrefs; class DataReductionProxyStatisticsPrefs;
class MockDataReductionProxyConfig; class MockDataReductionProxyConfig;
class TestDataReductionProxyConfig; class TestDataReductionProxyConfig;
class TestDataReductionProxyConfigurator; class TestDataReductionProxyConfigurator;
class TestDataReductionProxyParams;
// Test version of |DataReductionProxyRequestOptions|. // Test version of |DataReductionProxyRequestOptions|.
class TestDataReductionProxyRequestOptions class TestDataReductionProxyRequestOptions
...@@ -83,6 +87,69 @@ class MockDataReductionProxyRequestOptions ...@@ -83,6 +87,69 @@ class MockDataReductionProxyRequestOptions
void(base::DictionaryValue* response)); void(base::DictionaryValue* response));
}; };
// Test version of |DataReductionProxyConfigServiceClient|, which permits
// finely controlling the backoff timer.
class TestDataReductionProxyConfigServiceClient
: public DataReductionProxyConfigServiceClient {
public:
TestDataReductionProxyConfigServiceClient(
scoped_ptr<DataReductionProxyParams> params,
DataReductionProxyRequestOptions* request_options,
DataReductionProxyMutableConfigValues* config_values,
DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~TestDataReductionProxyConfigServiceClient() override;
void SetNow(const base::Time& time);
void SetCustomReleaseTime(const base::TimeTicks& release_time);
base::TimeDelta GetDelay() const;
protected:
// Overrides of DataReductionProxyConfigServiceClient
base::Time Now() const override;
net::BackoffEntry* GetBackoffEntry() override;
private:
// A clock which returns a fixed value in both base::Time and base::TimeTicks.
class TestTickClock {
public:
TestTickClock(const base::Time& initial_time);
// Returns the current base::TimeTicks
base::TimeTicks NowTicks() const;
// Returns the current base::Time
base::Time Now() const;
// Sets the current time.
void SetTime(const base::Time& time);
private:
base::Time time_;
};
// A net::BackoffEntry which uses an injected base::TickClock to control
// the backoff expiration time.
class TestBackoffEntry : public net::BackoffEntry {
public:
TestBackoffEntry(const BackoffEntry::Policy* const policy,
const TestTickClock* tick_clock);
protected:
// Override of net::BackoffEntry.
base::TimeTicks ImplGetTimeNow() const override;
private:
const TestTickClock* tick_clock_;
};
TestTickClock tick_clock_;
TestBackoffEntry test_backoff_entry_;
};
// Test version of |DataReductionProxyService|, which permits mocking of various // Test version of |DataReductionProxyService|, which permits mocking of various
// methods. // methods.
class MockDataReductionProxyService : public DataReductionProxyService { class MockDataReductionProxyService : public DataReductionProxyService {
...@@ -105,15 +172,20 @@ class TestDataReductionProxyIOData : public DataReductionProxyIOData { ...@@ -105,15 +172,20 @@ class TestDataReductionProxyIOData : public DataReductionProxyIOData {
public: public:
TestDataReductionProxyIOData( TestDataReductionProxyIOData(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
scoped_ptr<TestDataReductionProxyConfig> config, scoped_ptr<DataReductionProxyConfig> config,
scoped_ptr<DataReductionProxyEventStore> event_store, scoped_ptr<DataReductionProxyEventStore> event_store,
scoped_ptr<DataReductionProxyRequestOptions> request_options, scoped_ptr<DataReductionProxyRequestOptions> request_options,
scoped_ptr<DataReductionProxyConfigurator> configurator); scoped_ptr<DataReductionProxyConfigurator> configurator,
scoped_ptr<DataReductionProxyConfigServiceClient> config_client);
~TestDataReductionProxyIOData() override; ~TestDataReductionProxyIOData() override;
DataReductionProxyConfigurator* configurator() const { DataReductionProxyConfigurator* configurator() const {
return configurator_.get(); return configurator_.get();
} }
DataReductionProxyConfigServiceClient* config_client() const {
return config_client_.get();
}
}; };
// Builds a test version of the Data Reduction Proxy stack for use in tests. // Builds a test version of the Data Reduction Proxy stack for use in tests.
...@@ -165,6 +237,13 @@ class DataReductionProxyTestContext { ...@@ -165,6 +237,13 @@ class DataReductionProxyTestContext {
// |DataReductionProxyRequestOptions|. // |DataReductionProxyRequestOptions|.
Builder& WithMockRequestOptions(); Builder& WithMockRequestOptions();
// Specifies the use of the |DataReductionProxyConfigServiceClient|.
Builder& WithConfigClient();
// Specifies the use of the a |TestDataReductionProxyConfigServiceClient|
// instead of a |DataReductionProxyConfigServiceClient|.
Builder& WithTestConfigClient();
// Construct, but do not initialize the |DataReductionProxySettings| object. // Construct, but do not initialize the |DataReductionProxySettings| object.
Builder& SkipSettingsInitialization(); Builder& SkipSettingsInitialization();
...@@ -182,6 +261,8 @@ class DataReductionProxyTestContext { ...@@ -182,6 +261,8 @@ class DataReductionProxyTestContext {
bool use_test_configurator_; bool use_test_configurator_;
bool use_mock_service_; bool use_mock_service_;
bool use_mock_request_options_; bool use_mock_request_options_;
bool use_config_client_;
bool use_test_config_client_;
bool skip_settings_initialization_; bool skip_settings_initialization_;
}; };
...@@ -231,6 +312,17 @@ class DataReductionProxyTestContext { ...@@ -231,6 +312,17 @@ class DataReductionProxyTestContext {
// only be called if built with WithMockRequestOptions. // only be called if built with WithMockRequestOptions.
MockDataReductionProxyRequestOptions* mock_request_options() const; MockDataReductionProxyRequestOptions* mock_request_options() const;
// Returns the underlying |TestDataReductionProxyConfig|.
TestDataReductionProxyConfig* config() const;
// Returns the underlying |DataReductionProxyMutableConfigValues|. This can
// only be called if built with WithConfigClient.
DataReductionProxyMutableConfigValues* mutable_config_values();
// Returns the underlying |TestDataReductionProxyConfigServiceClient|. This
// can only be called if built with WithTestConfigClient.
TestDataReductionProxyConfigServiceClient* test_config_client();
// Obtains a callback for notifying that the Data Reduction Proxy is no // Obtains a callback for notifying that the Data Reduction Proxy is no
// longer reachable. // longer reachable.
DataReductionProxyUsageStats::UnreachableCallback DataReductionProxyUsageStats::UnreachableCallback
...@@ -260,10 +352,6 @@ class DataReductionProxyTestContext { ...@@ -260,10 +352,6 @@ class DataReductionProxyTestContext {
return io_data_->configurator(); return io_data_->configurator();
} }
TestDataReductionProxyConfig* config() const {
return reinterpret_cast<TestDataReductionProxyConfig*>(io_data_->config());
}
TestDataReductionProxyIOData* io_data() const { TestDataReductionProxyIOData* io_data() const {
return io_data_.get(); return io_data_.get();
} }
...@@ -272,6 +360,10 @@ class DataReductionProxyTestContext { ...@@ -272,6 +360,10 @@ class DataReductionProxyTestContext {
return settings_.get(); return settings_.get();
} }
TestDataReductionProxyParams* test_params() const {
return params_;
}
private: private:
enum TestContextOptions { enum TestContextOptions {
// Permits mocking of the underlying |DataReductionProxyConfig|. // Permits mocking of the underlying |DataReductionProxyConfig|.
...@@ -287,6 +379,10 @@ class DataReductionProxyTestContext { ...@@ -287,6 +379,10 @@ class DataReductionProxyTestContext {
USE_MOCK_SERVICE = 0x8, USE_MOCK_SERVICE = 0x8,
// Permits mocking of the underlying |DataReductionProxyRequestOptions|. // Permits mocking of the underlying |DataReductionProxyRequestOptions|.
USE_MOCK_REQUEST_OPTIONS = 0x10, USE_MOCK_REQUEST_OPTIONS = 0x10,
// Specifies the use of the |DataReductionProxyConfigServiceClient|.
USE_CONFIG_CLIENT = 0x20,
// Specifies the use of the |TESTDataReductionProxyConfigServiceClient|.
USE_TEST_CONFIG_CLIENT = 0x40,
}; };
DataReductionProxyTestContext( DataReductionProxyTestContext(
...@@ -298,6 +394,7 @@ class DataReductionProxyTestContext { ...@@ -298,6 +394,7 @@ class DataReductionProxyTestContext {
net::MockClientSocketFactory* mock_socket_factory, net::MockClientSocketFactory* mock_socket_factory,
scoped_ptr<TestDataReductionProxyIOData> io_data, scoped_ptr<TestDataReductionProxyIOData> io_data,
scoped_ptr<DataReductionProxySettings> settings, scoped_ptr<DataReductionProxySettings> settings,
TestDataReductionProxyParams* params,
unsigned int test_context_flags); unsigned int test_context_flags);
void InitSettingsWithoutCheck(); void InitSettingsWithoutCheck();
...@@ -320,6 +417,8 @@ class DataReductionProxyTestContext { ...@@ -320,6 +417,8 @@ class DataReductionProxyTestContext {
scoped_ptr<TestDataReductionProxyIOData> io_data_; scoped_ptr<TestDataReductionProxyIOData> io_data_;
scoped_ptr<DataReductionProxySettings> settings_; scoped_ptr<DataReductionProxySettings> settings_;
TestDataReductionProxyParams* params_;
DISALLOW_COPY_AND_ASSIGN(DataReductionProxyTestContext); DISALLOW_COPY_AND_ASSIGN(DataReductionProxyTestContext);
}; };
......
...@@ -130,6 +130,12 @@ std::string DataReductionProxyParams::GetQuicFieldTrialName() { ...@@ -130,6 +130,12 @@ std::string DataReductionProxyParams::GetQuicFieldTrialName() {
return kQuicFieldTrial; return kQuicFieldTrial;
} }
// static
bool DataReductionProxyParams::IsConfigClientEnabled() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
data_reduction_proxy::switches::kEnableDataReductionProxyConfigClient);
}
void DataReductionProxyParams::EnableQuic(bool enable) { void DataReductionProxyParams::EnableQuic(bool enable) {
quic_enabled_ = enable; quic_enabled_ = enable;
DCHECK(!quic_enabled_ || IsIncludedInQuicFieldTrial()); DCHECK(!quic_enabled_ || IsIncludedInQuicFieldTrial());
......
...@@ -113,6 +113,9 @@ class DataReductionProxyParams : public DataReductionProxyConfigValues { ...@@ -113,6 +113,9 @@ class DataReductionProxyParams : public DataReductionProxyConfigValues {
static std::string GetQuicFieldTrialName(); static std::string GetQuicFieldTrialName();
// Returns true if the Data Reduction Proxy config client should be used.
static bool IsConfigClientEnabled();
// Constructs configuration parameters. If |kAllowed|, then the standard // Constructs configuration parameters. If |kAllowed|, then the standard
// data reduction proxy configuration is allowed to be used. If // data reduction proxy configuration is allowed to be used. If
// |kfallbackAllowed| a fallback proxy can be used if the primary proxy is // |kfallbackAllowed| a fallback proxy can be used if the primary proxy is
......
...@@ -70,5 +70,9 @@ const char kEnableDataReductionProxyBypassWarning[] = ...@@ -70,5 +70,9 @@ const char kEnableDataReductionProxyBypassWarning[] =
const char kClearDataReductionProxyDataSavings[] = const char kClearDataReductionProxyDataSavings[] =
"clear-data-reduction-proxy-data-savings"; "clear-data-reduction-proxy-data-savings";
// Enable the data reduction proxy config client.
const char kEnableDataReductionProxyConfigClient[] =
"enable-data-reduction-proxy-config-client";
} // namespace switches } // namespace switches
} // namespace data_reduction_proxy } // namespace data_reduction_proxy
...@@ -28,6 +28,7 @@ extern const char kEnableDataReductionProxyAlt[]; ...@@ -28,6 +28,7 @@ extern const char kEnableDataReductionProxyAlt[];
extern const char kEnableDataReductionProxyLoFi[]; extern const char kEnableDataReductionProxyLoFi[];
extern const char kEnableDataReductionProxyBypassWarning[]; extern const char kEnableDataReductionProxyBypassWarning[];
extern const char kClearDataReductionProxyDataSavings[]; extern const char kClearDataReductionProxyDataSavings[];
extern const char kEnableDataReductionProxyConfigClient[];
} // namespace switches } // namespace switches
} // namespace data_reduction_proxy } // namespace data_reduction_proxy
......
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