summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-23 22:20:39 +0000
committerasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-23 22:20:39 +0000
commit54af732e80e6638e1948aedc39c958ea8bf335a6 (patch)
tree2daeffa3b149a474b58c2586b48104d28b300378
parent25d0b8b724f0cc2d7041e8cf8ae040efe129d95f (diff)
downloadchromium_src-54af732e80e6638e1948aedc39c958ea8bf335a6.zip
chromium_src-54af732e80e6638e1948aedc39c958ea8bf335a6.tar.gz
chromium_src-54af732e80e6638e1948aedc39c958ea8bf335a6.tar.bz2
Add plumbing for persisting a signature for the variations seed.
In a later CL, I will add logic to actually use this signature for validating the integrity of the seed. BUG=336536 Review URL: https://codereview.chromium.org/143803008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246702 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chrome_browser_main.cc4
-rw-r--r--chrome/browser/first_run/first_run.cc2
-rw-r--r--chrome/browser/first_run/first_run.h1
-rw-r--r--chrome/browser/first_run/first_run_unittest.cc19
-rw-r--r--chrome/browser/metrics/variations/variations_seed_store.cc20
-rw-r--r--chrome/browser/metrics/variations/variations_seed_store.h10
-rw-r--r--chrome/browser/metrics/variations/variations_seed_store_unittest.cc39
-rw-r--r--chrome/browser/metrics/variations/variations_service.cc6
-rw-r--r--chrome/common/pref_names.cc3
-rw-r--r--chrome/common/pref_names.h1
-rw-r--r--chrome/installer/util/master_preferences.cc19
-rw-r--r--chrome/installer/util/master_preferences.h9
12 files changed, 103 insertions, 30 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index df7f182..77205a8 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -940,6 +940,10 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
if (!master_prefs_->variations_seed.empty()) {
local_state_->SetString(prefs::kVariationsSeed,
master_prefs_->variations_seed);
+ if (!master_prefs_->variations_seed_signature.empty()) {
+ local_state_->SetString(prefs::kVariationsSeedSignature,
+ master_prefs_->variations_seed_signature);
+ }
// Set the variation seed date to the current system time. If the user's
// clock is incorrect, this may cause some field trial expiry checks to
// not do the right thing until the next seed update from the server,
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index add798e..ef33f3e 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -564,6 +564,8 @@ void SetupMasterPrefsFromInstallPrefs(
&out_prefs->import_bookmarks_path);
out_prefs->variations_seed = install_prefs.GetVariationsSeed();
+ out_prefs->variations_seed_signature =
+ install_prefs.GetVariationsSeedSignature();
install_prefs.GetString(
installer::master_preferences::kDistroSuppressDefaultBrowserPromptPref,
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h
index c1570cb..58911f3 100644
--- a/chrome/browser/first_run/first_run.h
+++ b/chrome/browser/first_run/first_run.h
@@ -79,6 +79,7 @@ struct MasterPrefs {
std::vector<GURL> bookmarks;
std::string import_bookmarks_path;
std::string variations_seed;
+ std::string variations_seed_signature;
std::string suppress_default_browser_prompt_for_version;
};
diff --git a/chrome/browser/first_run/first_run_unittest.cc b/chrome/browser/first_run/first_run_unittest.cc
index badf91b..bccc9e8 100644
--- a/chrome/browser/first_run/first_run_unittest.cc
+++ b/chrome/browser/first_run/first_run_unittest.cc
@@ -7,6 +7,7 @@
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/test/scoped_path_override.h"
+#include "base/values.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/first_run/first_run_internal.h"
#include "chrome/common/chrome_paths.h"
@@ -42,18 +43,36 @@ TEST_F(FirstRunTest, RemoveSentinel) {
TEST_F(FirstRunTest, SetupMasterPrefsFromInstallPrefs_VariationsSeed) {
installer::MasterPreferences install_prefs("{ \"variations_seed\":\"xyz\" }");
+ EXPECT_EQ(1U, install_prefs.master_dictionary().size());
MasterPrefs out_prefs;
internal::SetupMasterPrefsFromInstallPrefs(install_prefs, &out_prefs);
EXPECT_EQ("xyz", out_prefs.variations_seed);
+ // Variations prefs should have been extracted (removed) from the dictionary.
+ EXPECT_TRUE(install_prefs.master_dictionary().empty());
}
TEST_F(FirstRunTest, SetupMasterPrefsFromInstallPrefs_NoVariationsSeed) {
installer::MasterPreferences install_prefs("{ }");
+ EXPECT_TRUE(install_prefs.master_dictionary().empty());
MasterPrefs out_prefs;
internal::SetupMasterPrefsFromInstallPrefs(install_prefs, &out_prefs);
EXPECT_TRUE(out_prefs.variations_seed.empty());
+ EXPECT_TRUE(out_prefs.variations_seed_signature.empty());
+}
+
+TEST_F(FirstRunTest, SetupMasterPrefsFromInstallPrefs_VariationsSeedSignature) {
+ installer::MasterPreferences install_prefs(
+ "{ \"variations_seed\":\"xyz\", \"variations_seed_signature\":\"abc\" }");
+ EXPECT_EQ(2U, install_prefs.master_dictionary().size());
+
+ MasterPrefs out_prefs;
+ internal::SetupMasterPrefsFromInstallPrefs(install_prefs, &out_prefs);
+ EXPECT_EQ("xyz", out_prefs.variations_seed);
+ EXPECT_EQ("abc", out_prefs.variations_seed_signature);
+ // Variations prefs should have been extracted (removed) from the dictionary.
+ EXPECT_TRUE(install_prefs.master_dictionary().empty());
}
} // namespace first_run
diff --git a/chrome/browser/metrics/variations/variations_seed_store.cc b/chrome/browser/metrics/variations/variations_seed_store.cc
index 2bf3b54..45ce323 100644
--- a/chrome/browser/metrics/variations/variations_seed_store.cc
+++ b/chrome/browser/metrics/variations/variations_seed_store.cc
@@ -63,9 +63,7 @@ bool VariationsSeedStore::LoadSeed(VariationsSeed* seed) {
!seed->ParseFromString(seed_data)) {
VLOG(1) << "Variations seed data in local pref is corrupt, clearing the "
<< "pref.";
- local_state_->ClearPref(prefs::kVariationsSeed);
- local_state_->ClearPref(prefs::kVariationsSeedDate);
- local_state_->ClearPref(prefs::kVariationsSeedHash);
+ ClearPrefs();
RecordVariationSeedEmptyHistogram(VARIATIONS_SEED_CORRUPT);
return false;
}
@@ -74,8 +72,10 @@ bool VariationsSeedStore::LoadSeed(VariationsSeed* seed) {
return true;
}
-bool VariationsSeedStore::StoreSeedData(const std::string& seed_data,
- const base::Time& date_fetched) {
+bool VariationsSeedStore::StoreSeedData(
+ const std::string& seed_data,
+ const std::string& base64_seed_signature,
+ const base::Time& date_fetched) {
if (seed_data.empty()) {
VLOG(1) << "Variations seed data is empty, rejecting the seed.";
return false;
@@ -96,6 +96,8 @@ bool VariationsSeedStore::StoreSeedData(const std::string& seed_data,
local_state_->SetString(prefs::kVariationsSeedHash, HashSeed(seed_data));
local_state_->SetInt64(prefs::kVariationsSeedDate,
date_fetched.ToInternalValue());
+ local_state_->SetString(prefs::kVariationsSeedSignature,
+ base64_seed_signature);
variations_serial_number_ = seed.serial_number();
return true;
@@ -107,6 +109,14 @@ void VariationsSeedStore::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kVariationsSeedHash, std::string());
registry->RegisterInt64Pref(prefs::kVariationsSeedDate,
base::Time().ToInternalValue());
+ registry->RegisterStringPref(prefs::kVariationsSeedSignature, std::string());
+}
+
+void VariationsSeedStore::ClearPrefs() {
+ local_state_->ClearPref(prefs::kVariationsSeed);
+ local_state_->ClearPref(prefs::kVariationsSeedDate);
+ local_state_->ClearPref(prefs::kVariationsSeedHash);
+ local_state_->ClearPref(prefs::kVariationsSeedSignature);
}
} // namespace chrome_variations
diff --git a/chrome/browser/metrics/variations/variations_seed_store.h b/chrome/browser/metrics/variations/variations_seed_store.h
index 80c5d64..5f8ddd7 100644
--- a/chrome/browser/metrics/variations/variations_seed_store.h
+++ b/chrome/browser/metrics/variations/variations_seed_store.h
@@ -30,10 +30,11 @@ class VariationsSeedStore {
bool LoadSeed(VariationsSeed* seed);
// Stores the given seed data (serialized protobuf data) to local state, along
- // with the date when it was fetched. The |seed_data| will be Base64 encoded
- // for storage. If the string is invalid, the existing prefs are left as is
- // and the function returns false.
+ // with a base64-encoded digital signature for seed and the date when it was
+ // fetched. The |seed_data| will be base64 encoded for storage. If the string
+ // is invalid, the existing prefs are left as is and false is returned.
bool StoreSeedData(const std::string& seed_data,
+ const std::string& base64_seed_signature,
const base::Time& date_fetched);
// Returns the serial number of the last loaded or stored seed.
@@ -45,6 +46,9 @@ class VariationsSeedStore {
static void RegisterPrefs(PrefRegistrySimple* registry);
private:
+ // Clears all prefs related to variations seed storage.
+ void ClearPrefs();
+
// The pref service used to persist the variations seed.
PrefService* local_state_;
diff --git a/chrome/browser/metrics/variations/variations_seed_store_unittest.cc b/chrome/browser/metrics/variations/variations_seed_store_unittest.cc
index 738386b..03965f6 100644
--- a/chrome/browser/metrics/variations/variations_seed_store_unittest.cc
+++ b/chrome/browser/metrics/variations/variations_seed_store_unittest.cc
@@ -53,6 +53,13 @@ std::string SerializeSeedBase64(const VariationsSeed& seed, std::string* hash) {
return base64_serialized_seed;
}
+// Checks whether the pref with name |pref_name| is at its default value in
+// |prefs|.
+bool PrefHasDefaultValue(const TestingPrefServiceSimple& prefs,
+ const char* pref_name) {
+ return prefs.FindPreference(pref_name)->IsDefaultValue();
+}
+
} // namespace
TEST(VariationsSeedStoreTest, LoadSeed) {
@@ -74,7 +81,7 @@ TEST(VariationsSeedStoreTest, LoadSeed) {
// Check that the loaded data is the same as the original.
EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
// Make sure the pref hasn't been changed.
- EXPECT_FALSE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
EXPECT_EQ(base64_seed, prefs.GetString(prefs::kVariationsSeed));
// Check that loading a seed with the correct hash works.
@@ -90,24 +97,22 @@ TEST(VariationsSeedStoreTest, LoadSeed) {
prefs.SetString(prefs::kVariationsSeed,
SerializeSeedBase64(different_seed, &different_hash));
ASSERT_NE(different_hash, prefs.GetString(prefs::kVariationsSeedHash));
- EXPECT_FALSE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed));
- EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
- EXPECT_TRUE(
- prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
- EXPECT_TRUE(
- prefs.FindPreference(prefs::kVariationsSeedHash)->IsDefaultValue());
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedHash));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
// Check that loading a bad seed returns false and clears the pref.
prefs.ClearPref(prefs::kVariationsSeed);
prefs.SetString(prefs::kVariationsSeed, "this should fail");
- EXPECT_FALSE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed));
- EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
- EXPECT_TRUE(
- prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
- EXPECT_TRUE(
- prefs.FindPreference(prefs::kVariationsSeedHash)->IsDefaultValue());
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedHash));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
// Check that having no seed in prefs results in a return value of false.
prefs.ClearPref(prefs::kVariationsSeed);
@@ -124,9 +129,9 @@ TEST(VariationsSeedStoreTest, StoreSeedData) {
VariationsSeedStore seed_store(&prefs);
- EXPECT_TRUE(seed_store.StoreSeedData(serialized_seed, now));
+ EXPECT_TRUE(seed_store.StoreSeedData(serialized_seed, std::string(), now));
// Make sure the pref was actually set.
- EXPECT_FALSE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
std::string loaded_serialized_seed = prefs.GetString(prefs::kVariationsSeed);
std::string decoded_serialized_seed;
@@ -137,8 +142,8 @@ TEST(VariationsSeedStoreTest, StoreSeedData) {
// Check if trying to store a bad seed leaves the pref unchanged.
prefs.ClearPref(prefs::kVariationsSeed);
- EXPECT_FALSE(seed_store.StoreSeedData("should fail", now));
- EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
+ EXPECT_FALSE(seed_store.StoreSeedData("should fail", std::string(), now));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
}
} // namespace chrome_variations
diff --git a/chrome/browser/metrics/variations/variations_service.cc b/chrome/browser/metrics/variations/variations_service.cc
index e800b7e..1494d3b 100644
--- a/chrome/browser/metrics/variations/variations_service.cc
+++ b/chrome/browser/metrics/variations/variations_service.cc
@@ -422,7 +422,11 @@ void VariationsService::OnURLFetchComplete(const net::URLFetcher* source) {
bool success = request->GetResponseAsString(&seed_data);
DCHECK(success);
- if (seed_store_.StoreSeedData(seed_data, response_date))
+ std::string seed_signature;
+ request->GetResponseHeaders()->EnumerateHeader(NULL,
+ "X-Seed-Signature",
+ &seed_signature);
+ if (seed_store_.StoreSeedData(seed_data, seed_signature, response_date))
RecordLastFetchTime();
}
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 1b05dc1..c87909e 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1391,6 +1391,9 @@ const char kVariationsSeedDate[] = "variations_seed_date";
// SHA-1 hash of the serialized variations seed data (hex encoded).
const char kVariationsSeedHash[] = "variations_seed_hash";
+// Digital signature of the binary variations seed data, base64-encoded.
+const char kVariationsSeedSignature[] = "variations_seed_signature";
+
// An enum value to indicate the execution phase the browser was in.
const char kStabilityExecutionPhase[] =
"user_experience_metrics.stability.execution_phase";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index de08c4c..732a438 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -445,6 +445,7 @@ extern const char kVariationsRestrictParameter[];
extern const char kVariationsSeed[];
extern const char kVariationsSeedDate[];
extern const char kVariationsSeedHash[];
+extern const char kVariationsSeedSignature[];
extern const char kDeviceOpenNetworkConfiguration[];
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc
index 76b544f..625a32d 100644
--- a/chrome/installer/util/master_preferences.cc
+++ b/chrome/installer/util/master_preferences.cc
@@ -311,9 +311,22 @@ bool MasterPreferences::GetExtensionsBlock(
}
std::string MasterPreferences::GetVariationsSeed() const {
- std::string variations_seed;
- master_dictionary_->GetString(prefs::kVariationsSeed, &variations_seed);
- return variations_seed;
+ return ExtractPrefString(prefs::kVariationsSeed);
+}
+
+std::string MasterPreferences::GetVariationsSeedSignature() const {
+ return ExtractPrefString(prefs::kVariationsSeedSignature);
+}
+
+std::string MasterPreferences::ExtractPrefString(
+ const std::string& name) const {
+ std::string result;
+ scoped_ptr<base::Value> pref_value;
+ if (master_dictionary_->Remove(name, &pref_value)) {
+ if (!pref_value->GetAsString(&result))
+ NOTREACHED();
+ }
+ return result;
}
// static
diff --git a/chrome/installer/util/master_preferences.h b/chrome/installer/util/master_preferences.h
index 1b27c7e..b068b46 100644
--- a/chrome/installer/util/master_preferences.h
+++ b/chrome/installer/util/master_preferences.h
@@ -159,6 +159,9 @@ class MasterPreferences {
// Returns the variations seed entry from the master prefs.
std::string GetVariationsSeed() const;
+ // Returns the variations seed signature entry from the master prefs.
+ std::string GetVariationsSeedSignature() const;
+
// Returns true iff the master preferences were successfully read from a file.
bool read_from_file() const {
return preferences_read_from_file_;
@@ -200,7 +203,11 @@ class MasterPreferences {
// found in older master_preferences files.
void EnforceLegacyPreferences();
- protected:
+ // Removes the specified string pref from the master preferences and returns
+ // its value. Should be used for master prefs that shouldn't be automatically
+ // copied over to profile preferences.
+ std::string ExtractPrefString(const std::string& name) const;
+
scoped_ptr<base::DictionaryValue> master_dictionary_;
base::DictionaryValue* distribution_;
bool preferences_read_from_file_;