Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prefs / pref_hash_browsertest.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 <set>
6 #include <vector>
7
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 "chrome/browser/browser_process.h"
21 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
22 #include "chrome/browser/prefs/pref_hash_store.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_info_cache.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/browser/profiles/profiles_state.h"
27 #include "chrome/common/pref_names.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/common/content_switches.h"
31 #include "content/public/test/test_utils.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 namespace {
35
36 // An observer that returns back to test code after a new profile is
37 // initialized.
38 void OnUnblockOnProfileCreation(const base::Closure& callback,
39                                 Profile* profile,
40                                 Profile::CreateStatus status) {
41   switch (status) {
42     case Profile::CREATE_STATUS_CREATED:
43       // Wait for CREATE_STATUS_INITIALIZED.
44       break;
45     case Profile::CREATE_STATUS_INITIALIZED:
46       callback.Run();
47       break;
48     default:
49       ADD_FAILURE() << "Unexpected Profile::CreateStatus: " << status;
50       callback.Run();
51       break;
52   }
53 }
54
55 // Finds a profile path corresponding to a profile that has not been loaded yet.
56 base::FilePath GetUnloadedProfilePath() {
57   ProfileManager* profile_manager = g_browser_process->profile_manager();
58   const ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
59   const std::vector<Profile*> loaded_profiles =
60       profile_manager->GetLoadedProfiles();
61   std::set<base::FilePath> profile_paths;
62   for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i)
63     profile_paths.insert(cache.GetPathOfProfileAtIndex(i));
64   for (size_t i = 0; i < loaded_profiles.size(); ++i)
65     EXPECT_EQ(1U, profile_paths.erase(loaded_profiles[i]->GetPath()));
66   if (profile_paths.size())
67     return *profile_paths.begin();
68   return base::FilePath();
69 }
70
71 // Returns the number of times |histogram_name| was reported so far; adding the
72 // results of the first 100 buckets (there are only ~14 reporting IDs as of this
73 // writting; varies depending on the platform). If |expect_zero| is true, this
74 // method will explicitly report IDs that are non-zero for ease of diagnosis.
75 int GetTrackedPrefHistogramCount(const char* histogram_name, bool expect_zero) {
76   const base::HistogramBase* histogram =
77       base::StatisticsRecorder::FindHistogram(histogram_name);
78   if (!histogram)
79     return 0;
80
81   scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
82   int sum = 0;
83   for (int i = 0; i < 100; ++i) {
84     int count_for_id = samples->GetCount(i);
85     sum += count_for_id;
86
87     if (expect_zero)
88       EXPECT_EQ(0, count_for_id) << "Faulty reporting_id: " << i;
89   }
90   return sum;
91 }
92
93 }  // namespace
94
95 class PrefHashBrowserTest : public InProcessBrowserTest,
96                             public testing::WithParamInterface<std::string> {
97  public:
98   PrefHashBrowserTest()
99       : is_unloaded_profile_seeding_allowed_(
100             GetParam() !=
101             chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways) {}
102
103   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
104     InProcessBrowserTest::SetUpCommandLine(command_line);
105     command_line->AppendSwitchASCII(
106         switches::kForceFieldTrials,
107         std::string(chrome_prefs::internals::kSettingsEnforcementTrialName) +
108             "/" + GetParam() + "/");
109   }
110
111   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
112     // Force the delayed PrefHashStore update task to happen immediately.
113     chrome_prefs::EnableZeroDelayPrefHashStoreUpdateForTesting();
114   }
115
116   virtual void SetUpOnMainThread() OVERRIDE {
117     // content::RunAllPendingInMessageLoop() is already called before
118     // SetUpOnMainThread() in in_process_browser_test.cc which guarantees that
119     // UpdateAllPrefHashStoresIfRequired() has already been called.
120
121     // Now flush the blocking pool to force any pending JsonPrefStore async read
122     // requests.
123     content::BrowserThread::GetBlockingPool()->FlushForTesting();
124
125     // And finally run tasks on this message loop again to process the OnRead()
126     // callbacks resulting from the file reads above.
127     content::RunAllPendingInMessageLoop();
128   }
129
130  protected:
131   const bool is_unloaded_profile_seeding_allowed_;
132 };
133
134 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
135                        PRE_PRE_InitializeUnloadedProfiles) {
136   if (!profiles::IsMultipleProfilesEnabled())
137     return;
138   ProfileManager* profile_manager = g_browser_process->profile_manager();
139
140   // Create an additional profile.
141   const base::FilePath new_path =
142       profile_manager->GenerateNextProfileDirectoryPath();
143   const scoped_refptr<content::MessageLoopRunner> runner(
144       new content::MessageLoopRunner);
145   profile_manager->CreateProfileAsync(
146       new_path,
147       base::Bind(&OnUnblockOnProfileCreation, runner->QuitClosure()),
148       base::string16(),
149       base::string16(),
150       std::string());
151
152   // Spin to allow profile creation to take place, loop is terminated
153   // by OnUnblockOnProfileCreation when the profile is created.
154   runner->Run();
155
156   // No profile should have gone through the unloaded profile initialization in
157   // this phase as both profiles should have been loaded normally.
158   EXPECT_EQ(
159       0, GetTrackedPrefHistogramCount(
160              "Settings.TrackedPreferencesInitializedForUnloadedProfile",
161              true));
162 }
163
164 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
165                        PRE_InitializeUnloadedProfiles) {
166   if (!profiles::IsMultipleProfilesEnabled())
167     return;
168
169   // Creating the profile would have initialized its hash store. Also, we don't
170   // know whether the newly created or original profile will be launched (does
171   // creating a profile cause it to be the most recently used?).
172
173   // So we will find the profile that isn't loaded, reset its hash store, and
174   // then verify in the _next_ launch that it is, indeed, restored despite not
175   // having been loaded.
176
177   const base::DictionaryValue* hashes =
178       g_browser_process->local_state()->GetDictionary(
179           prefs::kProfilePreferenceHashes);
180
181   // 4 is for hash_of_hashes, versions_dict, default profile, and new profile.
182   EXPECT_EQ(4U, hashes->size());
183
184   // One of the two profiles should not have been loaded. Reset its hash store.
185   const base::FilePath unloaded_profile_path = GetUnloadedProfilePath();
186   chrome_prefs::ResetPrefHashStore(unloaded_profile_path);
187
188   // One of the profile hash collections should be gone.
189   EXPECT_EQ(3U, hashes->size());
190
191   // No profile should have gone through the unloaded profile initialization in
192   // this phase as both profiles were already initialized at the beginning of
193   // this phase (resetting the unloaded profile's PrefHashStore should only
194   // force initialization in the next phase's startup).
195   EXPECT_EQ(
196       0, GetTrackedPrefHistogramCount(
197              "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
198              true));
199 }
200
201 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
202                        InitializeUnloadedProfiles) {
203   if (!profiles::IsMultipleProfilesEnabled())
204     return;
205
206   const base::DictionaryValue* hashes =
207       g_browser_process->local_state()->GetDictionary(
208           prefs::kProfilePreferenceHashes);
209
210   // The deleted hash collection should be restored only if the current
211   // SettingsEnforcement group allows it.
212   if (is_unloaded_profile_seeding_allowed_) {
213     EXPECT_EQ(4U, hashes->size());
214
215     // Verify that the initialization truly did occur in this phase's startup;
216     // rather than in the previous phase's shutdown.
217     EXPECT_EQ(
218         1, GetTrackedPrefHistogramCount(
219                "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
220                false));
221   } else {
222     EXPECT_EQ(3U, hashes->size());
223
224     EXPECT_EQ(
225         0, GetTrackedPrefHistogramCount(
226                "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
227                true));
228   }
229
230   ProfileManager* profile_manager = g_browser_process->profile_manager();
231
232   // Verify that only one profile was loaded. We assume that the unloaded
233   // profile is the same one that wasn't loaded in the last launch (i.e., it's
234   // the one whose hash store we reset, and the fact that it is now restored is
235   // evidence that we restored the hashes of an unloaded profile.).
236   ASSERT_EQ(1U, profile_manager->GetLoadedProfiles().size());
237
238   // Loading the first profile should only have produced unchanged reports.
239   EXPECT_EQ(
240       0, GetTrackedPrefHistogramCount(
241              "Settings.TrackedPreferenceChanged", true));
242   EXPECT_EQ(
243       0, GetTrackedPrefHistogramCount(
244              "Settings.TrackedPreferenceCleared", true));
245   EXPECT_EQ(
246       0, GetTrackedPrefHistogramCount(
247              "Settings.TrackedPreferenceInitialized", true));
248   EXPECT_EQ(
249       0, GetTrackedPrefHistogramCount(
250              "Settings.TrackedPreferenceTrustedInitialized", true));
251   EXPECT_EQ(
252       0, GetTrackedPrefHistogramCount(
253              "Settings.TrackedPreferenceMigrated", true));
254   int initial_unchanged_count =
255       GetTrackedPrefHistogramCount("Settings.TrackedPreferenceUnchanged",
256                                    false);
257   EXPECT_GT(initial_unchanged_count, 0);
258
259   if (is_unloaded_profile_seeding_allowed_) {
260     // Explicitly load the unloaded profile.
261     profile_manager->GetProfile(GetUnloadedProfilePath());
262     ASSERT_EQ(2U, profile_manager->GetLoadedProfiles().size());
263
264     // Loading the unloaded profile should only generate unchanged pings; and
265     // should have produced as many of them as loading the first profile.
266     EXPECT_EQ(
267         0, GetTrackedPrefHistogramCount(
268                "Settings.TrackedPreferenceChanged", true));
269     EXPECT_EQ(
270         0, GetTrackedPrefHistogramCount(
271                "Settings.TrackedPreferenceCleared", true));
272     EXPECT_EQ(
273         0, GetTrackedPrefHistogramCount(
274                "Settings.TrackedPreferenceInitialized", true));
275     EXPECT_EQ(
276         0, GetTrackedPrefHistogramCount(
277                "Settings.TrackedPreferenceTrustedInitialized", true));
278     EXPECT_EQ(
279         0, GetTrackedPrefHistogramCount(
280                "Settings.TrackedPreferenceMigrated", true));
281     EXPECT_EQ(
282         initial_unchanged_count * 2,
283         GetTrackedPrefHistogramCount("Settings.TrackedPreferenceUnchanged",
284                                      false));
285   }
286 }
287
288 // TODO(gab): Also test kSettingsEnforcementGroupEnforceAlways below; for some
289 // reason it doesn't pass on the try bots, yet I can't repro the failure
290 // locally, it's as if GROUP_NO_ENFORCEMENT is always picked on bots..?
291 INSTANTIATE_TEST_CASE_P(
292     PrefHashBrowserTestInstance,
293     PrefHashBrowserTest,
294     testing::Values(
295         chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
296         chrome_prefs::internals::kSettingsEnforcementGroupEnforceOnload));