Chromium Code Reviews| 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 |