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"
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/files/file_path.h"
13 #include "base/metrics/field_trial.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/prefs/default_pref_store.h"
16 #include "base/prefs/json_pref_store.h"
17 #include "base/prefs/pref_filter.h"
18 #include "base/prefs/pref_notifier_impl.h"
19 #include "base/prefs/pref_registry.h"
20 #include "base/prefs/pref_registry_simple.h"
21 #include "base/prefs/pref_service.h"
22 #include "base/prefs/pref_store.h"
23 #include "base/prefs/pref_value_store.h"
24 #include "base/threading/sequenced_worker_pool.h"
25 #include "base/time/time.h"
26 #include "base/trace_event/trace_event.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/prefs/chrome_pref_model_associator_client.h"
29 #include "chrome/browser/prefs/command_line_pref_store.h"
30 #include "chrome/browser/prefs/profile_pref_store_manager.h"
31 #include "chrome/browser/profiles/file_path_verifier_win.h"
32 #include "chrome/browser/profiles/profile.h"
33 #include "chrome/browser/sync/glue/sync_start_util.h"
34 #include "chrome/browser/ui/profile_error_dialog.h"
35 #include "chrome/common/chrome_constants.h"
36 #include "chrome/common/pref_names.h"
37 #include "chrome/grit/chromium_strings.h"
38 #include "chrome/grit/generated_resources.h"
39 #include "components/component_updater/pref_names.h"
40 #include "components/pref_registry/pref_registry_syncable.h"
41 #include "components/search_engines/default_search_manager.h"
42 #include "components/search_engines/default_search_pref_migration.h"
43 #include "components/search_engines/search_engines_pref_names.h"
44 #include "components/sync_driver/pref_names.h"
45 #include "components/syncable_prefs/pref_model_associator.h"
46 #include "components/syncable_prefs/pref_service_syncable.h"
47 #include "components/syncable_prefs/pref_service_syncable_factory.h"
48 #include "components/user_prefs/tracked/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"
60 #if defined(ENABLE_EXTENSIONS)
61 #include "extensions/browser/pref_names.h"
64 #if defined(ENABLE_SUPERVISED_USERS)
65 #include "chrome/browser/supervised_user/supervised_user_pref_store.h"
69 #include "base/win/win_util.h"
70 #if defined(ENABLE_RLZ)
71 #include "rlz/lib/machine_id.h"
72 #endif // defined(ENABLE_RLZ)
73 #endif // defined(OS_WIN)
75 using content::BrowserContext
;
76 using content::BrowserThread
;
81 // Whether we are in testing mode; can be enabled via
82 // DisableDomainCheckForTesting(). Forces startup checks to ignore the presence
83 // of a domain when determining the active SettingsEnforcement group.
84 bool g_disable_domain_check_for_testing
= false;
87 // These preferences must be kept in sync with the TrackedPreference enum in
88 // tools/metrics/histograms/histograms.xml. To add a new preference, append it
89 // to the array and add a corresponding value to the histogram enum. Each
90 // tracked preference must be given a unique reporting ID.
91 // See CleanupDeprecatedTrackedPreferences() in pref_hash_filter.cc to remove a
92 // deprecated tracked preference.
93 const PrefHashFilter::TrackedPreferenceMetadata kTrackedPrefs
[] = {
95 0, prefs::kShowHomeButton
,
96 PrefHashFilter::ENFORCE_ON_LOAD
,
97 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
98 PrefHashFilter::VALUE_IMPERSONAL
101 1, prefs::kHomePageIsNewTabPage
,
102 PrefHashFilter::ENFORCE_ON_LOAD
,
103 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
104 PrefHashFilter::VALUE_IMPERSONAL
108 PrefHashFilter::ENFORCE_ON_LOAD
,
109 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
110 PrefHashFilter::VALUE_IMPERSONAL
113 3, prefs::kRestoreOnStartup
,
114 PrefHashFilter::ENFORCE_ON_LOAD
,
115 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
116 PrefHashFilter::VALUE_IMPERSONAL
119 4, prefs::kURLsToRestoreOnStartup
,
120 PrefHashFilter::ENFORCE_ON_LOAD
,
121 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
122 PrefHashFilter::VALUE_IMPERSONAL
124 #if defined(ENABLE_EXTENSIONS)
126 5, extensions::pref_names::kExtensions
,
127 PrefHashFilter::NO_ENFORCEMENT
,
128 PrefHashFilter::TRACKING_STRATEGY_SPLIT
,
129 PrefHashFilter::VALUE_IMPERSONAL
133 6, prefs::kGoogleServicesLastUsername
,
134 PrefHashFilter::ENFORCE_ON_LOAD
,
135 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
136 PrefHashFilter::VALUE_PERSONAL
139 7, prefs::kSearchProviderOverrides
,
140 PrefHashFilter::ENFORCE_ON_LOAD
,
141 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
142 PrefHashFilter::VALUE_IMPERSONAL
145 8, prefs::kDefaultSearchProviderSearchURL
,
146 PrefHashFilter::ENFORCE_ON_LOAD
,
147 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
148 PrefHashFilter::VALUE_IMPERSONAL
151 9, prefs::kDefaultSearchProviderKeyword
,
152 PrefHashFilter::ENFORCE_ON_LOAD
,
153 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
154 PrefHashFilter::VALUE_IMPERSONAL
157 10, prefs::kDefaultSearchProviderName
,
158 PrefHashFilter::ENFORCE_ON_LOAD
,
159 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
160 PrefHashFilter::VALUE_IMPERSONAL
162 #if !defined(OS_ANDROID)
164 11, prefs::kPinnedTabs
,
165 PrefHashFilter::ENFORCE_ON_LOAD
,
166 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
167 PrefHashFilter::VALUE_IMPERSONAL
170 13, prefs::kProfileResetPromptMementoInProfilePrefs
,
171 PrefHashFilter::ENFORCE_ON_LOAD
,
172 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
173 PrefHashFilter::VALUE_IMPERSONAL
177 14, DefaultSearchManager::kDefaultSearchProviderDataPrefName
,
178 PrefHashFilter::NO_ENFORCEMENT
,
179 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
180 PrefHashFilter::VALUE_IMPERSONAL
183 // Protecting kPreferenceResetTime does two things:
184 // 1) It ensures this isn't accidently set by someone stomping the pref
186 // 2) More importantly, it declares kPreferenceResetTime as a protected
187 // pref which is required for it to be visible when queried via the
188 // SegregatedPrefStore. This is because it's written directly in the
189 // protected JsonPrefStore by that store's PrefHashFilter if there was
190 // a reset in FilterOnLoad and SegregatedPrefStore will not look for it
191 // in the protected JsonPrefStore unless it's declared as a protected
193 15, user_prefs::kPreferenceResetTime
,
194 PrefHashFilter::ENFORCE_ON_LOAD
,
195 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
196 PrefHashFilter::VALUE_IMPERSONAL
199 17, sync_driver::prefs::kSyncRemainingRollbackTries
,
200 PrefHashFilter::ENFORCE_ON_LOAD
,
201 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
202 PrefHashFilter::VALUE_IMPERSONAL
205 18, prefs::kSafeBrowsingIncidentsSent
,
206 PrefHashFilter::ENFORCE_ON_LOAD
,
207 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
208 PrefHashFilter::VALUE_IMPERSONAL
212 19, prefs::kSwReporterPromptVersion
,
213 PrefHashFilter::ENFORCE_ON_LOAD
,
214 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
215 PrefHashFilter::VALUE_IMPERSONAL
218 // This pref is deprecated and will be removed a few releases after M43.
219 // kGoogleServicesAccountId replaces it.
221 21, prefs::kGoogleServicesUsername
,
222 PrefHashFilter::ENFORCE_ON_LOAD
,
223 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
224 PrefHashFilter::VALUE_PERSONAL
228 22, prefs::kSwReporterPromptSeed
,
229 PrefHashFilter::ENFORCE_ON_LOAD
,
230 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
231 PrefHashFilter::VALUE_IMPERSONAL
235 23, prefs::kGoogleServicesAccountId
,
236 PrefHashFilter::ENFORCE_ON_LOAD
,
237 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
,
238 PrefHashFilter::VALUE_PERSONAL
240 // See note at top, new items added here also need to be added to
241 // histograms.xml's TrackedPreference enum.
244 // One more than the last tracked preferences ID above.
245 const size_t kTrackedPrefsReportingIDsCount
=
246 kTrackedPrefs
[arraysize(kTrackedPrefs
) - 1].reporting_id
+ 1;
248 // Each group enforces a superset of the protection provided by the previous
250 enum SettingsEnforcementGroup
{
251 GROUP_NO_ENFORCEMENT
,
252 // Enforce protected settings on profile loads.
253 GROUP_ENFORCE_ALWAYS
,
254 // Also enforce extension default search.
255 GROUP_ENFORCE_ALWAYS_WITH_DSE
,
256 // Also enforce extension settings and default search.
257 GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE
,
258 // The default enforcement group contains all protection features.
259 GROUP_ENFORCE_DEFAULT
262 SettingsEnforcementGroup
GetSettingsEnforcementGroup() {
264 if (!g_disable_domain_check_for_testing
) {
265 static bool first_call
= true;
266 static const bool is_enrolled_to_domain
= base::win::IsEnrolledToDomain();
268 UMA_HISTOGRAM_BOOLEAN("Settings.TrackedPreferencesNoEnforcementOnDomain",
269 is_enrolled_to_domain
);
272 if (is_enrolled_to_domain
)
273 return GROUP_NO_ENFORCEMENT
;
278 const char* group_name
;
279 SettingsEnforcementGroup group
;
280 } static const kEnforcementLevelMap
[] = {
281 { chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement
,
282 GROUP_NO_ENFORCEMENT
},
283 { chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways
,
284 GROUP_ENFORCE_ALWAYS
},
285 { chrome_prefs::internals::
286 kSettingsEnforcementGroupEnforceAlwaysWithDSE
,
287 GROUP_ENFORCE_ALWAYS_WITH_DSE
},
288 { chrome_prefs::internals::
289 kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE
,
290 GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE
},
293 // Use the strongest enforcement setting in the absence of a field trial
294 // config on Windows. Remember to update the OFFICIAL_BUILD section of
295 // extension_startup_browsertest.cc and pref_hash_browsertest.cc when updating
296 // the default value below.
297 // TODO(gab): Enforce this on all platforms.
298 SettingsEnforcementGroup enforcement_group
=
300 GROUP_ENFORCE_DEFAULT
;
302 GROUP_NO_ENFORCEMENT
;
304 bool group_determined_from_trial
= false;
305 base::FieldTrial
* trial
=
306 base::FieldTrialList::Find(
307 chrome_prefs::internals::kSettingsEnforcementTrialName
);
309 const std::string
& group_name
= trial
->group_name();
310 for (size_t i
= 0; i
< arraysize(kEnforcementLevelMap
); ++i
) {
311 if (kEnforcementLevelMap
[i
].group_name
== group_name
) {
312 enforcement_group
= kEnforcementLevelMap
[i
].group
;
313 group_determined_from_trial
= true;
318 UMA_HISTOGRAM_BOOLEAN("Settings.EnforcementGroupDeterminedFromTrial",
319 group_determined_from_trial
);
320 return enforcement_group
;
323 // Returns the effective preference tracking configuration.
324 std::vector
<PrefHashFilter::TrackedPreferenceMetadata
>
325 GetTrackingConfiguration() {
326 const SettingsEnforcementGroup enforcement_group
=
327 GetSettingsEnforcementGroup();
329 std::vector
<PrefHashFilter::TrackedPreferenceMetadata
> result
;
330 for (size_t i
= 0; i
< arraysize(kTrackedPrefs
); ++i
) {
331 PrefHashFilter::TrackedPreferenceMetadata data
= kTrackedPrefs
[i
];
333 if (GROUP_NO_ENFORCEMENT
== enforcement_group
) {
334 // Remove enforcement for all tracked preferences.
335 data
.enforcement_level
= PrefHashFilter::NO_ENFORCEMENT
;
338 if (enforcement_group
>= GROUP_ENFORCE_ALWAYS_WITH_DSE
&&
339 data
.name
== DefaultSearchManager::kDefaultSearchProviderDataPrefName
) {
340 // Specifically enable default search settings enforcement.
341 data
.enforcement_level
= PrefHashFilter::ENFORCE_ON_LOAD
;
344 #if defined(ENABLE_EXTENSIONS)
345 if (enforcement_group
>= GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE
&&
346 data
.name
== extensions::pref_names::kExtensions
) {
347 // Specifically enable extension settings enforcement.
348 data
.enforcement_level
= PrefHashFilter::ENFORCE_ON_LOAD
;
352 result
.push_back(data
);
357 // Shows notifications which correspond to PersistentPrefStore's reading errors.
358 void HandleReadError(PersistentPrefStore::PrefReadError error
) {
359 // Sample the histogram also for the successful case in order to get a
360 // baseline on the success rate in addition to the error distribution.
361 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error
,
362 PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM
);
364 if (error
!= PersistentPrefStore::PREF_READ_ERROR_NONE
) {
365 #if !defined(OS_CHROMEOS)
366 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
367 // an example problem that this can cause.
368 // Do some diagnosis and try to avoid losing data.
370 if (error
<= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE
) {
371 message_id
= IDS_PREFERENCES_CORRUPT_ERROR
;
372 } else if (error
!= PersistentPrefStore::PREF_READ_ERROR_NO_FILE
) {
373 message_id
= IDS_PREFERENCES_UNREADABLE_ERROR
;
377 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
378 base::Bind(&ShowProfileErrorDialog
,
379 PROFILE_ERROR_PREFERENCES
,
383 // On ChromeOS error screen with message about broken local state
384 // will be displayed.
386 // A supplementary error message about broken local state - is included
387 // in logs and user feedbacks.
388 if (error
!= PersistentPrefStore::PREF_READ_ERROR_NONE
&&
389 error
!= PersistentPrefStore::PREF_READ_ERROR_NO_FILE
) {
390 LOG(ERROR
) << "An error happened during prefs loading: " << error
;
396 scoped_ptr
<ProfilePrefStoreManager
> CreateProfilePrefStoreManager(
397 const base::FilePath
& profile_path
) {
398 std::string device_id
;
399 #if defined(OS_WIN) && defined(ENABLE_RLZ)
401 // chrome/browser/extensions/api/music_manager_private/device_id_win.cc
402 // but that API is private (http://crbug.com/276485) and other platforms are
403 // not available synchronously.
404 // As part of improving pref metrics on other platforms we may want to find
405 // ways to defer preference loading until the device ID can be used.
406 rlz_lib::GetMachineId(&device_id
);
409 #if defined(GOOGLE_CHROME_BUILD)
410 seed
= ResourceBundle::GetSharedInstance().GetRawDataResource(
411 IDR_PREF_HASH_SEED_BIN
).as_string();
413 return make_scoped_ptr(new ProfilePrefStoreManager(
415 GetTrackingConfiguration(),
416 kTrackedPrefsReportingIDsCount
,
419 g_browser_process
->local_state()));
423 syncable_prefs::PrefServiceSyncableFactory
* factory
,
424 policy::PolicyService
* policy_service
,
425 SupervisedUserSettingsService
* supervised_user_settings
,
426 scoped_refptr
<PersistentPrefStore
> user_pref_store
,
427 const scoped_refptr
<PrefStore
>& extension_prefs
,
429 #if defined(ENABLE_CONFIGURATION_POLICY)
430 policy::BrowserPolicyConnector
* policy_connector
=
431 g_browser_process
->browser_policy_connector();
432 factory
->SetManagedPolicies(policy_service
, policy_connector
);
433 factory
->SetRecommendedPolicies(policy_service
, policy_connector
);
434 #endif // ENABLE_CONFIGURATION_POLICY
436 #if defined(ENABLE_SUPERVISED_USERS)
437 if (supervised_user_settings
) {
438 scoped_refptr
<PrefStore
> supervised_user_prefs
= make_scoped_refptr(
439 new SupervisedUserPrefStore(supervised_user_settings
));
440 // TODO(bauerb): Temporary CHECK while investigating
441 // https://crbug.com/425785. Remove when that bug is fixed.
442 CHECK(async
|| supervised_user_prefs
->IsInitializationComplete());
443 factory
->set_supervised_user_prefs(supervised_user_prefs
);
447 factory
->set_async(async
);
448 factory
->set_extension_prefs(extension_prefs
);
449 factory
->set_command_line_prefs(make_scoped_refptr(
450 new CommandLinePrefStore(base::CommandLine::ForCurrentProcess())));
451 factory
->set_read_error_callback(base::Bind(&HandleReadError
));
452 factory
->set_user_prefs(user_pref_store
);
453 factory
->SetPrefModelAssociatorClient(
454 ChromePrefModelAssociatorClient::GetInstance());
459 namespace chrome_prefs
{
461 namespace internals
{
463 // Group modifications should be reflected in first_run_browsertest.cc and
464 // pref_hash_browsertest.cc.
465 const char kSettingsEnforcementTrialName
[] = "SettingsEnforcement";
466 const char kSettingsEnforcementGroupNoEnforcement
[] = "no_enforcement";
467 const char kSettingsEnforcementGroupEnforceAlways
[] = "enforce_always";
468 const char kSettingsEnforcementGroupEnforceAlwaysWithDSE
[] =
469 "enforce_always_with_dse";
470 const char kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE
[] =
471 "enforce_always_with_extensions_and_dse";
473 } // namespace internals
475 scoped_ptr
<PrefService
> CreateLocalState(
476 const base::FilePath
& pref_filename
,
477 base::SequencedTaskRunner
* pref_io_task_runner
,
478 policy::PolicyService
* policy_service
,
479 const scoped_refptr
<PrefRegistry
>& pref_registry
,
481 syncable_prefs::PrefServiceSyncableFactory factory
;
485 NULL
, // supervised_user_settings
487 pref_filename
, pref_io_task_runner
, scoped_ptr
<PrefFilter
>()),
488 NULL
, // extension_prefs
490 return factory
.Create(pref_registry
.get());
493 scoped_ptr
<syncable_prefs::PrefServiceSyncable
> CreateProfilePrefs(
494 const base::FilePath
& profile_path
,
495 base::SequencedTaskRunner
* pref_io_task_runner
,
496 TrackedPreferenceValidationDelegate
* validation_delegate
,
497 policy::PolicyService
* policy_service
,
498 SupervisedUserSettingsService
* supervised_user_settings
,
499 const scoped_refptr
<PrefStore
>& extension_prefs
,
500 const scoped_refptr
<user_prefs::PrefRegistrySyncable
>& pref_registry
,
502 TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
503 SCOPED_UMA_HISTOGRAM_TIMER("PrefService.CreateProfilePrefsTime");
505 // A StartSyncFlare used to kick sync early in case of a reset event. This is
506 // done since sync may bring back the user's server value post-reset which
507 // could potentially cause a "settings flash" between the factory default and
508 // the re-instantiated server value. Starting sync ASAP minimizes the window
509 // before the server value is re-instantiated (this window can otherwise be
510 // as long as 10 seconds by default).
511 const base::Closure start_sync_flare_for_prefs
=
512 base::Bind(sync_start_util::GetFlareForSyncableService(profile_path
),
513 syncer::PREFERENCES
);
515 syncable_prefs::PrefServiceSyncableFactory factory
;
516 scoped_refptr
<PersistentPrefStore
> user_pref_store(
517 CreateProfilePrefStoreManager(profile_path
)
518 ->CreateProfilePrefStore(pref_io_task_runner
,
519 start_sync_flare_for_prefs
,
520 validation_delegate
));
521 PrepareFactory(&factory
,
523 supervised_user_settings
,
527 scoped_ptr
<syncable_prefs::PrefServiceSyncable
> pref_service
=
528 factory
.CreateSyncable(pref_registry
.get());
530 ConfigureDefaultSearchPrefMigrationToDictionaryValue(pref_service
.get());
532 return pref_service
.Pass();
535 void SchedulePrefsFilePathVerification(const base::FilePath
& profile_path
) {
537 // Only do prefs file verification on Windows.
538 const int kVerifyPrefsFileDelaySeconds
= 60;
539 BrowserThread::GetBlockingPool()->PostDelayedTask(
541 base::Bind(&VerifyPreferencesFile
,
542 ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
544 base::TimeDelta::FromSeconds(kVerifyPrefsFileDelaySeconds
));
548 void DisableDomainCheckForTesting() {
550 g_disable_domain_check_for_testing
= true;
554 bool InitializePrefsFromMasterPrefs(
555 const base::FilePath
& profile_path
,
556 const base::DictionaryValue
& master_prefs
) {
557 return CreateProfilePrefStoreManager(profile_path
)
558 ->InitializePrefsFromMasterPrefs(master_prefs
);
561 base::Time
GetResetTime(Profile
* profile
) {
562 return ProfilePrefStoreManager::GetResetTime(profile
->GetPrefs());
565 void ClearResetTime(Profile
* profile
) {
566 ProfilePrefStoreManager::ClearResetTime(profile
->GetPrefs());
569 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable
* registry
) {
570 ProfilePrefStoreManager::RegisterProfilePrefs(registry
);
573 void RegisterPrefs(PrefRegistrySimple
* registry
) {
574 ProfilePrefStoreManager::RegisterPrefs(registry
);
577 } // namespace chrome_prefs