Roll src/third_party/WebKit bf18a82:a9cee16 (svn 185297:185304)
[chromium-blink-merge.git] / chrome / browser / prefs / chrome_pref_service_factory.cc
blob4f66ad20a140fad027eead28ee7964a27eec7814
1 // Copyright (c) 2012 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 "chrome/browser/prefs/chrome_pref_service_factory.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/debug/trace_event.h"
13 #include "base/files/file_path.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/default_pref_store.h"
17 #include "base/prefs/json_pref_store.h"
18 #include "base/prefs/pref_filter.h"
19 #include "base/prefs/pref_notifier_impl.h"
20 #include "base/prefs/pref_registry.h"
21 #include "base/prefs/pref_registry_simple.h"
22 #include "base/prefs/pref_service.h"
23 #include "base/prefs/pref_store.h"
24 #include "base/prefs/pref_value_store.h"
25 #include "base/threading/sequenced_worker_pool.h"
26 #include "base/time/time.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/prefs/browser_ui_prefs_migrator.h"
29 #include "chrome/browser/prefs/command_line_pref_store.h"
30 #include "chrome/browser/prefs/pref_model_associator.h"
31 #include "chrome/browser/prefs/pref_service_syncable.h"
32 #include "chrome/browser/prefs/pref_service_syncable_factory.h"
33 #include "chrome/browser/prefs/profile_pref_store_manager.h"
34 #include "chrome/browser/prefs/tracked/pref_hash_filter.h"
35 #include "chrome/browser/profiles/file_path_verifier_win.h"
36 #include "chrome/browser/profiles/profile.h"
37 #include "chrome/browser/search_engines/default_search_pref_migration.h"
38 #include "chrome/browser/sync/glue/sync_start_util.h"
39 #include "chrome/browser/ui/profile_error_dialog.h"
40 #include "chrome/common/chrome_constants.h"
41 #include "chrome/common/pref_names.h"
42 #include "chrome/grit/chromium_strings.h"
43 #include "chrome/grit/generated_resources.h"
44 #include "components/component_updater/pref_names.h"
45 #include "components/pref_registry/pref_registry_syncable.h"
46 #include "components/search_engines/default_search_manager.h"
47 #include "components/search_engines/search_engines_pref_names.h"
48 #include "components/sync_driver/pref_names.h"
49 #include "content/public/browser/browser_context.h"
50 #include "content/public/browser/browser_thread.h"
51 #include "grit/browser_resources.h"
52 #include "sync/internal_api/public/base/model_type.h"
53 #include "ui/base/resource/resource_bundle.h"
55 #if defined(ENABLE_CONFIGURATION_POLICY)
56 #include "components/policy/core/browser/browser_policy_connector.h"
57 #include "components/policy/core/browser/configuration_policy_pref_store.h"
58 #include "components/policy/core/common/policy_types.h"
59 #endif
61 #if defined(ENABLE_EXTENSIONS)
62 #include "extensions/browser/pref_names.h"
63 #endif
65 #if defined(ENABLE_MANAGED_USERS)
66 #include "chrome/browser/supervised_user/supervised_user_pref_store.h"
67 #endif
69 #if defined(OS_WIN) && defined(ENABLE_RLZ)
70 #include "rlz/lib/machine_id.h"
71 #endif // defined(ENABLE_RLZ) && defined(OS_WIN)
73 using content::BrowserContext;
74 using content::BrowserThread;
76 namespace {
78 // These preferences must be kept in sync with the TrackedPreference enum in
79 // tools/metrics/histograms/histograms.xml. To add a new preference, append it
80 // to the array and add a corresponding value to the histogram enum. Each
81 // tracked preference must be given a unique reporting ID.
82 // See CleanupDeprecatedTrackedPreferences() in pref_hash_filter.cc to remove a
83 // deprecated tracked preference.
84 const PrefHashFilter::TrackedPreferenceMetadata kTrackedPrefs[] = {
86 0, prefs::kShowHomeButton,
87 PrefHashFilter::ENFORCE_ON_LOAD,
88 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
91 1, prefs::kHomePageIsNewTabPage,
92 PrefHashFilter::ENFORCE_ON_LOAD,
93 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
96 2, prefs::kHomePage,
97 PrefHashFilter::ENFORCE_ON_LOAD,
98 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
101 3, prefs::kRestoreOnStartup,
102 PrefHashFilter::ENFORCE_ON_LOAD,
103 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
106 4, prefs::kURLsToRestoreOnStartup,
107 PrefHashFilter::ENFORCE_ON_LOAD,
108 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
110 #if defined(ENABLE_EXTENSIONS)
112 5, extensions::pref_names::kExtensions,
113 PrefHashFilter::NO_ENFORCEMENT,
114 PrefHashFilter::TRACKING_STRATEGY_SPLIT
116 #endif
118 6, prefs::kGoogleServicesLastUsername,
119 PrefHashFilter::ENFORCE_ON_LOAD,
120 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
123 7, prefs::kSearchProviderOverrides,
124 PrefHashFilter::ENFORCE_ON_LOAD,
125 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
128 8, prefs::kDefaultSearchProviderSearchURL,
129 PrefHashFilter::ENFORCE_ON_LOAD,
130 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
133 9, prefs::kDefaultSearchProviderKeyword,
134 PrefHashFilter::ENFORCE_ON_LOAD,
135 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
138 10, prefs::kDefaultSearchProviderName,
139 PrefHashFilter::ENFORCE_ON_LOAD,
140 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
142 #if !defined(OS_ANDROID)
144 11, prefs::kPinnedTabs,
145 PrefHashFilter::ENFORCE_ON_LOAD,
146 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
149 13, prefs::kProfileResetPromptMementoInProfilePrefs,
150 PrefHashFilter::ENFORCE_ON_LOAD,
151 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
153 #endif
155 14, DefaultSearchManager::kDefaultSearchProviderDataPrefName,
156 PrefHashFilter::NO_ENFORCEMENT,
157 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
160 // Protecting kPreferenceResetTime does two things:
161 // 1) It ensures this isn't accidently set by someone stomping the pref
162 // file.
163 // 2) More importantly, it declares kPreferenceResetTime as a protected
164 // pref which is required for it to be visible when queried via the
165 // SegregatedPrefStore. This is because it's written directly in the
166 // protected JsonPrefStore by that store's PrefHashFilter if there was
167 // a reset in FilterOnLoad and SegregatedPrefStore will not look for it
168 // in the protected JsonPrefStore unless it's declared as a protected
169 // preference here.
170 15, prefs::kPreferenceResetTime,
171 PrefHashFilter::ENFORCE_ON_LOAD,
172 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
175 16, prefs::kSafeBrowsingIncidentReportSent,
176 PrefHashFilter::ENFORCE_ON_LOAD,
177 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
180 17, sync_driver::prefs::kSyncRemainingRollbackTries,
181 PrefHashFilter::ENFORCE_ON_LOAD,
182 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
185 18, prefs::kSafeBrowsingIncidentsSent,
186 PrefHashFilter::ENFORCE_ON_LOAD,
187 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
189 #if defined(OS_WIN)
191 19, prefs::kSwReporterPromptVersion,
192 PrefHashFilter::ENFORCE_ON_LOAD,
193 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
196 20, prefs::kSwReporterPromptReason,
197 PrefHashFilter::ENFORCE_ON_LOAD,
198 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
200 #endif
203 // One more than the last tracked preferences ID above.
204 const size_t kTrackedPrefsReportingIDsCount =
205 kTrackedPrefs[arraysize(kTrackedPrefs) - 1].reporting_id + 1;
207 // Each group enforces a superset of the protection provided by the previous
208 // one.
209 enum SettingsEnforcementGroup {
210 GROUP_NO_ENFORCEMENT,
211 // Enforce protected settings on profile loads.
212 GROUP_ENFORCE_ALWAYS,
213 // Also enforce extension default search.
214 GROUP_ENFORCE_ALWAYS_WITH_DSE,
215 // Also enforce extension settings and default search.
216 GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE,
217 // The default enforcement group contains all protection features.
218 GROUP_ENFORCE_DEFAULT
221 SettingsEnforcementGroup GetSettingsEnforcementGroup() {
222 struct {
223 const char* group_name;
224 SettingsEnforcementGroup group;
225 } static const kEnforcementLevelMap[] = {
226 { chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
227 GROUP_NO_ENFORCEMENT },
228 { chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
229 GROUP_ENFORCE_ALWAYS },
230 { chrome_prefs::internals::
231 kSettingsEnforcementGroupEnforceAlwaysWithDSE,
232 GROUP_ENFORCE_ALWAYS_WITH_DSE },
233 { chrome_prefs::internals::
234 kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE,
235 GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE },
238 // Use the strongest enforcement setting in the absence of a field trial
239 // config on Windows. Remember to update the OFFICIAL_BUILD section of
240 // extension_startup_browsertest.cc and pref_hash_browsertest.cc when updating
241 // the default value below.
242 // TODO(gab): Enforce this on all platforms.
243 SettingsEnforcementGroup enforcement_group =
244 #if defined(OS_WIN)
245 GROUP_ENFORCE_DEFAULT;
246 #else
247 GROUP_NO_ENFORCEMENT;
248 #endif
249 bool group_determined_from_trial = false;
250 base::FieldTrial* trial =
251 base::FieldTrialList::Find(
252 chrome_prefs::internals::kSettingsEnforcementTrialName);
253 if (trial) {
254 const std::string& group_name = trial->group_name();
255 for (size_t i = 0; i < arraysize(kEnforcementLevelMap); ++i) {
256 if (kEnforcementLevelMap[i].group_name == group_name) {
257 enforcement_group = kEnforcementLevelMap[i].group;
258 group_determined_from_trial = true;
259 break;
263 UMA_HISTOGRAM_BOOLEAN("Settings.EnforcementGroupDeterminedFromTrial",
264 group_determined_from_trial);
265 return enforcement_group;
268 // Returns the effective preference tracking configuration.
269 std::vector<PrefHashFilter::TrackedPreferenceMetadata>
270 GetTrackingConfiguration() {
271 const SettingsEnforcementGroup enforcement_group =
272 GetSettingsEnforcementGroup();
274 std::vector<PrefHashFilter::TrackedPreferenceMetadata> result;
275 for (size_t i = 0; i < arraysize(kTrackedPrefs); ++i) {
276 PrefHashFilter::TrackedPreferenceMetadata data = kTrackedPrefs[i];
278 if (GROUP_NO_ENFORCEMENT == enforcement_group) {
279 // Remove enforcement for all tracked preferences.
280 data.enforcement_level = PrefHashFilter::NO_ENFORCEMENT;
283 if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_DSE &&
284 data.name == DefaultSearchManager::kDefaultSearchProviderDataPrefName) {
285 // Specifically enable default search settings enforcement.
286 data.enforcement_level = PrefHashFilter::ENFORCE_ON_LOAD;
289 #if defined(ENABLE_EXTENSIONS)
290 if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE &&
291 data.name == extensions::pref_names::kExtensions) {
292 // Specifically enable extension settings enforcement.
293 data.enforcement_level = PrefHashFilter::ENFORCE_ON_LOAD;
295 #endif
297 result.push_back(data);
299 return result;
302 // Shows notifications which correspond to PersistentPrefStore's reading errors.
303 void HandleReadError(PersistentPrefStore::PrefReadError error) {
304 // Sample the histogram also for the successful case in order to get a
305 // baseline on the success rate in addition to the error distribution.
306 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error,
307 PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
309 if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
310 #if !defined(OS_CHROMEOS)
311 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
312 // an example problem that this can cause.
313 // Do some diagnosis and try to avoid losing data.
314 int message_id = 0;
315 if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE ||
316 error == PersistentPrefStore::PREF_READ_ERROR_LEVELDB_CORRUPTION) {
317 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
318 } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
319 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
322 if (message_id) {
323 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
324 base::Bind(&ShowProfileErrorDialog,
325 PROFILE_ERROR_PREFERENCES,
326 message_id));
328 #else
329 // On ChromeOS error screen with message about broken local state
330 // will be displayed.
332 // A supplementary error message about broken local state - is included
333 // in logs and user feedbacks.
334 if (error != PersistentPrefStore::PREF_READ_ERROR_NONE &&
335 error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
336 LOG(ERROR) << "An error happened during prefs loading: " << error;
338 #endif
342 scoped_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager(
343 const base::FilePath& profile_path) {
344 std::string device_id;
345 #if defined(OS_WIN) && defined(ENABLE_RLZ)
346 // This is used by
347 // chrome/browser/extensions/api/music_manager_private/device_id_win.cc
348 // but that API is private (http://crbug.com/276485) and other platforms are
349 // not available synchronously.
350 // As part of improving pref metrics on other platforms we may want to find
351 // ways to defer preference loading until the device ID can be used.
352 rlz_lib::GetMachineId(&device_id);
353 #endif
354 std::string seed;
355 #if defined(GOOGLE_CHROME_BUILD)
356 seed = ResourceBundle::GetSharedInstance().GetRawDataResource(
357 IDR_PREF_HASH_SEED_BIN).as_string();
358 #endif
359 return make_scoped_ptr(new ProfilePrefStoreManager(
360 profile_path,
361 GetTrackingConfiguration(),
362 kTrackedPrefsReportingIDsCount,
363 seed,
364 device_id,
365 g_browser_process->local_state()));
368 void PrepareFactory(
369 PrefServiceSyncableFactory* factory,
370 policy::PolicyService* policy_service,
371 SupervisedUserSettingsService* supervised_user_settings,
372 scoped_refptr<PersistentPrefStore> user_pref_store,
373 const scoped_refptr<PrefStore>& extension_prefs,
374 bool async) {
375 #if defined(ENABLE_CONFIGURATION_POLICY)
376 using policy::ConfigurationPolicyPrefStore;
377 factory->set_managed_prefs(
378 make_scoped_refptr(new ConfigurationPolicyPrefStore(
379 policy_service,
380 g_browser_process->browser_policy_connector()->GetHandlerList(),
381 policy::POLICY_LEVEL_MANDATORY)));
382 factory->set_recommended_prefs(
383 make_scoped_refptr(new ConfigurationPolicyPrefStore(
384 policy_service,
385 g_browser_process->browser_policy_connector()->GetHandlerList(),
386 policy::POLICY_LEVEL_RECOMMENDED)));
387 #endif // ENABLE_CONFIGURATION_POLICY
389 #if defined(ENABLE_MANAGED_USERS)
390 if (supervised_user_settings) {
391 factory->set_supervised_user_prefs(
392 make_scoped_refptr(
393 new SupervisedUserPrefStore(supervised_user_settings)));
395 #endif
397 factory->set_async(async);
398 factory->set_extension_prefs(extension_prefs);
399 factory->set_command_line_prefs(
400 make_scoped_refptr(
401 new CommandLinePrefStore(CommandLine::ForCurrentProcess())));
402 factory->set_read_error_callback(base::Bind(&HandleReadError));
403 factory->set_user_prefs(user_pref_store);
406 } // namespace
408 namespace chrome_prefs {
410 namespace internals {
412 // Group modifications should be reflected in first_run_browsertest.cc and
413 // pref_hash_browsertest.cc.
414 const char kSettingsEnforcementTrialName[] = "SettingsEnforcement";
415 const char kSettingsEnforcementGroupNoEnforcement[] = "no_enforcement";
416 const char kSettingsEnforcementGroupEnforceAlways[] = "enforce_always";
417 const char kSettingsEnforcementGroupEnforceAlwaysWithDSE[] =
418 "enforce_always_with_dse";
419 const char kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE[] =
420 "enforce_always_with_extensions_and_dse";
422 } // namespace internals
424 scoped_ptr<PrefService> CreateLocalState(
425 const base::FilePath& pref_filename,
426 base::SequencedTaskRunner* pref_io_task_runner,
427 policy::PolicyService* policy_service,
428 const scoped_refptr<PrefRegistry>& pref_registry,
429 bool async) {
430 PrefServiceSyncableFactory factory;
431 PrepareFactory(
432 &factory,
433 policy_service,
434 NULL, // supervised_user_settings
435 new JsonPrefStore(
436 pref_filename, pref_io_task_runner, scoped_ptr<PrefFilter>()),
437 NULL, // extension_prefs
438 async);
439 return factory.Create(pref_registry.get());
442 scoped_ptr<PrefServiceSyncable> CreateProfilePrefs(
443 const base::FilePath& profile_path,
444 base::SequencedTaskRunner* pref_io_task_runner,
445 TrackedPreferenceValidationDelegate* validation_delegate,
446 policy::PolicyService* policy_service,
447 SupervisedUserSettingsService* supervised_user_settings,
448 const scoped_refptr<PrefStore>& extension_prefs,
449 const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry,
450 bool async) {
451 TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
453 // A StartSyncFlare used to kick sync early in case of a reset event. This is
454 // done since sync may bring back the user's server value post-reset which
455 // could potentially cause a "settings flash" between the factory default and
456 // the re-instantiated server value. Starting sync ASAP minimizes the window
457 // before the server value is re-instantiated (this window can otherwise be
458 // as long as 10 seconds by default).
459 const base::Closure start_sync_flare_for_prefs =
460 base::Bind(sync_start_util::GetFlareForSyncableService(profile_path),
461 syncer::PREFERENCES);
463 PrefServiceSyncableFactory factory;
464 scoped_refptr<PersistentPrefStore> user_pref_store(
465 CreateProfilePrefStoreManager(profile_path)
466 ->CreateProfilePrefStore(pref_io_task_runner,
467 start_sync_flare_for_prefs,
468 validation_delegate));
469 // BrowserUIPrefsMigrator unregisters and deletes itself after it is done.
470 user_pref_store->AddObserver(
471 new BrowserUIPrefsMigrator(user_pref_store.get()));
472 PrepareFactory(&factory,
473 policy_service,
474 supervised_user_settings,
475 user_pref_store,
476 extension_prefs,
477 async);
478 scoped_ptr<PrefServiceSyncable> pref_service =
479 factory.CreateSyncable(pref_registry.get());
481 ConfigureDefaultSearchPrefMigrationToDictionaryValue(pref_service.get());
483 return pref_service.Pass();
486 void SchedulePrefsFilePathVerification(const base::FilePath& profile_path) {
487 #if defined(OS_WIN)
488 // Only do prefs file verification on Windows.
489 const int kVerifyPrefsFileDelaySeconds = 60;
490 BrowserThread::GetBlockingPool()->PostDelayedTask(
491 FROM_HERE,
492 base::Bind(&VerifyPreferencesFile,
493 ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
494 profile_path)),
495 base::TimeDelta::FromSeconds(kVerifyPrefsFileDelaySeconds));
496 #endif
499 bool InitializePrefsFromMasterPrefs(
500 const base::FilePath& profile_path,
501 const base::DictionaryValue& master_prefs) {
502 return CreateProfilePrefStoreManager(profile_path)
503 ->InitializePrefsFromMasterPrefs(master_prefs);
506 base::Time GetResetTime(Profile* profile) {
507 return ProfilePrefStoreManager::GetResetTime(profile->GetPrefs());
510 void ClearResetTime(Profile* profile) {
511 ProfilePrefStoreManager::ClearResetTime(profile->GetPrefs());
514 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
515 ProfilePrefStoreManager::RegisterProfilePrefs(registry);
518 void RegisterPrefs(PrefRegistrySimple* registry) {
519 ProfilePrefStoreManager::RegisterPrefs(registry);
522 } // namespace chrome_prefs