Index: chrome/browser/protector/protected_prefs_watcher.cc |
diff --git a/chrome/browser/protector/protected_prefs_watcher.cc b/chrome/browser/protector/protected_prefs_watcher.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4a6451a5f988d62bc9f01d09b3726585c39e6ca5 |
--- /dev/null |
+++ b/chrome/browser/protector/protected_prefs_watcher.cc |
@@ -0,0 +1,180 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/protector/protected_prefs_watcher.h" |
+ |
+#include <sstream> |
+ |
+#include "base/base64.h" |
+#include "base/values.h" |
+#include "chrome/browser/extensions/extension_prefs.h" |
+#include "chrome/browser/prefs/pref_service.h" |
+#include "chrome/browser/prefs/pref_set_observer.h" |
+#include "chrome/browser/prefs/scoped_user_pref_update.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/protector/protector_service.h" |
+#include "chrome/common/chrome_notification_types.h" |
+#include "chrome/common/pref_names.h" |
+#include "content/public/browser/notification_service.h" |
+ |
+namespace protector { |
+ |
+namespace { |
+ |
+// Backup pref names. |
+const char kBackupHomePage[] = "backup.homepage"; |
+const char kBackupHomePageIsNewTabPage[] = "backup.homepage_is_newtabpage"; |
+const char kBackupShowHomeButton[] = "backup.browser.show_home_button"; |
+const char kBackupRestoreOnStartup[] = "backup.session.restore_on_startup"; |
+const char kBackupURLsToRestoreOnStartup[] = |
+ "backup.session.urls_to_restore_on_startup"; |
+const char kBackupExtensionsIDs[] = "backup.extensions.ids"; |
+const char kBackupSignature[] = "backup._signature"; |
whywhat
2012/03/07 18:53:30
why this pref name has underscore?
Ivan Korotkov
2012/03/11 12:59:44
To emphasize that it's special among other "backup
|
+ |
+} // namespace |
+ |
+ProtectedPrefsWatcher::ProtectedPrefsWatcher(Profile* profile) |
+ : did_startup_settings_change_(false), |
+ profile_(profile) { |
+ pref_observer_.reset(PrefSetObserver::CreateProtectedPrefSetObserver( |
+ profile->GetPrefs(), this)); |
+ UpdateCachedPrefs(); |
+ if (!HasBackup()) |
+ UpdateBackupSignature(); |
+ VLOG(1) << "Initialized pref watcher"; |
+} |
+ |
+ProtectedPrefsWatcher::~ProtectedPrefsWatcher() { |
+} |
+ |
+// static |
+void ProtectedPrefsWatcher::RegisterUserPrefs(PrefService* prefs) { |
+ prefs->RegisterStringPref(kBackupHomePage, "", |
+ PrefService::UNSYNCABLE_PREF); |
+ prefs->RegisterBooleanPref(kBackupHomePageIsNewTabPage, false, |
+ PrefService::UNSYNCABLE_PREF); |
+ prefs->RegisterBooleanPref(kBackupShowHomeButton, false, |
+ PrefService::UNSYNCABLE_PREF); |
+ prefs->RegisterIntegerPref(kBackupRestoreOnStartup, 0, |
+ PrefService::UNSYNCABLE_PREF); |
+ prefs->RegisterListPref(kBackupURLsToRestoreOnStartup, |
+ PrefService::UNSYNCABLE_PREF); |
+ prefs->RegisterListPref(kBackupExtensionsIDs, |
+ PrefService::UNSYNCABLE_PREF); |
+ prefs->RegisterStringPref(kBackupSignature, "", |
+ PrefService::UNSYNCABLE_PREF); |
+} |
+ |
+void ProtectedPrefsWatcher::CheckForPrefChanges() { |
+ // TODO(ivankr): this is a stub that always updates the backup to match the |
+ // settings. Replace it with an actual check. |
+ UpdateBackupSignature(); |
+} |
+ |
+void ProtectedPrefsWatcher::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED); |
+ const std::string* pref_name = content::Details<std::string>(details).ptr(); |
+ DCHECK(pref_name && pref_observer_->IsObserved(*pref_name)); |
+ // For changes in extension dictionary, do nothing if the IDs list remained |
+ // the same. |
+ if (*pref_name == ExtensionPrefs::kExtensionsPref && !UpdateCachedPrefs()) |
+ return; |
+ UpdateBackupSignature(); |
+} |
+ |
+bool ProtectedPrefsWatcher::UpdateCachedPrefs() { |
+ PrefService* prefs = profile_->GetPrefs(); |
+ const base::DictionaryValue* extensions = |
+ prefs->GetDictionary(ExtensionPrefs::kExtensionsPref); |
+ std::set<std::string> extension_ids(extensions->begin_keys(), |
+ extensions->end_keys()); |
+ if (extension_ids == cached_extension_ids_) |
+ return false; |
+ cached_extension_ids_.swap(extension_ids); |
+ return true; |
+} |
+ |
+void ProtectedPrefsWatcher::UpdateBackupSignature() { |
+ PrefService* prefs = profile_->GetPrefs(); |
+ // Copy actual settings into backup. |
+ prefs->SetString(kBackupHomePage, prefs->GetString(prefs::kHomePage)); |
+ prefs->SetBoolean(kBackupHomePageIsNewTabPage, |
+ prefs->GetBoolean(prefs::kHomePageIsNewTabPage)); |
+ prefs->SetBoolean(kBackupShowHomeButton, |
+ prefs->GetBoolean(prefs::kShowHomeButton)); |
+ prefs->SetInteger(kBackupRestoreOnStartup, |
+ prefs->GetInteger(prefs::kRestoreOnStartup)); |
+ prefs->Set(kBackupURLsToRestoreOnStartup, |
+ *prefs->GetList(prefs::kURLsToRestoreOnStartup)); |
+ { |
+ ListPrefUpdate extension_ids_update(prefs, kBackupExtensionsIDs); |
+ base::ListValue* extension_ids = extension_ids_update.Get(); |
+ extension_ids->Clear(); |
+ for (std::set<std::string>::const_iterator it = |
+ cached_extension_ids_.begin(); |
+ it != cached_extension_ids_.end(); ++it) { |
+ extension_ids->Append(base::Value::CreateStringValue(*it)); |
+ } |
+ } |
+ // Update the signature. |
+ std::string signed_data = GetSignatureData(prefs); |
+ DCHECK(!signed_data.empty()); |
+ std::string signature = SignSetting(signed_data); |
+ DCHECK(!signature.empty()); |
+ std::string signature_base64; |
+ if (!base::Base64Encode(signature, &signature_base64)) |
+ NOTREACHED(); |
+ prefs->SetString(kBackupSignature, signature_base64); |
+ // Schedule disk write on FILE thread as soon as possible. |
+ prefs->CommitPendingWrite(); |
+ VLOG(1) << "Updated backup signature"; |
+} |
+ |
+bool ProtectedPrefsWatcher::IsSignatureValid() { |
+ DCHECK(HasBackup()); |
+ PrefService* prefs = profile_->GetPrefs(); |
+ std::string signed_data = GetSignatureData(prefs); |
+ DCHECK(!signed_data.empty()); |
+ std::string signature; |
+ if (!base::Base64Decode(prefs->GetString(kBackupSignature), &signature)) |
+ return false; |
+ return IsSettingValid(signed_data, signature); |
+} |
+ |
+bool ProtectedPrefsWatcher::HasBackup() { |
+ // TODO(ivankr): as soon as some irreversible change to Preferences happens, |
+ // add a condition that this change has occured as well (otherwise it's |
+ // possible to simply clear the "backup" dictionary to make settings |
+ // unprotected). |
+ return profile_->GetPrefs()->HasPrefPath(kBackupSignature); |
+} |
+ |
+std::string ProtectedPrefsWatcher::GetSignatureData(PrefService* prefs) { |
+ std::stringstream data; |
whywhat
2012/03/07 18:53:30
Don't we have StringPrintf in chrome code base?
Ivan Korotkov
2012/03/11 12:59:44
We do. I thought stream IO is a bit more expressiv
|
+ data << prefs->GetString(kBackupHomePage) << " " |
+ << prefs->GetBoolean(kBackupHomePageIsNewTabPage) << " " |
+ << prefs->GetBoolean(kBackupShowHomeButton) << " " |
+ << prefs->GetInteger(kBackupRestoreOnStartup) << " "; |
+ const base::ListValue* startup_urls = |
+ prefs->GetList(kBackupURLsToRestoreOnStartup); |
+ for (base::ListValue::const_iterator it = startup_urls->begin(); |
+ it != startup_urls->end(); ++it) { |
+ std::string url; |
+ if (!(*it)->GetAsString(&url)) |
+ NOTREACHED(); |
+ data << url << " "; |
+ } |
+ // These are safe to use becase they are always up-to-date and returned in |
+ // a consistent (sorted) order. |
+ for (std::set<std::string>::const_iterator it = cached_extension_ids_.begin(); |
+ it != cached_extension_ids_.end(); ++it) { |
+ data << *it << " "; |
+ } |
+ return data.str(); |
+} |
+ |
+} // namespace protector |