diff options
author | ivankr@chromium.org <ivankr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-15 16:53:48 +0000 |
---|---|---|
committer | ivankr@chromium.org <ivankr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-15 16:53:48 +0000 |
commit | ee78d8a3ceadcb70fe5d561140c45f8cfdf3b576 (patch) | |
tree | 8d095f6743db57b84358a04f0a26dd198bc5ff38 /chrome/browser/protector | |
parent | cb5956b3d5a07c08993a4f3d3995bba5a4de0709 (diff) | |
download | chromium_src-ee78d8a3ceadcb70fe5d561140c45f8cfdf3b576.zip chromium_src-ee78d8a3ceadcb70fe5d561140c45f8cfdf3b576.tar.gz chromium_src-ee78d8a3ceadcb70fe5d561140c45f8cfdf3b576.tar.bz2 |
Added Protector backup for Preferences.
BUG=114288
TEST=ProtectedPrefsWatcherTest.*; no user-visible changes
Review URL: http://codereview.chromium.org/9620010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126927 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/protector')
-rw-r--r-- | chrome/browser/protector/histograms.cc | 3 | ||||
-rw-r--r-- | chrome/browser/protector/histograms.h | 3 | ||||
-rw-r--r-- | chrome/browser/protector/protected_prefs_watcher.cc | 261 | ||||
-rw-r--r-- | chrome/browser/protector/protected_prefs_watcher.h | 96 | ||||
-rw-r--r-- | chrome/browser/protector/protected_prefs_watcher_unittest.cc | 141 | ||||
-rw-r--r-- | chrome/browser/protector/protector_service.cc | 7 | ||||
-rw-r--r-- | chrome/browser/protector/protector_service.h | 12 | ||||
-rw-r--r-- | chrome/browser/protector/protector_service_factory.cc | 16 | ||||
-rw-r--r-- | chrome/browser/protector/protector_service_factory.h | 2 |
9 files changed, 540 insertions, 1 deletions
diff --git a/chrome/browser/protector/histograms.cc b/chrome/browser/protector/histograms.cc index 2be23e2..c0ba393 100644 --- a/chrome/browser/protector/histograms.cc +++ b/chrome/browser/protector/histograms.cc @@ -13,6 +13,9 @@ namespace protector { const char kProtectorHistogramDefaultSearchProvider[] = "Protector.DefaultSearchProvider"; +const char kProtectorHistogramPrefs[] = + "Protector.Preferences"; + const char kProtectorHistogramSearchProviderApplied[] = "Protector.SearchProvider.Applied"; const char kProtectorHistogramSearchProviderCorrupt[] = diff --git a/chrome/browser/protector/histograms.h b/chrome/browser/protector/histograms.h index 410026a..fe46cfa 100644 --- a/chrome/browser/protector/histograms.h +++ b/chrome/browser/protector/histograms.h @@ -14,6 +14,9 @@ namespace protector { // provider. Values are below. extern const char kProtectorHistogramDefaultSearchProvider[]; +// Histogram name to report protection errors for preferences. Values are below. +extern const char kProtectorHistogramPrefs[]; + // Protector histogram values. enum ProtectorError { kProtectorErrorBackupInvalid, diff --git a/chrome/browser/protector/protected_prefs_watcher.cc b/chrome/browser/protector/protected_prefs_watcher.cc new file mode 100644 index 0000000..73b036f --- /dev/null +++ b/chrome/browser/protector/protected_prefs_watcher.cc @@ -0,0 +1,261 @@ +// 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 "base/base64.h" +#include "base/logging.h" +#include "base/metrics/histogram.h" +#include "base/stringprintf.h" +#include "base/values.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/prefs/session_startup_pref.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/protector/histograms.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 { + +const char kBackupPrefsPrefix[] = "backup."; + +// 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"; + +} // namespace + +ProtectedPrefsWatcher::ProtectedPrefsWatcher(Profile* profile) + : is_backup_valid_(true), + profile_(profile) { + // Perform necessary pref migrations before actually starting to observe + // pref changes, otherwise the migration would affect the backup data as well. + EnsurePrefsMigration(); + pref_observer_.reset(PrefSetObserver::CreateProtectedPrefSetObserver( + profile->GetPrefs(), this)); + UpdateCachedPrefs(); + ValidateBackup(); + 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); +} + +const base::Value* ProtectedPrefsWatcher::GetBackupForPref( + const std::string& path) const { + if (!is_backup_valid_) + return NULL; + std::string backup_path = std::string(kBackupPrefsPrefix) + path; + const PrefService::Preference* backup_pref = + profile_->GetPrefs()->FindPreference(backup_path.c_str()); + DCHECK(backup_pref && + // These do not directly correspond to any real preference. + backup_path != kBackupExtensionsIDs && + backup_path != kBackupSignature); + return backup_pref->GetValue(); +} + +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)); + if (UpdateBackupEntry(*pref_name)) + UpdateBackupSignature(); +} + +void ProtectedPrefsWatcher::EnsurePrefsMigration() { + // Force SessionStartupPref migration, if necessary. + SessionStartupPref::GetStartupPref(profile_); +} + +bool ProtectedPrefsWatcher::UpdateCachedPrefs() { + // Direct access to the extensions prefs is required becase ExtensionService + // may not yet have been initialized. + ExtensionPrefs::ExtensionIdSet extension_ids = + ExtensionPrefs::GetExtensionsFrom( + profile_->GetPrefs()->GetDictionary(ExtensionPrefs::kExtensionsPref)); + if (extension_ids == cached_extension_ids_) + return false; + cached_extension_ids_.swap(extension_ids); + return true; +} + +bool ProtectedPrefsWatcher::HasBackup() const { + // 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); +} + +void ProtectedPrefsWatcher::InitBackup() { + PrefService* prefs = profile_->GetPrefs(); + 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 (ExtensionPrefs::ExtensionIdSet::const_iterator it = + cached_extension_ids_.begin(); + it != cached_extension_ids_.end(); ++it) { + extension_ids->Append(base::Value::CreateStringValue(*it)); + } + UpdateBackupSignature(); +} + +bool ProtectedPrefsWatcher::UpdateBackupEntry(const std::string& pref_name) { + PrefService* prefs = profile_->GetPrefs(); + if (pref_name == ExtensionPrefs::kExtensionsPref) { + // For changes in extension dictionary, do nothing if the IDs list remained + // the same. + if (!UpdateCachedPrefs()) + return false; + ListPrefUpdate extension_ids_update(prefs, kBackupExtensionsIDs); + base::ListValue* extension_ids = extension_ids_update.Get(); + extension_ids->Clear(); + for (ExtensionPrefs::ExtensionIdSet::const_iterator it = + cached_extension_ids_.begin(); + it != cached_extension_ids_.end(); ++it) { + extension_ids->Append(base::Value::CreateStringValue(*it)); + } + } else if (pref_name == prefs::kHomePage) { + prefs->SetString(kBackupHomePage, prefs->GetString(prefs::kHomePage)); + } else if (pref_name == prefs::kHomePageIsNewTabPage) { + prefs->SetBoolean(kBackupHomePageIsNewTabPage, + prefs->GetBoolean(prefs::kHomePageIsNewTabPage)); + } else if (pref_name == prefs::kShowHomeButton) { + prefs->SetBoolean(kBackupShowHomeButton, + prefs->GetBoolean(prefs::kShowHomeButton)); + } else if (pref_name == prefs::kRestoreOnStartup) { + prefs->SetInteger(kBackupRestoreOnStartup, + prefs->GetInteger(prefs::kRestoreOnStartup)); + } else if (pref_name == prefs::kURLsToRestoreOnStartup) { + prefs->Set(kBackupURLsToRestoreOnStartup, + *prefs->GetList(prefs::kURLsToRestoreOnStartup)); + } else { + NOTREACHED(); + return false; + } + VLOG(1) << "Updated backup entry for: " << pref_name; + return true; +} + +void ProtectedPrefsWatcher::UpdateBackupSignature() { + PrefService* prefs = profile_->GetPrefs(); + 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() const { + 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); +} + +void ProtectedPrefsWatcher::ValidateBackup() { + if (!HasBackup()) { + // Create initial backup entries and sign them. + InitBackup(); + UMA_HISTOGRAM_ENUMERATION( + kProtectorHistogramPrefs, + kProtectorErrorValueValidZero, + kProtectorErrorCount); + } else if (IsSignatureValid()) { + UMA_HISTOGRAM_ENUMERATION( + kProtectorHistogramPrefs, + kProtectorErrorValueValid, + kProtectorErrorCount); + } else { + LOG(WARNING) << "Invalid backup signature"; + // Further changes to protected prefs will overwrite the signature. + is_backup_valid_ = false; + UMA_HISTOGRAM_ENUMERATION( + kProtectorHistogramPrefs, + kProtectorErrorBackupInvalid, + kProtectorErrorCount); + } +} + +std::string ProtectedPrefsWatcher::GetSignatureData(PrefService* prefs) const { + // std::stringstream data; + std::string data = base::StringPrintf( + "%s|%d|%d|%d", + prefs->GetString(kBackupHomePage).c_str(), + prefs->GetBoolean(kBackupHomePageIsNewTabPage) ? 1 : 0, + prefs->GetBoolean(kBackupShowHomeButton) ? 1 : 0, + 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(); + base::StringAppendF(&data, "|%s", url.c_str()); + } + // These are safe to use becase they are always up-to-date and returned in + // a consistent (sorted) order. + for (ExtensionPrefs::ExtensionIdSet::const_iterator it = + cached_extension_ids_.begin(); + it != cached_extension_ids_.end(); ++it) { + base::StringAppendF(&data, "|%s", it->c_str()); + } + return data; +} + +} // namespace protector diff --git a/chrome/browser/protector/protected_prefs_watcher.h b/chrome/browser/protector/protected_prefs_watcher.h new file mode 100644 index 0000000..5316fc6 --- /dev/null +++ b/chrome/browser/protector/protected_prefs_watcher.h @@ -0,0 +1,96 @@ +// 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. + +#ifndef CHROME_BROWSER_PROTECTOR_PROTECTED_PREFS_WATCHER_H_ +#define CHROME_BROWSER_PROTECTOR_PROTECTED_PREFS_WATCHER_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/extensions/extension_prefs.h" +#include "content/public/browser/notification_observer.h" + +class PrefService; +class PrefSetObserver; +class Profile; + +namespace base { +class Value; +} + +namespace protector { + +class ProtectedPrefsWatcher : public content::NotificationObserver { + public: + explicit ProtectedPrefsWatcher(Profile* profile); + virtual ~ProtectedPrefsWatcher(); + + // Registers prefs on a new Profile instance. + static void RegisterUserPrefs(PrefService* prefs); + + // Returns the backup value for pref named |path| or |NULL| if the pref is + // not protected or does not exist. The returned Value instance is owned by + // the PrefService. + const base::Value* GetBackupForPref(const std::string& path) const; + + // True if the backup was valid at the profile load time. + bool is_backup_valid() { return is_backup_valid_; } + + private: + friend class ProtectedPrefsWatcherTest; + + // content::NotificationObserver overrides: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // Makes sure that all protected prefs have been migrated before starting to + // observe them. + void EnsurePrefsMigration(); + + // Updates cached prefs from their actual values and returns |true| if there + // were any changes. + bool UpdateCachedPrefs(); + + // Returns |false| if profile does not have a backup yet (needs to be + // initialized). + bool HasBackup() const; + + // Creates initial backup entries. + void InitBackup(); + + // Updates the backup утекн for |pref_name| and кeturns |true| if the + // backup has changed. + bool UpdateBackupEntry(const std::string& pref_name); + + // Updates the backup signature. + void UpdateBackupSignature(); + + // Perform a check that backup is valid and settings have not been modified. + void ValidateBackup(); + + // Returns |true| if backup signature is valid. + bool IsSignatureValid() const; + + // Returns data to be signed as string. + std::string GetSignatureData(PrefService* prefs) const; + + // Cached set of extension IDs. They are not changed as frequently + ExtensionPrefs::ExtensionIdSet cached_extension_ids_; + + scoped_ptr<PrefSetObserver> pref_observer_; + + // True if the backup was valid at the profile load time. + bool is_backup_valid_; + + Profile* profile_; + + DISALLOW_COPY_AND_ASSIGN(ProtectedPrefsWatcher); +}; + +} // namespace protector + +#endif // CHROME_BROWSER_PROTECTOR_PROTECTED_PREFS_WATCHER_H_ diff --git a/chrome/browser/protector/protected_prefs_watcher_unittest.cc b/chrome/browser/protector/protected_prefs_watcher_unittest.cc new file mode 100644 index 0000000..b1ec3ae --- /dev/null +++ b/chrome/browser/protector/protected_prefs_watcher_unittest.cc @@ -0,0 +1,141 @@ +// 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 "base/message_loop.h" +#include "base/values.h" +#include "chrome/browser/extensions/extension_pref_value_map.h" +#include "chrome/browser/extensions/extension_prefs.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/protector/protected_prefs_watcher.h" +#include "chrome/browser/protector/protector_service.h" +#include "chrome/browser/protector/protector_service_factory.h" +#include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_profile.h" +#include "content/test/test_browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace protector { + +namespace { + +const char kNewHomePage[] = "http://example.com"; + +} + +class ProtectedPrefsWatcherTest : public testing::Test { + public: + virtual void SetUp() OVERRIDE { + prefs_watcher_ = + ProtectorServiceFactory::GetForProfile(&profile_)->GetPrefsWatcher(); + prefs_ = profile_.GetPrefs(); + } + + bool IsSignatureValid() { + return prefs_watcher_->IsSignatureValid(); + } + + bool HasBackup() { + return prefs_watcher_->HasBackup(); + } + + void RevalidateBackup() { + prefs_watcher_->ValidateBackup(); + } + + protected: + ProtectedPrefsWatcher* prefs_watcher_; + TestingProfile profile_; + PrefService* prefs_; +}; + +TEST_F(ProtectedPrefsWatcherTest, ValidOnCleanProfile) { + EXPECT_TRUE(HasBackup()); + EXPECT_TRUE(IsSignatureValid()); + EXPECT_TRUE(prefs_watcher_->is_backup_valid()); +} + +TEST_F(ProtectedPrefsWatcherTest, ValidAfterPrefChange) { + // Signature is still valid after a protected pref has been changed. + base::StringValue new_homepage(kNewHomePage); + EXPECT_NE(prefs_->GetString(prefs::kHomePage), kNewHomePage); + EXPECT_FALSE(new_homepage.Equals( + prefs_watcher_->GetBackupForPref(prefs::kHomePage))); + + prefs_->SetString(prefs::kHomePage, kNewHomePage); + + EXPECT_TRUE(HasBackup()); + EXPECT_TRUE(IsSignatureValid()); + EXPECT_TRUE(prefs_watcher_->is_backup_valid()); + EXPECT_EQ(prefs_->GetString(prefs::kHomePage), kNewHomePage); + // Backup is updated accordingly. + EXPECT_TRUE(new_homepage.Equals( + prefs_watcher_->GetBackupForPref(prefs::kHomePage))); +} + +TEST_F(ProtectedPrefsWatcherTest, InvalidSignature) { + // Make backup invalid by changing one of its members directly. + prefs_->SetString("backup.homepage", kNewHomePage); + RevalidateBackup(); + EXPECT_TRUE(HasBackup()); + EXPECT_FALSE(IsSignatureValid()); + EXPECT_FALSE(prefs_watcher_->is_backup_valid()); + // No backup values available. + EXPECT_FALSE(prefs_watcher_->GetBackupForPref(prefs::kHomePage)); + + // Now change the corresponding protected prefernce: backup should be signed + // again but still invalid. + prefs_->SetString(prefs::kHomePage, kNewHomePage); + EXPECT_TRUE(IsSignatureValid()); + EXPECT_FALSE(prefs_watcher_->is_backup_valid()); + EXPECT_FALSE(prefs_watcher_->GetBackupForPref(prefs::kHomePage)); +} + +TEST_F(ProtectedPrefsWatcherTest, ExtensionPrefChange) { + // Changes to extensions data (but not to extension IDs) do not update + // the backup and its signature. + MessageLoopForUI message_loop; + content::TestBrowserThread ui_thread(content::BrowserThread::UI, + &message_loop); + + FilePath extensions_install_dir = + profile_.GetPath().AppendASCII(ExtensionService::kInstallDirectoryName); + scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_( + new ExtensionPrefValueMap); + scoped_ptr<ExtensionPrefs> extension_prefs( + new ExtensionPrefs(profile_.GetPrefs(), + extensions_install_dir, + extension_pref_value_map_.get())); + std::string sample_id = extension_misc::kWebStoreAppId; + extension_prefs->Init(false); + // Flip a pref value of an extension (this will actually add it to the list). + extension_prefs->SetAppNotificationDisabled( + sample_id, !extension_prefs->IsAppNotificationDisabled(sample_id)); + + // Backup is still valid. + EXPECT_TRUE(IsSignatureValid()); + EXPECT_TRUE(prefs_watcher_->is_backup_valid()); + + // Make backup invalid by changing one of its members directly. + prefs_->SetString("backup.homepage", kNewHomePage); + RevalidateBackup(); + EXPECT_FALSE(IsSignatureValid()); + + // Flip another pref value of that extension. + extension_prefs->SetIsIncognitoEnabled( + sample_id, !extension_prefs->IsIncognitoEnabled(sample_id)); + + // No changes to the backup and signature. + EXPECT_FALSE(IsSignatureValid()); + + // Blacklisting the extension does update the backup and signature. + std::set<std::string> blacklist; + blacklist.insert(sample_id); + extension_prefs->UpdateBlacklist(blacklist); + + EXPECT_TRUE(IsSignatureValid()); +} + +} // namespace protector diff --git a/chrome/browser/protector/protector_service.cc b/chrome/browser/protector/protector_service.cc index 93e353d..b35c294 100644 --- a/chrome/browser/protector/protector_service.cc +++ b/chrome/browser/protector/protector_service.cc @@ -10,6 +10,7 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/protector/settings_change_global_error.h" #include "chrome/browser/protector/keys.h" +#include "chrome/browser/protector/protected_prefs_watcher.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" @@ -22,6 +23,8 @@ namespace protector { ProtectorService::ProtectorService(Profile* profile) : profile_(profile), has_active_change_(false) { + // Start observing pref changes. + prefs_watcher_.reset(new ProtectedPrefsWatcher(profile)); } ProtectorService::~ProtectorService() { @@ -74,6 +77,10 @@ void ProtectorService::OpenTab(const GURL& url, Browser* browser) { browser->ShowSingletonTab(url); } +ProtectedPrefsWatcher* ProtectorService::GetPrefsWatcher() { + return prefs_watcher_.get(); +} + void ProtectorService::Shutdown() { while (IsShowingChange()) items_[0].error->RemoveFromProfile(); diff --git a/chrome/browser/protector/protector_service.h b/chrome/browser/protector/protector_service.h index 942e567..59ce7f0 100644 --- a/chrome/browser/protector/protector_service.h +++ b/chrome/browser/protector/protector_service.h @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/linked_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/message_loop_helpers.h" #include "chrome/browser/profiles/profile_keyed_service.h" #include "chrome/browser/protector/base_setting_change.h" @@ -23,6 +24,7 @@ class TemplateURLService; namespace protector { +class ProtectedPrefsWatcher; class SettingsChangeGlobalError; // Presents a SettingChange to user and handles possible user actions. @@ -56,6 +58,10 @@ class ProtectorService : public ProfileKeyedService, // bubble for. virtual void OpenTab(const GURL& url, Browser* browser); + // Returns the ProtectedPrefsWatcher instance for access to protected prefs + // backup. + ProtectedPrefsWatcher* GetPrefsWatcher(); + // Returns the most recent change instance or NULL if there are no changes. BaseSettingChange* GetLastChange(); @@ -65,7 +71,8 @@ class ProtectorService : public ProfileKeyedService, private: friend class ProtectorServiceTest; - // Pair of error and corresponding change instance. + // Pair of error and corresponding change instance. linked_ptr is used because + // Item instances are stored in a std::vector and must be copyable. struct Item { Item(); ~Item(); @@ -117,6 +124,9 @@ class ProtectorService : public ProfileKeyedService, // discarded by user. bool has_active_change_; + // Observes changes to protected prefs and updates the backup. + scoped_ptr<ProtectedPrefsWatcher> prefs_watcher_; + DISALLOW_COPY_AND_ASSIGN(ProtectorService); }; diff --git a/chrome/browser/protector/protector_service_factory.cc b/chrome/browser/protector/protector_service_factory.cc index 504673c..ceb487b 100644 --- a/chrome/browser/protector/protector_service_factory.cc +++ b/chrome/browser/protector/protector_service_factory.cc @@ -6,6 +6,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_dependency_manager.h" +#include "chrome/browser/protector/protected_prefs_watcher.h" #include "chrome/browser/protector/protector_service.h" #include "chrome/browser/search_engines/template_url_service_factory.h" @@ -25,8 +26,13 @@ ProtectorServiceFactory* ProtectorServiceFactory::GetInstance() { ProtectorServiceFactory::ProtectorServiceFactory() : ProfileKeyedServiceFactory("ProtectorService", ProfileDependencyManager::GetInstance()) { + // Dependencies for the correct service shutdown order. DependsOn(GlobalErrorServiceFactory::GetInstance()); DependsOn(TemplateURLServiceFactory::GetInstance()); + // BUG(ivankr): to be bullet-proof, ProtectorService must outlive the + // ExtensionService as well and be the second to last thing destroyed in + // ProfileImpl (the last being the PrefService itself). This cannot be + // accomplished with ProfileKeyedService implementation. } ProtectorServiceFactory::~ProtectorServiceFactory() { @@ -37,6 +43,16 @@ ProfileKeyedService* ProtectorServiceFactory::BuildServiceInstanceFor( return new ProtectorService(profile); } +void ProtectorServiceFactory::RegisterUserPrefs(PrefService* user_prefs) { + ProtectedPrefsWatcher::RegisterUserPrefs(user_prefs); +} + +bool ProtectorServiceFactory::ServiceIsCreatedWithProfile() { + // ProtectorService watches changes for protected prefs so it must be started + // right with the profile creation. + return true; +} + bool ProtectorServiceFactory::ServiceRedirectedInIncognito() { return true; } diff --git a/chrome/browser/protector/protector_service_factory.h b/chrome/browser/protector/protector_service_factory.h index e78186a..5d95979 100644 --- a/chrome/browser/protector/protector_service_factory.h +++ b/chrome/browser/protector/protector_service_factory.h @@ -31,6 +31,8 @@ class ProtectorServiceFactory : public ProfileKeyedServiceFactory { // ProfileKeyedServiceFactory implementation. virtual ProfileKeyedService* BuildServiceInstanceFor( Profile* profile) const OVERRIDE; + virtual void RegisterUserPrefs(PrefService* user_prefs) OVERRIDE; + virtual bool ServiceIsCreatedWithProfile() OVERRIDE; virtual bool ServiceRedirectedInIncognito() OVERRIDE; DISALLOW_COPY_AND_ASSIGN(ProtectorServiceFactory); |