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 <stddef.h>
8 
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/bind.h"
14 #include "base/compiler_specific.h"
15 #include "base/files/file_path.h"
16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/stl_util.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/time/time.h"
21 #include "base/trace_event/trace_event.h"
22 #include "build/branding_buildflags.h"
23 #include "build/build_config.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
26 #include "chrome/browser/prefs/chrome_command_line_pref_store.h"
27 #include "chrome/browser/prefs/chrome_pref_model_associator_client.h"
28 #include "chrome/browser/prefs/profile_pref_store_manager.h"
29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/browser/sync/glue/sync_start_util.h"
31 #include "chrome/browser/ui/profile_error_dialog.h"
32 #include "chrome/common/buildflags.h"
33 #include "chrome/common/chrome_constants.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/grit/browser_resources.h"
36 #include "chrome/grit/chromium_strings.h"
37 #include "chrome/grit/generated_resources.h"
38 #include "components/component_updater/pref_names.h"
39 #include "components/policy/core/browser/configuration_policy_pref_store.h"
40 #include "components/pref_registry/pref_registry_syncable.h"
41 #include "components/prefs/default_pref_store.h"
42 #include "components/prefs/json_pref_store.h"
43 #include "components/prefs/pref_filter.h"
44 #include "components/prefs/pref_notifier_impl.h"
45 #include "components/prefs/pref_registry.h"
46 #include "components/prefs/pref_registry_simple.h"
47 #include "components/prefs/pref_service.h"
48 #include "components/prefs/pref_store.h"
49 #include "components/prefs/pref_value_store.h"
50 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
51 #include "components/search_engines/default_search_manager.h"
52 #include "components/search_engines/search_engines_pref_names.h"
53 #include "components/signin/public/base/signin_pref_names.h"
54 #include "components/sync/base/model_type.h"
55 #include "components/sync/base/pref_names.h"
56 #include "components/sync_preferences/pref_model_associator.h"
57 #include "components/sync_preferences/pref_service_syncable.h"
58 #include "components/sync_preferences/pref_service_syncable_factory.h"
59 #include "content/public/browser/browser_context.h"
60 #include "content/public/browser/browser_thread.h"
61 #include "extensions/buildflags/buildflags.h"
62 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
63 #include "rlz/buildflags/buildflags.h"
64 #include "services/preferences/public/cpp/tracked/configuration.h"
65 #include "services/preferences/public/cpp/tracked/pref_names.h"
66 #include "sql/error_delegate_util.h"
67 #include "ui/base/resource/resource_bundle.h"
68 
69 #if BUILDFLAG(ENABLE_EXTENSIONS)
70 #include "extensions/browser/pref_names.h"
71 #endif
72 
73 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
74 #include "chrome/browser/supervised_user/supervised_user_pref_store.h"
75 #endif
76 
77 #if defined(OS_WIN)
78 #include "base/enterprise_util.h"
79 #if BUILDFLAG(ENABLE_RLZ)
80 #include "rlz/lib/machine_id.h"
81 #endif  // BUILDFLAG(ENABLE_RLZ)
82 #endif  // defined(OS_WIN)
83 
84 using content::BrowserContext;
85 using content::BrowserThread;
86 
87 using EnforcementLevel =
88     prefs::mojom::TrackedPreferenceMetadata::EnforcementLevel;
89 using PrefTrackingStrategy =
90     prefs::mojom::TrackedPreferenceMetadata::PrefTrackingStrategy;
91 using ValueType = prefs::mojom::TrackedPreferenceMetadata::ValueType;
92 
93 namespace {
94 
95 #if defined(OS_WIN)
96 // Whether we are in testing mode; can be enabled via
97 // DisableDomainCheckForTesting(). Forces startup checks to ignore the presence
98 // of a domain when determining the active SettingsEnforcement group.
99 bool g_disable_domain_check_for_testing = false;
100 #endif  // OS_WIN
101 
102 // These preferences must be kept in sync with the TrackedPreference enum in
103 // tools/metrics/histograms/enums.xml. To add a new preference, append it to the
104 // array and add a corresponding value to the histogram enum. Each tracked
105 // preference must be given a unique reporting ID.
106 // See CleanupDeprecatedTrackedPreferences() in pref_hash_filter.cc to remove a
107 // deprecated tracked preference.
108 const prefs::TrackedPreferenceMetadata kTrackedPrefs[] = {
109     {0, prefs::kShowHomeButton, EnforcementLevel::ENFORCE_ON_LOAD,
110      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
111     {1, prefs::kHomePageIsNewTabPage, EnforcementLevel::ENFORCE_ON_LOAD,
112      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
113     {2, prefs::kHomePage, EnforcementLevel::ENFORCE_ON_LOAD,
114      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
115     {3, prefs::kRestoreOnStartup, EnforcementLevel::ENFORCE_ON_LOAD,
116      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
117     {4, prefs::kURLsToRestoreOnStartup, EnforcementLevel::ENFORCE_ON_LOAD,
118      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
119 #if BUILDFLAG(ENABLE_EXTENSIONS)
120     {5, extensions::pref_names::kExtensions, EnforcementLevel::NO_ENFORCEMENT,
121      PrefTrackingStrategy::SPLIT, ValueType::IMPERSONAL},
122 #endif
123     {6, prefs::kGoogleServicesLastUsername, EnforcementLevel::ENFORCE_ON_LOAD,
124      PrefTrackingStrategy::ATOMIC, ValueType::PERSONAL},
125     {7, prefs::kSearchProviderOverrides, EnforcementLevel::ENFORCE_ON_LOAD,
126      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
127 #if !defined(OS_ANDROID)
128     {11, prefs::kPinnedTabs, EnforcementLevel::ENFORCE_ON_LOAD,
129      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
130 #endif
131     {14, DefaultSearchManager::kDefaultSearchProviderDataPrefName,
132      EnforcementLevel::NO_ENFORCEMENT, PrefTrackingStrategy::ATOMIC,
133      ValueType::IMPERSONAL},
134     {// Protecting kPreferenceResetTime does two things:
135      //  1) It ensures this isn't accidently set by someone stomping the pref
136      //     file.
137      //  2) More importantly, it declares kPreferenceResetTime as a protected
138      //     pref which is required for it to be visible when queried via the
139      //     SegregatedPrefStore. This is because it's written directly in the
140      //     protected JsonPrefStore by that store's PrefHashFilter if there was
141      //     a reset in FilterOnLoad and SegregatedPrefStore will not look for it
142      //     in the protected JsonPrefStore unless it's declared as a protected
143      //     preference here.
144      15, user_prefs::kPreferenceResetTime, EnforcementLevel::ENFORCE_ON_LOAD,
145      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
146     // kSyncRemainingRollbackTries is deprecated and will be removed a few
147     // releases after M50.
148     {18, prefs::kSafeBrowsingIncidentsSent, EnforcementLevel::ENFORCE_ON_LOAD,
149      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
150 #if defined(OS_WIN)
151     {19, prefs::kSwReporterPromptVersion, EnforcementLevel::ENFORCE_ON_LOAD,
152      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
153 #endif
154 #if defined(OS_WIN)
155     {22, prefs::kSwReporterPromptSeed, EnforcementLevel::ENFORCE_ON_LOAD,
156      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
157 #endif
158     {23, prefs::kGoogleServicesAccountId, EnforcementLevel::ENFORCE_ON_LOAD,
159      PrefTrackingStrategy::ATOMIC, ValueType::PERSONAL},
160     {24, prefs::kGoogleServicesLastAccountId, EnforcementLevel::ENFORCE_ON_LOAD,
161      PrefTrackingStrategy::ATOMIC, ValueType::PERSONAL},
162 #if defined(OS_WIN)
163     {25, prefs::kSettingsResetPromptPromptWave,
164      EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
165      ValueType::IMPERSONAL},
166     {26, prefs::kSettingsResetPromptLastTriggeredForDefaultSearch,
167      EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
168      ValueType::IMPERSONAL},
169     {27, prefs::kSettingsResetPromptLastTriggeredForStartupUrls,
170      EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
171      ValueType::IMPERSONAL},
172     {28, prefs::kSettingsResetPromptLastTriggeredForHomepage,
173      EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
174      ValueType::IMPERSONAL},
175 #endif  // defined(OS_WIN)
176     {29, prefs::kMediaStorageIdSalt, EnforcementLevel::ENFORCE_ON_LOAD,
177      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
178 #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
179     {30, prefs::kModuleBlacklistCacheMD5Digest,
180      EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
181      ValueType::IMPERSONAL},
182 #endif
183 #if defined(OS_WIN)
184     {31, prefs::kSwReporterReportingEnabled, EnforcementLevel::ENFORCE_ON_LOAD,
185      PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
186 #endif  // defined(OS_WIN)
187 
188     // See note at top, new items added here also need to be added to
189     // histograms.xml's TrackedPreference enum.
190 };
191 
192 // One more than the last tracked preferences ID above.
193 const size_t kTrackedPrefsReportingIDsCount =
194     kTrackedPrefs[base::size(kTrackedPrefs) - 1].reporting_id + 1;
195 
196 // Each group enforces a superset of the protection provided by the previous
197 // one.
198 enum SettingsEnforcementGroup {
199   GROUP_NO_ENFORCEMENT,
200   // Enforce protected settings on profile loads.
201   GROUP_ENFORCE_ALWAYS,
202   // Also enforce extension default search.
203   GROUP_ENFORCE_ALWAYS_WITH_DSE,
204   // Also enforce extension settings and default search.
205   GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE,
206   // The default enforcement group contains all protection features.
207   GROUP_ENFORCE_DEFAULT
208 };
209 
GetSettingsEnforcementGroup()210 SettingsEnforcementGroup GetSettingsEnforcementGroup() {
211 # if defined(OS_WIN)
212   if (!g_disable_domain_check_for_testing) {
213     static bool first_call = true;
214     static const bool is_managed = base::IsMachineExternallyManaged();
215     if (first_call) {
216       UMA_HISTOGRAM_BOOLEAN("Settings.TrackedPreferencesNoEnforcementOnDomain",
217                             is_managed);
218       first_call = false;
219     }
220     if (is_managed)
221       return GROUP_NO_ENFORCEMENT;
222   }
223 #endif
224 
225   struct {
226     const char* group_name;
227     SettingsEnforcementGroup group;
228   } static const kEnforcementLevelMap[] = {
229     { chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
230       GROUP_NO_ENFORCEMENT },
231     { chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
232       GROUP_ENFORCE_ALWAYS },
233     { chrome_prefs::internals::
234           kSettingsEnforcementGroupEnforceAlwaysWithDSE,
235       GROUP_ENFORCE_ALWAYS_WITH_DSE },
236     { chrome_prefs::internals::
237           kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE,
238       GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE },
239   };
240 
241   // Use the strongest enforcement setting in the absence of a field trial
242   // config on Windows and MacOS. Remember to update the OFFICIAL_BUILD section
243   // of extension_startup_browsertest.cc and pref_hash_browsertest.cc when
244   // updating the default value below.
245   // TODO(gab): Enforce this on all platforms.
246   SettingsEnforcementGroup enforcement_group =
247 #if defined(OS_WIN) || defined(OS_MACOSX)
248       GROUP_ENFORCE_DEFAULT;
249 #else
250       GROUP_NO_ENFORCEMENT;
251 #endif
252   bool group_determined_from_trial = false;
253   base::FieldTrial* trial =
254       base::FieldTrialList::Find(
255           chrome_prefs::internals::kSettingsEnforcementTrialName);
256   if (trial) {
257     const std::string& group_name = trial->group_name();
258     for (size_t i = 0; i < base::size(kEnforcementLevelMap); ++i) {
259       if (kEnforcementLevelMap[i].group_name == group_name) {
260         enforcement_group = kEnforcementLevelMap[i].group;
261         group_determined_from_trial = true;
262         break;
263       }
264     }
265   }
266   UMA_HISTOGRAM_BOOLEAN("Settings.EnforcementGroupDeterminedFromTrial",
267                         group_determined_from_trial);
268   return enforcement_group;
269 }
270 
271 // Returns the effective preference tracking configuration.
272 std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
GetTrackingConfiguration()273 GetTrackingConfiguration() {
274   const SettingsEnforcementGroup enforcement_group =
275       GetSettingsEnforcementGroup();
276 
277   std::vector<prefs::mojom::TrackedPreferenceMetadataPtr> result;
278   for (size_t i = 0; i < base::size(kTrackedPrefs); ++i) {
279     prefs::mojom::TrackedPreferenceMetadataPtr data =
280         prefs::ConstructTrackedMetadata(kTrackedPrefs[i]);
281 
282     if (GROUP_NO_ENFORCEMENT == enforcement_group) {
283       // Remove enforcement for all tracked preferences.
284       data->enforcement_level = EnforcementLevel::NO_ENFORCEMENT;
285     }
286 
287     if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_DSE &&
288         data->name ==
289             DefaultSearchManager::kDefaultSearchProviderDataPrefName) {
290       // Specifically enable default search settings enforcement.
291       data->enforcement_level = EnforcementLevel::ENFORCE_ON_LOAD;
292     }
293 
294 #if BUILDFLAG(ENABLE_EXTENSIONS)
295     if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE &&
296         data->name == extensions::pref_names::kExtensions) {
297       // Specifically enable extension settings enforcement.
298       data->enforcement_level = EnforcementLevel::ENFORCE_ON_LOAD;
299     }
300 #endif
301 
302     result.push_back(std::move(data));
303   }
304   return result;
305 }
306 
CreateProfilePrefStoreManager(const base::FilePath & profile_path)307 std::unique_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager(
308     const base::FilePath& profile_path) {
309   std::string legacy_device_id;
310 #if defined(OS_WIN) && BUILDFLAG(ENABLE_RLZ)
311   // This is used by
312   // chrome/browser/apps/platform_apps/api/music_manager_private/device_id_win.cc
313   // but that API is private (http://crbug.com/276485) and other platforms are
314   // not available synchronously.
315   // As part of improving pref metrics on other platforms we may want to find
316   // ways to defer preference loading until the device ID can be used.
317   rlz_lib::GetMachineId(&legacy_device_id);
318 #endif
319   std::string seed;
320   CHECK(ui::ResourceBundle::HasSharedInstance());
321 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
322   seed = ui::ResourceBundle::GetSharedInstance()
323              .GetRawDataResource(IDR_PREF_HASH_SEED_BIN)
324              .as_string();
325 #endif
326   return std::make_unique<ProfilePrefStoreManager>(profile_path, seed,
327                                                    legacy_device_id);
328 }
329 
PrepareFactory(sync_preferences::PrefServiceSyncableFactory * factory,const base::FilePath & pref_filename,policy::PolicyService * policy_service,SupervisedUserSettingsService * supervised_user_settings,scoped_refptr<PersistentPrefStore> user_pref_store,scoped_refptr<PrefStore> extension_prefs,bool async,policy::BrowserPolicyConnector * policy_connector)330 void PrepareFactory(sync_preferences::PrefServiceSyncableFactory* factory,
331                     const base::FilePath& pref_filename,
332                     policy::PolicyService* policy_service,
333                     SupervisedUserSettingsService* supervised_user_settings,
334                     scoped_refptr<PersistentPrefStore> user_pref_store,
335                     scoped_refptr<PrefStore> extension_prefs,
336                     bool async,
337                     policy::BrowserPolicyConnector* policy_connector) {
338   factory->SetManagedPolicies(policy_service, policy_connector);
339   factory->SetRecommendedPolicies(policy_service, policy_connector);
340 
341 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
342   if (supervised_user_settings) {
343     scoped_refptr<PrefStore> supervised_user_prefs =
344         base::MakeRefCounted<SupervisedUserPrefStore>(supervised_user_settings);
345     DCHECK(async || supervised_user_prefs->IsInitializationComplete());
346     factory->set_supervised_user_prefs(supervised_user_prefs);
347   }
348 #endif
349 
350   factory->set_async(async);
351   factory->set_extension_prefs(std::move(extension_prefs));
352   factory->set_command_line_prefs(
353       base::MakeRefCounted<ChromeCommandLinePrefStore>(
354           base::CommandLine::ForCurrentProcess()));
355   factory->set_read_error_callback(base::BindRepeating(
356       &chrome_prefs::HandlePersistentPrefStoreReadError, pref_filename));
357   factory->set_user_prefs(std::move(user_pref_store));
358   factory->SetPrefModelAssociatorClient(
359       ChromePrefModelAssociatorClient::GetInstance());
360 }
361 
362 class ResetOnLoadObserverImpl : public prefs::mojom::ResetOnLoadObserver {
363  public:
ResetOnLoadObserverImpl(const base::FilePath & profile_path)364   explicit ResetOnLoadObserverImpl(const base::FilePath& profile_path)
365       : profile_path_(profile_path) {}
366 
OnResetOnLoad()367   void OnResetOnLoad() override {
368     // A StartSyncFlare used to kick sync early in case of a reset event. This
369     // is done since sync may bring back the user's server value post-reset
370     // which could potentially cause a "settings flash" between the factory
371     // default and the re-instantiated server value. Starting sync ASAP
372     // minimizes the window before the server value is re-instantiated (this
373     // window can otherwise be as long as 10 seconds by default).
374     sync_start_util::GetFlareForSyncableService(profile_path_)
375         .Run(syncer::PREFERENCES);
376   }
377 
378  private:
379   const base::FilePath profile_path_;
380 
381   DISALLOW_COPY_AND_ASSIGN(ResetOnLoadObserverImpl);
382 };
383 
384 }  // namespace
385 
386 namespace chrome_prefs {
387 
388 namespace internals {
389 
390 // Group modifications should be reflected in first_run_browsertest.cc and
391 // pref_hash_browsertest.cc.
392 const char kSettingsEnforcementTrialName[] = "SettingsEnforcement";
393 const char kSettingsEnforcementGroupNoEnforcement[] = "no_enforcement";
394 const char kSettingsEnforcementGroupEnforceAlways[] = "enforce_always";
395 const char kSettingsEnforcementGroupEnforceAlwaysWithDSE[] =
396     "enforce_always_with_dse";
397 const char kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE[] =
398     "enforce_always_with_extensions_and_dse";
399 
400 }  // namespace internals
401 
CreateLocalState(const base::FilePath & pref_filename,policy::PolicyService * policy_service,scoped_refptr<PrefRegistry> pref_registry,bool async,policy::BrowserPolicyConnector * policy_connector)402 std::unique_ptr<PrefService> CreateLocalState(
403     const base::FilePath& pref_filename,
404     policy::PolicyService* policy_service,
405     scoped_refptr<PrefRegistry> pref_registry,
406     bool async,
407     policy::BrowserPolicyConnector* policy_connector) {
408   sync_preferences::PrefServiceSyncableFactory factory;
409   PrepareFactory(&factory, pref_filename, policy_service,
410                  nullptr,  // supervised_user_settings
411                  base::MakeRefCounted<JsonPrefStore>(
412                      pref_filename, std::unique_ptr<PrefFilter>()),
413                  nullptr,  // extension_prefs
414                  async, policy_connector);
415 
416   return factory.Create(std::move(pref_registry));
417 }
418 
CreateProfilePrefs(const base::FilePath & profile_path,mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate> validation_delegate,policy::PolicyService * policy_service,SupervisedUserSettingsService * supervised_user_settings,scoped_refptr<PrefStore> extension_prefs,scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,policy::BrowserPolicyConnector * connector,bool async,scoped_refptr<base::SequencedTaskRunner> io_task_runner)419 std::unique_ptr<sync_preferences::PrefServiceSyncable> CreateProfilePrefs(
420     const base::FilePath& profile_path,
421     mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
422         validation_delegate,
423     policy::PolicyService* policy_service,
424     SupervisedUserSettingsService* supervised_user_settings,
425     scoped_refptr<PrefStore> extension_prefs,
426     scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,
427     policy::BrowserPolicyConnector* connector,
428     bool async,
429     scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
430   TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
431 
432   mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver> reset_on_load_observer;
433   mojo::MakeSelfOwnedReceiver(
434       std::make_unique<ResetOnLoadObserverImpl>(profile_path),
435       reset_on_load_observer.InitWithNewPipeAndPassReceiver());
436   sync_preferences::PrefServiceSyncableFactory factory;
437   scoped_refptr<PersistentPrefStore> user_pref_store =
438       CreateProfilePrefStoreManager(profile_path)
439           ->CreateProfilePrefStore(
440               GetTrackingConfiguration(), kTrackedPrefsReportingIDsCount,
441               std::move(io_task_runner), std::move(reset_on_load_observer),
442               std::move(validation_delegate));
443   PrepareFactory(&factory, profile_path, policy_service,
444                  supervised_user_settings, std::move(user_pref_store),
445                  std::move(extension_prefs), async, connector);
446   return factory.CreateSyncable(std::move(pref_registry));
447 }
448 
DisableDomainCheckForTesting()449 void DisableDomainCheckForTesting() {
450 #if defined(OS_WIN)
451   g_disable_domain_check_for_testing = true;
452 #endif  // OS_WIN
453 }
454 
InitializePrefsFromMasterPrefs(const base::FilePath & profile_path,std::unique_ptr<base::DictionaryValue> master_prefs)455 bool InitializePrefsFromMasterPrefs(
456     const base::FilePath& profile_path,
457     std::unique_ptr<base::DictionaryValue> master_prefs) {
458   return CreateProfilePrefStoreManager(profile_path)
459       ->InitializePrefsFromMasterPrefs(GetTrackingConfiguration(),
460                                        kTrackedPrefsReportingIDsCount,
461                                        std::move(master_prefs));
462 }
463 
GetResetTime(Profile * profile)464 base::Time GetResetTime(Profile* profile) {
465   return ProfilePrefStoreManager::GetResetTime(profile->GetPrefs());
466 }
467 
ClearResetTime(Profile * profile)468 void ClearResetTime(Profile* profile) {
469   ProfilePrefStoreManager::ClearResetTime(profile->GetPrefs());
470 }
471 
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)472 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
473   ProfilePrefStoreManager::RegisterProfilePrefs(registry);
474 }
475 
HandlePersistentPrefStoreReadError(const base::FilePath & pref_filename,PersistentPrefStore::PrefReadError error)476 void HandlePersistentPrefStoreReadError(
477     const base::FilePath& pref_filename,
478     PersistentPrefStore::PrefReadError error) {
479   // The error callback is always invoked back on the main thread (which is
480   // BrowserThread::UI unless called during early initialization before the main
481   // thread is promoted to BrowserThread::UI).
482   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
483          !BrowserThread::IsThreadInitialized(BrowserThread::UI));
484 
485   // Sample the histogram also for the successful case in order to get a
486   // baseline on the success rate in addition to the error distribution.
487   UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error,
488                             PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
489 
490   if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
491 #if !defined(OS_CHROMEOS)
492     // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
493     // an example problem that this can cause.
494     // Do some diagnosis and try to avoid losing data.
495     int message_id = 0;
496     if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
497       message_id = IDS_PREFERENCES_CORRUPT_ERROR;
498     } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
499       message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
500     }
501 
502     if (message_id) {
503       // Note: ThreadTaskRunnerHandle() is usually BrowserThread::UI but during
504       // early startup it can be ChromeBrowserMainParts::DeferringTaskRunner
505       // which will forward to BrowserThread::UI when it's initialized.
506       base::ThreadTaskRunnerHandle::Get()->PostTask(
507           FROM_HERE,
508           base::BindOnce(&ShowProfileErrorDialog, ProfileErrorType::PREFERENCES,
509                          message_id,
510                          sql::GetCorruptFileDiagnosticsInfo(pref_filename)));
511     }
512 #else
513     // On ChromeOS error screen with message about broken local state
514     // will be displayed.
515 
516     // A supplementary error message about broken local state - is included
517     // in logs and user feedbacks.
518     if (error != PersistentPrefStore::PREF_READ_ERROR_NONE &&
519         error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
520       LOG(ERROR) << "An error happened during prefs loading: " << error;
521     }
522 #endif
523   }
524 }
525 
526 }  // namespace chrome_prefs
527