• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
6 
7 #include <string>
8 #include <vector>
9 
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/command_line_pref_store.h"
29 #include "chrome/browser/prefs/pref_hash_filter.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/profiles/file_path_verifier_win.h"
35 #include "chrome/browser/profiles/profile.h"
36 #include "chrome/browser/search_engines/default_search_manager.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 "components/pref_registry/pref_registry_syncable.h"
43 #include "components/sync_driver/pref_names.h"
44 #include "content/public/browser/browser_context.h"
45 #include "content/public/browser/browser_thread.h"
46 #include "extensions/browser/pref_names.h"
47 #include "grit/browser_resources.h"
48 #include "grit/chromium_strings.h"
49 #include "grit/generated_resources.h"
50 #include "sync/internal_api/public/base/model_type.h"
51 #include "ui/base/resource/resource_bundle.h"
52 
53 #if defined(ENABLE_CONFIGURATION_POLICY)
54 #include "components/policy/core/browser/browser_policy_connector.h"
55 #include "components/policy/core/browser/configuration_policy_pref_store.h"
56 #include "components/policy/core/common/policy_types.h"
57 #endif
58 
59 #if defined(ENABLE_MANAGED_USERS)
60 #include "chrome/browser/supervised_user/supervised_user_pref_store.h"
61 #endif
62 
63 #if defined(OS_WIN)
64 #include "base/win/win_util.h"
65 #if defined(ENABLE_RLZ)
66 #include "rlz/lib/machine_id.h"
67 #endif  // defined(ENABLE_RLZ)
68 #endif  // defined(OS_WIN)
69 
70 using content::BrowserContext;
71 using content::BrowserThread;
72 
73 namespace {
74 
75 // Whether we are in testing mode; can be enabled via
76 // DisableDelaysAndDomainCheckForTesting(). Forces startup checks to occur
77 // with no delay and ignores the presence of a domain when determining the
78 // active SettingsEnforcement group.
79 bool g_disable_delays_and_domain_check_for_testing = false;
80 
81 // These preferences must be kept in sync with the TrackedPreference enum in
82 // tools/metrics/histograms/histograms.xml. To add a new preference, append it
83 // to the array and add a corresponding value to the histogram enum. Each
84 // tracked preference must be given a unique reporting ID.
85 const PrefHashFilter::TrackedPreferenceMetadata kTrackedPrefs[] = {
86   {
87     0, prefs::kShowHomeButton,
88     PrefHashFilter::ENFORCE_ON_LOAD,
89     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
90   },
91   {
92     1, prefs::kHomePageIsNewTabPage,
93     PrefHashFilter::ENFORCE_ON_LOAD,
94     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
95   },
96   {
97     2, prefs::kHomePage,
98     PrefHashFilter::ENFORCE_ON_LOAD,
99     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
100   },
101   {
102     3, prefs::kRestoreOnStartup,
103     PrefHashFilter::ENFORCE_ON_LOAD,
104     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
105   },
106   {
107     4, prefs::kURLsToRestoreOnStartup,
108     PrefHashFilter::ENFORCE_ON_LOAD,
109     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
110   },
111   {
112     5, extensions::pref_names::kExtensions,
113     PrefHashFilter::NO_ENFORCEMENT,
114     PrefHashFilter::TRACKING_STRATEGY_SPLIT
115   },
116   {
117     6, prefs::kGoogleServicesLastUsername,
118     PrefHashFilter::ENFORCE_ON_LOAD,
119     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
120   },
121   {
122     7, prefs::kSearchProviderOverrides,
123     PrefHashFilter::ENFORCE_ON_LOAD,
124     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
125   },
126   {
127     8, prefs::kDefaultSearchProviderSearchURL,
128     PrefHashFilter::ENFORCE_ON_LOAD,
129     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
130   },
131   {
132     9, prefs::kDefaultSearchProviderKeyword,
133     PrefHashFilter::ENFORCE_ON_LOAD,
134     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
135   },
136   {
137     10, prefs::kDefaultSearchProviderName,
138     PrefHashFilter::ENFORCE_ON_LOAD,
139     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
140   },
141 #if !defined(OS_ANDROID)
142   {
143     11, prefs::kPinnedTabs,
144     PrefHashFilter::ENFORCE_ON_LOAD,
145     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
146   },
147 #endif
148   {
149     12, extensions::pref_names::kKnownDisabled,
150     PrefHashFilter::NO_ENFORCEMENT,
151     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
152   },
153   {
154     13, prefs::kProfileResetPromptMemento,
155     PrefHashFilter::ENFORCE_ON_LOAD,
156     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
157   },
158   {
159     14, DefaultSearchManager::kDefaultSearchProviderDataPrefName,
160     PrefHashFilter::NO_ENFORCEMENT,
161     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
162   },
163   {
164     // Protecting kPreferenceResetTime does two things:
165     //  1) It ensures this isn't accidently set by someone stomping the pref
166     //     file.
167     //  2) More importantly, it declares kPreferenceResetTime as a protected
168     //     pref which is required for it to be visible when queried via the
169     //     SegregatedPrefStore. This is because it's written directly in the
170     //     protected JsonPrefStore by that store's PrefHashFilter if there was
171     //     a reset in FilterOnLoad and SegregatedPrefStore will not look for it
172     //     in the protected JsonPrefStore unless it's declared as a protected
173     //     preference here.
174     15, prefs::kPreferenceResetTime,
175     PrefHashFilter::ENFORCE_ON_LOAD,
176     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
177   },
178   {
179     16, prefs::kSafeBrowsingIncidentReportSent,
180     PrefHashFilter::ENFORCE_ON_LOAD,
181     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
182   },
183   {
184     17, sync_driver::prefs::kSyncRemainingRollbackTries,
185     PrefHashFilter::ENFORCE_ON_LOAD,
186     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
187   },
188 };
189 
190 // The count of tracked preferences IDs across all platforms.
191 const size_t kTrackedPrefsReportingIDsCount = 18;
192 COMPILE_ASSERT(kTrackedPrefsReportingIDsCount >= arraysize(kTrackedPrefs),
193                need_to_increment_ids_count);
194 
195 // Each group enforces a superset of the protection provided by the previous
196 // one.
197 enum SettingsEnforcementGroup {
198   GROUP_NO_ENFORCEMENT,
199   // Enforce protected settings on profile loads.
200   GROUP_ENFORCE_ALWAYS,
201   // Also enforce extension default search.
202   GROUP_ENFORCE_ALWAYS_WITH_DSE,
203   // Also enforce extension settings and default search.
204   GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE,
205   // The default enforcement group contains all protection features.
206   GROUP_ENFORCE_DEFAULT
207 };
208 
GetSettingsEnforcementGroup()209 SettingsEnforcementGroup GetSettingsEnforcementGroup() {
210 # if defined(OS_WIN)
211   if (!g_disable_delays_and_domain_check_for_testing) {
212     static bool first_call = true;
213     static const bool is_enrolled_to_domain = base::win::IsEnrolledToDomain();
214     if (first_call) {
215       UMA_HISTOGRAM_BOOLEAN("Settings.TrackedPreferencesNoEnforcementOnDomain",
216                             is_enrolled_to_domain);
217       first_call = false;
218     }
219     if (is_enrolled_to_domain)
220       return GROUP_NO_ENFORCEMENT;
221   }
222 #endif
223 
224   struct {
225     const char* group_name;
226     SettingsEnforcementGroup group;
227   } static const kEnforcementLevelMap[] = {
228     { chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
229       GROUP_NO_ENFORCEMENT },
230     { chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
231       GROUP_ENFORCE_ALWAYS },
232     { chrome_prefs::internals::
233           kSettingsEnforcementGroupEnforceAlwaysWithDSE,
234       GROUP_ENFORCE_ALWAYS_WITH_DSE },
235     { chrome_prefs::internals::
236           kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE,
237       GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE },
238   };
239 
240   // Use the strongest enforcement setting in the absence of a field trial
241   // config on Windows. Remember to update the OFFICIAL_BUILD section of
242   // extension_startup_browsertest.cc when updating the default value below.
243   // TODO(gab): Enforce this on all platforms.
244   SettingsEnforcementGroup enforcement_group =
245 #if defined(OS_WIN)
246       GROUP_ENFORCE_DEFAULT;
247 #else
248       GROUP_NO_ENFORCEMENT;
249 #endif
250   bool group_determined_from_trial = false;
251   base::FieldTrial* trial =
252       base::FieldTrialList::Find(
253           chrome_prefs::internals::kSettingsEnforcementTrialName);
254   if (trial) {
255     const std::string& group_name = trial->group_name();
256     // ARRAYSIZE_UNSAFE must be used since the array is declared locally; it is
257     // only unsafe because it could not trigger a compile error on some
258     // non-array pointer types; this is fine since kEnforcementLevelMap is
259     // clearly an array.
260     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kEnforcementLevelMap); ++i) {
261       if (kEnforcementLevelMap[i].group_name == group_name) {
262         enforcement_group = kEnforcementLevelMap[i].group;
263         group_determined_from_trial = true;
264         break;
265       }
266     }
267   }
268   UMA_HISTOGRAM_BOOLEAN("Settings.EnforcementGroupDeterminedFromTrial",
269                         group_determined_from_trial);
270   return enforcement_group;
271 }
272 
273 // Returns the effective preference tracking configuration.
274 std::vector<PrefHashFilter::TrackedPreferenceMetadata>
GetTrackingConfiguration()275 GetTrackingConfiguration() {
276   const SettingsEnforcementGroup enforcement_group =
277       GetSettingsEnforcementGroup();
278 
279   std::vector<PrefHashFilter::TrackedPreferenceMetadata> result;
280   for (size_t i = 0; i < arraysize(kTrackedPrefs); ++i) {
281     PrefHashFilter::TrackedPreferenceMetadata data = kTrackedPrefs[i];
282 
283     if (GROUP_NO_ENFORCEMENT == enforcement_group) {
284       // Remove enforcement for all tracked preferences.
285       data.enforcement_level = PrefHashFilter::NO_ENFORCEMENT;
286     }
287 
288     if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_DSE &&
289         data.name == DefaultSearchManager::kDefaultSearchProviderDataPrefName) {
290       // Specifically enable default search settings enforcement.
291       data.enforcement_level = PrefHashFilter::ENFORCE_ON_LOAD;
292     }
293 
294     if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE &&
295         (data.name == extensions::pref_names::kExtensions ||
296          data.name == extensions::pref_names::kKnownDisabled)) {
297       // Specifically enable extension settings enforcement and ensure
298       // kKnownDisabled follows it in the Protected Preferences.
299       // TODO(gab): Get rid of kKnownDisabled altogether.
300       data.enforcement_level = PrefHashFilter::ENFORCE_ON_LOAD;
301     }
302 
303     result.push_back(data);
304   }
305   return result;
306 }
307 
308 
309 // Shows notifications which correspond to PersistentPrefStore's reading errors.
HandleReadError(PersistentPrefStore::PrefReadError error)310 void HandleReadError(PersistentPrefStore::PrefReadError error) {
311   // Sample the histogram also for the successful case in order to get a
312   // baseline on the success rate in addition to the error distribution.
313   UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error,
314                             PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
315 
316   if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
317 #if !defined(OS_CHROMEOS)
318     // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
319     // an example problem that this can cause.
320     // Do some diagnosis and try to avoid losing data.
321     int message_id = 0;
322     if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE ||
323         error == PersistentPrefStore::PREF_READ_ERROR_LEVELDB_CORRUPTION) {
324       message_id = IDS_PREFERENCES_CORRUPT_ERROR;
325     } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
326       message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
327     }
328 
329     if (message_id) {
330       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
331                               base::Bind(&ShowProfileErrorDialog,
332                                          PROFILE_ERROR_PREFERENCES,
333                                          message_id));
334     }
335 #else
336     // On ChromeOS error screen with message about broken local state
337     // will be displayed.
338 #endif
339   }
340 }
341 
CreateProfilePrefStoreManager(const base::FilePath & profile_path)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   return make_scoped_ptr(new ProfilePrefStoreManager(
355       profile_path,
356       GetTrackingConfiguration(),
357       kTrackedPrefsReportingIDsCount,
358       ResourceBundle::GetSharedInstance()
359           .GetRawDataResource(IDR_PREF_HASH_SEED_BIN)
360           .as_string(),
361       device_id,
362       g_browser_process->local_state()));
363 }
364 
PrepareFactory(PrefServiceSyncableFactory * factory,policy::PolicyService * policy_service,SupervisedUserSettingsService * supervised_user_settings,scoped_refptr<PersistentPrefStore> user_pref_store,const scoped_refptr<PrefStore> & extension_prefs,bool async)365 void PrepareFactory(
366     PrefServiceSyncableFactory* factory,
367     policy::PolicyService* policy_service,
368     SupervisedUserSettingsService* supervised_user_settings,
369     scoped_refptr<PersistentPrefStore> user_pref_store,
370     const scoped_refptr<PrefStore>& extension_prefs,
371     bool async) {
372 #if defined(ENABLE_CONFIGURATION_POLICY)
373   using policy::ConfigurationPolicyPrefStore;
374   factory->set_managed_prefs(
375       make_scoped_refptr(new ConfigurationPolicyPrefStore(
376           policy_service,
377           g_browser_process->browser_policy_connector()->GetHandlerList(),
378           policy::POLICY_LEVEL_MANDATORY)));
379   factory->set_recommended_prefs(
380       make_scoped_refptr(new ConfigurationPolicyPrefStore(
381           policy_service,
382           g_browser_process->browser_policy_connector()->GetHandlerList(),
383           policy::POLICY_LEVEL_RECOMMENDED)));
384 #endif  // ENABLE_CONFIGURATION_POLICY
385 
386 #if defined(ENABLE_MANAGED_USERS)
387   if (supervised_user_settings) {
388     factory->set_supervised_user_prefs(
389         make_scoped_refptr(
390             new SupervisedUserPrefStore(supervised_user_settings)));
391   }
392 #endif
393 
394   factory->set_async(async);
395   factory->set_extension_prefs(extension_prefs);
396   factory->set_command_line_prefs(
397       make_scoped_refptr(
398           new CommandLinePrefStore(CommandLine::ForCurrentProcess())));
399   factory->set_read_error_callback(base::Bind(&HandleReadError));
400   factory->set_user_prefs(user_pref_store);
401 }
402 
403 }  // namespace
404 
405 namespace chrome_prefs {
406 
407 namespace internals {
408 
409 const char kSettingsEnforcementTrialName[] = "SettingsEnforcement";
410 const char kSettingsEnforcementGroupNoEnforcement[] = "no_enforcement";
411 const char kSettingsEnforcementGroupEnforceAlways[] = "enforce_always";
412 const char kSettingsEnforcementGroupEnforceAlwaysWithDSE[] =
413     "enforce_always_with_dse";
414 const char kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE[] =
415     "enforce_always_with_extensions_and_dse";
416 
417 }  // namespace internals
418 
CreateLocalState(const base::FilePath & pref_filename,base::SequencedTaskRunner * pref_io_task_runner,policy::PolicyService * policy_service,const scoped_refptr<PrefRegistry> & pref_registry,bool async)419 scoped_ptr<PrefService> CreateLocalState(
420     const base::FilePath& pref_filename,
421     base::SequencedTaskRunner* pref_io_task_runner,
422     policy::PolicyService* policy_service,
423     const scoped_refptr<PrefRegistry>& pref_registry,
424     bool async) {
425   PrefServiceSyncableFactory factory;
426   PrepareFactory(
427       &factory,
428       policy_service,
429       NULL,  // supervised_user_settings
430       new JsonPrefStore(
431           pref_filename, pref_io_task_runner, scoped_ptr<PrefFilter>()),
432       NULL,  // extension_prefs
433       async);
434   return factory.Create(pref_registry.get());
435 }
436 
CreateProfilePrefs(const base::FilePath & profile_path,base::SequencedTaskRunner * pref_io_task_runner,TrackedPreferenceValidationDelegate * validation_delegate,policy::PolicyService * policy_service,SupervisedUserSettingsService * supervised_user_settings,const scoped_refptr<PrefStore> & extension_prefs,const scoped_refptr<user_prefs::PrefRegistrySyncable> & pref_registry,bool async)437 scoped_ptr<PrefServiceSyncable> CreateProfilePrefs(
438     const base::FilePath& profile_path,
439     base::SequencedTaskRunner* pref_io_task_runner,
440     TrackedPreferenceValidationDelegate* validation_delegate,
441     policy::PolicyService* policy_service,
442     SupervisedUserSettingsService* supervised_user_settings,
443     const scoped_refptr<PrefStore>& extension_prefs,
444     const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry,
445     bool async) {
446   TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
447 
448   // A StartSyncFlare used to kick sync early in case of a reset event. This is
449   // done since sync may bring back the user's server value post-reset which
450   // could potentially cause a "settings flash" between the factory default and
451   // the re-instantiated server value. Starting sync ASAP minimizes the window
452   // before the server value is re-instantiated (this window can otherwise be
453   // as long as 10 seconds by default).
454   const base::Closure start_sync_flare_for_prefs =
455       base::Bind(sync_start_util::GetFlareForSyncableService(profile_path),
456                  syncer::PREFERENCES);
457 
458   PrefServiceSyncableFactory factory;
459   PrepareFactory(&factory,
460                  policy_service,
461                  supervised_user_settings,
462                  scoped_refptr<PersistentPrefStore>(
463                      CreateProfilePrefStoreManager(profile_path)
464                          ->CreateProfilePrefStore(pref_io_task_runner,
465                                                   start_sync_flare_for_prefs,
466                                                   validation_delegate)),
467                  extension_prefs,
468                  async);
469   scoped_ptr<PrefServiceSyncable> pref_service =
470       factory.CreateSyncable(pref_registry.get());
471 
472   ConfigureDefaultSearchPrefMigrationToDictionaryValue(pref_service.get());
473 
474   return pref_service.Pass();
475 }
476 
SchedulePrefsFilePathVerification(const base::FilePath & profile_path)477 void SchedulePrefsFilePathVerification(const base::FilePath& profile_path) {
478 #if defined(OS_WIN)
479   // Only do prefs file verification on Windows.
480   const int kVerifyPrefsFileDelaySeconds = 60;
481   BrowserThread::GetBlockingPool()->PostDelayedTask(
482       FROM_HERE,
483       base::Bind(&VerifyPreferencesFile,
484                  ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
485                      profile_path)),
486       base::TimeDelta::FromSeconds(g_disable_delays_and_domain_check_for_testing
487                                        ? 0
488                                        : kVerifyPrefsFileDelaySeconds));
489 #endif
490 }
491 
DisableDelaysAndDomainCheckForTesting()492 void DisableDelaysAndDomainCheckForTesting() {
493   g_disable_delays_and_domain_check_for_testing = true;
494 }
495 
InitializePrefsFromMasterPrefs(const base::FilePath & profile_path,const base::DictionaryValue & master_prefs)496 bool InitializePrefsFromMasterPrefs(
497     const base::FilePath& profile_path,
498     const base::DictionaryValue& master_prefs) {
499   return CreateProfilePrefStoreManager(profile_path)
500       ->InitializePrefsFromMasterPrefs(master_prefs);
501 }
502 
GetResetTime(Profile * profile)503 base::Time GetResetTime(Profile* profile) {
504   return ProfilePrefStoreManager::GetResetTime(profile->GetPrefs());
505 }
506 
ClearResetTime(Profile * profile)507 void ClearResetTime(Profile* profile) {
508   ProfilePrefStoreManager::ClearResetTime(profile->GetPrefs());
509 }
510 
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)511 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
512   ProfilePrefStoreManager::RegisterProfilePrefs(registry);
513 }
514 
RegisterPrefs(PrefRegistrySimple * registry)515 void RegisterPrefs(PrefRegistrySimple* registry) {
516   ProfilePrefStoreManager::RegisterPrefs(registry);
517 }
518 
519 }  // namespace chrome_prefs
520