Add GCMChannelStatusSyncer to schedule requests and enable/disable GCM
[chromium-blink-merge.git] / chrome / browser / prefs / chrome_pref_service_factory.cc
blob733491a0f74fd71c6e28c009366a90e3e1debb3d
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_hash_filter.h"
31 #include "chrome/browser/prefs/pref_model_associator.h"
32 #include "chrome/browser/prefs/pref_service_syncable.h"
33 #include "chrome/browser/prefs/pref_service_syncable_factory.h"
34 #include "chrome/browser/prefs/profile_pref_store_manager.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/pref_registry/pref_registry_syncable.h"
45 #include "components/search_engines/default_search_manager.h"
46 #include "components/search_engines/search_engines_pref_names.h"
47 #include "components/sync_driver/pref_names.h"
48 #include "content/public/browser/browser_context.h"
49 #include "content/public/browser/browser_thread.h"
50 #include "grit/browser_resources.h"
51 #include "sync/internal_api/public/base/model_type.h"
52 #include "ui/base/resource/resource_bundle.h"
54 #if defined(ENABLE_CONFIGURATION_POLICY)
55 #include "components/policy/core/browser/browser_policy_connector.h"
56 #include "components/policy/core/browser/configuration_policy_pref_store.h"
57 #include "components/policy/core/common/policy_types.h"
58 #endif
60 #if defined(ENABLE_EXTENSIONS)
61 #include "extensions/browser/pref_names.h"
62 #endif
64 #if defined(ENABLE_MANAGED_USERS)
65 #include "chrome/browser/supervised_user/supervised_user_pref_store.h"
66 #endif
68 #if defined(OS_WIN)
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;
78 namespace {
80 // Whether we are in testing mode; can be enabled via
81 // DisableDelaysAndDomainCheckForTesting(). Forces startup checks to occur
82 // with no delay and ignores the presence of a domain when determining the
83 // active SettingsEnforcement group.
84 bool g_disable_delays_and_domain_check_for_testing = false;
86 // These preferences must be kept in sync with the TrackedPreference enum in
87 // tools/metrics/histograms/histograms.xml. To add a new preference, append it
88 // to the array and add a corresponding value to the histogram enum. Each
89 // tracked preference must be given a unique reporting ID.
90 // See CleanupDeprecatedTrackedPreferences() in pref_hash_filter.cc to remove a
91 // deprecated tracked preference.
92 const PrefHashFilter::TrackedPreferenceMetadata kTrackedPrefs[] = {
94 0, prefs::kShowHomeButton,
95 PrefHashFilter::ENFORCE_ON_LOAD,
96 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
99 1, prefs::kHomePageIsNewTabPage,
100 PrefHashFilter::ENFORCE_ON_LOAD,
101 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
104 2, prefs::kHomePage,
105 PrefHashFilter::ENFORCE_ON_LOAD,
106 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
109 3, prefs::kRestoreOnStartup,
110 PrefHashFilter::ENFORCE_ON_LOAD,
111 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
114 4, prefs::kURLsToRestoreOnStartup,
115 PrefHashFilter::ENFORCE_ON_LOAD,
116 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
118 #if defined(ENABLE_EXTENSIONS)
120 5, extensions::pref_names::kExtensions,
121 PrefHashFilter::NO_ENFORCEMENT,
122 PrefHashFilter::TRACKING_STRATEGY_SPLIT
124 #endif
126 6, prefs::kGoogleServicesLastUsername,
127 PrefHashFilter::ENFORCE_ON_LOAD,
128 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
131 7, prefs::kSearchProviderOverrides,
132 PrefHashFilter::ENFORCE_ON_LOAD,
133 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
136 8, prefs::kDefaultSearchProviderSearchURL,
137 PrefHashFilter::ENFORCE_ON_LOAD,
138 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
141 9, prefs::kDefaultSearchProviderKeyword,
142 PrefHashFilter::ENFORCE_ON_LOAD,
143 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
146 10, prefs::kDefaultSearchProviderName,
147 PrefHashFilter::ENFORCE_ON_LOAD,
148 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
150 #if !defined(OS_ANDROID)
152 11, prefs::kPinnedTabs,
153 PrefHashFilter::ENFORCE_ON_LOAD,
154 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
157 13, prefs::kProfileResetPromptMementoInProfilePrefs,
158 PrefHashFilter::ENFORCE_ON_LOAD,
159 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
161 #endif
163 14, DefaultSearchManager::kDefaultSearchProviderDataPrefName,
164 PrefHashFilter::NO_ENFORCEMENT,
165 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
168 // Protecting kPreferenceResetTime does two things:
169 // 1) It ensures this isn't accidently set by someone stomping the pref
170 // file.
171 // 2) More importantly, it declares kPreferenceResetTime as a protected
172 // pref which is required for it to be visible when queried via the
173 // SegregatedPrefStore. This is because it's written directly in the
174 // protected JsonPrefStore by that store's PrefHashFilter if there was
175 // a reset in FilterOnLoad and SegregatedPrefStore will not look for it
176 // in the protected JsonPrefStore unless it's declared as a protected
177 // preference here.
178 15, prefs::kPreferenceResetTime,
179 PrefHashFilter::ENFORCE_ON_LOAD,
180 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
183 16, prefs::kSafeBrowsingIncidentReportSent,
184 PrefHashFilter::ENFORCE_ON_LOAD,
185 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
188 17, sync_driver::prefs::kSyncRemainingRollbackTries,
189 PrefHashFilter::ENFORCE_ON_LOAD,
190 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
193 18, prefs::kSafeBrowsingIncidentsSent,
194 PrefHashFilter::ENFORCE_ON_LOAD,
195 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
199 // One more than the last tracked preferences ID above.
200 const size_t kTrackedPrefsReportingIDsCount =
201 kTrackedPrefs[arraysize(kTrackedPrefs) - 1].reporting_id + 1;
203 // Each group enforces a superset of the protection provided by the previous
204 // one.
205 enum SettingsEnforcementGroup {
206 GROUP_NO_ENFORCEMENT,
207 // Enforce protected settings on profile loads.
208 GROUP_ENFORCE_ALWAYS,
209 // Also enforce extension default search.
210 GROUP_ENFORCE_ALWAYS_WITH_DSE,
211 // Also enforce extension settings and default search.
212 GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE,
213 // The default enforcement group contains all protection features.
214 GROUP_ENFORCE_DEFAULT
217 SettingsEnforcementGroup GetSettingsEnforcementGroup() {
218 # if defined(OS_WIN)
219 if (!g_disable_delays_and_domain_check_for_testing) {
220 static bool first_call = true;
221 static const bool is_enrolled_to_domain = base::win::IsEnrolledToDomain();
222 if (first_call) {
223 UMA_HISTOGRAM_BOOLEAN("Settings.TrackedPreferencesNoEnforcementOnDomain",
224 is_enrolled_to_domain);
225 first_call = false;
227 if (is_enrolled_to_domain)
228 return GROUP_NO_ENFORCEMENT;
230 #endif
232 struct {
233 const char* group_name;
234 SettingsEnforcementGroup group;
235 } static const kEnforcementLevelMap[] = {
236 { chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
237 GROUP_NO_ENFORCEMENT },
238 { chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
239 GROUP_ENFORCE_ALWAYS },
240 { chrome_prefs::internals::
241 kSettingsEnforcementGroupEnforceAlwaysWithDSE,
242 GROUP_ENFORCE_ALWAYS_WITH_DSE },
243 { chrome_prefs::internals::
244 kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE,
245 GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE },
248 // Use the strongest enforcement setting in the absence of a field trial
249 // config on Windows. Remember to update the OFFICIAL_BUILD section of
250 // extension_startup_browsertest.cc and pref_hash_browsertest.cc when updating
251 // the default value below.
252 // TODO(gab): Enforce this on all platforms.
253 SettingsEnforcementGroup enforcement_group =
254 #if defined(OS_WIN)
255 GROUP_ENFORCE_DEFAULT;
256 #else
257 GROUP_NO_ENFORCEMENT;
258 #endif
259 bool group_determined_from_trial = false;
260 base::FieldTrial* trial =
261 base::FieldTrialList::Find(
262 chrome_prefs::internals::kSettingsEnforcementTrialName);
263 if (trial) {
264 const std::string& group_name = trial->group_name();
265 // ARRAYSIZE_UNSAFE must be used since the array is declared locally; it is
266 // only unsafe because it could not trigger a compile error on some
267 // non-array pointer types; this is fine since kEnforcementLevelMap is
268 // clearly an array.
269 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kEnforcementLevelMap); ++i) {
270 if (kEnforcementLevelMap[i].group_name == group_name) {
271 enforcement_group = kEnforcementLevelMap[i].group;
272 group_determined_from_trial = true;
273 break;
277 UMA_HISTOGRAM_BOOLEAN("Settings.EnforcementGroupDeterminedFromTrial",
278 group_determined_from_trial);
279 return enforcement_group;
282 // Returns the effective preference tracking configuration.
283 std::vector<PrefHashFilter::TrackedPreferenceMetadata>
284 GetTrackingConfiguration() {
285 const SettingsEnforcementGroup enforcement_group =
286 GetSettingsEnforcementGroup();
288 std::vector<PrefHashFilter::TrackedPreferenceMetadata> result;
289 for (size_t i = 0; i < arraysize(kTrackedPrefs); ++i) {
290 PrefHashFilter::TrackedPreferenceMetadata data = kTrackedPrefs[i];
292 if (GROUP_NO_ENFORCEMENT == enforcement_group) {
293 // Remove enforcement for all tracked preferences.
294 data.enforcement_level = PrefHashFilter::NO_ENFORCEMENT;
297 if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_DSE &&
298 data.name == DefaultSearchManager::kDefaultSearchProviderDataPrefName) {
299 // Specifically enable default search settings enforcement.
300 data.enforcement_level = PrefHashFilter::ENFORCE_ON_LOAD;
303 #if defined(ENABLE_EXTENSIONS)
304 if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE &&
305 data.name == extensions::pref_names::kExtensions) {
306 // Specifically enable extension settings enforcement.
307 data.enforcement_level = PrefHashFilter::ENFORCE_ON_LOAD;
309 #endif
311 result.push_back(data);
313 return result;
316 // Shows notifications which correspond to PersistentPrefStore's reading errors.
317 void HandleReadError(PersistentPrefStore::PrefReadError error) {
318 // Sample the histogram also for the successful case in order to get a
319 // baseline on the success rate in addition to the error distribution.
320 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error,
321 PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
323 if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
324 #if !defined(OS_CHROMEOS)
325 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
326 // an example problem that this can cause.
327 // Do some diagnosis and try to avoid losing data.
328 int message_id = 0;
329 if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE ||
330 error == PersistentPrefStore::PREF_READ_ERROR_LEVELDB_CORRUPTION) {
331 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
332 } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
333 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
336 if (message_id) {
337 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
338 base::Bind(&ShowProfileErrorDialog,
339 PROFILE_ERROR_PREFERENCES,
340 message_id));
342 #else
343 // On ChromeOS error screen with message about broken local state
344 // will be displayed.
346 // A supplementary error message about broken local state - is included
347 // in logs and user feedbacks.
348 if (error != PersistentPrefStore::PREF_READ_ERROR_NONE &&
349 error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
350 LOG(ERROR) << "An error happened during prefs loading: " << error;
352 #endif
356 scoped_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager(
357 const base::FilePath& profile_path) {
358 std::string device_id;
359 #if defined(OS_WIN) && defined(ENABLE_RLZ)
360 // This is used by
361 // chrome/browser/extensions/api/music_manager_private/device_id_win.cc
362 // but that API is private (http://crbug.com/276485) and other platforms are
363 // not available synchronously.
364 // As part of improving pref metrics on other platforms we may want to find
365 // ways to defer preference loading until the device ID can be used.
366 rlz_lib::GetMachineId(&device_id);
367 #endif
368 std::string seed;
369 #if defined(GOOGLE_CHROME_BUILD)
370 seed = ResourceBundle::GetSharedInstance().GetRawDataResource(
371 IDR_PREF_HASH_SEED_BIN).as_string();
372 #endif
373 return make_scoped_ptr(new ProfilePrefStoreManager(
374 profile_path,
375 GetTrackingConfiguration(),
376 kTrackedPrefsReportingIDsCount,
377 seed,
378 device_id,
379 g_browser_process->local_state()));
382 void PrepareFactory(
383 PrefServiceSyncableFactory* factory,
384 policy::PolicyService* policy_service,
385 SupervisedUserSettingsService* supervised_user_settings,
386 scoped_refptr<PersistentPrefStore> user_pref_store,
387 const scoped_refptr<PrefStore>& extension_prefs,
388 bool async) {
389 #if defined(ENABLE_CONFIGURATION_POLICY)
390 using policy::ConfigurationPolicyPrefStore;
391 factory->set_managed_prefs(
392 make_scoped_refptr(new ConfigurationPolicyPrefStore(
393 policy_service,
394 g_browser_process->browser_policy_connector()->GetHandlerList(),
395 policy::POLICY_LEVEL_MANDATORY)));
396 factory->set_recommended_prefs(
397 make_scoped_refptr(new ConfigurationPolicyPrefStore(
398 policy_service,
399 g_browser_process->browser_policy_connector()->GetHandlerList(),
400 policy::POLICY_LEVEL_RECOMMENDED)));
401 #endif // ENABLE_CONFIGURATION_POLICY
403 #if defined(ENABLE_MANAGED_USERS)
404 if (supervised_user_settings) {
405 factory->set_supervised_user_prefs(
406 make_scoped_refptr(
407 new SupervisedUserPrefStore(supervised_user_settings)));
409 #endif
411 factory->set_async(async);
412 factory->set_extension_prefs(extension_prefs);
413 factory->set_command_line_prefs(
414 make_scoped_refptr(
415 new CommandLinePrefStore(CommandLine::ForCurrentProcess())));
416 factory->set_read_error_callback(base::Bind(&HandleReadError));
417 factory->set_user_prefs(user_pref_store);
420 } // namespace
422 namespace chrome_prefs {
424 namespace internals {
426 // Group modifications should be reflected in first_run_browsertest.cc and
427 // pref_hash_browsertest.cc.
428 const char kSettingsEnforcementTrialName[] = "SettingsEnforcement";
429 const char kSettingsEnforcementGroupNoEnforcement[] = "no_enforcement";
430 const char kSettingsEnforcementGroupEnforceAlways[] = "enforce_always";
431 const char kSettingsEnforcementGroupEnforceAlwaysWithDSE[] =
432 "enforce_always_with_dse";
433 const char kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE[] =
434 "enforce_always_with_extensions_and_dse";
436 } // namespace internals
438 scoped_ptr<PrefService> CreateLocalState(
439 const base::FilePath& pref_filename,
440 base::SequencedTaskRunner* pref_io_task_runner,
441 policy::PolicyService* policy_service,
442 const scoped_refptr<PrefRegistry>& pref_registry,
443 bool async) {
444 PrefServiceSyncableFactory factory;
445 PrepareFactory(
446 &factory,
447 policy_service,
448 NULL, // supervised_user_settings
449 new JsonPrefStore(
450 pref_filename, pref_io_task_runner, scoped_ptr<PrefFilter>()),
451 NULL, // extension_prefs
452 async);
453 return factory.Create(pref_registry.get());
456 scoped_ptr<PrefServiceSyncable> CreateProfilePrefs(
457 const base::FilePath& profile_path,
458 base::SequencedTaskRunner* pref_io_task_runner,
459 TrackedPreferenceValidationDelegate* validation_delegate,
460 policy::PolicyService* policy_service,
461 SupervisedUserSettingsService* supervised_user_settings,
462 const scoped_refptr<PrefStore>& extension_prefs,
463 const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry,
464 bool async) {
465 TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
467 // A StartSyncFlare used to kick sync early in case of a reset event. This is
468 // done since sync may bring back the user's server value post-reset which
469 // could potentially cause a "settings flash" between the factory default and
470 // the re-instantiated server value. Starting sync ASAP minimizes the window
471 // before the server value is re-instantiated (this window can otherwise be
472 // as long as 10 seconds by default).
473 const base::Closure start_sync_flare_for_prefs =
474 base::Bind(sync_start_util::GetFlareForSyncableService(profile_path),
475 syncer::PREFERENCES);
477 PrefServiceSyncableFactory factory;
478 scoped_refptr<PersistentPrefStore> user_pref_store(
479 CreateProfilePrefStoreManager(profile_path)
480 ->CreateProfilePrefStore(pref_io_task_runner,
481 start_sync_flare_for_prefs,
482 validation_delegate));
483 // BrowserUIPrefsMigrator unregisters and deletes itself after it is done.
484 user_pref_store->AddObserver(
485 new BrowserUIPrefsMigrator(user_pref_store.get()));
486 PrepareFactory(&factory,
487 policy_service,
488 supervised_user_settings,
489 user_pref_store,
490 extension_prefs,
491 async);
492 scoped_ptr<PrefServiceSyncable> pref_service =
493 factory.CreateSyncable(pref_registry.get());
495 ConfigureDefaultSearchPrefMigrationToDictionaryValue(pref_service.get());
497 return pref_service.Pass();
500 void SchedulePrefsFilePathVerification(const base::FilePath& profile_path) {
501 #if defined(OS_WIN)
502 // Only do prefs file verification on Windows.
503 const int kVerifyPrefsFileDelaySeconds = 60;
504 BrowserThread::GetBlockingPool()->PostDelayedTask(
505 FROM_HERE,
506 base::Bind(&VerifyPreferencesFile,
507 ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
508 profile_path)),
509 base::TimeDelta::FromSeconds(g_disable_delays_and_domain_check_for_testing
511 : kVerifyPrefsFileDelaySeconds));
512 #endif
515 void DisableDelaysAndDomainCheckForTesting() {
516 g_disable_delays_and_domain_check_for_testing = true;
519 bool InitializePrefsFromMasterPrefs(
520 const base::FilePath& profile_path,
521 const base::DictionaryValue& master_prefs) {
522 return CreateProfilePrefStoreManager(profile_path)
523 ->InitializePrefsFromMasterPrefs(master_prefs);
526 base::Time GetResetTime(Profile* profile) {
527 return ProfilePrefStoreManager::GetResetTime(profile->GetPrefs());
530 void ClearResetTime(Profile* profile) {
531 ProfilePrefStoreManager::ClearResetTime(profile->GetPrefs());
534 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
535 ProfilePrefStoreManager::RegisterProfilePrefs(registry);
538 void RegisterPrefs(PrefRegistrySimple* registry) {
539 ProfilePrefStoreManager::RegisterPrefs(registry);
542 } // namespace chrome_prefs