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

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: Fix copyright. 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 FirstEqualsPredicate(key))) 54 FirstEqualsPredicate(key)))
54 << "Unregistered key " << key << " was changed."; 55 << "Unregistered key " << key << " was changed.";
55 } 56 }
56 57
57 virtual void OnInitializationCompleted(bool succeeded) OVERRIDE {} 58 virtual void OnInitializationCompleted(bool succeeded) OVERRIDE {}
58 59
59 private: 60 private:
60 scoped_refptr<PrefRegistry> pref_registry_; 61 scoped_refptr<PrefRegistry> pref_registry_;
61 }; 62 };
62 63
64 const char kUnprotectedAtomic[] = "unprotected_atomic";
63 const char kTrackedAtomic[] = "tracked_atomic"; 65 const char kTrackedAtomic[] = "tracked_atomic";
64 const char kProtectedAtomic[] = "protected_atomic"; 66 const char kProtectedAtomic[] = "protected_atomic";
65 const char kProtectedSplit[] = "protected_split"; 67 const char kProtectedSplit[] = "protected_split";
66 68
67 const char kFoobar[] = "FOOBAR"; 69 const char kFoobar[] = "FOOBAR";
68 const char kBarfoo[] = "BARFOO"; 70 const char kBarfoo[] = "BARFOO";
69 const char kHelloWorld[] = "HELLOWORLD"; 71 const char kHelloWorld[] = "HELLOWORLD";
70 const char kGoodbyeWorld[] = "GOODBYEWORLD"; 72 const char kGoodbyeWorld[] = "GOODBYEWORLD";
71 73
72 const PrefHashFilter::TrackedPreferenceMetadata kConfiguration[] = { 74 const PrefHashFilter::TrackedPreferenceMetadata kConfiguration[] = {
(...skipping 21 matching lines...) Expand all
94 it != kConfiguration + arraysize(kConfiguration); 96 it != kConfiguration + arraysize(kConfiguration);
95 ++it) { 97 ++it) {
96 if (it->strategy == PrefHashFilter::TRACKING_STRATEGY_ATOMIC) { 98 if (it->strategy == PrefHashFilter::TRACKING_STRATEGY_ATOMIC) {
97 profile_pref_registry_->RegisterStringPref( 99 profile_pref_registry_->RegisterStringPref(
98 it->name, "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 100 it->name, "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
99 } else { 101 } else {
100 profile_pref_registry_->RegisterDictionaryPref( 102 profile_pref_registry_->RegisterDictionaryPref(
101 it->name, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 103 it->name, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
102 } 104 }
103 } 105 }
106 profile_pref_registry_->RegisterStringPref(
107 kUnprotectedAtomic,
108 std::string(),
109 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
110
104 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); 111 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
112 ReloadConfiguration();
113 }
105 114
115 void ReloadConfiguration() {
106 manager_.reset(new ProfilePrefStoreManager(profile_dir_.path(), 116 manager_.reset(new ProfilePrefStoreManager(profile_dir_.path(),
107 configuration_, 117 configuration_,
108 configuration_.size(), 118 configuration_.size(),
109 "seed", 119 "seed",
110 "device_id", 120 "device_id",
111 &local_state_)); 121 &local_state_));
112 } 122 }
113 123
114 virtual void TearDown() OVERRIDE { 124 virtual void TearDown() OVERRIDE { DestroyPrefStore(); }
125
126 protected:
127 void InitializePrefs() {
128 scoped_refptr<PersistentPrefStore> pref_store =
129 manager_->CreateProfilePrefStore(
130 main_message_loop_.message_loop_proxy());
131 InitializePrefStore(pref_store);
132 pref_store = NULL;
133 base::RunLoop().RunUntilIdle();
134 }
135
136 void DestroyPrefStore() {
115 if (pref_store_) { 137 if (pref_store_) {
116 // Force everything to be written to disk, triggering the PrefHashFilter 138 // Force everything to be written to disk, triggering the PrefHashFilter
117 // while our RegistryVerifier is watching. 139 // while our RegistryVerifier is watching.
118 pref_store_->CommitPendingWrite(); 140 pref_store_->CommitPendingWrite();
119 base::RunLoop().RunUntilIdle(); 141 base::RunLoop().RunUntilIdle();
120 142
121 pref_store_->RemoveObserver(&registry_verifier_); 143 pref_store_->RemoveObserver(&registry_verifier_);
122 pref_store_ = NULL; 144 pref_store_ = NULL;
123 // Nothing should have to happen on the background threads, but just in 145 // Nothing should have to happen on the background threads, but just in
124 // case... 146 // case...
125 base::RunLoop().RunUntilIdle(); 147 base::RunLoop().RunUntilIdle();
126 } 148 }
127 } 149 }
128 150
129 protected: 151 void InitializeDeprecatedCombinedProfilePrefStore() {
130 void InitializePrefs() {
131 scoped_refptr<PersistentPrefStore> pref_store = 152 scoped_refptr<PersistentPrefStore> pref_store =
132 manager_->CreateProfilePrefStore( 153 manager_->CreateDeprecatedCombinedProfilePrefStore(
133 main_message_loop_.message_loop_proxy()); 154 main_message_loop_.message_loop_proxy());
155 InitializePrefStore(pref_store);
156 pref_store = NULL;
157 base::RunLoop().RunUntilIdle();
158 }
159
160 void InitializePrefStore(PersistentPrefStore* pref_store) {
134 pref_store->AddObserver(&registry_verifier_); 161 pref_store->AddObserver(&registry_verifier_);
135 PersistentPrefStore::PrefReadError error = pref_store->ReadPrefs(); 162 PersistentPrefStore::PrefReadError error = pref_store->ReadPrefs();
136 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, error); 163 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, error);
137 pref_store->SetValue(kTrackedAtomic, new base::StringValue(kFoobar)); 164 pref_store->SetValue(kTrackedAtomic, new base::StringValue(kFoobar));
138 pref_store->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld)); 165 pref_store->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld));
166 pref_store->SetValue(kUnprotectedAtomic, new base::StringValue(kFoobar));
139 pref_store->RemoveObserver(&registry_verifier_); 167 pref_store->RemoveObserver(&registry_verifier_);
140 pref_store = NULL; 168 pref_store->CommitPendingWrite();
141 base::RunLoop().RunUntilIdle(); 169 base::RunLoop().RunUntilIdle();
142 } 170 }
143 171
144 void LoadExistingPrefs() { 172 void LoadExistingPrefs() {
173 DestroyPrefStore();
145 pref_store_ = manager_->CreateProfilePrefStore( 174 pref_store_ = manager_->CreateProfilePrefStore(
146 main_message_loop_.message_loop_proxy()); 175 main_message_loop_.message_loop_proxy());
147 pref_store_->AddObserver(&registry_verifier_); 176 pref_store_->AddObserver(&registry_verifier_);
148 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, 177 pref_store_->ReadPrefs();
149 pref_store_->ReadPrefs());
150 } 178 }
151 179
152 void ReplaceStringInPrefs(const std::string& find, 180 void ReplaceStringInPrefs(const std::string& find,
153 const std::string& replace) { 181 const std::string& replace) {
154 // Tamper with the file's contents 182 base::FileEnumerator file_enumerator(
155 base::FilePath pref_file_path = 183 profile_dir_.path(), true, base::FileEnumerator::FILES);
156 ProfilePrefStoreManager::GetPrefFilePathFromProfilePath( 184
157 profile_dir_.path()); 185 base::FilePath pref_file_path;
158 std::string pref_file_contents; 186 while (!(pref_file_path = file_enumerator.Next()).empty()) {
159 EXPECT_TRUE(base::ReadFileToString(pref_file_path, &pref_file_contents)); 187 // Tamper with the file's contents
160 ReplaceSubstringsAfterOffset(&pref_file_contents, 0u, find, replace); 188 std::string pref_file_contents;
161 EXPECT_EQ(static_cast<int>(pref_file_contents.length()), 189 EXPECT_TRUE(base::ReadFileToString(pref_file_path, &pref_file_contents));
162 base::WriteFile(pref_file_path, 190 ReplaceSubstringsAfterOffset(&pref_file_contents, 0u, find, replace);
163 pref_file_contents.c_str(), 191 EXPECT_EQ((int)pref_file_contents.length(),
robertshield 2014/03/26 21:41:54 why is this using a C-style cast?
erikwright (departed) 2014/03/27 14:59:19 Done.
164 pref_file_contents.length())); 192 base::WriteFile(pref_file_path,
193 pref_file_contents.c_str(),
194 pref_file_contents.length()));
195 }
165 } 196 }
166 197
167 void ExpectStringValueEquals(const std::string& name, 198 void ExpectStringValueEquals(const std::string& name,
168 const std::string& expected) { 199 const std::string& expected) {
169 const base::Value* value = NULL; 200 const base::Value* value = NULL;
170 std::string as_string; 201 std::string as_string;
171 if (!pref_store_->GetValue(name, &value)) { 202 if (!pref_store_->GetValue(name, &value)) {
172 ADD_FAILURE() << name << " is not a defined value."; 203 ADD_FAILURE() << name << " is not a defined value.";
173 } else if (!value->GetAsString(&as_string)) { 204 } else if (!value->GetAsString(&as_string)) {
174 ADD_FAILURE() << name << " could not be coerced to a string."; 205 ADD_FAILURE() << name << " could not be coerced to a string.";
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 LoadExistingPrefs(); 280 LoadExistingPrefs();
250 281
251 // kTrackedAtomic is loaded as it appears on disk. 282 // kTrackedAtomic is loaded as it appears on disk.
252 ExpectStringValueEquals(kTrackedAtomic, kFoobar); 283 ExpectStringValueEquals(kTrackedAtomic, kFoobar);
253 // If preference tracking is supported, kProtectedAtomic will be undefined 284 // If preference tracking is supported, kProtectedAtomic will be undefined
254 // because the value was discarded due to loss of the hash store contents. 285 // because the value was discarded due to loss of the hash store contents.
255 EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking, 286 EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
256 pref_store_->GetValue(kProtectedAtomic, NULL)); 287 pref_store_->GetValue(kProtectedAtomic, NULL));
257 } 288 }
258 289
290 TEST_F(ProfilePrefStoreManagerTest, MigrateFromOneFile) {
291 InitializeDeprecatedCombinedProfilePrefStore();
292
293 LoadExistingPrefs();
294
295 ExpectStringValueEquals(kTrackedAtomic, kFoobar);
296 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
297 }
298
259 TEST_F(ProfilePrefStoreManagerTest, UpdateProfileHashStoreIfRequired) { 299 TEST_F(ProfilePrefStoreManagerTest, UpdateProfileHashStoreIfRequired) {
260 InitializePrefs(); 300 scoped_refptr<JsonPrefStore> legacy_prefs(
261 301 new JsonPrefStore(ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
262 manager_->ResetPrefHashStore(); 302 profile_dir_.path()),
303 main_message_loop_.message_loop_proxy(),
304 scoped_ptr<PrefFilter>()));
305 legacy_prefs->SetValue(kTrackedAtomic, new base::StringValue(kFoobar));
306 legacy_prefs->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld));
307 legacy_prefs = NULL;
308 base::RunLoop().RunUntilIdle();
263 309
264 // This is a no-op if !kPlatformSupportsPreferenceTracking. 310 // This is a no-op if !kPlatformSupportsPreferenceTracking.
265 manager_->UpdateProfileHashStoreIfRequired( 311 manager_->UpdateProfileHashStoreIfRequired(
266 main_message_loop_.message_loop_proxy()); 312 main_message_loop_.message_loop_proxy());
267 base::RunLoop().RunUntilIdle(); 313 base::RunLoop().RunUntilIdle();
268 314
269 // At the moment, UpdateProfileHashStoreIfRequired will accept existing 315 // At the moment, UpdateProfileHashStoreIfRequired will accept existing
270 // values. 316 // values.
271 LoadExistingPrefs(); 317 LoadExistingPrefs();
272 318
(...skipping 10 matching lines...) Expand all
283 ASSERT_TRUE( 329 ASSERT_TRUE(
284 manager_->InitializePrefsFromMasterPrefs(*master_prefs)); 330 manager_->InitializePrefsFromMasterPrefs(*master_prefs));
285 331
286 LoadExistingPrefs(); 332 LoadExistingPrefs();
287 333
288 // Verify that InitializePrefsFromMasterPrefs correctly applied the MACs 334 // Verify that InitializePrefsFromMasterPrefs correctly applied the MACs
289 // necessary to authenticate these values. 335 // necessary to authenticate these values.
290 ExpectStringValueEquals(kTrackedAtomic, kFoobar); 336 ExpectStringValueEquals(kTrackedAtomic, kFoobar);
291 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld); 337 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
292 } 338 }
339
340 TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtected) {
341 InitializePrefs();
342 LoadExistingPrefs();
343 ExpectStringValueEquals(kUnprotectedAtomic, kFoobar);
344
345 PrefHashFilter::TrackedPreferenceMetadata new_protected = {
346 99u, kUnprotectedAtomic, PrefHashFilter::ENFORCE_ON_LOAD,
347 PrefHashFilter::TRACKING_STRATEGY_ATOMIC};
348 configuration_.push_back(new_protected);
349 ReloadConfiguration();
350 LoadExistingPrefs();
351 ExpectStringValueEquals(kUnprotectedAtomic, kFoobar);
352 }
353
354 TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtectedWithoutTrust) {
355 InitializePrefs();
356 PrefHashFilter::TrackedPreferenceMetadata new_protected = {
357 99u, kUnprotectedAtomic, PrefHashFilter::ENFORCE_ON_LOAD,
358 PrefHashFilter::TRACKING_STRATEGY_ATOMIC};
359 configuration_.push_back(new_protected);
360 ReloadConfiguration();
361 ProfilePrefStoreManager::ResetAllPrefHashStores(&local_state_);
362
363 LoadExistingPrefs();
364 ASSERT_FALSE(pref_store_->GetValue(kUnprotectedAtomic, NULL));
365 }
366
367
368 TEST_F(ProfilePrefStoreManagerTest, ProtectedToUnprotected) {
369 InitializePrefs();
370 ProfilePrefStoreManager::ResetAllPrefHashStores(&local_state_);
371
372 for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
373 configuration_.begin();
374 it != configuration_.end();
375 ++it) {
376 if (it->name == std::string(kProtectedAtomic)) {
377 configuration_.erase(it);
378 break;
379 }
380 }
381
382 ReloadConfiguration();
383
384 LoadExistingPrefs();
385 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
386
387 // Accessing the value of the previously proteted pref didn't trigger its move
robertshield 2014/03/26 21:41:54 protected
erikwright (departed) 2014/03/27 14:59:19 Done.
388 // to the unprotected preferences file, though the loading of the pref store
389 // should still have caused the MAC store to be recalculated.
390 LoadExistingPrefs();
391 ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
392
393 // Trigger the logic that migrates it back to the unprotected preferences
394 // file.
395 pref_store_->SetValue(kProtectedAtomic, new base::StringValue(kGoodbyeWorld));
396 LoadExistingPrefs();
397 ExpectStringValueEquals(kProtectedAtomic, kGoodbyeWorld);
robertshield 2014/03/26 21:41:54 It's not clear to me how this test checks that the
erikwright (departed) 2014/03/27 14:59:19 Clarified the purpose of the test with a comment a
398 }
399
400 // Add test coverage for when Reset events should and should not be recorded.
robertshield 2014/03/26 21:41:54 Please make this a TODO if you're not planning on
erikwright (departed) 2014/03/27 14:59:19 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698