Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prefs / chrome_pref_service_factory.cc
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_info_cache.h"
36 #include "chrome/browser/profiles/profile_manager.h"
37 #include "chrome/browser/ui/profile_error_dialog.h"
38 #include "chrome/common/chrome_constants.h"
39 #include "chrome/common/pref_names.h"
40 #include "components/user_prefs/pref_registry_syncable.h"
41 #include "content/public/browser/browser_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "extensions/browser/pref_names.h"
44 #include "grit/browser_resources.h"
45 #include "grit/chromium_strings.h"
46 #include "grit/generated_resources.h"
47 #include "ui/base/resource/resource_bundle.h"
48
49 #if defined(ENABLE_CONFIGURATION_POLICY)
50 #include "components/policy/core/browser/browser_policy_connector.h"
51 #include "components/policy/core/browser/configuration_policy_pref_store.h"
52 #include "components/policy/core/common/policy_types.h"
53 #endif
54
55 #if defined(ENABLE_MANAGED_USERS)
56 #include "chrome/browser/managed_mode/supervised_user_pref_store.h"
57 #endif
58
59 #if defined(OS_WIN)
60 #include "base/win/win_util.h"
61 #if defined(ENABLE_RLZ)
62 #include "rlz/lib/machine_id.h"
63 #endif  // defined(ENABLE_RLZ)
64 #endif  // defined(OS_WIN)
65
66 using content::BrowserContext;
67 using content::BrowserThread;
68
69 namespace {
70
71 // Whether we are in testing mode; can be enabled via
72 // DisableDelaysAndDomainCheckForTesting(). Forces startup checks to occur
73 // with no delay and ignores the presence of a domain when determining the
74 // active SettingsEnforcement group.
75 bool g_disable_delays_and_domain_check_for_testing = false;
76
77 // These preferences must be kept in sync with the TrackedPreference enum in
78 // tools/metrics/histograms/histograms.xml. To add a new preference, append it
79 // to the array and add a corresponding value to the histogram enum. Each
80 // tracked preference must be given a unique reporting ID.
81 const PrefHashFilter::TrackedPreferenceMetadata kTrackedPrefs[] = {
82   {
83     0, prefs::kShowHomeButton,
84     PrefHashFilter::ENFORCE_ON_LOAD,
85     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
86   },
87   {
88     1, prefs::kHomePageIsNewTabPage,
89     PrefHashFilter::ENFORCE_ON_LOAD,
90     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
91   },
92   {
93     2, prefs::kHomePage,
94     PrefHashFilter::ENFORCE_ON_LOAD,
95     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
96   },
97   {
98     3, prefs::kRestoreOnStartup,
99     PrefHashFilter::ENFORCE_ON_LOAD,
100     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
101   },
102   {
103     4, prefs::kURLsToRestoreOnStartup,
104     PrefHashFilter::ENFORCE_ON_LOAD,
105     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
106   },
107   {
108     5, extensions::pref_names::kExtensions,
109     PrefHashFilter::NO_ENFORCEMENT,
110     PrefHashFilter::TRACKING_STRATEGY_SPLIT
111   },
112   {
113     6, prefs::kGoogleServicesLastUsername,
114     PrefHashFilter::ENFORCE_ON_LOAD,
115     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
116   },
117   {
118     7, prefs::kSearchProviderOverrides,
119     PrefHashFilter::ENFORCE_ON_LOAD,
120     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
121   },
122   {
123     8, prefs::kDefaultSearchProviderSearchURL,
124     PrefHashFilter::ENFORCE_ON_LOAD,
125     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
126   },
127   {
128     9, prefs::kDefaultSearchProviderKeyword,
129     PrefHashFilter::ENFORCE_ON_LOAD,
130     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
131   },
132   {
133     10, prefs::kDefaultSearchProviderName,
134     PrefHashFilter::ENFORCE_ON_LOAD,
135     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
136   },
137 #if !defined(OS_ANDROID)
138   {
139     11, prefs::kPinnedTabs,
140     PrefHashFilter::ENFORCE_ON_LOAD,
141     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
142   },
143 #endif
144   {
145     12, extensions::pref_names::kKnownDisabled,
146     PrefHashFilter::NO_ENFORCEMENT,
147     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
148   },
149   {
150     13, prefs::kProfileResetPromptMemento,
151     PrefHashFilter::ENFORCE_ON_LOAD,
152     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
153   },
154 };
155
156 // The count of tracked preferences IDs across all platforms.
157 const size_t kTrackedPrefsReportingIDsCount = 14;
158 COMPILE_ASSERT(kTrackedPrefsReportingIDsCount >= arraysize(kTrackedPrefs),
159                need_to_increment_ids_count);
160
161 // Each group enforces a superset of the protection provided by the previous
162 // one.
163 enum SettingsEnforcementGroup {
164   GROUP_NO_ENFORCEMENT,
165   // Only enforce settings on profile loads; still allow seeding of unloaded
166   // profiles.
167   GROUP_ENFORCE_ON_LOAD,
168   // Also disallow seeding of unloaded profiles.
169   GROUP_ENFORCE_ALWAYS,
170   // Also enforce extension settings.
171   GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS,
172   // The default enforcement group contains all protection features.
173   GROUP_ENFORCE_DEFAULT
174 };
175
176 SettingsEnforcementGroup GetSettingsEnforcementGroup() {
177 # if defined(OS_WIN)
178   if (!g_disable_delays_and_domain_check_for_testing) {
179     static bool first_call = true;
180     static const bool is_enrolled_to_domain = base::win::IsEnrolledToDomain();
181     if (first_call) {
182       UMA_HISTOGRAM_BOOLEAN("Settings.TrackedPreferencesNoEnforcementOnDomain",
183                             is_enrolled_to_domain);
184       first_call = false;
185     }
186     if (is_enrolled_to_domain)
187       return GROUP_NO_ENFORCEMENT;
188   }
189 #endif
190
191   struct {
192     const char* group_name;
193     SettingsEnforcementGroup group;
194   } static const kEnforcementLevelMap[] = {
195     { chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
196       GROUP_NO_ENFORCEMENT },
197     { chrome_prefs::internals::kSettingsEnforcementGroupEnforceOnload,
198       GROUP_ENFORCE_ON_LOAD },
199     { chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
200       GROUP_ENFORCE_ALWAYS },
201     { chrome_prefs::internals::
202           kSettingsEnforcementGroupEnforceAlwaysWithExtensions,
203       GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS },
204   };
205
206   // Use the strongest enforcement setting in the absence of a field trial
207   // config on Windows. Remember to update the OFFICIAL_BUILD sections of
208   // pref_hash_browsertest.cc and extension_startup_browsertest.cc when updating
209   // the default value below.
210   // TODO(gab): Enforce this on all platforms.
211   SettingsEnforcementGroup enforcement_group =
212 #if defined(OS_WIN)
213       GROUP_ENFORCE_DEFAULT;
214 #else
215       GROUP_NO_ENFORCEMENT;
216 #endif
217   bool group_determined_from_trial = false;
218   base::FieldTrial* trial =
219       base::FieldTrialList::Find(
220           chrome_prefs::internals::kSettingsEnforcementTrialName);
221   if (trial) {
222     const std::string& group_name = trial->group_name();
223     // ARRAYSIZE_UNSAFE must be used since the array is declared locally; it is
224     // only unsafe because it could not trigger a compile error on some
225     // non-array pointer types; this is fine since kEnforcementLevelMap is
226     // clearly an array.
227     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kEnforcementLevelMap); ++i) {
228       if (kEnforcementLevelMap[i].group_name == group_name) {
229         enforcement_group = kEnforcementLevelMap[i].group;
230         group_determined_from_trial = true;
231         break;
232       }
233     }
234   }
235   UMA_HISTOGRAM_BOOLEAN("Settings.EnforcementGroupDeterminedFromTrial",
236                         group_determined_from_trial);
237   return enforcement_group;
238 }
239
240 // Returns the effective preference tracking configuration.
241 std::vector<PrefHashFilter::TrackedPreferenceMetadata>
242 GetTrackingConfiguration() {
243   const SettingsEnforcementGroup enforcement_group =
244       GetSettingsEnforcementGroup();
245
246   std::vector<PrefHashFilter::TrackedPreferenceMetadata> result;
247   for (size_t i = 0; i < arraysize(kTrackedPrefs); ++i) {
248     PrefHashFilter::TrackedPreferenceMetadata data = kTrackedPrefs[i];
249
250     switch (enforcement_group) {
251       case GROUP_NO_ENFORCEMENT:
252         // Remove enforcement for all tracked preferences.
253         data.enforcement_level = PrefHashFilter::NO_ENFORCEMENT;
254         break;
255       case GROUP_ENFORCE_ON_LOAD:  // Falls through.
256       case GROUP_ENFORCE_ALWAYS:
257         // Keep the default enforcement level for this tracked preference.
258         break;
259       case GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS:  // Falls through.
260       case GROUP_ENFORCE_DEFAULT:
261         // Specifically enable extension settings enforcement.
262         if (data.name == extensions::pref_names::kExtensions)
263           data.enforcement_level = PrefHashFilter::ENFORCE_ON_LOAD;
264     }
265
266     result.push_back(data);
267   }
268   return result;
269 }
270
271
272 // Shows notifications which correspond to PersistentPrefStore's reading errors.
273 void HandleReadError(PersistentPrefStore::PrefReadError error) {
274   // Sample the histogram also for the successful case in order to get a
275   // baseline on the success rate in addition to the error distribution.
276   UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error,
277                             PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
278
279   if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
280 #if !defined(OS_CHROMEOS)
281     // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
282     // an example problem that this can cause.
283     // Do some diagnosis and try to avoid losing data.
284     int message_id = 0;
285     if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
286       message_id = IDS_PREFERENCES_CORRUPT_ERROR;
287     } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
288       message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
289     }
290
291     if (message_id) {
292       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
293                               base::Bind(&ShowProfileErrorDialog,
294                                          PROFILE_ERROR_PREFERENCES,
295                                          message_id));
296     }
297 #else
298     // On ChromeOS error screen with message about broken local state
299     // will be displayed.
300 #endif
301   }
302 }
303
304 scoped_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager(
305     const base::FilePath& profile_path) {
306   std::string device_id;
307 #if defined(OS_WIN) && defined(ENABLE_RLZ)
308   // This is used by
309   // chrome/browser/extensions/api/music_manager_private/device_id_win.cc
310   // but that API is private (http://crbug.com/276485) and other platforms are
311   // not available synchronously.
312   // As part of improving pref metrics on other platforms we may want to find
313   // ways to defer preference loading until the device ID can be used.
314   rlz_lib::GetMachineId(&device_id);
315 #endif
316   return make_scoped_ptr(new ProfilePrefStoreManager(
317       profile_path,
318       GetTrackingConfiguration(),
319       kTrackedPrefsReportingIDsCount,
320       ResourceBundle::GetSharedInstance()
321           .GetRawDataResource(IDR_PREF_HASH_SEED_BIN)
322           .as_string(),
323       device_id,
324       g_browser_process->local_state()));
325 }
326
327 void PrepareFactory(
328     PrefServiceSyncableFactory* factory,
329     policy::PolicyService* policy_service,
330     ManagedUserSettingsService* managed_user_settings,
331     scoped_refptr<PersistentPrefStore> user_pref_store,
332     const scoped_refptr<PrefStore>& extension_prefs,
333     bool async) {
334 #if defined(ENABLE_CONFIGURATION_POLICY)
335   using policy::ConfigurationPolicyPrefStore;
336   factory->set_managed_prefs(
337       make_scoped_refptr(new ConfigurationPolicyPrefStore(
338           policy_service,
339           g_browser_process->browser_policy_connector()->GetHandlerList(),
340           policy::POLICY_LEVEL_MANDATORY)));
341   factory->set_recommended_prefs(
342       make_scoped_refptr(new ConfigurationPolicyPrefStore(
343           policy_service,
344           g_browser_process->browser_policy_connector()->GetHandlerList(),
345           policy::POLICY_LEVEL_RECOMMENDED)));
346 #endif  // ENABLE_CONFIGURATION_POLICY
347
348 #if defined(ENABLE_MANAGED_USERS)
349   if (managed_user_settings) {
350     factory->set_supervised_user_prefs(
351         make_scoped_refptr(new SupervisedUserPrefStore(managed_user_settings)));
352   }
353 #endif
354
355   factory->set_async(async);
356   factory->set_extension_prefs(extension_prefs);
357   factory->set_command_line_prefs(
358       make_scoped_refptr(
359           new CommandLinePrefStore(CommandLine::ForCurrentProcess())));
360   factory->set_read_error_callback(base::Bind(&HandleReadError));
361   factory->set_user_prefs(user_pref_store);
362 }
363
364 // Initialize/update preference hash stores for all profiles but the one whose
365 // path matches |ignored_profile_path|.
366 void UpdateAllPrefHashStoresIfRequired(
367     const base::FilePath& ignored_profile_path) {
368   if (GetSettingsEnforcementGroup() >= GROUP_ENFORCE_ALWAYS)
369     return;
370   const ProfileInfoCache& profile_info_cache =
371       g_browser_process->profile_manager()->GetProfileInfoCache();
372   const size_t n_profiles = profile_info_cache.GetNumberOfProfiles();
373   for (size_t i = 0; i < n_profiles; ++i) {
374     const base::FilePath profile_path =
375         profile_info_cache.GetPathOfProfileAtIndex(i);
376     if (profile_path != ignored_profile_path) {
377       CreateProfilePrefStoreManager(profile_path)
378           ->UpdateProfileHashStoreIfRequired(
379               JsonPrefStore::GetTaskRunnerForFile(
380                   profile_path, BrowserThread::GetBlockingPool()));
381     }
382   }
383 }
384
385 }  // namespace
386
387 namespace chrome_prefs {
388
389 namespace internals {
390
391 const char kSettingsEnforcementTrialName[] = "SettingsEnforcement";
392 const char kSettingsEnforcementGroupNoEnforcement[] = "no_enforcement";
393 const char kSettingsEnforcementGroupEnforceOnload[] = "enforce_on_load";
394 const char kSettingsEnforcementGroupEnforceAlways[] = "enforce_always";
395 const char kSettingsEnforcementGroupEnforceAlwaysWithExtensions[] =
396     "enforce_always_with_extensions";
397
398 }  // namespace internals
399
400 scoped_ptr<PrefService> CreateLocalState(
401     const base::FilePath& pref_filename,
402     base::SequencedTaskRunner* pref_io_task_runner,
403     policy::PolicyService* policy_service,
404     const scoped_refptr<PrefRegistry>& pref_registry,
405     bool async) {
406   PrefServiceSyncableFactory factory;
407   PrepareFactory(
408       &factory,
409       policy_service,
410       NULL,  // managed_user_settings
411       new JsonPrefStore(
412           pref_filename, pref_io_task_runner, scoped_ptr<PrefFilter>()),
413       NULL,  // extension_prefs
414       async);
415   return factory.Create(pref_registry.get());
416 }
417
418 scoped_ptr<PrefServiceSyncable> CreateProfilePrefs(
419     const base::FilePath& profile_path,
420     base::SequencedTaskRunner* pref_io_task_runner,
421     policy::PolicyService* policy_service,
422     ManagedUserSettingsService* managed_user_settings,
423     const scoped_refptr<PrefStore>& extension_prefs,
424     const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry,
425     bool async) {
426   TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
427   PrefServiceSyncableFactory factory;
428   PrepareFactory(&factory,
429                  policy_service,
430                  managed_user_settings,
431                  scoped_refptr<PersistentPrefStore>(
432                      CreateProfilePrefStoreManager(profile_path)
433                          ->CreateProfilePrefStore(pref_io_task_runner)),
434                  extension_prefs,
435                  async);
436   return factory.CreateSyncable(pref_registry.get());
437 }
438
439 void SchedulePrefsFilePathVerification(const base::FilePath& profile_path) {
440 #if defined(OS_WIN)
441   // Only do prefs file verification on Windows.
442   const int kVerifyPrefsFileDelaySeconds = 60;
443   BrowserThread::GetBlockingPool()->PostDelayedTask(
444       FROM_HERE,
445       base::Bind(&VerifyPreferencesFile,
446                  ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
447                      profile_path)),
448       base::TimeDelta::FromSeconds(g_disable_delays_and_domain_check_for_testing
449                                        ? 0
450                                        : kVerifyPrefsFileDelaySeconds));
451 #endif
452 }
453
454 void DisableDelaysAndDomainCheckForTesting() {
455   g_disable_delays_and_domain_check_for_testing = true;
456 }
457
458 void SchedulePrefHashStoresUpdateCheck(
459     const base::FilePath& initial_profile_path) {
460   if (!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking) {
461     ProfilePrefStoreManager::ResetAllPrefHashStores(
462         g_browser_process->local_state());
463     return;
464   }
465
466   const int kDefaultPrefHashStoresUpdateCheckDelaySeconds = 55;
467   BrowserThread::PostDelayedTask(
468         BrowserThread::UI,
469         FROM_HERE,
470         base::Bind(&UpdateAllPrefHashStoresIfRequired,
471                    initial_profile_path),
472         base::TimeDelta::FromSeconds(
473             g_disable_delays_and_domain_check_for_testing ?
474                 0 : kDefaultPrefHashStoresUpdateCheckDelaySeconds));
475 }
476
477 void ResetPrefHashStore(const base::FilePath& profile_path) {
478   CreateProfilePrefStoreManager(profile_path)->ResetPrefHashStore();
479 }
480
481 bool InitializePrefsFromMasterPrefs(
482     const base::FilePath& profile_path,
483     const base::DictionaryValue& master_prefs) {
484   return CreateProfilePrefStoreManager(profile_path)
485       ->InitializePrefsFromMasterPrefs(master_prefs);
486 }
487
488 base::Time GetResetTime(Profile* profile) {
489   return ProfilePrefStoreManager::GetResetTime(profile->GetPrefs());
490 }
491
492 void ClearResetTime(Profile* profile) {
493   ProfilePrefStoreManager::ClearResetTime(profile->GetPrefs());
494 }
495
496 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
497   ProfilePrefStoreManager::RegisterProfilePrefs(registry);
498 }
499
500 void RegisterPrefs(PrefRegistrySimple* registry) {
501   ProfilePrefStoreManager::RegisterPrefs(registry);
502 }
503
504 }  // namespace chrome_prefs