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"
8 #include "base/debug/trace_event.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/metrics/histogram.h"
13 #include "base/prefs/default_pref_store.h"
14 #include "base/prefs/json_pref_store.h"
15 #include "base/prefs/pref_notifier_impl.h"
16 #include "base/prefs/pref_registry.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/prefs/pref_value_store.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/prefs/command_line_pref_store.h"
21 #include "chrome/browser/prefs/pref_hash_filter.h"
22 #include "chrome/browser/prefs/pref_hash_store.h"
23 #include "chrome/browser/prefs/pref_model_associator.h"
24 #include "chrome/browser/prefs/pref_service_syncable.h"
25 #include "chrome/browser/prefs/pref_service_syncable_factory.h"
26 #include "chrome/browser/ui/profile_error_dialog.h"
27 #include "chrome/common/pref_names.h"
28 #include "components/user_prefs/pref_registry_syncable.h"
29 #include "content/public/browser/browser_context.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "extensions/browser/pref_names.h"
32 #include "grit/chromium_strings.h"
33 #include "grit/generated_resources.h"
35 #if defined(ENABLE_CONFIGURATION_POLICY)
36 #include "chrome/browser/policy/browser_policy_connector.h"
37 #include "components/policy/core/browser/configuration_policy_pref_store.h"
38 #include "components/policy/core/common/policy_types.h"
41 #if defined(ENABLE_MANAGED_USERS)
42 #include "chrome/browser/managed_mode/supervised_user_pref_store.h"
45 using content::BrowserContext
;
46 using content::BrowserThread
;
50 // These preferences must be kept in sync with the TrackedPreference enum in
51 // tools/metrics/histograms/histograms.xml. To add a new preference, append it
52 // to the array and add a corresponding value to the histogram enum. Each
53 // tracked preference must be given a unique reporting ID.
54 const PrefHashFilter::TrackedPreference kTrackedPrefs
[] = {
55 { 0, prefs::kShowHomeButton
, true },
56 { 1, prefs::kHomePageIsNewTabPage
, true },
57 { 2, prefs::kHomePage
, true },
58 { 3, prefs::kRestoreOnStartup
, true },
59 { 4, prefs::kURLsToRestoreOnStartup
, true },
60 { 5, extensions::pref_names::kExtensions
, false },
61 { 6, prefs::kGoogleServicesLastUsername
, true },
62 { 7, prefs::kSearchProviderOverrides
, true },
63 { 8, prefs::kDefaultSearchProviderSearchURL
, true },
64 { 9, prefs::kDefaultSearchProviderKeyword
, true },
65 { 10, prefs::kDefaultSearchProviderName
, true },
66 #if !defined(OS_ANDROID)
67 { 11, prefs::kPinnedTabs
, true },
69 { 12, extensions::pref_names::kKnownDisabled
, true },
70 { 13, prefs::kProfileResetPromptMemento
, true },
73 // The count of tracked preferences IDs across all platforms.
74 const size_t kTrackedPrefsReportingIDsCount
= 14;
75 COMPILE_ASSERT(kTrackedPrefsReportingIDsCount
>= arraysize(kTrackedPrefs
),
76 need_to_increment_ids_count
);
78 PrefHashFilter::EnforcementLevel
GetSettingsEnforcementLevel() {
79 static const char kSettingsEnforcementExperiment
[] = "SettingsEnforcement";
81 const char* level_name
;
82 PrefHashFilter::EnforcementLevel level
;
83 } static const kEnforcementLevelMap
[] = {
86 PrefHashFilter::NO_ENFORCEMENT
90 PrefHashFilter::ENFORCE
94 PrefHashFilter::ENFORCE_NO_SEEDING
97 "enforce_no_seeding_no_migration",
98 PrefHashFilter::ENFORCE_NO_SEEDING_NO_MIGRATION
102 base::FieldTrial
* trial
=
103 base::FieldTrialList::Find(kSettingsEnforcementExperiment
);
105 const std::string
& group_name
= trial
->group_name();
106 // ARRAYSIZE_UNSAFE must be used since the array is declared locally; it is
107 // only unsafe because it could not trigger a compile error on some
108 // non-array pointer types; this is fine since kEnforcementLevelMap is
110 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kEnforcementLevelMap
); ++i
) {
111 if (kEnforcementLevelMap
[i
].level_name
== group_name
)
112 return kEnforcementLevelMap
[i
].level
;
115 // TODO(gab): Switch default to ENFORCE_ALL when the field trial config is up.
116 return PrefHashFilter::NO_ENFORCEMENT
;
119 // Shows notifications which correspond to PersistentPrefStore's reading errors.
120 void HandleReadError(PersistentPrefStore::PrefReadError error
) {
121 // Sample the histogram also for the successful case in order to get a
122 // baseline on the success rate in addition to the error distribution.
123 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error
,
124 PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM
);
126 if (error
!= PersistentPrefStore::PREF_READ_ERROR_NONE
) {
127 #if !defined(OS_CHROMEOS)
128 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
129 // an example problem that this can cause.
130 // Do some diagnosis and try to avoid losing data.
132 if (error
<= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE
) {
133 message_id
= IDS_PREFERENCES_CORRUPT_ERROR
;
134 } else if (error
!= PersistentPrefStore::PREF_READ_ERROR_NO_FILE
) {
135 message_id
= IDS_PREFERENCES_UNREADABLE_ERROR
;
139 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
140 base::Bind(&ShowProfileErrorDialog
,
141 PROFILE_ERROR_PREFERENCES
,
145 // On ChromeOS error screen with message about broken local state
146 // will be displayed.
152 PrefServiceSyncableFactory
* factory
,
153 const base::FilePath
& pref_filename
,
154 base::SequencedTaskRunner
* pref_io_task_runner
,
155 policy::PolicyService
* policy_service
,
156 ManagedUserSettingsService
* managed_user_settings
,
157 scoped_ptr
<PrefHashStore
> pref_hash_store
,
158 const scoped_refptr
<PrefStore
>& extension_prefs
,
160 #if defined(OS_LINUX)
161 // We'd like to see what fraction of our users have the preferences
162 // stored on a network file system, as we've had no end of troubles
164 // TODO(evanm): remove this once we've collected state.
165 file_util::FileSystemType fstype
;
166 if (file_util::GetFileSystemType(pref_filename
.DirName(), &fstype
)) {
167 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
168 static_cast<int>(fstype
),
169 file_util::FILE_SYSTEM_TYPE_COUNT
);
173 #if defined(ENABLE_CONFIGURATION_POLICY)
174 using policy::ConfigurationPolicyPrefStore
;
175 factory
->set_managed_prefs(
176 make_scoped_refptr(new ConfigurationPolicyPrefStore(
178 g_browser_process
->browser_policy_connector()->GetHandlerList(),
179 policy::POLICY_LEVEL_MANDATORY
)));
180 factory
->set_recommended_prefs(
181 make_scoped_refptr(new ConfigurationPolicyPrefStore(
183 g_browser_process
->browser_policy_connector()->GetHandlerList(),
184 policy::POLICY_LEVEL_RECOMMENDED
)));
185 #endif // ENABLE_CONFIGURATION_POLICY
187 #if defined(ENABLE_MANAGED_USERS)
188 if (managed_user_settings
) {
189 factory
->set_supervised_user_prefs(
190 make_scoped_refptr(new SupervisedUserPrefStore(managed_user_settings
)));
194 factory
->set_async(async
);
195 factory
->set_extension_prefs(extension_prefs
);
196 factory
->set_command_line_prefs(
198 new CommandLinePrefStore(CommandLine::ForCurrentProcess())));
199 factory
->set_read_error_callback(base::Bind(&HandleReadError
));
200 scoped_ptr
<PrefFilter
> pref_filter
;
201 if (pref_hash_store
) {
202 pref_filter
.reset(new PrefHashFilter(pref_hash_store
.Pass(),
204 arraysize(kTrackedPrefs
),
205 kTrackedPrefsReportingIDsCount
,
206 GetSettingsEnforcementLevel()));
208 factory
->set_user_prefs(
212 pref_filter
.Pass()));
217 namespace chrome_prefs
{
219 scoped_ptr
<PrefService
> CreateLocalState(
220 const base::FilePath
& pref_filename
,
221 base::SequencedTaskRunner
* pref_io_task_runner
,
222 policy::PolicyService
* policy_service
,
223 const scoped_refptr
<PrefRegistry
>& pref_registry
,
225 PrefServiceSyncableFactory factory
;
226 PrepareBuilder(&factory
,
231 scoped_ptr
<PrefHashStore
>(),
234 return factory
.Create(pref_registry
.get());
237 scoped_ptr
<PrefServiceSyncable
> CreateProfilePrefs(
238 const base::FilePath
& pref_filename
,
239 base::SequencedTaskRunner
* pref_io_task_runner
,
240 policy::PolicyService
* policy_service
,
241 ManagedUserSettingsService
* managed_user_settings
,
242 scoped_ptr
<PrefHashStore
> pref_hash_store
,
243 const scoped_refptr
<PrefStore
>& extension_prefs
,
244 const scoped_refptr
<user_prefs::PrefRegistrySyncable
>& pref_registry
,
246 TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
247 PrefServiceSyncableFactory factory
;
248 PrepareBuilder(&factory
,
252 managed_user_settings
,
253 pref_hash_store
.Pass(),
256 return factory
.CreateSyncable(pref_registry
.get());
259 } // namespace chrome_prefs