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 "base/bind.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/histogram.h"
12#include "base/prefs/default_pref_store.h"
13#include "base/prefs/json_pref_store.h"
14#include "base/prefs/pref_notifier_impl.h"
15#include "base/prefs/pref_registry.h"
16#include "base/prefs/pref_service.h"
17#include "base/prefs/pref_value_store.h"
18#include "chrome/browser/browser_process.h"
19#include "chrome/browser/prefs/command_line_pref_store.h"
20#include "chrome/browser/prefs/pref_model_associator.h"
21#include "chrome/browser/prefs/pref_service_syncable.h"
22#include "chrome/browser/prefs/pref_service_syncable_factory.h"
23#include "chrome/browser/ui/profile_error_dialog.h"
24#include "components/user_prefs/pref_registry_syncable.h"
25#include "content/public/browser/browser_context.h"
26#include "content/public/browser/browser_thread.h"
27#include "grit/chromium_strings.h"
28#include "grit/generated_resources.h"
29
30#if defined(ENABLE_CONFIGURATION_POLICY)
31#include "chrome/browser/policy/browser_policy_connector.h"
32#include "components/policy/core/browser/configuration_policy_pref_store.h"
33#include "components/policy/core/common/policy_types.h"
34#endif
35
36#if defined(ENABLE_MANAGED_USERS)
37#include "chrome/browser/managed_mode/supervised_user_pref_store.h"
38#endif
39
40using content::BrowserContext;
41using content::BrowserThread;
42
43namespace {
44
45// Shows notifications which correspond to PersistentPrefStore's reading errors.
46void HandleReadError(PersistentPrefStore::PrefReadError error) {
47  // Sample the histogram also for the successful case in order to get a
48  // baseline on the success rate in addition to the error distribution.
49  UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error,
50                            PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
51
52  if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
53#if !defined(OS_CHROMEOS)
54    // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
55    // an example problem that this can cause.
56    // Do some diagnosis and try to avoid losing data.
57    int message_id = 0;
58    if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
59      message_id = IDS_PREFERENCES_CORRUPT_ERROR;
60    } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
61      message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
62    }
63
64    if (message_id) {
65      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
66                              base::Bind(&ShowProfileErrorDialog,
67                                         PROFILE_ERROR_PREFERENCES,
68                                         message_id));
69    }
70#else
71    // On ChromeOS error screen with message about broken local state
72    // will be displayed.
73#endif
74  }
75}
76
77void PrepareBuilder(
78    PrefServiceSyncableFactory* factory,
79    const base::FilePath& pref_filename,
80    base::SequencedTaskRunner* pref_io_task_runner,
81    policy::PolicyService* policy_service,
82    ManagedUserSettingsService* managed_user_settings,
83    const scoped_refptr<PrefStore>& extension_prefs,
84    bool async) {
85#if defined(OS_LINUX)
86  // We'd like to see what fraction of our users have the preferences
87  // stored on a network file system, as we've had no end of troubles
88  // with NFS/AFS.
89  // TODO(evanm): remove this once we've collected state.
90  file_util::FileSystemType fstype;
91  if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) {
92    UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
93                              static_cast<int>(fstype),
94                              file_util::FILE_SYSTEM_TYPE_COUNT);
95  }
96#endif
97
98#if defined(ENABLE_CONFIGURATION_POLICY)
99  using policy::ConfigurationPolicyPrefStore;
100  factory->set_managed_prefs(
101      make_scoped_refptr(new ConfigurationPolicyPrefStore(
102          policy_service,
103          g_browser_process->browser_policy_connector()->GetHandlerList(),
104          policy::POLICY_LEVEL_MANDATORY)));
105  factory->set_recommended_prefs(
106      make_scoped_refptr(new ConfigurationPolicyPrefStore(
107          policy_service,
108          g_browser_process->browser_policy_connector()->GetHandlerList(),
109          policy::POLICY_LEVEL_RECOMMENDED)));
110#endif  // ENABLE_CONFIGURATION_POLICY
111
112#if defined(ENABLE_MANAGED_USERS)
113  if (managed_user_settings) {
114    factory->set_supervised_user_prefs(
115        make_scoped_refptr(new SupervisedUserPrefStore(managed_user_settings)));
116  }
117#endif
118
119  factory->set_async(async);
120  factory->set_extension_prefs(extension_prefs);
121  factory->set_command_line_prefs(
122      make_scoped_refptr(
123          new CommandLinePrefStore(CommandLine::ForCurrentProcess())));
124  factory->set_read_error_callback(base::Bind(&HandleReadError));
125  factory->set_user_prefs(
126      new JsonPrefStore(pref_filename, pref_io_task_runner));
127}
128
129}  // namespace
130
131namespace chrome_prefs {
132
133scoped_ptr<PrefService> CreateLocalState(
134    const base::FilePath& pref_filename,
135    base::SequencedTaskRunner* pref_io_task_runner,
136    policy::PolicyService* policy_service,
137    const scoped_refptr<PrefRegistry>& pref_registry,
138    bool async) {
139  PrefServiceSyncableFactory factory;
140  PrepareBuilder(&factory,
141                 pref_filename,
142                 pref_io_task_runner,
143                 policy_service,
144                 NULL,
145                 NULL,
146                 async);
147  return factory.Create(pref_registry.get());
148}
149
150scoped_ptr<PrefServiceSyncable> CreateProfilePrefs(
151    const base::FilePath& pref_filename,
152    base::SequencedTaskRunner* pref_io_task_runner,
153    policy::PolicyService* policy_service,
154    ManagedUserSettingsService* managed_user_settings,
155    const scoped_refptr<PrefStore>& extension_prefs,
156    const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry,
157    bool async) {
158  TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
159  PrefServiceSyncableFactory factory;
160  PrepareBuilder(&factory,
161                 pref_filename,
162                 pref_io_task_runner,
163                 policy_service,
164                 managed_user_settings,
165                 extension_prefs,
166                 async);
167  return factory.CreateSyncable(pref_registry.get());
168}
169
170}  // namespace chrome_prefs
171