019b9306465f69be0aad5542f66da33cb0ae81f8
[platform/framework/web/crosswalk.git] / src / chrome / browser / prefs / profile_pref_store_manager.cc
1 // Copyright 2014 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/profile_pref_store_manager.h"
6
7 #include "base/file_util.h"
8 #include "base/json/json_file_value_serializer.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/prefs/json_pref_store.h"
12 #include "base/prefs/persistent_pref_store.h"
13 #include "base/prefs/pref_registry_simple.h"
14 #include "chrome/browser/prefs/pref_hash_store_impl.h"
15 #include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/user_prefs/pref_registry_syncable.h"
19
20 namespace {
21
22 // An in-memory PrefStore backed by an immutable DictionaryValue.
23 class DictionaryPrefStore : public PrefStore {
24  public:
25   explicit DictionaryPrefStore(const base::DictionaryValue* dictionary)
26       : dictionary_(dictionary) {}
27
28   virtual bool GetValue(const std::string& key,
29                         const base::Value** result) const OVERRIDE {
30     const base::Value* tmp = NULL;
31     if (!dictionary_->Get(key, &tmp))
32       return false;
33
34     if (result)
35       *result = tmp;
36     return true;
37   }
38
39  private:
40   virtual ~DictionaryPrefStore() {}
41
42   const base::DictionaryValue* dictionary_;
43
44   DISALLOW_COPY_AND_ASSIGN(DictionaryPrefStore);
45 };
46
47 }  // namespace
48
49 // TODO(erikwright): Enable this on Chrome OS and Android once MACs are moved
50 // out of Local State. This will resolve a race condition on Android and a
51 // privacy issue on ChromeOS. http://crbug.com/349158
52 const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking =
53 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
54     false;
55 #else
56     true;
57 #endif
58
59 // Waits for a PrefStore to be initialized and then initializes the
60 // corresponding PrefHashStore.
61 // The observer deletes itself when its work is completed.
62 class ProfilePrefStoreManager::InitializeHashStoreObserver
63     : public PrefStore::Observer {
64  public:
65   // Creates an observer that will initialize |pref_hash_store| with the
66   // contents of |pref_store| when the latter is fully loaded.
67   InitializeHashStoreObserver(
68       const std::vector<PrefHashFilter::TrackedPreferenceMetadata>&
69           tracking_configuration,
70       size_t reporting_ids_count,
71       const scoped_refptr<PrefStore>& pref_store,
72       scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl)
73       : tracking_configuration_(tracking_configuration),
74         reporting_ids_count_(reporting_ids_count),
75         pref_store_(pref_store),
76         pref_hash_store_impl_(pref_hash_store_impl.Pass()) {}
77
78   virtual ~InitializeHashStoreObserver();
79
80   // PrefStore::Observer implementation.
81   virtual void OnPrefValueChanged(const std::string& key) OVERRIDE;
82   virtual void OnInitializationCompleted(bool succeeded) OVERRIDE;
83
84  private:
85   const std::vector<PrefHashFilter::TrackedPreferenceMetadata>
86       tracking_configuration_;
87   const size_t reporting_ids_count_;
88   scoped_refptr<PrefStore> pref_store_;
89   scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl_;
90
91   DISALLOW_COPY_AND_ASSIGN(InitializeHashStoreObserver);
92 };
93
94 ProfilePrefStoreManager::InitializeHashStoreObserver::
95     ~InitializeHashStoreObserver() {}
96
97 void ProfilePrefStoreManager::InitializeHashStoreObserver::OnPrefValueChanged(
98     const std::string& key) {}
99
100 void
101 ProfilePrefStoreManager::InitializeHashStoreObserver::OnInitializationCompleted(
102     bool succeeded) {
103   // If we successfully loaded the preferences _and_ the PrefHashStoreImpl
104   // hasn't been initialized by someone else in the meantime, initialize it now.
105   const PrefHashStoreImpl::StoreVersion pre_update_version =
106       pref_hash_store_impl_->GetCurrentVersion();
107   if (succeeded && pre_update_version < PrefHashStoreImpl::VERSION_LATEST) {
108     PrefHashFilter(pref_hash_store_impl_.PassAs<PrefHashStore>(),
109                    tracking_configuration_,
110                    reporting_ids_count_).Initialize(*pref_store_);
111     UMA_HISTOGRAM_ENUMERATION(
112         "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
113         pre_update_version,
114         PrefHashStoreImpl::VERSION_LATEST + 1);
115   }
116   pref_store_->RemoveObserver(this);
117   delete this;
118 }
119
120 ProfilePrefStoreManager::ProfilePrefStoreManager(
121     const base::FilePath& profile_path,
122     const std::vector<PrefHashFilter::TrackedPreferenceMetadata>&
123         tracking_configuration,
124     size_t reporting_ids_count,
125     const std::string& seed,
126     const std::string& device_id,
127     PrefService* local_state)
128     : profile_path_(profile_path),
129       tracking_configuration_(tracking_configuration),
130       reporting_ids_count_(reporting_ids_count),
131       seed_(seed),
132       device_id_(device_id),
133       local_state_(local_state) {}
134
135 ProfilePrefStoreManager::~ProfilePrefStoreManager() {}
136
137 // static
138 void ProfilePrefStoreManager::RegisterPrefs(PrefRegistrySimple* registry) {
139   PrefServiceHashStoreContents::RegisterPrefs(registry);
140 }
141
142 // static
143 void ProfilePrefStoreManager::RegisterProfilePrefs(
144     user_prefs::PrefRegistrySyncable* registry) {
145   PrefHashFilter::RegisterProfilePrefs(registry);
146 }
147
148 // static
149 base::FilePath ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
150     const base::FilePath& profile_path) {
151   return profile_path.Append(chrome::kPreferencesFilename);
152 }
153
154 // static
155 void ProfilePrefStoreManager::ResetAllPrefHashStores(PrefService* local_state) {
156   PrefServiceHashStoreContents::ResetAllPrefHashStores(local_state);
157 }
158
159 //  static
160 base::Time ProfilePrefStoreManager::GetResetTime(PrefService* pref_service) {
161   return PrefHashFilter::GetResetTime(pref_service);
162 }
163
164 // static
165 void ProfilePrefStoreManager::ClearResetTime(PrefService* pref_service) {
166   PrefHashFilter::ClearResetTime(pref_service);
167 }
168
169 void ProfilePrefStoreManager::ResetPrefHashStore() {
170   if (kPlatformSupportsPreferenceTracking)
171     GetPrefHashStoreImpl()->Reset();
172 }
173
174 PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore(
175     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
176   scoped_ptr<PrefFilter> pref_filter;
177   if (kPlatformSupportsPreferenceTracking) {
178     pref_filter.reset(
179         new PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(),
180                            tracking_configuration_,
181                            reporting_ids_count_));
182   }
183   return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_),
184                            io_task_runner,
185                            pref_filter.Pass());
186 }
187
188 void ProfilePrefStoreManager::UpdateProfileHashStoreIfRequired(
189     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
190   if (!kPlatformSupportsPreferenceTracking)
191     return;
192   scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl(GetPrefHashStoreImpl());
193   const PrefHashStoreImpl::StoreVersion current_version =
194       pref_hash_store_impl->GetCurrentVersion();
195   UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferencesAlternateStoreVersion",
196                             current_version,
197                             PrefHashStoreImpl::VERSION_LATEST + 1);
198
199   // Update the pref hash store if it's not at the latest version.
200   if (current_version != PrefHashStoreImpl::VERSION_LATEST) {
201     scoped_refptr<JsonPrefStore> pref_store =
202         new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_),
203                           io_task_runner,
204                           scoped_ptr<PrefFilter>());
205     pref_store->AddObserver(
206         new InitializeHashStoreObserver(tracking_configuration_,
207                                         reporting_ids_count_,
208                                         pref_store,
209                                         pref_hash_store_impl.Pass()));
210     pref_store->ReadPrefsAsync(NULL);
211   }
212 }
213
214 bool ProfilePrefStoreManager::InitializePrefsFromMasterPrefs(
215     const base::DictionaryValue& master_prefs) {
216   // Create the profile directory if it doesn't exist yet (very possible on
217   // first run).
218   if (!base::CreateDirectory(profile_path_))
219     return false;
220
221   JSONFileValueSerializer serializer(
222       GetPrefFilePathFromProfilePath(profile_path_));
223
224   // Call Serialize (which does IO) on the main thread, which would _normally_
225   // be verboten. In this case however, we require this IO to synchronously
226   // complete before Chrome can start (as master preferences seed the Local
227   // State and Preferences files). This won't trip ThreadIORestrictions as they
228   // won't have kicked in yet on the main thread.
229   bool success = serializer.Serialize(master_prefs);
230
231   if (success && kPlatformSupportsPreferenceTracking) {
232     scoped_refptr<const PrefStore> pref_store(
233         new DictionaryPrefStore(&master_prefs));
234     PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(),
235                    tracking_configuration_,
236                    reporting_ids_count_).Initialize(*pref_store);
237   }
238
239   UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success);
240   return success;
241 }
242
243 scoped_ptr<PrefHashStoreImpl> ProfilePrefStoreManager::GetPrefHashStoreImpl() {
244   DCHECK(kPlatformSupportsPreferenceTracking);
245
246   return make_scoped_ptr(new PrefHashStoreImpl(
247       seed_,
248       device_id_,
249       scoped_ptr<HashStoreContents>(new PrefServiceHashStoreContents(
250           profile_path_.AsUTF8Unsafe(), local_state_))));
251 }