Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prefs / profile_pref_store_manager_unittest.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/prefs/profile_pref_store_manager.h"
6
7 #include <vector>
8
9 #include "base/compiler_specific.h"
10 #include "base/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/prefs/json_pref_store.h"
16 #include "base/prefs/persistent_pref_store.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/prefs/pref_store.h"
19 #include "base/prefs/testing_pref_service.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_util.h"
22 #include "base/values.h"
23 #include "chrome/browser/prefs/pref_hash_filter.h"
24 #include "components/user_prefs/pref_registry_syncable.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 namespace {
28
29 class FirstEqualsPredicate {
30  public:
31   explicit FirstEqualsPredicate(const std::string& expected)
32       : expected_(expected) {}
33   bool operator()(const std::pair<std::string, base::Value*>& pair) {
34     return pair.first == expected_;
35   }
36
37  private:
38   const std::string expected_;
39 };
40
41 // Observes changes to the PrefStore and verifies that only registered prefs are
42 // written.
43 class RegistryVerifier : public PrefStore::Observer {
44  public:
45   explicit RegistryVerifier(PrefRegistry* pref_registry)
46       : pref_registry_(pref_registry) {}
47
48   // PrefStore::Observer implementation
49   virtual void OnPrefValueChanged(const std::string& key) OVERRIDE {
50     EXPECT_TRUE(pref_registry_->end() !=
51                 std::find_if(pref_registry_->begin(),
52                              pref_registry_->end(),
53                              FirstEqualsPredicate(key)))
54         << "Unregistered key " << key << " was changed.";
55   }
56
57   virtual void OnInitializationCompleted(bool succeeded) OVERRIDE {}
58
59  private:
60   scoped_refptr<PrefRegistry> pref_registry_;
61 };
62
63 const char kTrackedAtomic[] = "tracked_atomic";
64 const char kProtectedAtomic[] = "protected_atomic";
65 const char kProtectedSplit[] = "protected_split";
66
67 const char kFoobar[] = "FOOBAR";
68 const char kBarfoo[] = "BARFOO";
69 const char kHelloWorld[] = "HELLOWORLD";
70 const char kGoodbyeWorld[] = "GOODBYEWORLD";
71
72 const PrefHashFilter::TrackedPreferenceMetadata kConfiguration[] = {
73     {0, kTrackedAtomic, PrefHashFilter::NO_ENFORCEMENT,
74      PrefHashFilter::TRACKING_STRATEGY_ATOMIC},
75     {1, kProtectedAtomic, PrefHashFilter::ENFORCE_ON_LOAD,
76      PrefHashFilter::TRACKING_STRATEGY_ATOMIC},
77     {2, kProtectedSplit, PrefHashFilter::ENFORCE_ON_LOAD,
78      PrefHashFilter::TRACKING_STRATEGY_SPLIT}};
79
80 }  // namespace
81
82 class ProfilePrefStoreManagerTest : public testing::Test {
83  public:
84   ProfilePrefStoreManagerTest()
85       : configuration_(kConfiguration,
86                        kConfiguration + arraysize(kConfiguration)),
87         profile_pref_registry_(new user_prefs::PrefRegistrySyncable),
88         registry_verifier_(profile_pref_registry_) {}
89
90   virtual void SetUp() OVERRIDE {
91     ProfilePrefStoreManager::RegisterPrefs(local_state_.registry());
92     ProfilePrefStoreManager::RegisterProfilePrefs(profile_pref_registry_);
93     for (const PrefHashFilter::TrackedPreferenceMetadata* it = kConfiguration;
94          it != kConfiguration + arraysize(kConfiguration);
95          ++it) {
96       if (it->strategy == PrefHashFilter::TRACKING_STRATEGY_ATOMIC) {
97         profile_pref_registry_->RegisterStringPref(
98             it->name, "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
99       } else {
100         profile_pref_registry_->RegisterDictionaryPref(
101             it->name, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
102       }
103     }
104     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
105
106     manager_.reset(new ProfilePrefStoreManager(profile_dir_.path(),
107                                                configuration_,
108                                                configuration_.size(),
109                                                "seed",
110                                                "device_id",
111                                                &local_state_));
112   }
113
114   virtual void TearDown() OVERRIDE {
115     if (pref_store_) {
116       // Force everything to be written to disk, triggering the PrefHashFilter
117       // while our RegistryVerifier is watching.
118       pref_store_->CommitPendingWrite();
119       base::RunLoop().RunUntilIdle();
120
121       pref_store_->RemoveObserver(&registry_verifier_);
122       pref_store_ = NULL;
123       // Nothing should have to happen on the background threads, but just in
124       // case...
125       base::RunLoop().RunUntilIdle();
126     }
127   }
128
129  protected:
130   void InitializePrefs() {
131     scoped_refptr<PersistentPrefStore> pref_store =
132         manager_->CreateProfilePrefStore(
133             main_message_loop_.message_loop_proxy());
134     pref_store->AddObserver(&registry_verifier_);
135     PersistentPrefStore::PrefReadError error = pref_store->ReadPrefs();
136     ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, error);
137     pref_store->SetValue(kTrackedAtomic, new base::StringValue(kFoobar));
138     pref_store->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld));
139     pref_store->RemoveObserver(&registry_verifier_);
140     pref_store = NULL;
141     base::RunLoop().RunUntilIdle();
142   }
143
144   void LoadExistingPrefs() {
145     pref_store_ = manager_->CreateProfilePrefStore(
146         main_message_loop_.message_loop_proxy());
147     pref_store_->AddObserver(&registry_verifier_);
148     EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
149               pref_store_->ReadPrefs());
150   }
151
152   void ReplaceStringInPrefs(const std::string& find,
153                             const std::string& replace) {
154     // Tamper with the file's contents
155     base::FilePath pref_file_path =
156         ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
157             profile_dir_.path());
158     std::string pref_file_contents;
159     EXPECT_TRUE(base::ReadFileToString(pref_file_path, &pref_file_contents));
160     ReplaceSubstringsAfterOffset(&pref_file_contents, 0u, find, replace);
161     EXPECT_EQ(static_cast<int>(pref_file_contents.length()),
162               base::WriteFile(pref_file_path,
163                               pref_file_contents.c_str(),
164                               pref_file_contents.length()));
165   }
166
167   void ExpectStringValueEquals(const std::string& name,
168                                const std::string& expected) {
169     const base::Value* value = NULL;
170     std::string as_string;
171     if (!pref_store_->GetValue(name, &value)) {
172       ADD_FAILURE() << name << " is not a defined value.";
173     } else if (!value->GetAsString(&as_string)) {
174       ADD_FAILURE() << name << " could not be coerced to a string.";
175     } else {
176       EXPECT_EQ(expected, as_string);
177     }
178   }
179
180   base::MessageLoop main_message_loop_;
181   std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration_;
182   base::ScopedTempDir profile_dir_;
183   TestingPrefServiceSimple local_state_;
184   scoped_refptr<user_prefs::PrefRegistrySyncable> profile_pref_registry_;
185   RegistryVerifier registry_verifier_;
186   scoped_ptr<ProfilePrefStoreManager> manager_;
187   scoped_refptr<PersistentPrefStore> pref_store_;
188 };
189
190 TEST_F(ProfilePrefStoreManagerTest, StoreValues) {
191   InitializePrefs();
192
193   LoadExistingPrefs();
194
195   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
196   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
197 }
198
199 TEST_F(ProfilePrefStoreManagerTest, GetPrefFilePathFromProfilePath) {
200   base::FilePath pref_file_path =
201       ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
202           profile_dir_.path());
203
204   ASSERT_FALSE(base::PathExists(pref_file_path));
205
206   InitializePrefs();
207
208   ASSERT_TRUE(base::PathExists(pref_file_path));
209 }
210
211 TEST_F(ProfilePrefStoreManagerTest, ProtectValues) {
212   InitializePrefs();
213
214   ReplaceStringInPrefs(kFoobar, kBarfoo);
215   ReplaceStringInPrefs(kHelloWorld, kGoodbyeWorld);
216
217   LoadExistingPrefs();
218
219   // kTrackedAtomic is unprotected and thus will be loaded as it appears on
220   // disk.
221   ExpectStringValueEquals(kTrackedAtomic, kBarfoo);
222
223   // If preference tracking is supported, the tampered value of kProtectedAtomic
224   // will be discarded at load time, leaving this preference undefined.
225   EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
226             pref_store_->GetValue(kProtectedAtomic, NULL));
227 }
228
229 TEST_F(ProfilePrefStoreManagerTest, ResetPrefHashStore) {
230   InitializePrefs();
231
232   manager_->ResetPrefHashStore();
233
234   LoadExistingPrefs();
235
236   // kTrackedAtomic is loaded as it appears on disk.
237   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
238   // If preference tracking is supported, the tampered value of kProtectedAtomic
239   // will be discarded at load time, leaving this preference undefined.
240   EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
241             pref_store_->GetValue(kProtectedAtomic, NULL));
242 }
243
244 TEST_F(ProfilePrefStoreManagerTest, ResetAllPrefHashStores) {
245   InitializePrefs();
246
247   ProfilePrefStoreManager::ResetAllPrefHashStores(&local_state_);
248
249   LoadExistingPrefs();
250
251   // kTrackedAtomic is loaded as it appears on disk.
252   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
253   // If preference tracking is supported, kProtectedAtomic will be undefined
254   // because the value was discarded due to loss of the hash store contents.
255   EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
256             pref_store_->GetValue(kProtectedAtomic, NULL));
257 }
258
259 TEST_F(ProfilePrefStoreManagerTest, UpdateProfileHashStoreIfRequired) {
260   InitializePrefs();
261
262   manager_->ResetPrefHashStore();
263
264   // This is a no-op if !kPlatformSupportsPreferenceTracking.
265   manager_->UpdateProfileHashStoreIfRequired(
266       main_message_loop_.message_loop_proxy());
267   base::RunLoop().RunUntilIdle();
268
269   // At the moment, UpdateProfileHashStoreIfRequired will accept existing
270   // values.
271   LoadExistingPrefs();
272
273   // These expectations hold whether or not tracking is supported.
274   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
275   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
276 }
277
278 TEST_F(ProfilePrefStoreManagerTest, InitializePrefsFromMasterPrefs) {
279   scoped_ptr<base::DictionaryValue> master_prefs(
280       new base::DictionaryValue);
281   master_prefs->Set(kTrackedAtomic, new base::StringValue(kFoobar));
282   master_prefs->Set(kProtectedAtomic, new base::StringValue(kHelloWorld));
283   ASSERT_TRUE(
284       manager_->InitializePrefsFromMasterPrefs(*master_prefs));
285
286   LoadExistingPrefs();
287
288   // Verify that InitializePrefsFromMasterPrefs correctly applied the MACs
289   // necessary to authenticate these values.
290   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
291   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
292 }