Revert 271602 "Implementation of leveldb-backed PrefStore."
[chromium-blink-merge.git] / chrome / browser / prefs / pref_hash_browsertest.cc
blobd818c6aaf30a2ca7fec6ae60c63e4c20a9350a43
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.
5 #include <set>
6 #include <vector>
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/macros.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/histogram_base.h"
14 #include "base/metrics/histogram_samples.h"
15 #include "base/metrics/statistics_recorder.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/strings/string16.h"
18 #include "base/threading/sequenced_worker_pool.h"
19 #include "base/values.h"
20 #include "build/build_config.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
23 #include "chrome/browser/prefs/pref_hash_store.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/profiles/profile_info_cache.h"
26 #include "chrome/browser/profiles/profile_manager.h"
27 #include "chrome/browser/profiles/profiles_state.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/test/base/in_process_browser_test.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/common/content_switches.h"
32 #include "content/public/test/test_utils.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 #if defined(OS_CHROMEOS)
36 #include "chromeos/chromeos_switches.h"
37 #endif
39 namespace {
41 // An observer that returns back to test code after a new profile is
42 // initialized.
43 void OnUnblockOnProfileCreation(const base::Closure& callback,
44 Profile* profile,
45 Profile::CreateStatus status) {
46 switch (status) {
47 case Profile::CREATE_STATUS_CREATED:
48 // Wait for CREATE_STATUS_INITIALIZED.
49 break;
50 case Profile::CREATE_STATUS_INITIALIZED:
51 callback.Run();
52 break;
53 default:
54 ADD_FAILURE() << "Unexpected Profile::CreateStatus: " << status;
55 callback.Run();
56 break;
60 // Finds a profile path corresponding to a profile that has not been loaded yet.
61 base::FilePath GetUnloadedProfilePath() {
62 ProfileManager* profile_manager = g_browser_process->profile_manager();
63 const ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
64 const std::vector<Profile*> loaded_profiles =
65 profile_manager->GetLoadedProfiles();
66 std::set<base::FilePath> profile_paths;
67 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i)
68 profile_paths.insert(cache.GetPathOfProfileAtIndex(i));
69 for (size_t i = 0; i < loaded_profiles.size(); ++i)
70 EXPECT_EQ(1U, profile_paths.erase(loaded_profiles[i]->GetPath()));
71 if (profile_paths.size())
72 return *profile_paths.begin();
73 return base::FilePath();
76 // Returns the number of times |histogram_name| was reported so far; adding the
77 // results of the first 100 buckets (there are only ~14 reporting IDs as of this
78 // writting; varies depending on the platform). If |expect_zero| is true, this
79 // method will explicitly report IDs that are non-zero for ease of diagnosis.
80 int GetTrackedPrefHistogramCount(const char* histogram_name, bool expect_zero) {
81 const base::HistogramBase* histogram =
82 base::StatisticsRecorder::FindHistogram(histogram_name);
83 if (!histogram)
84 return 0;
86 scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
87 int sum = 0;
88 for (int i = 0; i < 100; ++i) {
89 int count_for_id = samples->GetCount(i);
90 sum += count_for_id;
92 if (expect_zero)
93 EXPECT_EQ(0, count_for_id) << "Faulty reporting_id: " << i;
95 return sum;
98 } // namespace
100 class PrefHashBrowserTest : public InProcessBrowserTest,
101 public testing::WithParamInterface<std::string> {
102 public:
103 PrefHashBrowserTest()
104 : is_unloaded_profile_seeding_allowed_(
105 IsUnloadedProfileSeedingAllowed()) {}
107 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
108 InProcessBrowserTest::SetUpCommandLine(command_line);
109 command_line->AppendSwitchASCII(
110 switches::kForceFieldTrials,
111 std::string(chrome_prefs::internals::kSettingsEnforcementTrialName) +
112 "/" + GetParam() + "/");
113 #if defined(OS_CHROMEOS)
114 command_line->AppendSwitch(
115 chromeos::switches::kIgnoreUserProfileMappingForTests);
116 #endif
119 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
120 // Force the delayed PrefHashStore update task to happen immediately with
121 // no domain check (bots are on a domain).
122 chrome_prefs::DisableDelaysAndDomainCheckForTesting();
125 virtual void SetUpOnMainThread() OVERRIDE {
126 // content::RunAllPendingInMessageLoop() is already called before
127 // SetUpOnMainThread() in in_process_browser_test.cc which guarantees that
128 // UpdateAllPrefHashStoresIfRequired() has already been called.
130 // Now flush the blocking pool to force any pending JsonPrefStore async read
131 // requests.
132 content::BrowserThread::GetBlockingPool()->FlushForTesting();
134 // And finally run tasks on this message loop again to process the OnRead()
135 // callbacks resulting from the file reads above.
136 content::RunAllPendingInMessageLoop();
139 protected:
140 const bool is_unloaded_profile_seeding_allowed_;
142 private:
143 bool IsUnloadedProfileSeedingAllowed() const {
144 #if defined(OFFICIAL_BUILD)
145 // SettingsEnforcement can't be forced via --force-fieldtrials in official
146 // builds. Explicitly return whether the default in
147 // chrome_pref_service_factory.cc allows unloaded profile seeding on this
148 // platform.
149 #if defined(OS_WIN)
150 return false;
151 #else
152 return true;
153 #endif // defined(OS_WIN)
154 #endif // defined(OFFICIAL_BUILD)
155 return GetParam() == chrome_prefs::internals::
156 kSettingsEnforcementGroupNoEnforcement ||
157 GetParam() == chrome_prefs::internals::
158 kSettingsEnforcementGroupEnforceOnload;
162 #if defined(OS_CHROMEOS)
163 // PrefHash service has been disabled on ChromeOS: crbug.com/343261
164 #define MAYBE_PRE_PRE_InitializeUnloadedProfiles DISABLED_PRE_PRE_InitializeUnloadedProfiles
165 #define MAYBE_PRE_InitializeUnloadedProfiles DISABLED_PRE_InitializeUnloadedProfiles
166 #define MAYBE_InitializeUnloadedProfiles DISABLED_InitializeUnloadedProfiles
167 #else
168 #define MAYBE_PRE_PRE_InitializeUnloadedProfiles PRE_PRE_InitializeUnloadedProfiles
169 #define MAYBE_PRE_InitializeUnloadedProfiles PRE_InitializeUnloadedProfiles
170 #define MAYBE_InitializeUnloadedProfiles InitializeUnloadedProfiles
171 #endif
173 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
174 MAYBE_PRE_PRE_InitializeUnloadedProfiles) {
175 ProfileManager* profile_manager = g_browser_process->profile_manager();
177 // Create an additional profile.
178 const base::FilePath new_path =
179 profile_manager->GenerateNextProfileDirectoryPath();
180 const scoped_refptr<content::MessageLoopRunner> runner(
181 new content::MessageLoopRunner);
182 profile_manager->CreateProfileAsync(
183 new_path,
184 base::Bind(&OnUnblockOnProfileCreation, runner->QuitClosure()),
185 base::string16(),
186 base::string16(),
187 std::string());
189 // Spin to allow profile creation to take place, loop is terminated
190 // by OnUnblockOnProfileCreation when the profile is created.
191 runner->Run();
193 // No profile should have gone through the unloaded profile initialization in
194 // this phase as both profiles should have been loaded normally.
195 EXPECT_EQ(
196 0, GetTrackedPrefHistogramCount(
197 "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
198 true));
201 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
202 MAYBE_PRE_InitializeUnloadedProfiles) {
203 // Creating the profile would have initialized its hash store. Also, we don't
204 // know whether the newly created or original profile will be launched (does
205 // creating a profile cause it to be the most recently used?).
207 // So we will find the profile that isn't loaded, reset its hash store, and
208 // then verify in the _next_ launch that it is, indeed, restored despite not
209 // having been loaded.
211 const base::DictionaryValue* hashes =
212 g_browser_process->local_state()->GetDictionary(
213 prefs::kProfilePreferenceHashes);
215 // 4 is for hash_of_hashes, versions_dict, default profile, and new profile.
216 EXPECT_EQ(4U, hashes->size());
218 // One of the two profiles should not have been loaded. Reset its hash store.
219 const base::FilePath unloaded_profile_path = GetUnloadedProfilePath();
220 chrome_prefs::ResetPrefHashStore(unloaded_profile_path);
222 // One of the profile hash collections should be gone.
223 EXPECT_EQ(3U, hashes->size());
225 // No profile should have gone through the unloaded profile initialization in
226 // this phase as both profiles were already initialized at the beginning of
227 // this phase (resetting the unloaded profile's PrefHashStore should only
228 // force initialization in the next phase's startup).
229 EXPECT_EQ(
230 0, GetTrackedPrefHistogramCount(
231 "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
232 true));
235 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
236 MAYBE_InitializeUnloadedProfiles) {
237 const base::DictionaryValue* hashes =
238 g_browser_process->local_state()->GetDictionary(
239 prefs::kProfilePreferenceHashes);
241 // The deleted hash collection should be restored only if the current
242 // SettingsEnforcement group allows it.
243 if (is_unloaded_profile_seeding_allowed_) {
244 EXPECT_EQ(4U, hashes->size());
246 // Verify that the initialization truly did occur in this phase's startup;
247 // rather than in the previous phase's shutdown.
248 EXPECT_EQ(
249 1, GetTrackedPrefHistogramCount(
250 "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
251 false));
252 } else {
253 EXPECT_EQ(3U, hashes->size());
255 EXPECT_EQ(
256 0, GetTrackedPrefHistogramCount(
257 "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
258 true));
261 ProfileManager* profile_manager = g_browser_process->profile_manager();
263 // Verify that only one profile was loaded. We assume that the unloaded
264 // profile is the same one that wasn't loaded in the last launch (i.e., it's
265 // the one whose hash store we reset, and the fact that it is now restored is
266 // evidence that we restored the hashes of an unloaded profile.).
267 ASSERT_EQ(1U, profile_manager->GetLoadedProfiles().size());
269 // Loading the first profile should only have produced unchanged reports.
270 EXPECT_EQ(
271 0, GetTrackedPrefHistogramCount(
272 "Settings.TrackedPreferenceChanged", true));
273 EXPECT_EQ(
274 0, GetTrackedPrefHistogramCount(
275 "Settings.TrackedPreferenceCleared", true));
276 EXPECT_EQ(
277 0, GetTrackedPrefHistogramCount(
278 "Settings.TrackedPreferenceInitialized", true));
279 EXPECT_EQ(
280 0, GetTrackedPrefHistogramCount(
281 "Settings.TrackedPreferenceTrustedInitialized", true));
282 EXPECT_EQ(
283 0, GetTrackedPrefHistogramCount(
284 "Settings.TrackedPreferenceMigrated", true));
285 int initial_unchanged_count =
286 GetTrackedPrefHistogramCount("Settings.TrackedPreferenceUnchanged",
287 false);
288 EXPECT_GT(initial_unchanged_count, 0);
290 if (is_unloaded_profile_seeding_allowed_) {
291 // Explicitly load the unloaded profile.
292 profile_manager->GetProfile(GetUnloadedProfilePath());
293 ASSERT_EQ(2U, profile_manager->GetLoadedProfiles().size());
295 // Loading the unloaded profile should only generate unchanged pings; and
296 // should have produced as many of them as loading the first profile.
297 EXPECT_EQ(
298 0, GetTrackedPrefHistogramCount(
299 "Settings.TrackedPreferenceChanged", true));
300 EXPECT_EQ(
301 0, GetTrackedPrefHistogramCount(
302 "Settings.TrackedPreferenceCleared", true));
303 EXPECT_EQ(
304 0, GetTrackedPrefHistogramCount(
305 "Settings.TrackedPreferenceInitialized", true));
306 EXPECT_EQ(
307 0, GetTrackedPrefHistogramCount(
308 "Settings.TrackedPreferenceTrustedInitialized", true));
309 EXPECT_EQ(
310 0, GetTrackedPrefHistogramCount(
311 "Settings.TrackedPreferenceMigrated", true));
312 EXPECT_EQ(
313 initial_unchanged_count * 2,
314 GetTrackedPrefHistogramCount("Settings.TrackedPreferenceUnchanged",
315 false));
319 INSTANTIATE_TEST_CASE_P(
320 PrefHashBrowserTestInstance,
321 PrefHashBrowserTest,
322 testing::Values(
323 chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
324 chrome_prefs::internals::kSettingsEnforcementGroupEnforceOnload,
325 chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
326 chrome_prefs::internals::
327 kSettingsEnforcementGroupEnforceAlwaysWithExtensions,
328 chrome_prefs::internals::
329 kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE));