Commit 97652ebe authored by jeremyim's avatar jeremyim Committed by Commit bot

Add ClientConfig proto, and JSON generation/parsing.

- Add the ClientConfig proto definition corresponding to the response
  coming from the service.
- Create a means of generating a pseudo response from the built in
  params and request options.
- Create a class to parse the JSON response.
- Add necessary helper classes for the ProxyScheme and time values
  coming from the service.

BUG=466753

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

Cr-Commit-Position: refs/heads/master@{#321931}
parent a34e151b
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
'data_reduction_proxy_unittest_sources': [ 'data_reduction_proxy_unittest_sources': [
'data_reduction_proxy/content/browser/data_reduction_proxy_message_filter_unittest.cc', 'data_reduction_proxy/content/browser/data_reduction_proxy_message_filter_unittest.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc',
...@@ -115,6 +116,7 @@ ...@@ -115,6 +116,7 @@
'data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs_unittest.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_tamper_detection_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_tamper_detection_unittest.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats_unittest.cc',
'data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser_unittest.cc',
'data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc',
'data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc',
'data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc',
......
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
'../net/net.gyp:net', '../net/net.gyp:net',
'../url/url.gyp:url_lib', '../url/url.gyp:url_lib',
'data_reduction_proxy_core_common', 'data_reduction_proxy_core_common',
'data_reduction_proxy_proto',
'pref_registry', 'pref_registry',
], ],
'include_dirs': [ 'include_dirs': [
...@@ -95,6 +96,8 @@ ...@@ -95,6 +96,8 @@
'data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_config.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_config.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_config.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_config.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc',
'data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h',
'data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc',
...@@ -130,6 +133,7 @@ ...@@ -130,6 +133,7 @@
'dependencies': [ 'dependencies': [
'../base/base.gyp:base', '../base/base.gyp:base',
'../url/url.gyp:url_lib', '../url/url.gyp:url_lib',
'data_reduction_proxy_proto',
], ],
'include_dirs': [ 'include_dirs': [
'..', '..',
...@@ -137,6 +141,8 @@ ...@@ -137,6 +141,8 @@
'sources': [ 'sources': [
# Note: sources list duplicated in GN build. # Note: sources list duplicated in GN build.
'data_reduction_proxy/core/common/data_reduction_proxy_bypass_type_list.h', 'data_reduction_proxy/core/common/data_reduction_proxy_bypass_type_list.h',
'data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.cc',
'data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h',
'data_reduction_proxy/core/common/data_reduction_proxy_config_values.h', 'data_reduction_proxy/core/common/data_reduction_proxy_config_values.h',
'data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc',
'data_reduction_proxy/core/common/data_reduction_proxy_event_store.h', 'data_reduction_proxy/core/common/data_reduction_proxy_event_store.h',
...@@ -185,6 +191,24 @@ ...@@ -185,6 +191,24 @@
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations. # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [4267, ], 'msvs_disabled_warnings': [4267, ],
}, },
{
# GN version: //components/data_reduction_proxy/proto
'target_name': 'data_reduction_proxy_proto',
'type': 'static_library',
'dependencies': [
],
'include_dirs': [
],
'sources': [
# Note: sources list duplicated in GN build.
'data_reduction_proxy/proto/client_config.proto',
],
'variables': {
'proto_in_dir': 'data_reduction_proxy/proto',
'proto_out_dir': 'components/data_reduction_proxy/proto',
},
'includes': [ '../build/protoc.gypi' ],
},
{ {
'target_name': 'data_reduction_proxy_version_header', 'target_name': 'data_reduction_proxy_version_header',
'type': 'none', 'type': 'none',
......
...@@ -8,6 +8,8 @@ static_library("browser") { ...@@ -8,6 +8,8 @@ static_library("browser") {
"data_reduction_proxy_bypass_protocol.h", "data_reduction_proxy_bypass_protocol.h",
"data_reduction_proxy_config.cc", "data_reduction_proxy_config.cc",
"data_reduction_proxy_config.h", "data_reduction_proxy_config.h",
"data_reduction_proxy_config_service_client.cc",
"data_reduction_proxy_config_service_client.h",
"data_reduction_proxy_configurator.cc", "data_reduction_proxy_configurator.cc",
"data_reduction_proxy_configurator.h", "data_reduction_proxy_configurator.h",
"data_reduction_proxy_debug_ui_service.h", "data_reduction_proxy_debug_ui_service.h",
...@@ -41,6 +43,7 @@ static_library("browser") { ...@@ -41,6 +43,7 @@ static_library("browser") {
"//base", "//base",
"//base:prefs", "//base:prefs",
"//components/data_reduction_proxy/core/common", "//components/data_reduction_proxy/core/common",
"//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//components/pref_registry", "//components/pref_registry",
"//crypto", "//crypto",
"//net", "//net",
...@@ -85,6 +88,7 @@ source_set("unit_tests") { ...@@ -85,6 +88,7 @@ source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"data_reduction_proxy_bypass_protocol_unittest.cc", "data_reduction_proxy_bypass_protocol_unittest.cc",
"data_reduction_proxy_config_service_client_unittest.cc",
"data_reduction_proxy_config_unittest.cc", "data_reduction_proxy_config_unittest.cc",
"data_reduction_proxy_configurator_unittest.cc", "data_reduction_proxy_configurator_unittest.cc",
"data_reduction_proxy_interceptor_unittest.cc", "data_reduction_proxy_interceptor_unittest.cc",
...@@ -105,6 +109,7 @@ source_set("unit_tests") { ...@@ -105,6 +109,7 @@ source_set("unit_tests") {
"//base:prefs_test_support", "//base:prefs_test_support",
"//base/test:test_support", "//base/test:test_support",
"//components/data_reduction_proxy/core/common:test_support", "//components/data_reduction_proxy/core/common:test_support",
"//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//net:test_support", "//net:test_support",
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
......
// 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_config_service_client.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
namespace data_reduction_proxy {
DataReductionProxyConfigServiceClient::DataReductionProxyConfigServiceClient(
DataReductionProxyParams* params,
DataReductionProxyRequestOptions* request_options)
: params_(params),
request_options_(request_options) {
DCHECK(params);
DCHECK(request_options);
}
DataReductionProxyConfigServiceClient::
~DataReductionProxyConfigServiceClient() {
}
std::string
DataReductionProxyConfigServiceClient::ConstructStaticResponse() const {
std::string response;
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue());
params_->PopulateConfigResponse(values.get());
request_options_->PopulateConfigResponse(values.get());
base::JSONWriter::Write(values.get(), &response);
return response;
}
} // 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_CONFIG_SERVICE_CLIENT_H_
#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_CONFIG_SERVICE_CLIENT_H_
#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
namespace data_reduction_proxy {
class DataReductionProxyParams;
class DataReductionProxyRequestOptions;
// Retrieves the Data Reduction Proxy configuration from a remote service. This
// object lives on the IO thread.
class DataReductionProxyConfigServiceClient {
public:
// The caller must ensure that all parameters remain alive for the lifetime of
// the |DataReductionProxyConfigClient|.
DataReductionProxyConfigServiceClient(
DataReductionProxyParams* params,
DataReductionProxyRequestOptions* request_options);
~DataReductionProxyConfigServiceClient();
private:
FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigClientTest,
TestConstructStaticResponse);
// Constructs a synthetic response based on |params_|.
std::string ConstructStaticResponse() const;
// The caller must ensure that the |params_| outlives this instance.
DataReductionProxyParams* params_;
// The caller must ensure that the |request_options_| outlives this instance.
DataReductionProxyRequestOptions* request_options_;
DISALLOW_COPY_AND_ASSIGN(DataReductionProxyConfigServiceClient);
};
} // namespace data_reduction_proxy
#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_CONFIG_SERVICE_CLIENT_H_
// 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_config_service_client.h"
#include <string>
#include "base/memory/scoped_ptr.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_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_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_reduction_proxy {
class DataReductionProxyConfigClientTest : public testing::Test {
protected:
void SetUp() override {
test_context_ =
DataReductionProxyTestContext::Builder()
.WithParamsFlags(DataReductionProxyParams::kAllowed |
DataReductionProxyParams::kFallbackAllowed |
DataReductionProxyParams::kPromoAllowed)
.WithParamsDefinitions(TestDataReductionProxyParams::HAS_EVERYTHING)
.Build();
}
scoped_ptr<DataReductionProxyConfigServiceClient> BuildConfigClient() {
return make_scoped_ptr(new DataReductionProxyConfigServiceClient(
test_context_->config()->test_params(),
test_context_->io_data()->request_options()));
}
private:
scoped_ptr<DataReductionProxyTestContext> test_context_;
};
TEST_F(DataReductionProxyConfigClientTest, TestConstructStaticResponse) {
scoped_ptr<DataReductionProxyConfigServiceClient> config_client =
BuildConfigClient();
std::string config_data = config_client->ConstructStaticResponse();
ClientConfig config;
EXPECT_TRUE(config_parser::ParseClientConfig(config_data, &config));
}
} // namespace data_reduction_proxy
...@@ -13,8 +13,10 @@ ...@@ -13,8 +13,10 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/time/time.h" #include "base/time/time.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_config.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"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.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.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
...@@ -69,6 +71,29 @@ bool DataReductionProxyRequestOptions::IsKeySetOnCommandLine() { ...@@ -69,6 +71,29 @@ bool DataReductionProxyRequestOptions::IsKeySetOnCommandLine() {
data_reduction_proxy::switches::kDataReductionProxyKey); data_reduction_proxy::switches::kDataReductionProxyKey);
} }
// static
std::string DataReductionProxyRequestOptions::CreateLocalSessionKey(
const std::string& session,
const std::string& credentials) {
return base::StringPrintf("%s|%s", session.c_str(), credentials.c_str());
}
// static
bool DataReductionProxyRequestOptions::ParseLocalSessionKey(
const std::string& session_key,
std::string* session,
std::string* credentials) {
std::vector<std::string> auth_values;
base::SplitString(session_key, '|', &auth_values);
if (auth_values.size() == 2) {
*session = auth_values[0];
*credentials = auth_values[1];
return true;
}
return false;
}
DataReductionProxyRequestOptions::DataReductionProxyRequestOptions( DataReductionProxyRequestOptions::DataReductionProxyRequestOptions(
Client client, Client client,
DataReductionProxyConfig* config, DataReductionProxyConfig* config,
...@@ -172,7 +197,8 @@ base::Time DataReductionProxyRequestOptions::Now() const { ...@@ -172,7 +197,8 @@ base::Time DataReductionProxyRequestOptions::Now() const {
return base::Time::Now(); return base::Time::Now();
} }
void DataReductionProxyRequestOptions::RandBytes(void* output, size_t length) { void DataReductionProxyRequestOptions::RandBytes(void* output,
size_t length) const {
crypto::RandBytes(output, length); crypto::RandBytes(output, length);
} }
...@@ -200,10 +226,9 @@ void DataReductionProxyRequestOptions::MaybeAddProxyTunnelRequestHandler( ...@@ -200,10 +226,9 @@ void DataReductionProxyRequestOptions::MaybeAddProxyTunnelRequestHandler(
void DataReductionProxyRequestOptions::SetHeader( void DataReductionProxyRequestOptions::SetHeader(
net::HttpRequestHeaders* headers) { net::HttpRequestHeaders* headers) {
base::Time now = Now(); base::Time now = Now();
// Authorization credentials must be regenerated at least every 24 hours. // Authorization credentials must be regenerated if they are expired.
if (now - last_credentials_update_time_ > base::TimeDelta::FromHours(24)) { if (now > credentials_expiration_time_)
UpdateCredentials(); UpdateCredentials();
}
UpdateLoFi(); UpdateLoFi();
const char kChromeProxyHeader[] = "Chrome-Proxy"; const char kChromeProxyHeader[] = "Chrome-Proxy";
std::string header_value; std::string header_value;
...@@ -219,7 +244,7 @@ void DataReductionProxyRequestOptions::SetHeader( ...@@ -219,7 +244,7 @@ void DataReductionProxyRequestOptions::SetHeader(
void DataReductionProxyRequestOptions::ComputeCredentials( void DataReductionProxyRequestOptions::ComputeCredentials(
const base::Time& now, const base::Time& now,
std::string* session, std::string* session,
std::string* credentials) { std::string* credentials) const {
DCHECK(session); DCHECK(session);
DCHECK(credentials); DCHECK(credentials);
int64 timestamp = int64 timestamp =
...@@ -241,8 +266,9 @@ void DataReductionProxyRequestOptions::ComputeCredentials( ...@@ -241,8 +266,9 @@ void DataReductionProxyRequestOptions::ComputeCredentials(
void DataReductionProxyRequestOptions::UpdateCredentials() { void DataReductionProxyRequestOptions::UpdateCredentials() {
std::string session; std::string session;
std::string credentials; std::string credentials;
last_credentials_update_time_ = Now(); base::Time now = Now();
ComputeCredentials(last_credentials_update_time_, &session_, &credentials_); ComputeCredentials(now, &session_, &credentials_);
credentials_expiration_time_ = now + base::TimeDelta::FromHours(24);
RegenerateRequestHeaderValue(); RegenerateRequestHeaderValue();
} }
...@@ -253,6 +279,20 @@ void DataReductionProxyRequestOptions::SetKeyOnIO(const std::string& key) { ...@@ -253,6 +279,20 @@ void DataReductionProxyRequestOptions::SetKeyOnIO(const std::string& key) {
} }
} }
void DataReductionProxyRequestOptions::PopulateConfigResponse(
base::DictionaryValue* response) const {
DCHECK(network_task_runner_->BelongsToCurrentThread());
std::string session;
std::string credentials;
base::Time now = Now();
base::Time expiration_time = now + base::TimeDelta::FromHours(24);
ComputeCredentials(now, &session, &credentials);
response->SetString("sessionKey",
CreateLocalSessionKey(session, credentials));
response->SetString("expireTime",
config_parser::TimeToISO8601(expiration_time));
}
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();
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/time/time.h" #include "base/time/time.h"
namespace base { namespace base {
class DictionaryValue;
class SingleThreadTaskRunner; class SingleThreadTaskRunner;
} }
...@@ -65,6 +66,22 @@ class DataReductionProxyRequestOptions { ...@@ -65,6 +66,22 @@ class DataReductionProxyRequestOptions {
public: public:
static bool IsKeySetOnCommandLine(); static bool IsKeySetOnCommandLine();
// A pair of functions to convert the session and credentials for the Data
// Reduction Proxy to and from a single string; they are used to encode the
// session and credentials values into the |session_key| field of the
// ClientConfig protocol buffer. The delimiter used is '|', as it is not a
// valid character in a session or credentials string.
//
// CreateLocalSessionKey joins session and credentials with the delimiter.
static std::string CreateLocalSessionKey(const std::string& session,
const std::string& credentials);
// ParseLocalSessionKey splits the output of CreateLocalSessionKey into its
// two components. |session| and |credentials| must not be null.
static bool ParseLocalSessionKey(const std::string& session_key,
std::string* session,
std::string* credentials);
// Constructs a DataReductionProxyRequestOptions object with the given // Constructs a DataReductionProxyRequestOptions object with the given
// client type, config, and network task runner. // client type, config, and network task runner.
DataReductionProxyRequestOptions( DataReductionProxyRequestOptions(
...@@ -104,6 +121,10 @@ class DataReductionProxyRequestOptions { ...@@ -104,6 +121,10 @@ class DataReductionProxyRequestOptions {
// SetKeyOnIO is called. // SetKeyOnIO is called.
void SetKeyOnIO(const std::string& key); void SetKeyOnIO(const std::string& key);
// Populates |response| with the Data Reduction Proxy authentication info.
// Virtualized for testing.
virtual void PopulateConfigResponse(base::DictionaryValue* response) const;
protected: protected:
void SetHeader(net::HttpRequestHeaders* headers); void SetHeader(net::HttpRequestHeaders* headers);
...@@ -114,7 +135,7 @@ class DataReductionProxyRequestOptions { ...@@ -114,7 +135,7 @@ class DataReductionProxyRequestOptions {
const std::string& key); const std::string& key);
// Visible for testing. // Visible for testing.
virtual base::Time Now() const; virtual base::Time Now() const;
virtual void RandBytes(void* output, size_t length); virtual void RandBytes(void* output, size_t length) const;
// Visible for testing. // Visible for testing.
virtual std::string GetDefaultKey() const; virtual std::string GetDefaultKey() const;
...@@ -153,7 +174,7 @@ class DataReductionProxyRequestOptions { ...@@ -153,7 +174,7 @@ class DataReductionProxyRequestOptions {
// the data reduction proxy. // the data reduction proxy.
void ComputeCredentials(const base::Time& now, void ComputeCredentials(const base::Time& now,
std::string* session, std::string* session,
std::string* credentials); std::string* credentials) const;
// Generates and updates the session ID and credentials. // Generates and updates the session ID and credentials.
void UpdateCredentials(); void UpdateCredentials();
...@@ -186,9 +207,9 @@ class DataReductionProxyRequestOptions { ...@@ -186,9 +207,9 @@ class DataReductionProxyRequestOptions {
std::string lofi_; std::string lofi_;
std::vector<std::string> experiments_; std::vector<std::string> experiments_;
// The last time the session was updated. Used to ensure that a session is // The time at which the session expires. Used to ensure that a session is
// never used for more than twenty-four hours. // never used for more than twenty-four hours.
base::Time last_credentials_update_time_; base::Time credentials_expiration_time_;
DataReductionProxyConfig* data_reduction_proxy_config_; DataReductionProxyConfig* data_reduction_proxy_config_;
......
...@@ -28,7 +28,6 @@ const char kVersion[] = "0.1.2.3"; ...@@ -28,7 +28,6 @@ const char kVersion[] = "0.1.2.3";
const char kExpectedBuild[] = "2"; const char kExpectedBuild[] = "2";
const char kExpectedPatch[] = "3"; const char kExpectedPatch[] = "3";
const char kBogusVersion[] = "0.0"; const char kBogusVersion[] = "0.0";
const char kTestKey[] = "test-key";
const char kExpectedCredentials[] = "96bd72ec4a050ba60981743d41787768"; const char kExpectedCredentials[] = "96bd72ec4a050ba60981743d41787768";
const char kExpectedSession[] = "0-1633771873-1633771873-1633771873"; const char kExpectedSession[] = "0-1633771873-1633771873-1633771873";
...@@ -77,41 +76,6 @@ const Client kClient = Client::UNKNOWN; ...@@ -77,41 +76,6 @@ const Client kClient = Client::UNKNOWN;
const char kClientStr[] = ""; const char kClientStr[] = "";
#endif #endif
class TestDataReductionProxyRequestOptions
: public DataReductionProxyRequestOptions {
public:
TestDataReductionProxyRequestOptions(
Client client,
const std::string& version,
DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: DataReductionProxyRequestOptions(
client, version, config, task_runner) {}
std::string GetDefaultKey() const override {
return kTestKey;
}
base::Time Now() const override {
return base::Time::UnixEpoch() + now_offset_;
}
void RandBytes(void* output, size_t length) override {
char* c = static_cast<char*>(output);
for (size_t i = 0; i < length; ++i) {
c[i] = 'a';
}
}
// Time after the unix epoch that Now() reports.
void set_offset(const base::TimeDelta& now_offset) {
now_offset_ = now_offset;
}
private:
base::TimeDelta now_offset_;
};
void SetHeaderExpectations(const std::string& session, void SetHeaderExpectations(const std::string& session,
const std::string& credentials, const std::string& credentials,
const std::string& client, const std::string& client,
...@@ -339,4 +303,64 @@ TEST_F(DataReductionProxyRequestOptionsTest, ParseExperiments) { ...@@ -339,4 +303,64 @@ TEST_F(DataReductionProxyRequestOptionsTest, ParseExperiments) {
VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); VerifyExpectedHeader(params()->DefaultOrigin(), expected_header);
} }
TEST_F(DataReductionProxyRequestOptionsTest, ParseLocalSessionKey) {
const struct {
bool should_succeed;
std::string session_key;
std::string expected_session;
std::string expected_credentials;
} tests[] = {
{
true,
"foobar|1234",
"foobar",
"1234",
},
{
false,
"foobar|1234|foobaz",
std::string(),
std::string(),
},
{
false,
"foobar",
std::string(),
std::string(),
},
{
false,
std::string(),
std::string(),
std::string(),
},
};
std::string session;
std::string credentials;
for (size_t i = 0; i < arraysize(tests); ++i) {
EXPECT_EQ(tests[i].should_succeed,
DataReductionProxyRequestOptions::ParseLocalSessionKey(
tests[i].session_key, &session, &credentials));
if (tests[i].should_succeed) {
EXPECT_EQ(tests[i].expected_session, session);
EXPECT_EQ(tests[i].expected_credentials, credentials);
}
}
}
TEST_F(DataReductionProxyRequestOptionsTest, PopulateConfigResponse) {
CreateRequestOptions(kBogusVersion);
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue());
request_options()->PopulateConfigResponse(values.get());
std::string session;
std::string expire_time;
EXPECT_TRUE(values->GetString("sessionKey", &session));
EXPECT_TRUE(values->GetString("expireTime", &expire_time));
EXPECT_EQ(
"0-1633771873-1633771873-1633771873|96bd72ec4a050ba60981743d41787768",
session);
EXPECT_EQ("1970-01-02T00:00:00.000Z", expire_time);
}
} // namespace data_reduction_proxy } // namespace data_reduction_proxy
...@@ -22,8 +22,55 @@ ...@@ -22,8 +22,55 @@
#include "net/url_request/url_request_job_factory_impl.h" #include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_util.h" #include "net/url_request/url_request_test_util.h"
namespace {
const char kTestKey[] = "test-key";
} // namespace
namespace data_reduction_proxy { namespace data_reduction_proxy {
TestDataReductionProxyRequestOptions::TestDataReductionProxyRequestOptions(
Client client,
const std::string& version,
DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: DataReductionProxyRequestOptions(client, version, config, task_runner) {
}
std::string TestDataReductionProxyRequestOptions::GetDefaultKey() const {
return kTestKey;
}
base::Time TestDataReductionProxyRequestOptions::Now() const {
return base::Time::UnixEpoch() + now_offset_;
}
void TestDataReductionProxyRequestOptions::RandBytes(void* output,
size_t length) const {
char* c = static_cast<char*>(output);
for (size_t i = 0; i < length; ++i) {
c[i] = 'a';
}
}
// Time after the unix epoch that Now() reports.
void TestDataReductionProxyRequestOptions::set_offset(
const base::TimeDelta& now_offset) {
now_offset_ = now_offset;
}
MockDataReductionProxyRequestOptions::MockDataReductionProxyRequestOptions(
Client client,
const std::string& version,
DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: DataReductionProxyRequestOptions(client, version, config, task_runner) {
}
MockDataReductionProxyRequestOptions::~MockDataReductionProxyRequestOptions() {
}
MockDataReductionProxyService::MockDataReductionProxyService( MockDataReductionProxyService::MockDataReductionProxyService(
scoped_ptr<DataReductionProxyStatisticsPrefs> statistics_prefs, scoped_ptr<DataReductionProxyStatisticsPrefs> statistics_prefs,
DataReductionProxySettings* settings, DataReductionProxySettings* settings,
...@@ -65,6 +112,7 @@ DataReductionProxyTestContext::Builder::Builder() ...@@ -65,6 +112,7 @@ DataReductionProxyTestContext::Builder::Builder()
use_mock_config_(false), use_mock_config_(false),
use_test_configurator_(false), use_test_configurator_(false),
use_mock_service_(false), use_mock_service_(false),
use_mock_request_options_(false),
skip_settings_initialization_(false) { skip_settings_initialization_(false) {
} }
...@@ -119,6 +167,12 @@ DataReductionProxyTestContext::Builder::WithMockDataReductionProxyService() { ...@@ -119,6 +167,12 @@ DataReductionProxyTestContext::Builder::WithMockDataReductionProxyService() {
return *this; return *this;
} }
DataReductionProxyTestContext::Builder&
DataReductionProxyTestContext::Builder::WithMockRequestOptions() {
use_mock_request_options_ = true;
return *this;
}
DataReductionProxyTestContext::Builder& DataReductionProxyTestContext::Builder&
DataReductionProxyTestContext::Builder::SkipSettingsInitialization() { DataReductionProxyTestContext::Builder::SkipSettingsInitialization() {
skip_settings_initialization_ = true; skip_settings_initialization_ = true;
...@@ -173,8 +227,15 @@ DataReductionProxyTestContext::Builder::Build() { ...@@ -173,8 +227,15 @@ DataReductionProxyTestContext::Builder::Build() {
configurator.get(), event_store.get())); configurator.get(), event_store.get()));
} }
scoped_ptr<DataReductionProxyRequestOptions> request_options( scoped_ptr<DataReductionProxyRequestOptions> request_options;
new DataReductionProxyRequestOptions(client_, config.get(), task_runner)); if (use_mock_request_options_) {
test_context_flags |= USE_MOCK_REQUEST_OPTIONS;
request_options.reset(new MockDataReductionProxyRequestOptions(
client_, std::string(), config.get(), task_runner));
} else {
request_options.reset(new DataReductionProxyRequestOptions(
client_, config.get(), task_runner));
}
scoped_ptr<DataReductionProxySettings> settings( scoped_ptr<DataReductionProxySettings> settings(
new DataReductionProxySettings()); new DataReductionProxySettings());
...@@ -344,6 +405,14 @@ DataReductionProxyTestContext::mock_data_reduction_proxy_service() ...@@ -344,6 +405,14 @@ DataReductionProxyTestContext::mock_data_reduction_proxy_service()
data_reduction_proxy_service()); data_reduction_proxy_service());
} }
MockDataReductionProxyRequestOptions*
DataReductionProxyTestContext::mock_request_options() const {
DCHECK(test_context_flags_ &
DataReductionProxyTestContext::USE_MOCK_REQUEST_OPTIONS);
return reinterpret_cast<MockDataReductionProxyRequestOptions*>(
io_data_->request_options());
}
DataReductionProxyUsageStats::UnreachableCallback DataReductionProxyUsageStats::UnreachableCallback
DataReductionProxyTestContext::unreachable_callback() const { DataReductionProxyTestContext::unreachable_callback() const {
return base::Bind(&DataReductionProxySettings::SetUnreachable, return base::Bind(&DataReductionProxySettings::SetUnreachable,
......
...@@ -5,9 +5,15 @@ ...@@ -5,9 +5,15 @@
#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_TEST_UTILS_H_ #ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_TEST_UTILS_H_
#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_TEST_UTILS_H_ #define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_TEST_UTILS_H_
#include <string>
#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/single_thread_task_runner.h"
#include "base/time/time.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_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"
...@@ -18,7 +24,6 @@ class TestingPrefServiceSimple; ...@@ -18,7 +24,6 @@ class TestingPrefServiceSimple;
namespace base { namespace base {
class MessageLoopForUI; class MessageLoopForUI;
class SingleThreadTaskRunner;
} }
namespace net { namespace net {
...@@ -40,6 +45,44 @@ class MockDataReductionProxyConfig; ...@@ -40,6 +45,44 @@ class MockDataReductionProxyConfig;
class TestDataReductionProxyConfig; class TestDataReductionProxyConfig;
class TestDataReductionProxyConfigurator; class TestDataReductionProxyConfigurator;
// Test version of |DataReductionProxyRequestOptions|.
class TestDataReductionProxyRequestOptions
: public DataReductionProxyRequestOptions {
public:
TestDataReductionProxyRequestOptions(
Client client,
const std::string& version,
DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// Overrides of DataReductionProxyRequestOptions.
std::string GetDefaultKey() const override;
base::Time Now() const override;
void RandBytes(void* output, size_t length) const override;
// Time after the unix epoch that Now() reports.
void set_offset(const base::TimeDelta& now_offset);
private:
base::TimeDelta now_offset_;
};
// Mock version of |DataReductionProxyRequestOptions|.
class MockDataReductionProxyRequestOptions
: public DataReductionProxyRequestOptions {
public:
MockDataReductionProxyRequestOptions(
Client client,
const std::string& version,
DataReductionProxyConfig* config,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~MockDataReductionProxyRequestOptions();
MOCK_CONST_METHOD1(PopulateConfigResponse,
void(base::DictionaryValue* response));
};
// 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 {
...@@ -118,6 +161,10 @@ class DataReductionProxyTestContext { ...@@ -118,6 +161,10 @@ class DataReductionProxyTestContext {
// |DataReductionProxyService|. // |DataReductionProxyService|.
Builder& WithMockDataReductionProxyService(); Builder& WithMockDataReductionProxyService();
// Specifies the use of |MockDataReductionProxyRequestOptions| instead of
// |DataReductionProxyRequestOptions|.
Builder& WithMockRequestOptions();
// Construct, but do not initialize the |DataReductionProxySettings| object. // Construct, but do not initialize the |DataReductionProxySettings| object.
Builder& SkipSettingsInitialization(); Builder& SkipSettingsInitialization();
...@@ -134,6 +181,7 @@ class DataReductionProxyTestContext { ...@@ -134,6 +181,7 @@ class DataReductionProxyTestContext {
bool use_mock_config_; bool use_mock_config_;
bool use_test_configurator_; bool use_test_configurator_;
bool use_mock_service_; bool use_mock_service_;
bool use_mock_request_options_;
bool skip_settings_initialization_; bool skip_settings_initialization_;
}; };
...@@ -179,6 +227,10 @@ class DataReductionProxyTestContext { ...@@ -179,6 +227,10 @@ class DataReductionProxyTestContext {
// be called if built with WithMockDataReductionProxyService. // be called if built with WithMockDataReductionProxyService.
MockDataReductionProxyService* mock_data_reduction_proxy_service() const; MockDataReductionProxyService* mock_data_reduction_proxy_service() const;
// Returns the underlying |MockDataReductionProxyRequestOptions|. This can
// only be called if built with WithMockRequestOptions.
MockDataReductionProxyRequestOptions* mock_request_options() const;
// 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
...@@ -233,6 +285,8 @@ class DataReductionProxyTestContext { ...@@ -233,6 +285,8 @@ class DataReductionProxyTestContext {
SKIP_SETTINGS_INITIALIZATION = 0x4, SKIP_SETTINGS_INITIALIZATION = 0x4,
// Permits mocking of the underlying |DataReductionProxyService|. // Permits mocking of the underlying |DataReductionProxyService|.
USE_MOCK_SERVICE = 0x8, USE_MOCK_SERVICE = 0x8,
// Permits mocking of the underlying |DataReductionProxyRequestOptions|.
USE_MOCK_REQUEST_OPTIONS = 0x10,
}; };
DataReductionProxyTestContext( DataReductionProxyTestContext(
......
...@@ -7,6 +7,8 @@ import("//chrome/version.gni") ...@@ -7,6 +7,8 @@ import("//chrome/version.gni")
static_library("common") { static_library("common") {
sources = [ sources = [
"data_reduction_proxy_bypass_type_list.h", "data_reduction_proxy_bypass_type_list.h",
"data_reduction_proxy_client_config_parser.cc",
"data_reduction_proxy_client_config_parser.h",
"data_reduction_proxy_config_values.h", "data_reduction_proxy_config_values.h",
"data_reduction_proxy_event_store.cc", "data_reduction_proxy_event_store.cc",
"data_reduction_proxy_event_store.h", "data_reduction_proxy_event_store.h",
...@@ -25,6 +27,7 @@ static_library("common") { ...@@ -25,6 +27,7 @@ static_library("common") {
] ]
deps = [ deps = [
"//base", "//base",
"//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//net", "//net",
"//url", "//url",
] ]
...@@ -54,6 +57,7 @@ source_set("test_support") { ...@@ -54,6 +57,7 @@ source_set("test_support") {
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"data_reduction_proxy_client_config_parser_unittest.cc",
"data_reduction_proxy_event_store_unittest.cc", "data_reduction_proxy_event_store_unittest.cc",
"data_reduction_proxy_headers_unittest.cc", "data_reduction_proxy_headers_unittest.cc",
"data_reduction_proxy_params_unittest.cc", "data_reduction_proxy_params_unittest.cc",
...@@ -64,6 +68,7 @@ source_set("unit_tests") { ...@@ -64,6 +68,7 @@ source_set("unit_tests") {
":test_support", ":test_support",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//net:test_support", "//net:test_support",
"//testing/gtest", "//testing/gtest",
] ]
......
// 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/common/data_reduction_proxy_client_config_parser.h"
#include <string>
#include "base/json/json_reader.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
namespace {
// String representations of ProxyServer schemes.
const char kSchemeHTTP[] = "HTTP";
const char kSchemeHTTPS[] = "HTTPS";
const char kSchemeQUIC[] = "QUIC";
const char kSchemeUnspecified[] = "UNSPECIFIED";
} // namespace
namespace data_reduction_proxy {
namespace config_parser {
std::string GetSchemeString(net::ProxyServer::Scheme scheme) {
switch (scheme) {
case net::ProxyServer::SCHEME_HTTP:
return kSchemeHTTP;
case net::ProxyServer::SCHEME_HTTPS:
return kSchemeHTTPS;
case net::ProxyServer::SCHEME_QUIC:
return kSchemeQUIC;
default:
return kSchemeUnspecified;
}
}
net::ProxyServer::Scheme SchemeFromProxyScheme(
ProxyServer_ProxyScheme proxy_scheme) {
switch (proxy_scheme) {
case ProxyServer_ProxyScheme_HTTP:
return net::ProxyServer::SCHEME_HTTP;
case ProxyServer_ProxyScheme_HTTPS:
return net::ProxyServer::SCHEME_HTTPS;
case ProxyServer_ProxyScheme_QUIC:
return net::ProxyServer::SCHEME_QUIC;
default:
return net::ProxyServer::SCHEME_INVALID;
}
}
ProxyServer_ProxyScheme GetProxyScheme(const std::string& scheme) {
if (scheme == kSchemeHTTP)
return ProxyServer_ProxyScheme_HTTP;
if (scheme == kSchemeHTTPS)
return ProxyServer_ProxyScheme_HTTPS;
if (scheme == kSchemeQUIC)
return ProxyServer_ProxyScheme_QUIC;
return ProxyServer_ProxyScheme_UNSPECIFIED;
}
std::string TimeToISO8601(const base::Time& time) {
base::Time::Exploded exploded;
time.UTCExplode(&exploded);
return base::StringPrintf(
"%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month,
exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
exploded.millisecond);
}
bool ISO8601ToTimestamp(const std::string& time, Timestamp* timestamp) {
base::Time t;
if (!base::Time::FromUTCString(time.c_str(), &t))
return false;
timestamp->set_seconds((t - base::Time::UnixEpoch()).InSeconds());
// Discard fractional seconds; it isn't worth the code effort to
// calculate it.
timestamp->set_nanos(0);
return true;
}
base::Time TimestampToTime(const Timestamp& timestamp) {
base::Time t = base::Time::UnixEpoch();
t += base::TimeDelta::FromSeconds(timestamp.seconds());
t += base::TimeDelta::FromMicroseconds(
timestamp.nanos() / base::Time::kNanosecondsPerMicrosecond);
return t;
}
bool ParseClientConfig(const std::string& config_data, ClientConfig* config) {
scoped_ptr<base::Value> parsed_data(base::JSONReader::Read(config_data));
if (!parsed_data)
return false;
const base::DictionaryValue* parsed_dict;
if (!parsed_data->GetAsDictionary(&parsed_dict))
return false;
std::string session_key;
if (!parsed_dict->GetString("sessionKey", &session_key))
return false;
config->set_session_key(session_key);
std::string expire_time;
if (!parsed_dict->GetString("expireTime", &expire_time))
return false;
if (!ISO8601ToTimestamp(expire_time, config->mutable_expire_time()))
return false;
const base::DictionaryValue* proxy_config_dict;
if (!parsed_dict->GetDictionary("proxyConfig", &proxy_config_dict))
return false;
ProxyConfig* proxy_config = config->mutable_proxy_config();
const base::ListValue* http_proxy_servers;
if (!proxy_config_dict->GetList("httpProxyServers", &http_proxy_servers))
return false;
base::ListValue::const_iterator it = http_proxy_servers->begin();
for (; it != http_proxy_servers->end(); ++it) {
const base::DictionaryValue* server_value;
if (!(*it)->GetAsDictionary(&server_value)) {
continue;
}
std::string scheme;
std::string host;
int port;
if (!server_value->GetString("scheme", &scheme)) {
continue;
}
if (!server_value->GetString("host", &host)) {
continue;
}
if (!server_value->GetInteger("port", &port)) {
continue;
}
ProxyServer_ProxyScheme proxy_scheme = GetProxyScheme(scheme);
if (proxy_scheme == ProxyServer_ProxyScheme_UNSPECIFIED)
continue;
ProxyServer* proxy_server = proxy_config->add_http_proxy_servers();
proxy_server->set_scheme(GetProxyScheme(scheme));
proxy_server->set_host(host);
proxy_server->set_port(port);
}
return true;
}
} // namespace config_parser
} // 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_COMMON_DATA_REDUCTION_PROXY_CLIENT_CONFIG_RESPONSE_PARSER_H_
#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_CLIENT_CONFIG_RESPONSE_PARSER_H_
#include <string>
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "net/proxy/proxy_server.h"
namespace base {
class Time;
}
namespace data_reduction_proxy {
namespace config_parser {
// Returns a string representation (which is actually the string representation
// of ProxyServer_ProxyScheme) of a |net::ProxyServer::Scheme|.
std::string GetSchemeString(net::ProxyServer::Scheme scheme);
// Returns the |net::ProxyServer::Scheme| for a ProxyServer_ProxyScheme.
net::ProxyServer::Scheme SchemeFromProxyScheme(
ProxyServer_ProxyScheme proxy_scheme);
// Retrieves the ProxyServer_ProxyScheme for its string representation.
ProxyServer_ProxyScheme GetProxyScheme(const std::string& scheme);
// Returns the ISO-8601 representation of |time|.
std::string TimeToISO8601(const base::Time& time);
// Parses an ISO-8601 time string into a Timestamp proto.
bool ISO8601ToTimestamp(const std::string& time, Timestamp* timestamp);
// Returns the |base::Time| representation of |timestamp|.
base::Time TimestampToTime(const Timestamp& timestamp);
// Takes a JSON representation of a |ClientConfig| and populates |config|.
// Returns false if the JSON has an unexpected structure.
// TODO(jeremyim): This should be deprecated once gRPC support can be added
// (which would give the binary proto instead of JSON).
bool ParseClientConfig(const std::string& config_data, ClientConfig* config);
} // namespace config_parser
} // namespace data_reduction_proxy
#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_CLIENT_CONFIG_RESPONSE_PARSER_H_
// 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/common/data_reduction_proxy_client_config_parser.h"
#include <string>
#include "base/time/time.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_reduction_proxy {
namespace {
const char kValidPreamble[] =
"{ \"sessionKey\": \"foobar\", "
"\"expireTime\": \"2100-12-31T23:59:59.999999Z\", "
"\"proxyConfig\": { \"httpProxyServers\": [";
const char kValidPostamble[] = "] } }";
} // namespace
TEST(ClientConfigParserTest, TimeToISO8601) {
const struct {
base::Time time;
std::string expected;
} tests[] = {
{
base::Time(),
"1601-01-01T00:00:00.000Z",
},
{
base::Time::UnixEpoch(),
"1970-01-01T00:00:00.000Z",
},
};
for (const auto& test : tests) {
EXPECT_EQ(test.expected, config_parser::TimeToISO8601(test.time));
}
}
TEST(ClientConfigParserTest, ISO8601ToTimestamp) {
const struct {
std::string time_string;
int64 epoch_seconds;
} tests[] = {
{
"1970-01-01T00:00:00.000Z",
0,
},
{
"1970-01-01T00:00:00.999Z",
0,
},
{
"1950-01-01T00:00:00.000Z",
-631152000,
},
{
"1950-01-01T00:00:00.500Z",
-631151999, // Rounding of negative fractional values causes this.
},
};
for (const auto& test : tests) {
Timestamp timestamp;
EXPECT_TRUE(
config_parser::ISO8601ToTimestamp(test.time_string, &timestamp));
EXPECT_EQ(test.epoch_seconds, timestamp.seconds());
EXPECT_EQ(0, timestamp.nanos());
}
}
TEST(ClientConfigParserTest, ISO8601ToTimestampTestFailures) {
const std::string inputs[] = {
"",
"Not a time",
"1234",
"2099-43-12",
"2099-11-52",
};
for (const auto& input : inputs) {
Timestamp timestamp;
EXPECT_FALSE(config_parser::ISO8601ToTimestamp(input, &timestamp));
}
}
TEST(ClientConfigParserTest, TimestampToTime) {
base::Time::Exploded future = {
2100,
12,
5,
31,
23,
59,
59,
0,
};
const struct {
int64 timestamp_seconds;
int32 timestamp_nanos;
base::Time expected_time;
} tests[] = {
{
0,
0,
base::Time::UnixEpoch(),
},
{
24 * 60 * 60 - 1,
base::Time::kNanosecondsPerSecond - 1,
base::Time::UnixEpoch() + base::TimeDelta::FromDays(1) -
base::TimeDelta::FromMicroseconds(1),
},
{
// 2100-12-31T23:59:59.000Z
4133980799,
0,
base::Time::FromUTCExploded(future),
},
};
for (const auto& test : tests) {
Timestamp ts;
ts.set_seconds(test.timestamp_seconds);
ts.set_nanos(test.timestamp_nanos);
EXPECT_EQ(test.expected_time, config_parser::TimestampToTime(ts));
}
}
TEST(ClientConfigParserTest, SingleServer) {
const std::string inputs[] = {
"{ \"scheme\": \"HTTP\", \"host\": \"foo.com\", \"port\": 80 }",
"{ \"scheme\": \"HTTPS\", \"host\": \"foo.com\", \"port\": 443 }",
"{ \"scheme\": \"QUIC\", \"host\": \"foo.com\", \"port\": 443 }",
};
for (const auto& scheme_fragment : inputs) {
std::string input = kValidPreamble + scheme_fragment + kValidPostamble;
ClientConfig config;
EXPECT_TRUE(config_parser::ParseClientConfig(input, &config));
EXPECT_EQ(1, config.proxy_config().http_proxy_servers_size());
}
}
TEST(ClientConfigParserTest, MultipleServers) {
std::string input =
"{ \"scheme\": \"HTTP\", ""\"host\": \"foo.com\", \"port\": 80 }, "
"{ \"scheme\": \"HTTPS\", \"host\": \"foo.com\", \"port\": 443 }, "
"{ \"scheme\": \"QUIC\", \"host\": \"foo.com\", \"port\": 443 }";
ClientConfig config;
EXPECT_TRUE(config_parser::ParseClientConfig(
kValidPreamble + input + kValidPostamble, &config));
EXPECT_EQ(3, config.proxy_config().http_proxy_servers_size());
}
TEST(ClientConfigParserTest, FailureCases) {
const std::string inputs[] = {
"",
"invalid json",
// No sessionKey
"{ \"expireTime\": \"2100-12-31T23:59:59.999999Z\","
"\"proxyConfig\": { \"httpProxyServers\": [ ] } }",
// No expireTime
"{ \"sessionKey\": \"foobar\","
"\"proxyConfig\": { \"httpProxyServers\": [ ] } }",
// No proxyConfig
"{ \"sessionKey\": \"foobar\", "
"\"expireTime\": \"2100-12-31T23:59:59.999999Z\" }",
// No proxyConfig.httpProxyServers
"{ \"sessionKey\": \"foobar\", "
"\"expireTime\": \"2100-12-31T23:59:59.999999Z\", \"proxyConfig\": { } }",
// Invalid sessionKey
"{ \"sessionKey\": 12345, "
"\"expireTime\": \"2100-12-31T23:59:59.999999Z\","
" \"proxyConfig\": { \"httpProxyServers\": [ ] } }",
// Invalid sessionKey
"{ \"sessionKey\": { }, "
"\"expireTime\": \"2100-12-31T23:59:59.999999Z\","
" \"proxyConfig\": { \"httpProxyServers\": [ ] } }",
// Invalid sessionKey
"{ \"sessionKey\": [ ], "
"\"expireTime\": \"2100-12-31T23:59:59.999999Z\","
" \"proxyConfig\": { \"httpProxyServers\": [ ] } }",
// Invalid expireTime
"{ \"sessionKey\": \"foobar\", "
"\"expireTime\": \"abcd\","
" \"proxyConfig\": { \"httpProxyServers\": [ ] } }",
// Invalid expireTime
"{ \"sessionKey\": \"foobar\", "
"\"expireTime\": [ ],"
" \"proxyConfig\": { \"httpProxyServers\": [ ] } }",
// Invalid expireTime
"{ \"sessionKey\": \"foobar\", "
"\"expireTime\": { },"
" \"proxyConfig\": { \"httpProxyServers\": [ ] } }",
};
for (const auto& input : inputs) {
ClientConfig config;
EXPECT_FALSE(config_parser::ParseClientConfig(input, &config));
}
}
TEST(ClientConfigParserTest, EmptyServerLists) {
const std::string inputs[] = {
"",
"{ }",
"{ \"scheme\": \"foo\", \"host\": \"foo.com\", \"port\": 80 }",
"{ \"scheme\": \"HTTP\", \"port\": 80 }",
"{ \"scheme\": \"HTTP\", \"host\": \"foo.com\" }",
"{ \"scheme\": \"HTTP\", \"host\": \"foo.com\", \"port\": \"bar\" }",
"{ \"scheme\": \"HTTP\", \"host\": 12345, \"port\": 80 }",
};
for (const auto& scheme_fragment : inputs) {
std::string input = kValidPreamble + scheme_fragment + kValidPostamble;
ClientConfig config;
EXPECT_TRUE(config_parser::ParseClientConfig(input, &config));
EXPECT_EQ(0, config.proxy_config().http_proxy_servers_size());
}
}
} // namespace data_reduction_proxy
...@@ -7,8 +7,11 @@ ...@@ -7,8 +7,11 @@
#include <string> #include <string>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h" #include "base/metrics/field_trial.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/values.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_switches.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "net/base/host_port_pair.h" #include "net/base/host_port_pair.h"
#include "net/proxy/proxy_server.h" #include "net/proxy/proxy_server.h"
...@@ -36,6 +39,11 @@ const char kDefaultWarmupUrl[] = "http://www.gstatic.com/generate_204"; ...@@ -36,6 +39,11 @@ const char kDefaultWarmupUrl[] = "http://www.gstatic.com/generate_204";
const char kAndroidOneIdentifier[] = "sprout"; const char kAndroidOneIdentifier[] = "sprout";
const char kQuicFieldTrial[] = "DataReductionProxyUseQuic"; const char kQuicFieldTrial[] = "DataReductionProxyUseQuic";
const char kConfigScheme[] = "scheme";
const char kConfigHost[] = "host";
const char kConfigPort[] = "port";
} // namespace } // namespace
namespace data_reduction_proxy { namespace data_reduction_proxy {
...@@ -386,6 +394,41 @@ bool DataReductionProxyParams::IsDataReductionProxy( ...@@ -386,6 +394,41 @@ bool DataReductionProxyParams::IsDataReductionProxy(
return false; return false;
} }
void DataReductionProxyParams::PopulateConfigResponse(
base::DictionaryValue* response) const {
scoped_ptr<base::Value> proxy_config(new base::DictionaryValue());
if (!holdback_) {
base::DictionaryValue* proxy_config_dict = nullptr;
if (!proxy_config->GetAsDictionary(&proxy_config_dict))
return;
scoped_ptr<base::Value> proxy_servers(new base::ListValue());
base::ListValue* proxy_servers_list = nullptr;
if (!proxy_servers->GetAsList(&proxy_servers_list))
return;
proxy_servers->GetAsList(&proxy_servers_list);
scoped_ptr<base::DictionaryValue> server(new base::DictionaryValue());
server->SetString(kConfigScheme,
config_parser::GetSchemeString(origin_.scheme()));
server->SetString(kConfigHost, origin_.host_port_pair().host());
server->SetInteger(kConfigPort, origin_.host_port_pair().port());
proxy_servers_list->Append(server.release());
server.reset(new base::DictionaryValue());
server->SetString(kConfigScheme, config_parser::GetSchemeString(
fallback_origin_.scheme()));
server->SetString(kConfigHost, fallback_origin_.host_port_pair().host());
server->SetInteger(kConfigPort, fallback_origin_.host_port_pair().port());
proxy_servers_list->Append(server.release());
proxy_config_dict->Set("httpProxyServers", proxy_servers.Pass());
}
response->Set("proxyConfig", proxy_config.Pass());
}
// Returns the data reduction proxy primary origin. // Returns the data reduction proxy primary origin.
const net::ProxyServer& DataReductionProxyParams::origin() const { const net::ProxyServer& DataReductionProxyParams::origin() const {
return origin_; return origin_;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "url/gurl.h" #include "url/gurl.h"
namespace base { namespace base {
class DictionaryValue;
class TimeDelta; class TimeDelta;
} }
...@@ -131,6 +132,10 @@ class DataReductionProxyParams : public DataReductionProxyConfigValues { ...@@ -131,6 +132,10 @@ class DataReductionProxyParams : public DataReductionProxyConfigValues {
// If true, uses QUIC instead of SPDY to connect to proxies that use TLS. // If true, uses QUIC instead of SPDY to connect to proxies that use TLS.
void EnableQuic(bool enable); void EnableQuic(bool enable);
// Populates |response| with the Data Reduction Proxy server configuration.
// Virtual for mocking.
virtual void PopulateConfigResponse(base::DictionaryValue* response) const;
// Overrides of |DataReductionProxyConfigValues| // Overrides of |DataReductionProxyConfigValues|
bool UsingHTTPTunnel(const net::HostPortPair& proxy_server) const override; bool UsingHTTPTunnel(const net::HostPortPair& proxy_server) const override;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <map> #include <map>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/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 "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "net/proxy/proxy_server.h" #include "net/proxy/proxy_server.h"
...@@ -766,4 +767,30 @@ TEST_F(DataReductionProxyParamsTest, AndroidOnePromoFieldTrial) { ...@@ -766,4 +767,30 @@ TEST_F(DataReductionProxyParamsTest, AndroidOnePromoFieldTrial) {
"google/hammerhead/hammerhead:5.0/LRX210/1570415:user/release-keys")); "google/hammerhead/hammerhead:5.0/LRX210/1570415:user/release-keys"));
} }
TEST_F(DataReductionProxyParamsTest, PopulateConfigResponse) {
DataReductionProxyParams params(
DataReductionProxyParams::kAllowed |
DataReductionProxyParams::kAlternativeAllowed);
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue());
params.PopulateConfigResponse(values.get());
base::DictionaryValue* proxy_config;
EXPECT_TRUE(values->GetDictionary("proxyConfig", &proxy_config));
base::ListValue* proxy_servers;
EXPECT_TRUE(proxy_config->GetList("httpProxyServers", &proxy_servers));
EXPECT_TRUE(proxy_servers->GetSize() == 2);
base::DictionaryValue* server;
EXPECT_TRUE(proxy_servers->GetDictionary(0, &server));
std::string host;
int port;
EXPECT_TRUE(server->GetString("host", &host));
EXPECT_TRUE(server->GetInteger("port", &port));
EXPECT_EQ(params.origin().host_port_pair().host(), host);
EXPECT_EQ(params.origin().host_port_pair().port(), port);
EXPECT_TRUE(proxy_servers->GetDictionary(1, &server));
EXPECT_TRUE(server->GetString("host", &host));
EXPECT_TRUE(server->GetInteger("port", &port));
EXPECT_EQ(params.fallback_origin().host_port_pair().host(), host);
EXPECT_EQ(params.fallback_origin().host_port_pair().port(), port);
}
} // namespace data_reduction_proxy } // 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.
import("//third_party/protobuf/proto_library.gni")
proto_library("data_reduction_proxy_proto") {
sources = [
"client_config.proto",
]
}
// 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.
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package data_reduction_proxy;
// The client configuration information for using the Data Saver service.
message ClientConfig {
// An opaque per-session key assigned by the server which permits use of the
// Data Saver HTTP proxy servers.
optional string session_key = 1;
// The time at which the secure_session_key is no longer valid. This is
// enforced by the Data Saver service, and is provided to permit the client
// to request a new session key prior to expiration.
optional Timestamp expire_time = 2;
// The DataSaver proxy configuration that is valid for the session.
optional ProxyConfig proxy_config = 3;
}
// A Timestamp represents a point in time independent of any time zone
// or calendar, represented as seconds and fractions of seconds at
// nanosecond resolution in UTC Epoch time.
message Timestamp {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
optional int64 seconds = 1;
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
optional int32 nanos = 2;
}
// Data Saver proxy configuration.
message ProxyConfig {
// Provides proxy server information for HTTP URIs.
repeated ProxyServer http_proxy_servers = 1;
}
// Configuration information for a specific proxy server.
message ProxyServer {
// The scheme of the proxy server.
enum ProxyScheme {
// The proxy scheme is unspecified.
UNSPECIFIED = 0;
// HTTP
HTTP = 1;
// HTTPS
HTTPS = 2;
// HTTPS over QUIC
QUIC = 3;
}
// The scheme for the proxy server.
optional ProxyScheme scheme = 1;
// The host name for the proxy server.
optional string host = 2;
// The port number for the proxy server.
optional int32 port = 3;
}
// Request object to create a client configuration object.
message CreateClientConfigRequest {
}
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