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

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: Addressed review comments, removed blacklist from extension ID list, added unittest. 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/profiles/profile.h"
16 #include "chrome/browser/protector/histograms.h"
17 #include "chrome/browser/protector/protector_service.h"
18 #include "chrome/common/chrome_notification_types.h"
19 #include "chrome/common/pref_names.h"
20 #include "content/public/browser/notification_service.h"
21
22 namespace protector {
23
24 namespace {
25
26 const char kBackupPrefsPrefix[] = "backup.";
27
28 // Backup pref names.
29 const char kBackupHomePage[] = "backup.homepage";
30 const char kBackupHomePageIsNewTabPage[] = "backup.homepage_is_newtabpage";
31 const char kBackupShowHomeButton[] = "backup.browser.show_home_button";
32 const char kBackupRestoreOnStartup[] = "backup.session.restore_on_startup";
33 const char kBackupURLsToRestoreOnStartup[] =
34 "backup.session.urls_to_restore_on_startup";
35 const char kBackupExtensionsIDs[] = "backup.extensions.ids";
36 const char kBackupSignature[] = "backup._signature";
37
38 } // namespace
39
40 ProtectedPrefsWatcher::ProtectedPrefsWatcher(Profile* profile)
41 : did_startup_settings_change_(false),
42 profile_(profile) {
43 pref_observer_.reset(PrefSetObserver::CreateProtectedPrefSetObserver(
44 profile->GetPrefs(), this));
45 UpdateCachedPrefs();
46 if (!HasBackup()) {
47 UpdateBackupSignature();
48 UMA_HISTOGRAM_ENUMERATION(
49 kProtectorHistogramPrefs,
50 kProtectorErrorValueValidZero,
51 kProtectorErrorCount);
52 } else if (IsSignatureValid()) {
53 UMA_HISTOGRAM_ENUMERATION(
54 kProtectorHistogramPrefs,
55 kProtectorErrorValueValid,
56 kProtectorErrorCount);
57 } else {
58 // Report an invalid signature.
59 LOG(WARNING) << "Invalid backup signature";
60 UMA_HISTOGRAM_ENUMERATION(
61 kProtectorHistogramPrefs,
62 kProtectorErrorBackupInvalid,
63 kProtectorErrorCount);
64 }
65 VLOG(1) << "Initialized pref watcher";
66 }
67
68 ProtectedPrefsWatcher::~ProtectedPrefsWatcher() {
69 }
70
71 // static
72 void ProtectedPrefsWatcher::RegisterUserPrefs(PrefService* prefs) {
73 prefs->RegisterStringPref(kBackupHomePage, "",
74 PrefService::UNSYNCABLE_PREF);
75 prefs->RegisterBooleanPref(kBackupHomePageIsNewTabPage, false,
76 PrefService::UNSYNCABLE_PREF);
77 prefs->RegisterBooleanPref(kBackupShowHomeButton, false,
78 PrefService::UNSYNCABLE_PREF);
79 prefs->RegisterIntegerPref(kBackupRestoreOnStartup, 0,
80 PrefService::UNSYNCABLE_PREF);
81 prefs->RegisterListPref(kBackupURLsToRestoreOnStartup,
82 PrefService::UNSYNCABLE_PREF);
83 prefs->RegisterListPref(kBackupExtensionsIDs,
84 PrefService::UNSYNCABLE_PREF);
85 prefs->RegisterStringPref(kBackupSignature, "",
86 PrefService::UNSYNCABLE_PREF);
87 }
88
89 void ProtectedPrefsWatcher::ValidatePrefs() {
90 // TODO(ivankr): this is a stub that always updates the backup to match the
91 // settings. Replace it with an actual check.
92 UpdateBackupSignature();
93 }
94
95 const base::Value* ProtectedPrefsWatcher::GetBackupForPref(
96 const std::string& path) const {
97 std::string backup_path = std::string(kBackupPrefsPrefix) + path;
98 const PrefService::Preference* backup_pref =
99 profile_->GetPrefs()->FindPreference(backup_path.c_str());
100 if (!backup_pref || backup_pref->IsDefaultValue() ||
101 // These do not directly correspond to any real preference.
102 backup_path == kBackupExtensionsIDs ||
103 backup_path == kBackupSignature) {
104 LOG(WARNING) << "No backup for pref: " << path;
105 return NULL;
106 }
107 return backup_pref->GetValue();
108 }
109
110 void ProtectedPrefsWatcher::Observe(
111 int type,
112 const content::NotificationSource& source,
113 const content::NotificationDetails& details) {
114 DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED);
115 const std::string* pref_name = content::Details<std::string>(details).ptr();
116 DCHECK(pref_name && pref_observer_->IsObserved(*pref_name));
117 // For changes in extension dictionary, do nothing if the IDs list remained
118 // the same.
119 if (*pref_name == ExtensionPrefs::kExtensionsPref && !UpdateCachedPrefs())
120 return;
121 UpdateBackupSignature();
122 }
123
124 bool ProtectedPrefsWatcher::UpdateCachedPrefs() {
125 ExtensionPrefs::ExtensionIdSet extension_ids;
126 // Direct access to the extensions prefs is required becase ExtensionService
127 // may not yet have been initialized.
128 ExtensionPrefs::GetExtensionsFrom(
129 profile_->GetPrefs()->GetDictionary(ExtensionPrefs::kExtensionsPref),
130 &extension_ids);
131 if (extension_ids == cached_extension_ids_)
132 return false;
133 cached_extension_ids_.swap(extension_ids);
134 return true;
135 }
136
137 void ProtectedPrefsWatcher::UpdateBackupSignature() {
138 PrefService* prefs = profile_->GetPrefs();
139 // Copy actual settings into backup.
140 prefs->SetString(kBackupHomePage, prefs->GetString(prefs::kHomePage));
141 prefs->SetBoolean(kBackupHomePageIsNewTabPage,
142 prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
143 prefs->SetBoolean(kBackupShowHomeButton,
144 prefs->GetBoolean(prefs::kShowHomeButton));
145 prefs->SetInteger(kBackupRestoreOnStartup,
146 prefs->GetInteger(prefs::kRestoreOnStartup));
147 prefs->Set(kBackupURLsToRestoreOnStartup,
148 *prefs->GetList(prefs::kURLsToRestoreOnStartup));
149 {
150 ListPrefUpdate extension_ids_update(prefs, kBackupExtensionsIDs);
151 base::ListValue* extension_ids = extension_ids_update.Get();
152 extension_ids->Clear();
153 for (ExtensionPrefs::ExtensionIdSet::const_iterator it =
154 cached_extension_ids_.begin();
155 it != cached_extension_ids_.end(); ++it) {
156 extension_ids->Append(base::Value::CreateStringValue(*it));
157 }
158 }
159 // Update the signature.
160 std::string signed_data = GetSignatureData(prefs);
161 DCHECK(!signed_data.empty());
162 std::string signature = SignSetting(signed_data);
163 DCHECK(!signature.empty());
164 std::string signature_base64;
165 if (!base::Base64Encode(signature, &signature_base64))
166 NOTREACHED();
167 prefs->SetString(kBackupSignature, signature_base64);
168 // Schedule disk write on FILE thread as soon as possible.
169 prefs->CommitPendingWrite();
170 VLOG(1) << "Updated backup signature";
171 }
172
173 bool ProtectedPrefsWatcher::IsSignatureValid() const {
174 DCHECK(HasBackup());
175 PrefService* prefs = profile_->GetPrefs();
176 std::string signed_data = GetSignatureData(prefs);
177 DCHECK(!signed_data.empty());
178 std::string signature;
179 if (!base::Base64Decode(prefs->GetString(kBackupSignature), &signature))
180 return false;
181 return IsSettingValid(signed_data, signature);
182 }
183
184 bool ProtectedPrefsWatcher::HasBackup() const {
185 // TODO(ivankr): as soon as some irreversible change to Preferences happens,
186 // add a condition that this change has occured as well (otherwise it's
187 // possible to simply clear the "backup" dictionary to make settings
188 // unprotected).
189 return profile_->GetPrefs()->HasPrefPath(kBackupSignature);
190 }
191
192 std::string ProtectedPrefsWatcher::GetSignatureData(PrefService* prefs) const {
193 // std::stringstream data;
194 std::string data = base::StringPrintf(
195 "%s|%d|%d|%d",
196 prefs->GetString(kBackupHomePage).c_str(),
197 prefs->GetBoolean(kBackupHomePageIsNewTabPage) ? 1 : 0,
198 prefs->GetBoolean(kBackupShowHomeButton) ? 1 : 0,
199 prefs->GetInteger(kBackupRestoreOnStartup));
200 const base::ListValue* startup_urls =
201 prefs->GetList(kBackupURLsToRestoreOnStartup);
202 for (base::ListValue::const_iterator it = startup_urls->begin();
203 it != startup_urls->end(); ++it) {
204 std::string url;
205 if (!(*it)->GetAsString(&url))
206 NOTREACHED();
207 base::StringAppendF(&data, "|%s", url.c_str());
208 }
209 // These are safe to use becase they are always up-to-date and returned in
210 // a consistent (sorted) order.
211 for (ExtensionPrefs::ExtensionIdSet::const_iterator it =
212 cached_extension_ids_.begin();
213 it != cached_extension_ids_.end(); ++it) {
214 base::StringAppendF(&data, "|%s", it->c_str());
215 }
216 return data;
217 }
218
219 } // namespace protector
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698