Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(511)

Side by Side Diff: chrome/browser/protector/protected_prefs_watcher.cc

Issue 9620010: Added Protector backup for Preferences. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Reupload Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/protector/protected_prefs_watcher.h"
6
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "base/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/browser/prefs/pref_set_observer.h"
14 #include "chrome/browser/prefs/scoped_user_pref_update.h"
15 #include "chrome/browser/prefs/session_startup_pref.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/protector/histograms.h"
18 #include "chrome/browser/protector/protector_service.h"
19 #include "chrome/common/chrome_notification_types.h"
20 #include "chrome/common/pref_names.h"
21 #include "content/public/browser/notification_service.h"
22
23 namespace protector {
24
25 namespace {
26
27 const char kBackupPrefsPrefix[] = "backup.";
28
29 // Backup pref names.
30 const char kBackupHomePage[] = "backup.homepage";
31 const char kBackupHomePageIsNewTabPage[] = "backup.homepage_is_newtabpage";
32 const char kBackupShowHomeButton[] = "backup.browser.show_home_button";
33 const char kBackupRestoreOnStartup[] = "backup.session.restore_on_startup";
34 const char kBackupURLsToRestoreOnStartup[] =
35 "backup.session.urls_to_restore_on_startup";
36 const char kBackupExtensionsIDs[] = "backup.extensions.ids";
37 const char kBackupSignature[] = "backup._signature";
38
39 } // namespace
40
41 ProtectedPrefsWatcher::ProtectedPrefsWatcher(Profile* profile)
42 : is_backup_valid_(true),
43 profile_(profile) {
44 // Perform necessary pref migrations before actually starting to observe
45 // pref changes, otherwise the migration would affect the backup data as well.
46 EnsurePrefsMigration();
47 pref_observer_.reset(PrefSetObserver::CreateProtectedPrefSetObserver(
48 profile->GetPrefs(), this));
49 UpdateCachedPrefs();
50 ValidateBackup();
51 VLOG(1) << "Initialized pref watcher";
52 }
53
54 ProtectedPrefsWatcher::~ProtectedPrefsWatcher() {
55 }
56
57 // static
58 void ProtectedPrefsWatcher::RegisterUserPrefs(PrefService* prefs) {
59 prefs->RegisterStringPref(kBackupHomePage, "",
60 PrefService::UNSYNCABLE_PREF);
61 prefs->RegisterBooleanPref(kBackupHomePageIsNewTabPage, false,
62 PrefService::UNSYNCABLE_PREF);
63 prefs->RegisterBooleanPref(kBackupShowHomeButton, false,
64 PrefService::UNSYNCABLE_PREF);
65 prefs->RegisterIntegerPref(kBackupRestoreOnStartup, 0,
66 PrefService::UNSYNCABLE_PREF);
67 prefs->RegisterListPref(kBackupURLsToRestoreOnStartup,
68 PrefService::UNSYNCABLE_PREF);
69 prefs->RegisterListPref(kBackupExtensionsIDs,
70 PrefService::UNSYNCABLE_PREF);
71 prefs->RegisterStringPref(kBackupSignature, "",
72 PrefService::UNSYNCABLE_PREF);
73 }
74
75 const base::Value* ProtectedPrefsWatcher::GetBackupForPref(
76 const std::string& path) const {
77 if (!is_backup_valid_)
78 return NULL;
79 std::string backup_path = std::string(kBackupPrefsPrefix) + path;
80 const PrefService::Preference* backup_pref =
81 profile_->GetPrefs()->FindPreference(backup_path.c_str());
82 DCHECK(backup_pref &&
83 // These do not directly correspond to any real preference.
84 backup_path != kBackupExtensionsIDs &&
85 backup_path != kBackupSignature);
86 return backup_pref->GetValue();
87 }
88
89 void ProtectedPrefsWatcher::Observe(
90 int type,
91 const content::NotificationSource& source,
92 const content::NotificationDetails& details) {
93 DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED);
94 const std::string* pref_name = content::Details<std::string>(details).ptr();
95 DCHECK(pref_name && pref_observer_->IsObserved(*pref_name));
96 if (UpdateBackupEntry(*pref_name))
97 UpdateBackupSignature();
98 }
99
100 void ProtectedPrefsWatcher::EnsurePrefsMigration() {
101 // Force SessionStartupPref migration, if necessary.
102 SessionStartupPref::GetStartupPref(profile_);
103 }
104
105 bool ProtectedPrefsWatcher::UpdateCachedPrefs() {
106 // Direct access to the extensions prefs is required becase ExtensionService
107 // may not yet have been initialized.
108 ExtensionPrefs::ExtensionIdSet extension_ids =
109 ExtensionPrefs::GetExtensionsFrom(
110 profile_->GetPrefs()->GetDictionary(ExtensionPrefs::kExtensionsPref));
111 if (extension_ids == cached_extension_ids_)
112 return false;
113 cached_extension_ids_.swap(extension_ids);
114 return true;
115 }
116
117 bool ProtectedPrefsWatcher::HasBackup() const {
118 // TODO(ivankr): as soon as some irreversible change to Preferences happens,
119 // add a condition that this change has occured as well (otherwise it's
120 // possible to simply clear the "backup" dictionary to make settings
121 // unprotected).
122 return profile_->GetPrefs()->HasPrefPath(kBackupSignature);
123 }
124
125 void ProtectedPrefsWatcher::InitBackup() {
126 PrefService* prefs = profile_->GetPrefs();
127 prefs->SetString(kBackupHomePage, prefs->GetString(prefs::kHomePage));
128 prefs->SetBoolean(kBackupHomePageIsNewTabPage,
129 prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
130 prefs->SetBoolean(kBackupShowHomeButton,
131 prefs->GetBoolean(prefs::kShowHomeButton));
132 prefs->SetInteger(kBackupRestoreOnStartup,
133 prefs->GetInteger(prefs::kRestoreOnStartup));
134 prefs->Set(kBackupURLsToRestoreOnStartup,
135 *prefs->GetList(prefs::kURLsToRestoreOnStartup));
136 ListPrefUpdate extension_ids_update(prefs, kBackupExtensionsIDs);
137 base::ListValue* extension_ids = extension_ids_update.Get();
138 extension_ids->Clear();
139 for (ExtensionPrefs::ExtensionIdSet::const_iterator it =
140 cached_extension_ids_.begin();
141 it != cached_extension_ids_.end(); ++it) {
142 extension_ids->Append(base::Value::CreateStringValue(*it));
143 }
144 UpdateBackupSignature();
145 }
146
147 bool ProtectedPrefsWatcher::UpdateBackupEntry(const std::string& pref_name) {
148 PrefService* prefs = profile_->GetPrefs();
149 if (pref_name == ExtensionPrefs::kExtensionsPref) {
150 // For changes in extension dictionary, do nothing if the IDs list remained
151 // the same.
152 if (!UpdateCachedPrefs())
153 return false;
154 ListPrefUpdate extension_ids_update(prefs, kBackupExtensionsIDs);
155 base::ListValue* extension_ids = extension_ids_update.Get();
156 extension_ids->Clear();
157 for (ExtensionPrefs::ExtensionIdSet::const_iterator it =
158 cached_extension_ids_.begin();
159 it != cached_extension_ids_.end(); ++it) {
160 extension_ids->Append(base::Value::CreateStringValue(*it));
161 }
162 } else if (pref_name == prefs::kHomePage) {
163 prefs->SetString(kBackupHomePage, prefs->GetString(prefs::kHomePage));
164 } else if (pref_name == prefs::kHomePageIsNewTabPage) {
165 prefs->SetBoolean(kBackupHomePageIsNewTabPage,
166 prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
167 } else if (pref_name == prefs::kShowHomeButton) {
168 prefs->SetBoolean(kBackupShowHomeButton,
169 prefs->GetBoolean(prefs::kShowHomeButton));
170 } else if (pref_name == prefs::kRestoreOnStartup) {
171 prefs->SetInteger(kBackupRestoreOnStartup,
172 prefs->GetInteger(prefs::kRestoreOnStartup));
173 } else if (pref_name == prefs::kURLsToRestoreOnStartup) {
174 prefs->Set(kBackupURLsToRestoreOnStartup,
175 *prefs->GetList(prefs::kURLsToRestoreOnStartup));
176 } else {
177 NOTREACHED();
178 return false;
179 }
180 VLOG(1) << "Updated backup entry for: " << pref_name;
181 return true;
182 }
183
184 void ProtectedPrefsWatcher::UpdateBackupSignature() {
185 PrefService* prefs = profile_->GetPrefs();
186 std::string signed_data = GetSignatureData(prefs);
187 DCHECK(!signed_data.empty());
188 std::string signature = SignSetting(signed_data);
189 DCHECK(!signature.empty());
190 std::string signature_base64;
191 if (!base::Base64Encode(signature, &signature_base64))
192 NOTREACHED();
193 prefs->SetString(kBackupSignature, signature_base64);
194 // Schedule disk write on FILE thread as soon as possible.
195 prefs->CommitPendingWrite();
196 VLOG(1) << "Updated backup signature";
197 }
198
199 bool ProtectedPrefsWatcher::IsSignatureValid() const {
200 DCHECK(HasBackup());
201 PrefService* prefs = profile_->GetPrefs();
202 std::string signed_data = GetSignatureData(prefs);
203 DCHECK(!signed_data.empty());
204 std::string signature;
205 if (!base::Base64Decode(prefs->GetString(kBackupSignature), &signature))
206 return false;
207 return IsSettingValid(signed_data, signature);
208 }
209
210 void ProtectedPrefsWatcher::ValidateBackup() {
211 if (!HasBackup()) {
212 // Create initial backup entries and sign them.
213 InitBackup();
214 UMA_HISTOGRAM_ENUMERATION(
215 kProtectorHistogramPrefs,
216 kProtectorErrorValueValidZero,
217 kProtectorErrorCount);
218 } else if (IsSignatureValid()) {
219 UMA_HISTOGRAM_ENUMERATION(
220 kProtectorHistogramPrefs,
221 kProtectorErrorValueValid,
222 kProtectorErrorCount);
223 } else {
224 LOG(WARNING) << "Invalid backup signature";
225 // Further changes to protected prefs will overwrite the signature.
226 is_backup_valid_ = false;
227 UMA_HISTOGRAM_ENUMERATION(
228 kProtectorHistogramPrefs,
229 kProtectorErrorBackupInvalid,
230 kProtectorErrorCount);
231 }
232 }
233
234 std::string ProtectedPrefsWatcher::GetSignatureData(PrefService* prefs) const {
235 // std::stringstream data;
236 std::string data = base::StringPrintf(
237 "%s|%d|%d|%d",
238 prefs->GetString(kBackupHomePage).c_str(),
239 prefs->GetBoolean(kBackupHomePageIsNewTabPage) ? 1 : 0,
240 prefs->GetBoolean(kBackupShowHomeButton) ? 1 : 0,
241 prefs->GetInteger(kBackupRestoreOnStartup));
242 const base::ListValue* startup_urls =
243 prefs->GetList(kBackupURLsToRestoreOnStartup);
244 for (base::ListValue::const_iterator it = startup_urls->begin();
245 it != startup_urls->end(); ++it) {
246 std::string url;
247 if (!(*it)->GetAsString(&url))
248 NOTREACHED();
249 base::StringAppendF(&data, "|%s", url.c_str());
250 }
251 // These are safe to use becase they are always up-to-date and returned in
252 // a consistent (sorted) order.
253 for (ExtensionPrefs::ExtensionIdSet::const_iterator it =
254 cached_extension_ids_.begin();
255 it != cached_extension_ids_.end(); ++it) {
256 base::StringAppendF(&data, "|%s", it->c_str());
257 }
258 return data;
259 }
260
261 } // namespace protector
OLDNEW
« no previous file with comments | « chrome/browser/protector/protected_prefs_watcher.h ('k') | chrome/browser/protector/protected_prefs_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698