summaryrefslogtreecommitdiffstats
path: root/components/data_reduction_proxy
diff options
context:
space:
mode:
authorjeremyim <jeremyim@chromium.org>2015-03-23 21:08:35 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-24 04:10:06 +0000
commit97652ebe50c4be712aa976776bee9694cbce1178 (patch)
tree7c760d71d3b692a0729378fe64588654cdcea0a1 /components/data_reduction_proxy
parenta34e151bce4bdf56031c13941408e292815241ca (diff)
downloadchromium_src-97652ebe50c4be712aa976776bee9694cbce1178.zip
chromium_src-97652ebe50c4be712aa976776bee9694cbce1178.tar.gz
chromium_src-97652ebe50c4be712aa976776bee9694cbce1178.tar.bz2
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}
Diffstat (limited to 'components/data_reduction_proxy')
-rw-r--r--components/data_reduction_proxy/core/browser/BUILD.gn5
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc39
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h48
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc52
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc54
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h29
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc96
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc73
-rw-r--r--components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h56
-rw-r--r--components/data_reduction_proxy/core/common/BUILD.gn5
-rw-r--r--components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.cc166
-rw-r--r--components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h51
-rw-r--r--components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser_unittest.cc228
-rw-r--r--components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc43
-rw-r--r--components/data_reduction_proxy/core/common/data_reduction_proxy_params.h5
-rw-r--r--components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc27
-rw-r--r--components/data_reduction_proxy/proto/BUILD.gn11
-rw-r--r--components/data_reduction_proxy/proto/client_config.proto70
18 files changed, 1008 insertions, 50 deletions
diff --git a/components/data_reduction_proxy/core/browser/BUILD.gn b/components/data_reduction_proxy/core/browser/BUILD.gn
index 0bc2867..5790d4c 100644
--- a/components/data_reduction_proxy/core/browser/BUILD.gn
+++ b/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -8,6 +8,8 @@ static_library("browser") {
"data_reduction_proxy_bypass_protocol.h",
"data_reduction_proxy_config.cc",
"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.h",
"data_reduction_proxy_debug_ui_service.h",
@@ -41,6 +43,7 @@ static_library("browser") {
"//base",
"//base:prefs",
"//components/data_reduction_proxy/core/common",
+ "//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//components/pref_registry",
"//crypto",
"//net",
@@ -85,6 +88,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"data_reduction_proxy_bypass_protocol_unittest.cc",
+ "data_reduction_proxy_config_service_client_unittest.cc",
"data_reduction_proxy_config_unittest.cc",
"data_reduction_proxy_configurator_unittest.cc",
"data_reduction_proxy_interceptor_unittest.cc",
@@ -105,6 +109,7 @@ source_set("unit_tests") {
"//base:prefs_test_support",
"//base/test:test_support",
"//components/data_reduction_proxy/core/common:test_support",
+ "//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//net:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
new file mode 100644
index 0000000..39a9481
--- /dev/null
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -0,0 +1,39 @@
+// 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
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
new file mode 100644
index 0000000..648cee4
--- /dev/null
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
@@ -0,0 +1,48 @@
+// 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_
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
new file mode 100644
index 0000000..6b44ceb
--- /dev/null
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -0,0 +1,52 @@
+// 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
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
index 985dfa5..675b05c 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
@@ -13,8 +13,10 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.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_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_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
@@ -69,6 +71,29 @@ bool DataReductionProxyRequestOptions::IsKeySetOnCommandLine() {
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(
Client client,
DataReductionProxyConfig* config,
@@ -172,7 +197,8 @@ base::Time DataReductionProxyRequestOptions::Now() const {
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);
}
@@ -200,10 +226,9 @@ void DataReductionProxyRequestOptions::MaybeAddProxyTunnelRequestHandler(
void DataReductionProxyRequestOptions::SetHeader(
net::HttpRequestHeaders* headers) {
base::Time now = Now();
- // Authorization credentials must be regenerated at least every 24 hours.
- if (now - last_credentials_update_time_ > base::TimeDelta::FromHours(24)) {
+ // Authorization credentials must be regenerated if they are expired.
+ if (now > credentials_expiration_time_)
UpdateCredentials();
- }
UpdateLoFi();
const char kChromeProxyHeader[] = "Chrome-Proxy";
std::string header_value;
@@ -219,7 +244,7 @@ void DataReductionProxyRequestOptions::SetHeader(
void DataReductionProxyRequestOptions::ComputeCredentials(
const base::Time& now,
std::string* session,
- std::string* credentials) {
+ std::string* credentials) const {
DCHECK(session);
DCHECK(credentials);
int64 timestamp =
@@ -241,8 +266,9 @@ void DataReductionProxyRequestOptions::ComputeCredentials(
void DataReductionProxyRequestOptions::UpdateCredentials() {
std::string session;
std::string credentials;
- last_credentials_update_time_ = Now();
- ComputeCredentials(last_credentials_update_time_, &session_, &credentials_);
+ base::Time now = Now();
+ ComputeCredentials(now, &session_, &credentials_);
+ credentials_expiration_time_ = now + base::TimeDelta::FromHours(24);
RegenerateRequestHeaderValue();
}
@@ -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 {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
index e5f7ce1..5a0b3b0 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
@@ -14,6 +14,7 @@
#include "base/time/time.h"
namespace base {
+class DictionaryValue;
class SingleThreadTaskRunner;
}
@@ -65,6 +66,22 @@ class DataReductionProxyRequestOptions {
public:
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
// client type, config, and network task runner.
DataReductionProxyRequestOptions(
@@ -104,6 +121,10 @@ class DataReductionProxyRequestOptions {
// SetKeyOnIO is called.
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:
void SetHeader(net::HttpRequestHeaders* headers);
@@ -114,7 +135,7 @@ class DataReductionProxyRequestOptions {
const std::string& key);
// Visible for testing.
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.
virtual std::string GetDefaultKey() const;
@@ -153,7 +174,7 @@ class DataReductionProxyRequestOptions {
// the data reduction proxy.
void ComputeCredentials(const base::Time& now,
std::string* session,
- std::string* credentials);
+ std::string* credentials) const;
// Generates and updates the session ID and credentials.
void UpdateCredentials();
@@ -186,9 +207,9 @@ class DataReductionProxyRequestOptions {
std::string lofi_;
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.
- base::Time last_credentials_update_time_;
+ base::Time credentials_expiration_time_;
DataReductionProxyConfig* data_reduction_proxy_config_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
index 70ea1f4..d34ebf2 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
@@ -28,7 +28,6 @@ const char kVersion[] = "0.1.2.3";
const char kExpectedBuild[] = "2";
const char kExpectedPatch[] = "3";
const char kBogusVersion[] = "0.0";
-const char kTestKey[] = "test-key";
const char kExpectedCredentials[] = "96bd72ec4a050ba60981743d41787768";
const char kExpectedSession[] = "0-1633771873-1633771873-1633771873";
@@ -77,41 +76,6 @@ const Client kClient = Client::UNKNOWN;
const char kClientStr[] = "";
#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,
const std::string& credentials,
const std::string& client,
@@ -339,4 +303,64 @@ TEST_F(DataReductionProxyRequestOptionsTest, ParseExperiments) {
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
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
index 422cd42..e9ea65ee 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -22,8 +22,55 @@
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_util.h"
+namespace {
+
+const char kTestKey[] = "test-key";
+
+} // namespace
+
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(
scoped_ptr<DataReductionProxyStatisticsPrefs> statistics_prefs,
DataReductionProxySettings* settings,
@@ -65,6 +112,7 @@ DataReductionProxyTestContext::Builder::Builder()
use_mock_config_(false),
use_test_configurator_(false),
use_mock_service_(false),
+ use_mock_request_options_(false),
skip_settings_initialization_(false) {
}
@@ -120,6 +168,12 @@ DataReductionProxyTestContext::Builder::WithMockDataReductionProxyService() {
}
DataReductionProxyTestContext::Builder&
+DataReductionProxyTestContext::Builder::WithMockRequestOptions() {
+ use_mock_request_options_ = true;
+ return *this;
+}
+
+DataReductionProxyTestContext::Builder&
DataReductionProxyTestContext::Builder::SkipSettingsInitialization() {
skip_settings_initialization_ = true;
return *this;
@@ -173,8 +227,15 @@ DataReductionProxyTestContext::Builder::Build() {
configurator.get(), event_store.get()));
}
- scoped_ptr<DataReductionProxyRequestOptions> request_options(
- new DataReductionProxyRequestOptions(client_, config.get(), task_runner));
+ scoped_ptr<DataReductionProxyRequestOptions> request_options;
+ 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(
new DataReductionProxySettings());
@@ -344,6 +405,14 @@ DataReductionProxyTestContext::mock_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
DataReductionProxyTestContext::unreachable_callback() const {
return base::Bind(&DataReductionProxySettings::SetUnreachable,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
index 589e391..9e0695ef 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
@@ -5,9 +5,15 @@
#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_
+#include <string>
+
#include "base/macros.h"
+#include "base/memory/ref_counted.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_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_settings_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h"
@@ -18,7 +24,6 @@ class TestingPrefServiceSimple;
namespace base {
class MessageLoopForUI;
-class SingleThreadTaskRunner;
}
namespace net {
@@ -40,6 +45,44 @@ class MockDataReductionProxyConfig;
class TestDataReductionProxyConfig;
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
// methods.
class MockDataReductionProxyService : public DataReductionProxyService {
@@ -118,6 +161,10 @@ class DataReductionProxyTestContext {
// |DataReductionProxyService|.
Builder& WithMockDataReductionProxyService();
+ // Specifies the use of |MockDataReductionProxyRequestOptions| instead of
+ // |DataReductionProxyRequestOptions|.
+ Builder& WithMockRequestOptions();
+
// Construct, but do not initialize the |DataReductionProxySettings| object.
Builder& SkipSettingsInitialization();
@@ -134,6 +181,7 @@ class DataReductionProxyTestContext {
bool use_mock_config_;
bool use_test_configurator_;
bool use_mock_service_;
+ bool use_mock_request_options_;
bool skip_settings_initialization_;
};
@@ -179,6 +227,10 @@ class DataReductionProxyTestContext {
// be called if built with WithMockDataReductionProxyService.
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
// longer reachable.
DataReductionProxyUsageStats::UnreachableCallback
@@ -233,6 +285,8 @@ class DataReductionProxyTestContext {
SKIP_SETTINGS_INITIALIZATION = 0x4,
// Permits mocking of the underlying |DataReductionProxyService|.
USE_MOCK_SERVICE = 0x8,
+ // Permits mocking of the underlying |DataReductionProxyRequestOptions|.
+ USE_MOCK_REQUEST_OPTIONS = 0x10,
};
DataReductionProxyTestContext(
diff --git a/components/data_reduction_proxy/core/common/BUILD.gn b/components/data_reduction_proxy/core/common/BUILD.gn
index a28e6d0..6976004 100644
--- a/components/data_reduction_proxy/core/common/BUILD.gn
+++ b/components/data_reduction_proxy/core/common/BUILD.gn
@@ -7,6 +7,8 @@ import("//chrome/version.gni")
static_library("common") {
sources = [
"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_event_store.cc",
"data_reduction_proxy_event_store.h",
@@ -25,6 +27,7 @@ static_library("common") {
]
deps = [
"//base",
+ "//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//net",
"//url",
]
@@ -54,6 +57,7 @@ source_set("test_support") {
source_set("unit_tests") {
testonly = true
sources = [
+ "data_reduction_proxy_client_config_parser_unittest.cc",
"data_reduction_proxy_event_store_unittest.cc",
"data_reduction_proxy_headers_unittest.cc",
"data_reduction_proxy_params_unittest.cc",
@@ -64,6 +68,7 @@ source_set("unit_tests") {
":test_support",
"//base",
"//base/test:test_support",
+ "//components/data_reduction_proxy/proto:data_reduction_proxy_proto",
"//net:test_support",
"//testing/gtest",
]
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.cc
new file mode 100644
index 0000000..586ad68
--- /dev/null
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.cc
@@ -0,0 +1,166 @@
+// 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
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h
new file mode 100644
index 0000000..461d945
--- /dev/null
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h
@@ -0,0 +1,51 @@
+// 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_
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser_unittest.cc
new file mode 100644
index 0000000..b7a9704
--- /dev/null
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser_unittest.cc
@@ -0,0 +1,228 @@
+// 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
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index 770e331..3769f3a 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -7,8 +7,11 @@
#include <string>
#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.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 "net/base/host_port_pair.h"
#include "net/proxy/proxy_server.h"
@@ -36,6 +39,11 @@ const char kDefaultWarmupUrl[] = "http://www.gstatic.com/generate_204";
const char kAndroidOneIdentifier[] = "sprout";
const char kQuicFieldTrial[] = "DataReductionProxyUseQuic";
+
+const char kConfigScheme[] = "scheme";
+const char kConfigHost[] = "host";
+const char kConfigPort[] = "port";
+
} // namespace
namespace data_reduction_proxy {
@@ -386,6 +394,41 @@ bool DataReductionProxyParams::IsDataReductionProxy(
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.
const net::ProxyServer& DataReductionProxyParams::origin() const {
return origin_;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
index 256c6c4..30c51ff 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -13,6 +13,7 @@
#include "url/gurl.h"
namespace base {
+class DictionaryValue;
class TimeDelta;
}
@@ -131,6 +132,10 @@ class DataReductionProxyParams : public DataReductionProxyConfigValues {
// If true, uses QUIC instead of SPDY to connect to proxies that use TLS.
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|
bool UsingHTTPTunnel(const net::HostPortPair& proxy_server) const override;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
index e2e8120..aa50741 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
@@ -7,6 +7,7 @@
#include <map>
#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_switches.h"
#include "net/proxy/proxy_server.h"
@@ -766,4 +767,30 @@ TEST_F(DataReductionProxyParamsTest, AndroidOnePromoFieldTrial) {
"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
diff --git a/components/data_reduction_proxy/proto/BUILD.gn b/components/data_reduction_proxy/proto/BUILD.gn
new file mode 100644
index 0000000..889c106
--- /dev/null
+++ b/components/data_reduction_proxy/proto/BUILD.gn
@@ -0,0 +1,11 @@
+# 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",
+ ]
+}
diff --git a/components/data_reduction_proxy/proto/client_config.proto b/components/data_reduction_proxy/proto/client_config.proto
new file mode 100644
index 0000000..f2c796c
--- /dev/null
+++ b/components/data_reduction_proxy/proto/client_config.proto
@@ -0,0 +1,70 @@
+// 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 {
+}