Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: chrome/browser/prefs/profile_pref_store_manager_unittest.cc

Issue 205813002: Separate storage for protected preferences into Protected Preferences file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@pp4_profile_pref_store
Patch Set: Pre-review. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/prefs/profile_pref_store_manager.h" 5 #include "chrome/browser/prefs/profile_pref_store_manager.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/files/file_enumerator.h"
11 #include "base/files/scoped_temp_dir.h" 12 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
15 #include "base/prefs/json_pref_store.h" 16 #include "base/prefs/json_pref_store.h"
16 #include "base/prefs/persistent_pref_store.h" 17 #include "base/prefs/persistent_pref_store.h"
17 #include "base/prefs/pref_service.h" 18 #include "base/prefs/pref_service.h"
18 #include "base/prefs/pref_store.h" 19 #include "base/prefs/pref_store.h"
19 #include "base/prefs/testing_pref_service.h" 20 #include "base/prefs/testing_pref_service.h"
20 #include "base/run_loop.h" 21 #include "base/run_loop.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 pref_registry_->end(), 53 pref_registry_->end(),
53 FirstEqualsPredicate(key))); 54 FirstEqualsPredicate(key)));
54 } 55 }
55 56
56 virtual void OnInitializationCompleted(bool succeeded) OVERRIDE {} 57 virtual void OnInitializationCompleted(bool succeeded) OVERRIDE {}
57 58
58 private: 59 private:
59 scoped_refptr<PrefRegistry> pref_registry_; 60 scoped_refptr<PrefRegistry> pref_registry_;
60 }; 61 };
61 62
63 const char kUnprotectedAtomic[] = "unprotected_atomic";
62 const char kTrackedAtomic[] = "tracked_atomic"; 64 const char kTrackedAtomic[] = "tracked_atomic";
63 const char kProtectedAtomic[] = "protected_atomic"; 65 const char kProtectedAtomic[] = "protected_atomic";
64 const char kProtectedSplit[] = "protected_split"; 66 const char kProtectedSplit[] = "protected_split";
65 67
66 const char kFoobar[] = "FOOBAR"; 68 const char kFoobar[] = "FOOBAR";
67 const char kBarfoo[] = "BARFOO"; 69 const char kBarfoo[] = "BARFOO";
68 const char kHelloWorld[] = "HELLOWORLD"; 70 const char kHelloWorld[] = "HELLOWORLD";
69 const char kGoodbyeWorld[] = "GOODBYEWORLD"; 71 const char kGoodbyeWorld[] = "GOODBYEWORLD";
70 72
71 const PrefHashFilter::TrackedPreferenceMetadata kConfiguration[] = { 73 const PrefHashFilter::TrackedPreferenceMetadata kConfiguration[] = {
(...skipping 21 matching lines...) Expand all
93 it != kConfiguration + arraysize(kConfiguration); 95 it != kConfiguration + arraysize(kConfiguration);
94 ++it) { 96 ++it) {
95 if (it->strategy == PrefHashFilter::TRACKING_STRATEGY_ATOMIC) { 97 if (it->strategy == PrefHashFilter::TRACKING_STRATEGY_ATOMIC) {
96 profile_pref_registry_->RegisterStringPref( 98 profile_pref_registry_->RegisterStringPref(
97 it->name, "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 99 it->name, "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
98 } else { 100 } else {
99 profile_pref_registry_->RegisterDictionaryPref( 101 profile_pref_registry_->RegisterDictionaryPref(
100 it->name, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 102 it->name, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
101 } 103 }
102 } 104 }
105 profile_pref_registry_->RegisterStringPref(
106 kUnprotectedAtomic,
107 "",
108 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
109
103 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); 110 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
111 ReloadConfiguration();
112 }
104 113
114 void ReloadConfiguration() {
105 manager_.reset(new ProfilePrefStoreManager(profile_dir_.path(), 115 manager_.reset(new ProfilePrefStoreManager(profile_dir_.path(),
106 configuration_, 116 configuration_,
107 configuration_.size(), 117 configuration_.size(),
108 "seed", 118 "seed",
109 "device_id", 119 "device_id",
110 &local_state_)); 120 &local_state_));
111 } 121 }
112 122
113 virtual void TearDown() OVERRIDE { 123 virtual void TearDown() OVERRIDE { DestroyPrefStore(); }
124
125 protected:
126 void InitializePrefs() {
127 scoped_refptr<PersistentPrefStore> pref_store =
128 manager_->CreateProfilePrefStore(
129 main_message_loop_.message_loop_proxy());
130 InitializePrefStore(pref_store);
131 pref_store = NULL;
132 base::RunLoop().RunUntilIdle();
133 }
134 void DestroyPrefStore() {
114 if (pref_store_) { 135 if (pref_store_) {
115 // Force everything to be written to disk, triggering the PrefHashFilter 136 // Force everything to be written to disk, triggering the PrefHashFilter
116 // while our RegistryVerifier is watching. 137 // while our RegistryVerifier is watching.
117 pref_store_->CommitPendingWrite(); 138 pref_store_->CommitPendingWrite();
118 base::RunLoop().RunUntilIdle(); 139 base::RunLoop().RunUntilIdle();
119 140
120 pref_store_->RemoveObserver(&registry_verifier_); 141 pref_store_->RemoveObserver(&registry_verifier_);
121 pref_store_ = NULL; 142 pref_store_ = NULL;
122 // Nothing should have to happen on the background threads, but just in 143 // Nothing should have to happen on the background threads, but just in
123 // case... 144 // case...
124 base::RunLoop().RunUntilIdle(); 145 base::RunLoop().RunUntilIdle();
125 } 146 }
126 } 147 }
127 148
128 protected: 149 void InitializeDeprecatedCombinedProfilePrefStore() {
129 void InitializePrefs() {
130 scoped_refptr<PersistentPrefStore> pref_store = 150 scoped_refptr<PersistentPrefStore> pref_store =
131 manager_->CreateProfilePrefStore( 151 manager_->CreateDeprecatedCombinedProfilePrefStore(
132 main_message_loop_.message_loop_proxy()); 152 main_message_loop_.message_loop_proxy());
153 InitializePrefStore(pref_store);
154 pref_store = NULL;
155 base::RunLoop().RunUntilIdle();
156 }
157
158 void InitializePrefStore(PersistentPrefStore* pref_store) {
133 pref_store->AddObserver(&registry_verifier_); 159 pref_store->AddObserver(&registry_verifier_);
134 PersistentPrefStore::PrefReadError error = pref_store->ReadPrefs(); 160 PersistentPrefStore::PrefReadError error = pref_store->ReadPrefs();
135 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, error); 161 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, error);
136 pref_store->SetValue(kTrackedAtomic, new base::StringValue(kFoobar)); 162 pref_store->SetValue(kTrackedAtomic, new base::StringValue(kFoobar));
137 pref_store->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld)); 163 pref_store->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld));
164 pref_store->SetValue(kUnprotectedAtomic, new base::StringValue(kFoobar));
138 pref_store->RemoveObserver(&registry_verifier_); 165 pref_store->RemoveObserver(&registry_verifier_);
139 pref_store = NULL; 166 pref_store->CommitPendingWrite();
140 base::RunLoop().RunUntilIdle(); 167 base::RunLoop().RunUntilIdle();
141 } 168 }
142 169
143 void LoadExistingPrefs() { 170 void LoadExistingPrefs() {
171 DestroyPrefStore();
144 pref_store_ = manager_->CreateProfilePrefStore( 172 pref_store_ = manager_->CreateProfilePrefStore(
145 main_message_loop_.message_loop_proxy()); 173 main_message_loop_.message_loop_proxy());
146 pref_store_->AddObserver(&registry_verifier_); 174 pref_store_->AddObserver(&registry_verifier_);
147 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, 175 pref_store_->ReadPrefs();
148 pref_store_->ReadPrefs());
149 } 176 }
150 177
151 void ReplaceStringInPrefs(const std::string& find, 178 void ReplaceStringInPrefs(const std::string& find,
152 const std::string& replace) { 179 const std::string& replace) {
153 // Tamper with the file's contents 180 base::FileEnumerator file_enumerator(
154 base::FilePath pref_file_path = 181 profile_dir_.path(), true, base::FileEnumerator::FILES);
155 ProfilePrefStoreManager::GetPrefFilePathFromProfilePath( 182
156 profile_dir_.path()); 183 base::FilePath pref_file_path;
157 std::string pref_file_contents; 184 while (!(pref_file_path = file_enumerator.Next()).empty()) {
158 EXPECT_TRUE(base::ReadFileToString(pref_file_path, &pref_file_contents)); 185 // Tamper with the file's contents
159 ReplaceSubstringsAfterOffset(&pref_file_contents, 0u, find, replace); 186 std::string pref_file_contents;
160 EXPECT_EQ(static_cast<int>(pref_file_contents.length()), 187 EXPECT_TRUE(base::ReadFileToString(pref_file_path, &pref_file_contents));
161 base::WriteFile(pref_file_path, 188 ReplaceSubstringsAfterOffset(&pref_file_contents, 0u, find, replace);
162 pref_file_contents.c_str(), 189 EXPECT_EQ((int)pref_file_contents.length(),
163 pref_file_contents.length())); 190 base::WriteFile(pref_file_path,
191 pref_file_contents.c_str(),
192 pref_file_contents.length()));
193 }
164 } 194 }
165 195
166 void ExpectStringValueEquals(const std::string& name, 196 void ExpectStringValueEquals(const std::string& name,
167 const std::string& expected) { 197 const std::string& expected) {
168 const base::Value* value = NULL; 198 const base::Value* value = NULL;
169 std::string as_string; 199 std::string as_string;
170 if (!pref_store_->GetValue(name, &value)) { 200 if (!pref_store_->GetValue(name, &value)) {
171 ADD_FAILURE() << name << " is not a defined value."; 201 ADD_FAILURE() << name << " is not a defined value.";
172 } else if (!value->GetAsString(&as_string)) { 202 } else if (!value->GetAsString(&as_string)) {
173 ADD_FAILURE() << name << " could not be coerced to a string."; 203 ADD_FAILURE() << name << " could not be coerced to a string.";
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 LoadExistingPrefs(); 278 LoadExistingPrefs();
249 279
250 // kTrackedAtomic is loaded as it appears on disk. 280 // kTrackedAtomic is loaded as it appears on disk.
251 ExpectStringValueEquals(kTrackedAtomic, kFoobar); 281 ExpectStringValueEquals(kTrackedAtomic, kFoobar);
252 // If preference tracking is supported, kProtectedAtomic will be undefined 282 // If preference tracking is supported, kProtectedAtomic will be undefined
253 // because the value was discarded due to loss of the hash store contents. 283 // because the value was discarded due to loss of the hash store contents.
254 EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking, 284 EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
255 pref_store_->GetValue(kProtectedAtomic, NULL)); 285 pref_store_->GetValue(kProtectedAtomic, NULL));
256 } 286 }
257 287
288 TEST_F(ProfilePrefStoreManagerTest, MigrateFromOneFile) {
289 InitializeDeprecatedCombinedProfilePrefStore();
290
291 LoadExistingPrefs();
292
293 ExpectStringValueEquals(kTrackedAtomic, kFoobar);
294 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
295 }
296
258 TEST_F(ProfilePrefStoreManagerTest, UpdateProfileHashStoreIfRequired) { 297 TEST_F(ProfilePrefStoreManagerTest, UpdateProfileHashStoreIfRequired) {
259 InitializePrefs(); 298 scoped_refptr<JsonPrefStore> legacy_prefs(
260 299 new JsonPrefStore(ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
261 manager_->ResetPrefHashStore(); 300 profile_dir_.path()),
301 main_message_loop_.message_loop_proxy(),
302 scoped_ptr<PrefFilter>()));
303 legacy_prefs->SetValue(kTrackedAtomic, new base::StringValue(kFoobar));
304 legacy_prefs->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld));
305 legacy_prefs = NULL;
306 base::RunLoop().RunUntilIdle();
262 307
263 // This is a no-op if !kPlatformSupportsPreferenceTracking. 308 // This is a no-op if !kPlatformSupportsPreferenceTracking.
264 manager_->UpdateProfileHashStoreIfRequired( 309 manager_->UpdateProfileHashStoreIfRequired(
265 main_message_loop_.message_loop_proxy()); 310 main_message_loop_.message_loop_proxy());
266 base::RunLoop().RunUntilIdle(); 311 base::RunLoop().RunUntilIdle();
267 312
268 // At the moment, UpdateProfileHashStoreIfRequired will accept existing 313 // At the moment, UpdateProfileHashStoreIfRequired will accept existing
269 // values. 314 // values.
270 LoadExistingPrefs(); 315 LoadExistingPrefs();
271 316
(...skipping 10 matching lines...) Expand all
282 ASSERT_TRUE( 327 ASSERT_TRUE(
283 manager_->InitializePrefsFromMasterPrefs(*master_prefs)); 328 manager_->InitializePrefsFromMasterPrefs(*master_prefs));
284 329
285 LoadExistingPrefs(); 330 LoadExistingPrefs();
286 331
287 // Verify that InitializePrefsFromMasterPrefs correctly applied the MACs 332 // Verify that InitializePrefsFromMasterPrefs correctly applied the MACs
288 // necessary to authenticate these values. 333 // necessary to authenticate these values.
289 ExpectStringValueEquals(kTrackedAtomic, kFoobar); 334 ExpectStringValueEquals(kTrackedAtomic, kFoobar);
290 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld); 335 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
291 } 336 }
337
338 TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtected) {
339 InitializePrefs();
340 LoadExistingPrefs();
341 ExpectStringValueEquals(kUnprotectedAtomic, kFoobar);
342
343 PrefHashFilter::TrackedPreferenceMetadata new_protected = {
344 99u, kUnprotectedAtomic, PrefHashFilter::ENFORCE_ON_LOAD,
345 PrefHashFilter::TRACKING_STRATEGY_ATOMIC};
346 configuration_.push_back(new_protected);
347 ReloadConfiguration();
348 LoadExistingPrefs();
349 ExpectStringValueEquals(kUnprotectedAtomic, kFoobar);
350 }
351
352 TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtectedWithoutTrust) {
robertshield 2014/03/25 03:05:12 Can we add a test that simulates partial migration
erikwright (departed) 2014/03/25 20:28:26 Yes. That's a bit trickier so I'm going to upload
353 InitializePrefs();
354 PrefHashFilter::TrackedPreferenceMetadata new_protected = {
355 99u, kUnprotectedAtomic, PrefHashFilter::ENFORCE_ON_LOAD,
356 PrefHashFilter::TRACKING_STRATEGY_ATOMIC};
357 configuration_.push_back(new_protected);
358 ReloadConfiguration();
359 ProfilePrefStoreManager::ResetAllPrefHashStores(&local_state_);
360
361 LoadExistingPrefs();
362 ASSERT_FALSE(pref_store_->GetValue(kUnprotectedAtomic, NULL));
363 }
364
365
366 TEST_F(ProfilePrefStoreManagerTest, ProtectedToUnprotected) {
367 InitializePrefs();
368 ProfilePrefStoreManager::ResetAllPrefHashStores(&local_state_);
369
370 for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
371 configuration_.begin();
372 it != configuration_.end();
373 ++it) {
374 if (it->name == std::string(kProtectedAtomic)) {
375 configuration_.erase(it);
376 break;
377 }
378 }
379
380 ReloadConfiguration();
381
382 LoadExistingPrefs();
383 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
384
385 // Accessing the value of the previously proteted pref didn't trigger its move
386 // to the unprotected preferences file, though the loading of the pref store
387 // should still have caused the MAC store to be recalculated.
388 LoadExistingPrefs();
389 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
390
391 // Trigger the logic that migrates it back to the unprotected preferences
392 // file.
393 pref_store_->SetValue(kProtectedAtomic, new base::StringValue(kGoodbyeWorld));
394 LoadExistingPrefs();
395 ExpectStringValueEquals(kProtectedAtomic, kGoodbyeWorld);
396 }
397
398 // Add test coverage for when Reset events should and should not be recorded.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698