diff options
author | Kristian Monsen <kristianm@google.com> | 2011-06-28 21:49:31 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-07-08 17:55:00 +0100 |
commit | ddb351dbec246cf1fab5ec20d2d5520909041de1 (patch) | |
tree | 158e3fb57bdcac07c7f1e767fde3c70687c9fbb1 /chrome/browser/prefs | |
parent | 6b92e04f5f151c896e3088e86f70db7081009308 (diff) | |
download | external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.zip external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.tar.gz external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.tar.bz2 |
Merge Chromium at r12.0.742.93: Initial merge by git
Change-Id: Ic5ee2fec31358bbee305f7e915442377bfa6cda6
Diffstat (limited to 'chrome/browser/prefs')
37 files changed, 619 insertions, 255 deletions
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index b48945b..ed5e0b5 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -15,6 +15,7 @@ #include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/extensions/apps_promo.h" #include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/extension_web_ui.h" #include "chrome/browser/extensions/extensions_ui.h" @@ -33,11 +34,9 @@ #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/page_info_model.h" #include "chrome/browser/password_manager/password_manager.h" -#include "chrome/browser/policy/browser_policy_connector.h" -#include "chrome/browser/policy/profile_policy_connector.h" +#include "chrome/browser/policy/cloud_policy_subsystem.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile_impl.h" -#include "chrome/browser/renderer_host/browser_render_process_host.h" #include "chrome/browser/renderer_host/web_cache_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/search_engines/template_url_model.h" @@ -54,8 +53,10 @@ #include "chrome/browser/ui/webui/new_tab_ui.h" #include "chrome/browser/ui/webui/plugins_ui.h" #include "chrome/browser/upgrade_detector.h" +#include "chrome/browser/web_resource/promo_resource_service.h" #include "chrome/common/pref_names.h" #include "content/browser/host_zoom_map.h" +#include "content/browser/renderer_host/browser_render_process_host.h" #if defined(TOOLKIT_VIEWS) // TODO(port): whittle this down as we port #include "chrome/browser/ui/views/browser_actions_container.h" @@ -68,7 +69,7 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/audio_mixer_alsa.h" -#include "chrome/browser/chromeos/login/apply_services_customization.h" +#include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/chromeos/login/signed_settings_temp_storage.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" @@ -81,6 +82,7 @@ namespace browser { void RegisterLocalState(PrefService* local_state) { // Prefs in Local State + AppsPromo::RegisterPrefs(local_state); Browser::RegisterPrefs(local_state); FlagsUI::RegisterPrefs(local_state); WebCacheManager::RegisterPrefs(local_state); @@ -90,6 +92,7 @@ void RegisterLocalState(PrefService* local_state) { KeywordEditorController::RegisterPrefs(local_state); MetricsLog::RegisterPrefs(local_state); MetricsService::RegisterPrefs(local_state); + PromoResourceService::RegisterPrefs(local_state); SafeBrowsingService::RegisterPrefs(local_state); browser_shutdown::RegisterPrefs(local_state); #if defined(TOOLKIT_VIEWS) @@ -99,23 +102,25 @@ void RegisterLocalState(PrefService* local_state) { TaskManager::RegisterPrefs(local_state); geolocation::RegisterPrefs(local_state); AutofillManager::RegisterBrowserPrefs(local_state); + BackgroundModeManager::RegisterPrefs(local_state); BackgroundPageTracker::RegisterPrefs(local_state); NotificationUIManager::RegisterPrefs(local_state); PrefProxyConfigService::RegisterPrefs(local_state); - policy::BrowserPolicyConnector::RegisterPrefs(local_state); + policy::CloudPolicySubsystem::RegisterPrefs(local_state); #if defined(OS_CHROMEOS) chromeos::AudioMixerAlsa::RegisterPrefs(local_state); chromeos::UserManager::RegisterPrefs(local_state); chromeos::UserCrosSettingsProvider::RegisterPrefs(local_state); WizardController::RegisterPrefs(local_state); chromeos::InputMethodMenu::RegisterPrefs(local_state); - chromeos::ApplyServicesCustomization::RegisterPrefs(local_state); + chromeos::ServicesCustomizationDocument::RegisterPrefs(local_state); chromeos::SignedSettingsTempStorage::RegisterPrefs(local_state); #endif } void RegisterUserPrefs(PrefService* user_prefs) { // User prefs + AppsPromo::RegisterUserPrefs(user_prefs); AutofillManager::RegisterUserPrefs(user_prefs); SessionStartupPref::RegisterUserPrefs(user_prefs); Browser::RegisterUserPrefs(user_prefs); @@ -130,6 +135,7 @@ void RegisterUserPrefs(PrefService* user_prefs) { NewTabUI::RegisterUserPrefs(user_prefs); PluginsUI::RegisterUserPrefs(user_prefs); ProfileImpl::RegisterUserPrefs(user_prefs); + PromoResourceService::RegisterUserPrefs(user_prefs); HostContentSettingsMap::RegisterUserPrefs(user_prefs); HostZoomMap::RegisterUserPrefs(user_prefs); DevToolsManager::RegisterUserPrefs(user_prefs); @@ -152,7 +158,7 @@ void RegisterUserPrefs(PrefService* user_prefs) { TemplateURLModel::RegisterUserPrefs(user_prefs); InstantController::RegisterUserPrefs(user_prefs); NetPrefObserver::RegisterPrefs(user_prefs); - policy::ProfilePolicyConnector::RegisterPrefs(user_prefs); + policy::CloudPolicySubsystem::RegisterPrefs(user_prefs); ProtocolHandlerRegistry::RegisterPrefs(user_prefs); } @@ -176,9 +182,10 @@ void MigrateBrowserPrefs(PrefService* user_prefs, PrefService* local_state) { local_state->RegisterDictionaryPref(prefs::kBrowserWindowPlacement); DCHECK(user_prefs->FindPreference(prefs::kBrowserWindowPlacement)); if (local_state->HasPrefPath(prefs::kBrowserWindowPlacement)) { - user_prefs->Set(prefs::kBrowserWindowPlacement, - *(local_state->FindPreference(prefs::kBrowserWindowPlacement)-> - GetValue())); + const PrefService::Preference* pref = + local_state->FindPreference(prefs::kBrowserWindowPlacement); + DCHECK(pref); + user_prefs->Set(prefs::kBrowserWindowPlacement, *(pref->GetValue())); } local_state->ClearPref(prefs::kBrowserWindowPlacement); diff --git a/chrome/browser/prefs/command_line_pref_store.cc b/chrome/browser/prefs/command_line_pref_store.cc index 97e0d39..2f4c316 100644 --- a/chrome/browser/prefs/command_line_pref_store.cc +++ b/chrome/browser/prefs/command_line_pref_store.cc @@ -4,7 +4,6 @@ #include "chrome/browser/prefs/command_line_pref_store.h" -#include "app/app_switches.h" #include "base/logging.h" #include "base/values.h" #include "chrome/browser/prefs/proxy_config_dictionary.h" @@ -31,6 +30,9 @@ const CommandLinePrefStore::BooleanSwitchToPreferenceMapEntry { switches::kDisable3DAPIs, prefs::kDisable3DAPIs, true }, { switches::kEnableCloudPrintProxy, prefs::kCloudPrintProxyEnabled, true }, + { switches::kAllowOutdatedPlugins, prefs::kPluginsAllowOutdated, true }, + { switches::kNoPings, prefs::kEnableHyperlinkAuditing, false }, + { switches::kNoReferrers, prefs::kEnableReferrers, false }, }; CommandLinePrefStore::CommandLinePrefStore(const CommandLine* command_line) diff --git a/chrome/browser/prefs/command_line_pref_store.h b/chrome/browser/prefs/command_line_pref_store.h index 75d8b10..6a654e7 100644 --- a/chrome/browser/prefs/command_line_pref_store.h +++ b/chrome/browser/prefs/command_line_pref_store.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -8,7 +8,7 @@ #include "base/basictypes.h" #include "base/command_line.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/values.h" #include "chrome/browser/prefs/value_map_pref_store.h" diff --git a/chrome/browser/prefs/command_line_pref_store_unittest.cc b/chrome/browser/prefs/command_line_pref_store_unittest.cc index edc88d9..aa4eeb6 100644 --- a/chrome/browser/prefs/command_line_pref_store_unittest.cc +++ b/chrome/browser/prefs/command_line_pref_store_unittest.cc @@ -4,9 +4,8 @@ #include <gtest/gtest.h> -#include "app/app_switches.h" #include "base/command_line.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/string_util.h" #include "base/values.h" #include "chrome/browser/prefs/command_line_pref_store.h" @@ -27,10 +26,10 @@ class TestCommandLinePrefStore : public CommandLinePrefStore { } void VerifyProxyMode(ProxyPrefs::ProxyMode expected_mode) { - Value* value = NULL; + const Value* value = NULL; ASSERT_EQ(PrefStore::READ_OK, GetValue(prefs::kProxy, &value)); ASSERT_EQ(Value::TYPE_DICTIONARY, value->GetType()); - ProxyConfigDictionary dict(static_cast<DictionaryValue*>(value)); + ProxyConfigDictionary dict(static_cast<const DictionaryValue*>(value)); ProxyPrefs::ProxyMode actual_mode; ASSERT_TRUE(dict.GetMode(&actual_mode)); EXPECT_EQ(expected_mode, actual_mode); @@ -48,7 +47,7 @@ TEST(CommandLinePrefStoreTest, SimpleStringPref) { cl.AppendSwitchASCII(switches::kLang, "hi-MOM"); scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl); - Value* actual = NULL; + const Value* actual = NULL; EXPECT_EQ(PrefStore::READ_OK, store->GetValue(prefs::kApplicationLocale, &actual)); std::string result; @@ -73,7 +72,7 @@ TEST(CommandLinePrefStoreTest, NoPrefs) { cl.AppendSwitchASCII(unknown_bool, "a value"); scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl); - Value* actual = NULL; + const Value* actual = NULL; EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_bool, &actual)); EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_string, &actual)); } @@ -88,16 +87,16 @@ TEST(CommandLinePrefStoreTest, MultipleSwitches) { scoped_refptr<TestCommandLinePrefStore> store = new TestCommandLinePrefStore(&cl); - Value* actual = NULL; + const Value* actual = NULL; EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_bool, &actual)); EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_string, &actual)); store->VerifyProxyMode(ProxyPrefs::MODE_FIXED_SERVERS); - Value* value = NULL; + const Value* value = NULL; ASSERT_EQ(PrefStore::READ_OK, store->GetValue(prefs::kProxy, &value)); ASSERT_EQ(Value::TYPE_DICTIONARY, value->GetType()); - ProxyConfigDictionary dict(static_cast<DictionaryValue*>(value)); + ProxyConfigDictionary dict(static_cast<const DictionaryValue*>(value)); std::string string_result = ""; diff --git a/chrome/browser/prefs/default_pref_store.cc b/chrome/browser/prefs/default_pref_store.cc index cacc833..8e43438 100644 --- a/chrome/browser/prefs/default_pref_store.cc +++ b/chrome/browser/prefs/default_pref_store.cc @@ -14,7 +14,7 @@ void DefaultPrefStore::SetDefaultValue(const std::string& key, Value* value) { } Value::ValueType DefaultPrefStore::GetType(const std::string& key) const { - Value* value; + const Value* value; return GetValue(key, &value) == READ_OK ? value->GetType() : Value::TYPE_NULL; } diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.cc b/chrome/browser/prefs/overlay_persistent_pref_store.cc index 42fe389..e75fbc6 100644 --- a/chrome/browser/prefs/overlay_persistent_pref_store.cc +++ b/chrome/browser/prefs/overlay_persistent_pref_store.cc @@ -4,6 +4,8 @@ #include "chrome/browser/prefs/overlay_persistent_pref_store.h" +#include "base/values.h" + OverlayPersistentPrefStore::OverlayPersistentPrefStore( PersistentPrefStore* underlay) : underlay_(underlay) { @@ -13,6 +15,10 @@ OverlayPersistentPrefStore::~OverlayPersistentPrefStore() { underlay_->RemoveObserver(this); } +bool OverlayPersistentPrefStore::IsSetInOverlay(const std::string& key) const { + return overlay_.GetValue(key, NULL); +} + void OverlayPersistentPrefStore::AddObserver(PrefStore::Observer* observer) { observers_.AddObserver(observer); } @@ -26,12 +32,32 @@ bool OverlayPersistentPrefStore::IsInitializationComplete() const { } PrefStore::ReadResult OverlayPersistentPrefStore::GetValue( - const std::string& key, Value** result) const { + const std::string& key, + const Value** result) const { if (overlay_.GetValue(key, result)) return READ_OK; return underlay_->GetValue(key, result); } +PrefStore::ReadResult OverlayPersistentPrefStore::GetMutableValue( + const std::string& key, + Value** result) { + if (overlay_.GetValue(key, result)) + return READ_OK; + + // Try to create copy of underlay if the overlay does not contain a value. + Value* underlay_value = NULL; + PrefStore::ReadResult read_result = + underlay_->GetMutableValue(key, &underlay_value); + if (read_result == READ_OK) { + *result = underlay_value->DeepCopy(); + overlay_.SetValue(key, *result); + return READ_OK; + } + // Return read failure if underlay stores no value for |key|. + return read_result; +} + void OverlayPersistentPrefStore::SetValue(const std::string& key, Value* value) { if (overlay_.SetValue(key, value)) @@ -66,6 +92,10 @@ void OverlayPersistentPrefStore::ScheduleWritePrefs() { // We do not write intentionally. } +void OverlayPersistentPrefStore::CommitPendingWrite() { + // We do not write intentionally. +} + void OverlayPersistentPrefStore::ReportValueChanged(const std::string& key) { FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); } diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.h b/chrome/browser/prefs/overlay_persistent_pref_store.h index 1b926ad..bbb85c3 100644 --- a/chrome/browser/prefs/overlay_persistent_pref_store.h +++ b/chrome/browser/prefs/overlay_persistent_pref_store.h @@ -9,8 +9,8 @@ #include <string> #include "base/basictypes.h" +#include "base/memory/ref_counted.h" #include "base/observer_list.h" -#include "base/ref_counted.h" #include "chrome/browser/prefs/pref_value_map.h" #include "chrome/common/persistent_pref_store.h" @@ -24,13 +24,20 @@ class OverlayPersistentPrefStore : public PersistentPrefStore, explicit OverlayPersistentPrefStore(PersistentPrefStore* underlay); virtual ~OverlayPersistentPrefStore(); + // Returns true if a value has been set for the |key| in this + // OverlayPersistentPrefStore, i.e. if it potentially overrides a value + // from the |underlay_|. + virtual bool IsSetInOverlay(const std::string& key) const; + // Methods of PrefStore. virtual void AddObserver(PrefStore::Observer* observer); virtual void RemoveObserver(PrefStore::Observer* observer); virtual bool IsInitializationComplete() const; - virtual ReadResult GetValue(const std::string& key, Value** result) const; + virtual ReadResult GetValue(const std::string& key, + const Value** result) const; // Methods of PersistentPrefStore. + virtual ReadResult GetMutableValue(const std::string& key, Value** result); virtual void SetValue(const std::string& key, Value* value); virtual void SetValueSilently(const std::string& key, Value* value); virtual void RemoveValue(const std::string& key); @@ -38,7 +45,7 @@ class OverlayPersistentPrefStore : public PersistentPrefStore, virtual PrefReadError ReadPrefs(); virtual bool WritePrefs(); virtual void ScheduleWritePrefs(); - // TODO(battre) remove this function + virtual void CommitPendingWrite(); virtual void ReportValueChanged(const std::string& key); private: diff --git a/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc b/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc index 7e2e0a2..11dcc05 100644 --- a/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc +++ b/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc @@ -74,7 +74,7 @@ TEST_F(OverlayPersistentPrefStoreTest, Observer) { } TEST_F(OverlayPersistentPrefStoreTest, GetAndSet) { - Value* value = NULL; + const Value* value = NULL; int i = -1; EXPECT_EQ(PrefStore::READ_NO_VALUE, overlay_->GetValue(key, &value)); EXPECT_EQ(PrefStore::READ_NO_VALUE, underlay_->GetValue(key, &value)); @@ -117,3 +117,27 @@ TEST_F(OverlayPersistentPrefStoreTest, GetAndSet) { EXPECT_TRUE(value->GetAsInteger(&i)); EXPECT_EQ(42, i); } + +// Check that GetMutableValue does not return the dictionary of the underlay. +TEST_F(OverlayPersistentPrefStoreTest, ModifyDictionaries) { + underlay_->SetValue(key, new DictionaryValue); + + Value* modify = NULL; + EXPECT_EQ(PrefStore::READ_OK, overlay_->GetMutableValue(key, &modify)); + ASSERT_TRUE(modify); + ASSERT_TRUE(modify->GetType() == Value::TYPE_DICTIONARY); + static_cast<DictionaryValue*>(modify)->SetInteger(key, 42); + + Value* original_in_underlay = NULL; + EXPECT_EQ(PrefStore::READ_OK, + underlay_->GetMutableValue(key, &original_in_underlay)); + ASSERT_TRUE(original_in_underlay); + ASSERT_TRUE(original_in_underlay->GetType() == Value::TYPE_DICTIONARY); + EXPECT_TRUE(static_cast<DictionaryValue*>(original_in_underlay)->empty()); + + Value* modified = NULL; + EXPECT_EQ(PrefStore::READ_OK, overlay_->GetMutableValue(key, &modified)); + ASSERT_TRUE(modified); + ASSERT_TRUE(modified->GetType() == Value::TYPE_DICTIONARY); + EXPECT_TRUE(Value::Equals(modify, static_cast<DictionaryValue*>(modified))); +} diff --git a/chrome/browser/prefs/pref_member.cc b/chrome/browser/prefs/pref_member.cc index db17123..90b369b 100644 --- a/chrome/browser/prefs/pref_member.cc +++ b/chrome/browser/prefs/pref_member.cc @@ -1,14 +1,13 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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/prefs/pref_member.h" #include "base/logging.h" -#include "base/sys_string_conversions.h" -#include "base/utf_string_conversions.h" +#include "base/value_conversions.h" #include "chrome/browser/prefs/pref_service.h" -#include "chrome/common/notification_type.h" +#include "content/common/notification_type.h" namespace subtle { @@ -19,8 +18,7 @@ PrefMemberBase::PrefMemberBase() } PrefMemberBase::~PrefMemberBase() { - if (prefs_ && !pref_name_.empty()) - prefs_->RemovePrefObserver(pref_name_.c_str(), this); + Destroy(); } @@ -39,19 +37,12 @@ void PrefMemberBase::Init(const char* pref_name, PrefService* prefs, } void PrefMemberBase::Destroy() { - if (prefs_) { + if (prefs_ && !pref_name_.empty()) { prefs_->RemovePrefObserver(pref_name_.c_str(), this); prefs_ = NULL; } } -bool PrefMemberBase::IsManaged() const { - VerifyValuePrefName(); - const PrefService::Preference* pref = - prefs_->FindPreference(pref_name_.c_str()); - return pref && pref->IsManaged(); -} - void PrefMemberBase::MoveToThread(BrowserThread::ID thread_id) { VerifyValuePrefName(); // Load the value from preferences if it hasn't been loaded so far. @@ -70,10 +61,6 @@ void PrefMemberBase::Observe(NotificationType type, observer_->Observe(type, source, details); } -void PrefMemberBase::VerifyValuePrefName() const { - DCHECK(!pref_name_.empty()); -} - void PrefMemberBase::UpdateValueFromPref() const { VerifyValuePrefName(); const PrefService::Preference* pref = @@ -81,7 +68,13 @@ void PrefMemberBase::UpdateValueFromPref() const { DCHECK(pref); if (!internal()) CreateInternal(); - internal()->UpdateValue(pref->GetValue()->DeepCopy()); + internal()->UpdateValue(pref->GetValue()->DeepCopy(), pref->IsManaged()); +} + +void PrefMemberBase::VerifyPref() const { + VerifyValuePrefName(); + if (!internal()) + UpdateValueFromPref(); } PrefMemberBase::Internal::Internal() : thread_id_(BrowserThread::UI) { } @@ -94,17 +87,18 @@ bool PrefMemberBase::Internal::IsOnCorrectThread() const { !BrowserThread::IsMessageLoopValid(BrowserThread::UI))); } -void PrefMemberBase::Internal::UpdateValue(Value* v) const { +void PrefMemberBase::Internal::UpdateValue(Value* v, bool is_managed) const { scoped_ptr<Value> value(v); if (IsOnCorrectThread()) { bool rv = UpdateValueInternal(*value); DCHECK(rv); + is_managed_ = is_managed; } else { bool rv = BrowserThread::PostTask( thread_id_, FROM_HERE, NewRunnableMethod(this, &PrefMemberBase::Internal::UpdateValue, - value.release())); + value.release(), is_managed)); DCHECK(rv); } } @@ -166,6 +160,30 @@ void PrefMember<FilePath>::UpdatePref(const FilePath& value) { template <> bool PrefMember<FilePath>::Internal::UpdateValueInternal(const Value& value) const { - return value.GetAsFilePath(&value_); + return base::GetValueAsFilePath(value, &value_); +} + +template <> +void PrefMember<ListValue*>::UpdatePref(ListValue*const& value) { + // prefs takes ownership of the value passed, so make a copy. + prefs()->SetList(pref_name().c_str(), value->DeepCopy()); +} + +template <> +bool PrefMember<ListValue*>::Internal::UpdateValueInternal(const Value& value) + const { + // Verify the type before doing the DeepCopy to avoid leaking the copy. + if (value.GetType() != Value::TYPE_LIST) + return false; + + // ListPrefMember keeps a copy of the ListValue and of its contents. + // GetAsList() assigns its |this| (the DeepCopy) to |value_|. + delete value_; + return value.DeepCopy()->GetAsList(&value_); +} + +template <> +PrefMember<ListValue*>::Internal::~Internal() { + delete value_; } diff --git a/chrome/browser/prefs/pref_member.h b/chrome/browser/prefs/pref_member.h index c82e810..5fdd91d 100644 --- a/chrome/browser/prefs/pref_member.h +++ b/chrome/browser/prefs/pref_member.h @@ -29,10 +29,10 @@ #include "base/basictypes.h" #include "base/file_path.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/values.h" -#include "chrome/common/notification_observer.h" #include "content/browser/browser_thread.h" +#include "content/common/notification_observer.h" class PrefService; @@ -47,10 +47,15 @@ class PrefMemberBase : public NotificationObserver { // Update the value, either by calling |UpdateValueInternal| directly // or by dispatching to the right thread. // Takes ownership of |value|. - virtual void UpdateValue(Value* value) const; + virtual void UpdateValue(Value* value, bool is_managed) const; void MoveToThread(BrowserThread::ID thread_id); + // See PrefMember<> for description. + bool IsManaged() const { + return is_managed_; + } + protected: friend class base::RefCountedThreadSafe<Internal>; virtual ~Internal(); @@ -67,6 +72,7 @@ class PrefMemberBase : public NotificationObserver { bool IsOnCorrectThread() const; BrowserThread::ID thread_id_; + mutable bool is_managed_; DISALLOW_COPY_AND_ASSIGN(Internal); }; @@ -83,9 +89,6 @@ class PrefMemberBase : public NotificationObserver { // See PrefMember<> for description. void Destroy(); - // See PrefMember<> for description. - bool IsManaged() const; - void MoveToThread(BrowserThread::ID thread_id); // NotificationObserver @@ -93,13 +96,19 @@ class PrefMemberBase : public NotificationObserver { const NotificationSource& source, const NotificationDetails& details); - void VerifyValuePrefName() const; + void VerifyValuePrefName() const { + DCHECK(!pref_name_.empty()); + } // This method is used to do the actual sync with the preference. // Note: it is logically const, because it doesn't modify the state // seen by the outside world. It is just doing a lazy load behind the scenes. virtual void UpdateValueFromPref() const; + // Verifies the preference name, and lazily loads the preference value if + // it hasn't been loaded yet. + void VerifyPref() const; + const std::string& pref_name() const { return pref_name_; } PrefService* prefs() { return prefs_; } const PrefService* prefs() const { return prefs_; } @@ -153,20 +162,18 @@ class PrefMember : public subtle::PrefMemberBase { // Check whether the pref is managed, i.e. controlled externally through // enterprise configuration management (e.g. windows group policy). Returns // false for unknown prefs. - // This method should only be called on the UI thread. + // This method should only be used from the thread the PrefMember is currently + // on, which is the UI thread unless changed by |MoveToThread|. bool IsManaged() const { - return subtle::PrefMemberBase::IsManaged(); + VerifyPref(); + return internal_->IsManaged(); } // Retrieve the value of the member variable. // This method should only be used from the thread the PrefMember is currently // on, which is the UI thread unless changed by |MoveToThread|. ValueType GetValue() const { - VerifyValuePrefName(); - // We lazily fetch the value from the pref service the first time GetValue - // is called. - if (!internal_.get()) - UpdateValueFromPref(); + VerifyPref(); return internal_->value(); } @@ -237,5 +244,6 @@ typedef PrefMember<int> IntegerPrefMember; typedef PrefMember<double> DoublePrefMember; typedef PrefMember<std::string> StringPrefMember; typedef PrefMember<FilePath> FilePathPrefMember; +typedef PrefMember<ListValue*> ListPrefMember; #endif // CHROME_BROWSER_PREFS_PREF_MEMBER_H_ diff --git a/chrome/browser/prefs/pref_member_unittest.cc b/chrome/browser/prefs/pref_member_unittest.cc index b47a881..b8079dd 100644 --- a/chrome/browser/prefs/pref_member_unittest.cc +++ b/chrome/browser/prefs/pref_member_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -6,11 +6,11 @@ #include "base/message_loop.h" #include "chrome/browser/prefs/pref_value_store.h" -#include "chrome/common/notification_details.h" -#include "chrome/common/notification_source.h" -#include "chrome/common/notification_type.h" #include "chrome/test/testing_pref_service.h" #include "content/browser/browser_thread.h" +#include "content/common/notification_details.h" +#include "content/common/notification_source.h" +#include "content/common/notification_type.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -19,12 +19,14 @@ const char kBoolPref[] = "bool"; const char kIntPref[] = "int"; const char kDoublePref[] = "double"; const char kStringPref[] = "string"; +const char kListPref[] = "list"; void RegisterTestPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(kBoolPref, false); prefs->RegisterIntegerPref(kIntPref, 0); prefs->RegisterDoublePref(kDoublePref, 0.0); prefs->RegisterStringPref(kStringPref, "default"); + prefs->RegisterListPref(kListPref); } class GetPrefValueCallback @@ -179,6 +181,42 @@ TEST(PrefMemberTest, BasicGetAndSet) { EXPECT_EQ("bar", prefs.GetString(kStringPref)); EXPECT_EQ("bar", string.GetValue()); EXPECT_EQ("bar", *string); + + // Test list + ListPrefMember list; + list.Init(kListPref, &prefs, NULL); + + // Check the defaults + const ListValue* list_value = prefs.GetList(kListPref); + ASSERT_TRUE(list_value != NULL); + EXPECT_EQ(0u, list_value->GetSize()); + EXPECT_TRUE(list_value->empty()); + ASSERT_TRUE(list.GetValue() != NULL); + EXPECT_EQ(0u, list.GetValue()->GetSize()); + EXPECT_TRUE(list.GetValue()->empty()); + ASSERT_TRUE(*list != NULL); + EXPECT_EQ(0u, (*list)->GetSize()); + EXPECT_TRUE((*list)->empty()); + + // Try changing through the member variable. + scoped_ptr<ListValue> list_value_numbers(new ListValue()); + list_value_numbers->Append(new StringValue("one")); + list_value_numbers->Append(new StringValue("two")); + list_value_numbers->Append(new StringValue("three")); + list.SetValue(list_value_numbers.get()); + EXPECT_TRUE(list_value_numbers->Equals(list.GetValue())); + EXPECT_TRUE(list_value_numbers->Equals(prefs.GetList(kListPref))); + EXPECT_TRUE(list_value_numbers->Equals(*list)); + + // Try changing back through the pref. + ListValue* list_value_ints = new ListValue(); + list_value_ints->Append(new FundamentalValue(1)); + list_value_ints->Append(new FundamentalValue(2)); + list_value_ints->Append(new FundamentalValue(3)); + prefs.SetList(kListPref, list_value_ints); // takes ownership + EXPECT_TRUE(list_value_ints->Equals(list.GetValue())); + EXPECT_TRUE(list_value_ints->Equals(prefs.GetList(kListPref))); + EXPECT_TRUE(list_value_ints->Equals(*list)); } TEST(PrefMemberTest, TwoPrefs) { @@ -234,16 +272,15 @@ TEST(PrefMemberTest, NoInit) { IntegerPrefMember pref; } -// Flakily triggers an assertion, http://crbug.com/74386. -TEST(PrefMemberTest, DISABLED_MoveToThread) { +TEST(PrefMemberTest, MoveToThread) { + TestingPrefService prefs; + scoped_refptr<GetPrefValueCallback> callback = + make_scoped_refptr(new GetPrefValueCallback()); MessageLoop message_loop; BrowserThread ui_thread(BrowserThread::UI, &message_loop); BrowserThread io_thread(BrowserThread::IO); ASSERT_TRUE(io_thread.Start()); - TestingPrefService prefs; RegisterTestPrefs(&prefs); - scoped_refptr<GetPrefValueCallback> callback = - make_scoped_refptr(new GetPrefValueCallback()); callback->Init(kBoolPref, &prefs); ASSERT_TRUE(callback->FetchValue()); diff --git a/chrome/browser/prefs/pref_notifier_impl.cc b/chrome/browser/prefs/pref_notifier_impl.cc index d15f425..d5ad24c 100644 --- a/chrome/browser/prefs/pref_notifier_impl.cc +++ b/chrome/browser/prefs/pref_notifier_impl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -6,8 +6,8 @@ #include "base/stl_util-inl.h" #include "chrome/browser/prefs/pref_service.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_service.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_service.h" PrefNotifierImpl::PrefNotifierImpl(PrefService* service) : pref_service_(service) { diff --git a/chrome/browser/prefs/pref_observer_mock.h b/chrome/browser/prefs/pref_observer_mock.h index 0c651ca..eac1c13 100644 --- a/chrome/browser/prefs/pref_observer_mock.h +++ b/chrome/browser/prefs/pref_observer_mock.h @@ -9,10 +9,10 @@ #include <string> #include "chrome/browser/prefs/pref_service.h" -#include "chrome/common/notification_details.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_source.h" -#include "chrome/common/notification_type.h" +#include "content/common/notification_details.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_source.h" +#include "content/common/notification_type.h" #include "testing/gmock/include/gmock/gmock.h" using testing::Pointee; diff --git a/chrome/browser/prefs/pref_service.cc b/chrome/browser/prefs/pref_service.cc index ac2b5ec..aa71108 100644 --- a/chrome/browser/prefs/pref_service.cc +++ b/chrome/browser/prefs/pref_service.cc @@ -16,8 +16,7 @@ #include "base/stl_util-inl.h" #include "base/string_number_conversions.h" #include "base/string_util.h" -#include "base/sys_string_conversions.h" -#include "base/utf_string_conversions.h" +#include "base/value_conversions.h" #include "build/build_config.h" #include "chrome/browser/extensions/extension_pref_store.h" #include "chrome/browser/policy/configuration_policy_pref_store.h" @@ -26,9 +25,10 @@ #include "chrome/browser/prefs/overlay_persistent_pref_store.h" #include "chrome/browser/prefs/pref_notifier_impl.h" #include "chrome/browser/prefs/pref_value_store.h" +#include "chrome/browser/ui/profile_error_dialog.h" #include "chrome/common/json_pref_store.h" -#include "chrome/common/notification_service.h" #include "content/browser/browser_thread.h" +#include "content/common/notification_service.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -78,9 +78,7 @@ Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) { // Forwards a notification after a PostMessage so that we can wait for the // MessageLoop to run. void NotifyReadError(PrefService* pref, int message_id) { - Source<PrefService> source(pref); - NotificationService::current()->Notify(NotificationType::PROFILE_ERROR, - source, Details<int>(&message_id)); + ShowProfileErrorDialog(message_id); } } // namespace @@ -89,6 +87,15 @@ void NotifyReadError(PrefService* pref, int message_id) { PrefService* PrefService::CreatePrefService(const FilePath& pref_filename, PrefStore* extension_prefs, Profile* profile) { + return CreatePrefServiceAsync(pref_filename, extension_prefs, profile, NULL); +} + +// static +PrefService* PrefService::CreatePrefServiceAsync( + const FilePath& pref_filename, + PrefStore* extension_prefs, + Profile* profile, + PrefService::Delegate* delegate) { using policy::ConfigurationPolicyPrefStore; #if defined(OS_LINUX) @@ -122,7 +129,7 @@ PrefService* PrefService::CreatePrefService(const FilePath& pref_filename, return new PrefService(managed_platform, managed_cloud, extension_prefs, command_line, user, recommended_platform, - recommended_cloud, default_pref_store); + recommended_cloud, default_pref_store, delegate); } PrefService* PrefService::CreateIncognitoPrefService( @@ -137,9 +144,11 @@ PrefService::PrefService(PrefStore* managed_platform_prefs, PersistentPrefStore* user_prefs, PrefStore* recommended_platform_prefs, PrefStore* recommended_cloud_prefs, - DefaultPrefStore* default_store) + DefaultPrefStore* default_store, + PrefService::Delegate* delegate) : user_pref_store_(user_prefs), - default_store_(default_store) { + default_store_(default_store), + delegate_(delegate) { pref_notifier_.reset(new PrefNotifierImpl(this)); pref_value_store_.reset( new PrefValueStore(managed_platform_prefs, @@ -158,7 +167,8 @@ PrefService::PrefService(const PrefService& original, PrefStore* incognito_extension_prefs) : user_pref_store_( new OverlayPersistentPrefStore(original.user_pref_store_.get())), - default_store_(original.default_store_.get()){ + default_store_(original.default_store_.get()), + delegate_(NULL) { pref_notifier_.reset(new PrefNotifierImpl(this)); pref_value_store_.reset(original.pref_value_store_->CloneAndSpecialize( NULL, // managed_platform_prefs @@ -184,27 +194,48 @@ PrefService::~PrefService() { default_store_ = NULL; } -void PrefService::InitFromStorage() { - const PersistentPrefStore::PrefReadError error = - user_pref_store_->ReadPrefs(); - if (error == PersistentPrefStore::PREF_READ_ERROR_NONE) +void PrefService::OnPrefsRead(PersistentPrefStore::PrefReadError error, + bool no_dir) { + if (no_dir) { + // Bad news. When profile is created, the process that creates the directory + // is explicitly started. So if directory is missing it probably means that + // Chromium hasn't sufficient privileges. + CHECK(delegate_); + delegate_->OnPrefsLoaded(this, false); return; + } - // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for - // an example problem that this can cause. - // Do some diagnosis and try to avoid losing data. - int message_id = 0; - if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) { - message_id = IDS_PREFERENCES_CORRUPT_ERROR; - } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) { - message_id = IDS_PREFERENCES_UNREADABLE_ERROR; + if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) { + // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for + // an example problem that this can cause. + // Do some diagnosis and try to avoid losing data. + int message_id = 0; + if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) { + message_id = IDS_PREFERENCES_CORRUPT_ERROR; + } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) { + message_id = IDS_PREFERENCES_UNREADABLE_ERROR; + } + + if (message_id) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableFunction(&NotifyReadError, this, message_id)); + } + UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20); } - if (message_id) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - NewRunnableFunction(&NotifyReadError, this, message_id)); + if (delegate_) + delegate_->OnPrefsLoaded(this, true); +} + +void PrefService::InitFromStorage() { + if (!delegate_) { + const PersistentPrefStore::PrefReadError error = + user_pref_store_->ReadPrefs(); + OnPrefsRead(error, false); + } else { + // todo(altimofeev): move this method to PersistentPrefStore interface. + (static_cast<JsonPrefStore*>(user_pref_store_.get()))->ReadPrefs(this); } - UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20); } bool PrefService::ReloadPersistentPrefs() { @@ -214,16 +245,19 @@ bool PrefService::ReloadPersistentPrefs() { bool PrefService::SavePersistentPrefs() { DCHECK(CalledOnValidThread()); - return user_pref_store_->WritePrefs(); } void PrefService::ScheduleSavePersistentPrefs() { DCHECK(CalledOnValidThread()); - user_pref_store_->ScheduleWritePrefs(); } +void PrefService::CommitPendingWrite() { + DCHECK(CalledOnValidThread()); + user_pref_store_->CommitPendingWrite(); +} + void PrefService::RegisterBooleanPref(const char* path, bool default_value) { RegisterPreference(path, Value::CreateBooleanValue(default_value)); @@ -362,7 +396,7 @@ FilePath PrefService::GetFilePath(const char* path) const { NOTREACHED() << "Trying to read an unregistered pref: " << path; return FilePath(result); } - bool rv = pref->GetValue()->GetAsFilePath(&result); + bool rv = base::GetValueAsFilePath(*pref->GetValue(), &result); DCHECK(rv); return result; } @@ -377,7 +411,10 @@ DictionaryValue* PrefService::GetPreferenceValues() const { DictionaryValue* out = new DictionaryValue; DefaultPrefStore::const_iterator i = default_store_->begin(); for (; i != default_store_->end(); ++i) { - const Value* value = FindPreference(i->first.c_str())->GetValue(); + const Preference* pref = FindPreference(i->first.c_str()); + DCHECK(pref); + const Value* value = pref->GetValue(); + DCHECK(value); out->Set(i->first, value->DeepCopy()); } return out; @@ -402,10 +439,6 @@ bool PrefService::ReadOnly() const { return user_pref_store_->ReadOnly(); } -PrefNotifier* PrefService::pref_notifier() const { - return pref_notifier_.get(); -} - bool PrefService::IsManagedPreference(const char* pref_name) const { const Preference* pref = FindPreference(pref_name); return pref && pref->IsManaged(); @@ -518,7 +551,11 @@ void PrefService::SetString(const char* path, const std::string& value) { } void PrefService::SetFilePath(const char* path, const FilePath& value) { - SetUserPrefValue(path, Value::CreateFilePathValue(value)); + SetUserPrefValue(path, base::CreateFilePathValue(value)); +} + +void PrefService::SetList(const char* path, ListValue* value) { + SetUserPrefValue(path, value); } void PrefService::SetInt64(const char* path, int64 value) { @@ -547,7 +584,9 @@ void PrefService::RegisterInt64Pref(const char* path, int64 default_value) { path, Value::CreateStringValue(base::Int64ToString(default_value))); } -DictionaryValue* PrefService::GetMutableDictionary(const char* path) { +Value* PrefService::GetMutableUserPref(const char* path, + Value::ValueType type) { + CHECK(type == Value::TYPE_DICTIONARY || type == Value::TYPE_LIST); DCHECK(CalledOnValidThread()); DLOG_IF(WARNING, IsManagedPreference(path)) << "Attempt to change managed preference " << path; @@ -557,57 +596,30 @@ DictionaryValue* PrefService::GetMutableDictionary(const char* path) { NOTREACHED() << "Trying to get an unregistered pref: " << path; return NULL; } - if (pref->GetType() != Value::TYPE_DICTIONARY) { - NOTREACHED() << "Wrong type for GetMutableDictionary: " << path; + if (pref->GetType() != type) { + NOTREACHED() << "Wrong type for GetMutableValue: " << path; return NULL; } - DictionaryValue* dict = NULL; - Value* tmp_value = NULL; // Look for an existing preference in the user store. If it doesn't // exist or isn't the correct type, create a new user preference. - if (user_pref_store_->GetValue(path, &tmp_value) + Value* value = NULL; + if (user_pref_store_->GetMutableValue(path, &value) != PersistentPrefStore::READ_OK || - !tmp_value->IsType(Value::TYPE_DICTIONARY)) { - dict = new DictionaryValue; - user_pref_store_->SetValueSilently(path, dict); - } else { - dict = static_cast<DictionaryValue*>(tmp_value); - } - return dict; -} - -ListValue* PrefService::GetMutableList(const char* path) { - DCHECK(CalledOnValidThread()); - DLOG_IF(WARNING, IsManagedPreference(path)) << - "Attempt to change managed preference " << path; - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to get an unregistered pref: " << path; - return NULL; - } - if (pref->GetType() != Value::TYPE_LIST) { - NOTREACHED() << "Wrong type for GetMutableList: " << path; - return NULL; - } - - ListValue* list = NULL; - Value* tmp_value = NULL; - // Look for an existing preference in the user store. If it doesn't - // exist or isn't the correct type, create a new user preference. - if (user_pref_store_->GetValue(path, &tmp_value) - != PersistentPrefStore::READ_OK || - !tmp_value->IsType(Value::TYPE_LIST)) { - list = new ListValue; - user_pref_store_->SetValueSilently(path, list); - } else { - list = static_cast<ListValue*>(tmp_value); + !value->IsType(type)) { + if (type == Value::TYPE_DICTIONARY) { + value = new DictionaryValue; + } else if (type == Value::TYPE_LIST) { + value = new ListValue; + } else { + NOTREACHED(); + } + user_pref_store_->SetValueSilently(path, value); } - return list; + return value; } -void PrefService::ReportValueChanged(const std::string& key) { +void PrefService::ReportUserPrefChanged(const std::string& key) { user_pref_store_->ReportValueChanged(key); } @@ -652,7 +664,7 @@ const Value* PrefService::Preference::GetValue() const { DCHECK(pref_service_->FindPreference(name_.c_str())) << "Must register pref before getting its value"; - Value* found_value = NULL; + const Value* found_value = NULL; if (pref_value_store()->GetValue(name_, type_, &found_value)) { DCHECK(found_value->IsType(type_)); return found_value; diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h index 2ab7b96..9d360ba 100644 --- a/chrome/browser/prefs/pref_service.h +++ b/chrome/browser/prefs/pref_service.h @@ -11,10 +11,11 @@ #include <set> #include <string> -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/threading/non_thread_safe.h" #include "base/values.h" +#include "chrome/common/json_pref_store.h" class DefaultPrefStore; class FilePath; @@ -29,9 +30,11 @@ class Profile; namespace subtle { class PrefMemberBase; +class ScopedUserPrefUpdateBase; }; -class PrefService : public base::NonThreadSafe { +class PrefService : public base::NonThreadSafe, + public JsonPrefStore::Delegate { public: // A helper class to store all the information associated with a preference. class Preference { @@ -110,6 +113,15 @@ class PrefService : public base::NonThreadSafe { DISALLOW_COPY_AND_ASSIGN(Preference); }; + class Delegate { + public: + virtual void OnPrefsLoaded(PrefService* prefs, bool success) = 0; + }; + + // JsonPrefStore::Delegate implementaion. + virtual void OnPrefsRead(PersistentPrefStore::PrefReadError error, + bool no_dir); + // Factory method that creates a new instance of a PrefService with the // applicable PrefStores. The |pref_filename| points to the user preference // file. The |profile| is the one to which these preferences apply; it may be @@ -121,6 +133,12 @@ class PrefService : public base::NonThreadSafe { PrefStore* extension_pref_store, Profile* profile); + // Same as above, but with async initialization. + static PrefService* CreatePrefServiceAsync(const FilePath& pref_filename, + PrefStore* extension_pref_store, + Profile* profile, + Delegate* delegate); + // Creates an incognito copy of the pref service that shares most pref stores // but uses a fresh non-persistent overlay for the user pref store and an // individual extension pref store (to cache the effective extension prefs for @@ -148,6 +166,9 @@ class PrefService : public base::NonThreadSafe { // Serializes the data and schedules save using ImportantFileWriter. void ScheduleSavePersistentPrefs(); + // Lands pending writes to disk. + void CommitPendingWrite(); + // Make the PrefService aware of a pref. void RegisterBooleanPref(const char* path, bool default_value); void RegisterIntegerPref(const char* path, int default_value); @@ -189,15 +210,19 @@ class PrefService : public base::NonThreadSafe { void ClearPref(const char* path); // If the path is valid (i.e., registered), update the pref value in the user - // prefs. Seting a null value on a preference of List or Dictionary type is - // equivalent to removing the user value for that preference, allowing the - // default value to take effect unless another value takes precedence. + // prefs. + // To set the value of dictionary or list values in the pref tree use + // Set(), but to modify the value of a dictionary or list use either + // ListPrefUpdate or DictionaryPrefUpdate from scoped_user_pref_update.h. void Set(const char* path, const Value& value); void SetBoolean(const char* path, bool value); void SetInteger(const char* path, int value); void SetDouble(const char* path, double value); void SetString(const char* path, const std::string& value); void SetFilePath(const char* path, const FilePath& value); + // SetList() takes ownership of |value|. Pass a copy of the ListValue to + // keep ownership of the original list, if necessary. + void SetList(const char* path, ListValue* value); // Int64 helper methods that actually store the given value as a string. // Note that if obtaining the named value via GetDictionary or GetList, the @@ -206,20 +231,6 @@ class PrefService : public base::NonThreadSafe { int64 GetInt64(const char* path) const; void RegisterInt64Pref(const char* path, int64 default_value); - // Used to set the value of dictionary or list values in the pref tree. This - // will create a dictionary or list if one does not exist in the pref tree. - // This method returns NULL only if you're requesting an unregistered pref or - // a non-dict/non-list pref. - // WARNING: Changes to the dictionary or list will not automatically notify - // pref observers. - // Use a ScopedUserPrefUpdate to update observers on changes. - // These should really be GetUserMutable... since we will only ever get - // a mutable from the user preferences store. - DictionaryValue* GetMutableDictionary(const char* path); - ListValue* GetMutableList(const char* path); - // TODO(battre) remove this function (hack). - void ReportValueChanged(const std::string& key); - // Returns true if a value has been set for the specified path. // NOTE: this is NOT the same as FindPreference. In particular // FindPreference returns whether RegisterXXX has been invoked, where as @@ -247,7 +258,8 @@ class PrefService : public base::NonThreadSafe { PersistentPrefStore* user_prefs, PrefStore* recommended_platform_prefs, PrefStore* recommended_cloud_prefs, - DefaultPrefStore* default_store); + DefaultPrefStore* default_store, + Delegate* delegate); // The PrefNotifier handles registering and notifying preference observers. // It is created and owned by this PrefService. Subclasses may access it for @@ -274,17 +286,17 @@ class PrefService : public base::NonThreadSafe { friend class PrefChangeRegistrar; friend class subtle::PrefMemberBase; - // Give access to pref_notifier(); - friend class ScopedUserPrefUpdate; + // Give access to ReportUserPrefChanged() and GetMutableUserPref(). + friend class subtle::ScopedUserPrefUpdateBase; // Construct an incognito version of the pref service. Use // CreateIncognitoPrefService() instead of calling this constructor directly. PrefService(const PrefService& original, PrefStore* incognito_extension_prefs); - // Returns a PrefNotifier. If you desire access to this, you will probably - // want to use a ScopedUserPrefUpdate. - PrefNotifier* pref_notifier() const; + // Sends notification of a changed preference. This needs to be called by + // a ScopedUserPrefUpdate if a DictionaryValue or ListValue is changed. + void ReportUserPrefChanged(const std::string& key); // If the pref at the given path changes, we call the observer's Observe // method with PREF_CHANGED. Note that observers should not call these methods @@ -307,6 +319,15 @@ class PrefService : public base::NonThreadSafe { // This should only be called from the constructor. void InitFromStorage(); + // Used to set the value of dictionary or list values in the user pref store. + // This will create a dictionary or list if one does not exist in the user + // pref store. This method returns NULL only if you're requesting an + // unregistered pref or a non-dict/non-list pref. + // |type| may only be Values::TYPE_DICTIONARY or Values::TYPE_LIST and + // |path| must point to a registered preference of type |type|. + // Ownership of the returned value remains at the user pref store. + Value* GetMutableUserPref(const char* path, Value::ValueType type); + // The PrefValueStore provides prioritized preference values. It is created // and owned by this PrefService. Subclasses may access it for unit testing. scoped_ptr<PrefValueStore> pref_value_store_; @@ -320,6 +341,10 @@ class PrefService : public base::NonThreadSafe { // of registered preferences are. mutable PreferenceSet prefs_; + // Holds delegator to be called after initialization, if async version + // is used. + Delegate* delegate_; + DISALLOW_COPY_AND_ASSIGN(PrefService); }; diff --git a/chrome/browser/prefs/pref_service_mock_builder.cc b/chrome/browser/prefs/pref_service_mock_builder.cc index 14012d1..1de0403 100644 --- a/chrome/browser/prefs/pref_service_mock_builder.cc +++ b/chrome/browser/prefs/pref_service_mock_builder.cc @@ -113,7 +113,8 @@ PrefService* PrefServiceMockBuilder::Create() { user_prefs_.get(), recommended_platform_prefs_.get(), recommended_cloud_prefs_.get(), - new DefaultPrefStore()); + new DefaultPrefStore(), + NULL); managed_platform_prefs_ = NULL; managed_cloud_prefs_ = NULL; extension_prefs_ = NULL; diff --git a/chrome/browser/prefs/pref_service_mock_builder.h b/chrome/browser/prefs/pref_service_mock_builder.h index 3e4d1e0..24fc671 100644 --- a/chrome/browser/prefs/pref_service_mock_builder.h +++ b/chrome/browser/prefs/pref_service_mock_builder.h @@ -7,7 +7,7 @@ #pragma once #include "base/basictypes.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "chrome/common/persistent_pref_store.h" #include "chrome/common/pref_store.h" diff --git a/chrome/browser/prefs/pref_service_uitest.cc b/chrome/browser/prefs/pref_service_uitest.cc index fe2a79a..af2b1a6 100644 --- a/chrome/browser/prefs/pref_service_uitest.cc +++ b/chrome/browser/prefs/pref_service_uitest.cc @@ -6,28 +6,26 @@ #include "base/command_line.h" #include "base/file_util.h" -#include "base/path_service.h" #include "base/test/test_file_util.h" #include "base/values.h" +#include "base/memory/scoped_temp_dir.h" #include "build/build_config.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/json_value_serializer.h" #include "chrome/common/pref_names.h" #include "chrome/test/automation/browser_proxy.h" #include "chrome/test/automation/window_proxy.h" #include "chrome/test/ui/ui_test.h" +#include "content/common/json_value_serializer.h" #include "ui/gfx/rect.h" class PreferenceServiceTest : public UITest { public: void SetUp() { - PathService::Get(base::DIR_TEMP, &tmp_profile_); - tmp_profile_ = tmp_profile_.AppendASCII("tmp_profile"); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile"); - // Create a fresh, empty copy of this directory. - file_util::Delete(tmp_profile_, true); - file_util::CreateDirectory(tmp_profile_); + ASSERT_TRUE(file_util::CreateDirectory(tmp_profile)); FilePath reference_pref_file; if (new_profile_) { @@ -36,7 +34,7 @@ class PreferenceServiceTest : public UITest { .AppendASCII("window_placement") .AppendASCII("Default") .Append(chrome::kPreferencesFilename); - tmp_pref_file_ = tmp_profile_.AppendASCII("Default"); + tmp_pref_file_ = tmp_profile.AppendASCII("Default"); ASSERT_TRUE(file_util::CreateDirectory(tmp_pref_file_)); tmp_pref_file_ = tmp_pref_file_.Append(chrome::kPreferencesFilename); } else { @@ -44,7 +42,7 @@ class PreferenceServiceTest : public UITest { .AppendASCII("profiles") .AppendASCII("window_placement") .Append(chrome::kLocalStateFilename); - tmp_pref_file_ = tmp_profile_.Append(chrome::kLocalStateFilename); + tmp_pref_file_ = tmp_profile.Append(chrome::kLocalStateFilename); } ASSERT_TRUE(file_util::PathExists(reference_pref_file)); @@ -59,7 +57,7 @@ class PreferenceServiceTest : public UITest { FILE_ATTRIBUTE_NORMAL)); #endif - launch_arguments_.AppendSwitchPath(switches::kUserDataDir, tmp_profile_); + launch_arguments_.AppendSwitchPath(switches::kUserDataDir, tmp_profile); } bool LaunchAppWithProfile() { @@ -71,14 +69,14 @@ class PreferenceServiceTest : public UITest { void TearDown() { UITest::TearDown(); - - EXPECT_TRUE(file_util::DieFileDie(tmp_profile_, true)); } public: bool new_profile_; FilePath tmp_pref_file_; - FilePath tmp_profile_; + + private: + ScopedTempDir temp_dir_; }; #if !defined(OS_LINUX) diff --git a/chrome/browser/prefs/pref_service_unittest.cc b/chrome/browser/prefs/pref_service_unittest.cc index 90a1882..496e9de 100644 --- a/chrome/browser/prefs/pref_service_unittest.cc +++ b/chrome/browser/prefs/pref_service_unittest.cc @@ -6,7 +6,7 @@ #include "app/test/data/resource.h" #include "base/command_line.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/values.h" #include "chrome/browser/policy/configuration_policy_pref_store.h" #include "chrome/browser/policy/mock_configuration_policy_provider.h" diff --git a/chrome/browser/prefs/pref_set_observer.cc b/chrome/browser/prefs/pref_set_observer.cc index 117937e..916769e 100644 --- a/chrome/browser/prefs/pref_set_observer.cc +++ b/chrome/browser/prefs/pref_set_observer.cc @@ -1,11 +1,11 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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/prefs/pref_set_observer.h" -#include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" +#include "content/common/notification_type.h" PrefSetObserver::PrefSetObserver(PrefService* pref_service, NotificationObserver* observer) diff --git a/chrome/browser/prefs/pref_set_observer.h b/chrome/browser/prefs/pref_set_observer.h index 568265c..40c38e5 100644 --- a/chrome/browser/prefs/pref_set_observer.h +++ b/chrome/browser/prefs/pref_set_observer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -9,9 +9,9 @@ #include <set> #include "base/basictypes.h" -#include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/pref_change_registrar.h" -#include "chrome/common/notification_observer.h" +#include "chrome/browser/prefs/pref_service.h" +#include "content/common/notification_observer.h" // Observes the state of a set of preferences and allows to query their combined // managed bits. diff --git a/chrome/browser/prefs/pref_value_map.cc b/chrome/browser/prefs/pref_value_map.cc index 0857f6d..54967e1 100644 --- a/chrome/browser/prefs/pref_value_map.cc +++ b/chrome/browser/prefs/pref_value_map.cc @@ -5,7 +5,7 @@ #include "chrome/browser/prefs/pref_value_map.h" #include "base/logging.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/stl_util-inl.h" #include "base/values.h" @@ -15,7 +15,18 @@ PrefValueMap::~PrefValueMap() { Clear(); } -bool PrefValueMap::GetValue(const std::string& key, Value** value) const { +bool PrefValueMap::GetValue(const std::string& key, const Value** value) const { + const Map::const_iterator entry = prefs_.find(key); + if (entry != prefs_.end()) { + if (value) + *value = entry->second; + return true; + } + + return false; +} + +bool PrefValueMap::GetValue(const std::string& key, Value** value) { const Map::const_iterator entry = prefs_.find(key); if (entry != prefs_.end()) { if (value) @@ -76,13 +87,13 @@ PrefValueMap::const_iterator PrefValueMap::end() const { bool PrefValueMap::GetBoolean(const std::string& key, bool* value) const { - Value* stored_value = NULL; + const Value* stored_value = NULL; return GetValue(key, &stored_value) && stored_value->GetAsBoolean(value); } bool PrefValueMap::GetString(const std::string& key, std::string* value) const { - Value* stored_value = NULL; + const Value* stored_value = NULL; return GetValue(key, &stored_value) && stored_value->GetAsString(value); } diff --git a/chrome/browser/prefs/pref_value_map.h b/chrome/browser/prefs/pref_value_map.h index 19aeb05..d4b9f4e 100644 --- a/chrome/browser/prefs/pref_value_map.h +++ b/chrome/browser/prefs/pref_value_map.h @@ -26,7 +26,8 @@ class PrefValueMap { // Gets the value for |key| and stores it in |value|. Ownership remains with // the map. Returns true if a value is present. If not, |value| is not // touched. - bool GetValue(const std::string& key, Value** value) const; + bool GetValue(const std::string& key, const Value** value) const; + bool GetValue(const std::string& key, Value** value); // Sets a new |value| for |key|. Takes ownership of |value|, which must be // non-NULL. Returns true if the value changed. diff --git a/chrome/browser/prefs/pref_value_map_unittest.cc b/chrome/browser/prefs/pref_value_map_unittest.cc index 5e248b0..cc47a85 100644 --- a/chrome/browser/prefs/pref_value_map_unittest.cc +++ b/chrome/browser/prefs/pref_value_map_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -11,7 +11,7 @@ class PrefValueMapTest : public testing::Test { TEST_F(PrefValueMapTest, SetValue) { PrefValueMap map; - Value* result = NULL; + const Value* result = NULL; EXPECT_FALSE(map.GetValue("key", &result)); EXPECT_FALSE(result); diff --git a/chrome/browser/prefs/pref_value_store.cc b/chrome/browser/prefs/pref_value_store.cc index b97a4fb..3318a1d 100644 --- a/chrome/browser/prefs/pref_value_store.cc +++ b/chrome/browser/prefs/pref_value_store.cc @@ -102,7 +102,7 @@ PrefValueStore* PrefValueStore::CloneAndSpecialize( bool PrefValueStore::GetValue(const std::string& name, Value::ValueType type, - Value** out_value) const { + const Value** out_value) const { *out_value = NULL; // Check the |PrefStore|s in order of their priority from highest to lowest // to find the value of the preference described by the given preference name. @@ -175,7 +175,7 @@ bool PrefValueStore::PrefValueInStore( PrefValueStore::PrefStoreType store) const { // Declare a temp Value* and call GetValueFromStore, // ignoring the output value. - Value* tmp_value = NULL; + const Value* tmp_value = NULL; return GetValueFromStore(name, store, &tmp_value); } @@ -207,7 +207,7 @@ PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref( bool PrefValueStore::GetValueFromStore(const char* name, PrefValueStore::PrefStoreType store_type, - Value** out_value) const { + const Value** out_value) const { // Only return true if we find a value and it is the correct type, so stale // values with the incorrect type will be ignored. const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type)); diff --git a/chrome/browser/prefs/pref_value_store.h b/chrome/browser/prefs/pref_value_store.h index bddbdaa..6a492ba 100644 --- a/chrome/browser/prefs/pref_value_store.h +++ b/chrome/browser/prefs/pref_value_store.h @@ -12,7 +12,7 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/values.h" #include "chrome/common/pref_store.h" #include "content/browser/browser_thread.h" @@ -78,7 +78,7 @@ class PrefValueStore { // Preference::GetValue() instead of calling this method directly. bool GetValue(const std::string& name, Value::ValueType type, - Value** out_value) const; + const Value** out_value) const; // These methods return true if a preference with the given name is in the // indicated pref store, even if that value is currently being overridden by @@ -107,12 +107,15 @@ class PrefValueStore { // MANAGED_PLATFORM contains all managed preference values that are // provided by a platform-specific policy mechanism (e.g. Windows // Group Policy). - // DEVICE_MANAGEMENT contains all managed preference values supplied + // MANAGED_CLOUD contains all managed preference values supplied // by the device management server (cloud policy). // EXTENSION contains preference values set by extensions. // COMMAND_LINE contains preference values set by command-line switches. // USER contains all user-set preference values. - // RECOMMENDED contains all recommended (policy) preference values. + // RECOMMENDED_PLATFORM contains all recommended (policy) preference values + // that are provided by a platform-specific policy mechanism. + // RECOMMENDED_CLOUD contains all recommended (policy) preference values + // that are provided by the device management server (cloud policy). // DEFAULT contains all application default preference values. enum PrefStoreType { // INVALID_STORE is not associated with an actual PrefStore but used as @@ -195,7 +198,7 @@ class PrefValueStore { // Get a value from the specified store type. bool GetValueFromStore(const char* name, PrefStoreType store, - Value** out_value) const; + const Value** out_value) const; // Called upon changes in individual pref stores in order to determine whether // the user-visible pref value has changed. Triggers the change notification diff --git a/chrome/browser/prefs/pref_value_store_unittest.cc b/chrome/browser/prefs/pref_value_store_unittest.cc index 81c068c..6819e46 100644 --- a/chrome/browser/prefs/pref_value_store_unittest.cc +++ b/chrome/browser/prefs/pref_value_store_unittest.cc @@ -5,7 +5,7 @@ #include <set> #include <string> -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/values.h" #include "chrome/browser/policy/configuration_policy_pref_store.h" #include "chrome/browser/policy/dummy_configuration_policy_provider.h" @@ -289,7 +289,7 @@ class PrefValueStoreTest : public testing::Test { }; TEST_F(PrefValueStoreTest, GetValue) { - Value* value; + const Value* value; // The following tests read a value from the PrefService. The preferences are // set in a way such that all lower-priority stores have a value and we can diff --git a/chrome/browser/prefs/proxy_config_dictionary.h b/chrome/browser/prefs/proxy_config_dictionary.h index 7af2e27..c05f182 100644 --- a/chrome/browser/prefs/proxy_config_dictionary.h +++ b/chrome/browser/prefs/proxy_config_dictionary.h @@ -9,7 +9,7 @@ #include <string> #include "base/basictypes.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "chrome/browser/prefs/proxy_prefs.h" class DictionaryValue; diff --git a/chrome/browser/prefs/proxy_config_dictionary_unittest.cc b/chrome/browser/prefs/proxy_config_dictionary_unittest.cc index 07c6743..5575b66 100644 --- a/chrome/browser/prefs/proxy_config_dictionary_unittest.cc +++ b/chrome/browser/prefs/proxy_config_dictionary_unittest.cc @@ -4,7 +4,7 @@ #include <string> -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/values.h" #include "chrome/browser/prefs/proxy_config_dictionary.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/prefs/scoped_user_pref_update.cc b/chrome/browser/prefs/scoped_user_pref_update.cc index 2c3c995..2188f9a 100644 --- a/chrome/browser/prefs/scoped_user_pref_update.cc +++ b/chrome/browser/prefs/scoped_user_pref_update.cc @@ -1,20 +1,36 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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/prefs/scoped_user_pref_update.h" +#include "base/logging.h" #include "chrome/browser/prefs/pref_notifier.h" #include "chrome/browser/prefs/pref_service.h" -ScopedUserPrefUpdate::ScopedUserPrefUpdate( - PrefService* service, const char* path) +namespace subtle { + +ScopedUserPrefUpdateBase::ScopedUserPrefUpdateBase(PrefService* service, + const char* path) : service_(service), - path_(path) {} + path_(path), + value_(NULL) {} + +ScopedUserPrefUpdateBase::~ScopedUserPrefUpdateBase() { + Notify(); +} -ScopedUserPrefUpdate::~ScopedUserPrefUpdate() { - // TODO(mnissler, danno): This sends a notification unconditionally, which is - // wrong. We should rather tell the PrefService that the user pref got - // updated. - service_->ReportValueChanged(path_); +Value* ScopedUserPrefUpdateBase::Get(Value::ValueType type) { + if (!value_) + value_ = service_->GetMutableUserPref(path_.c_str(), type); + return value_; } + +void ScopedUserPrefUpdateBase::Notify() { + if (value_) { + service_->ReportUserPrefChanged(path_); + value_ = NULL; + } +} + +} // namespace subtle diff --git a/chrome/browser/prefs/scoped_user_pref_update.h b/chrome/browser/prefs/scoped_user_pref_update.h index 8992d09..9b99f30 100644 --- a/chrome/browser/prefs/scoped_user_pref_update.h +++ b/chrome/browser/prefs/scoped_user_pref_update.h @@ -1,24 +1,103 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. // // A helper class that assists preferences in firing notifications when lists -// are changed. +// or dictionaries are changed. #ifndef CHROME_BROWSER_PREFS_SCOPED_USER_PREF_UPDATE_H_ #define CHROME_BROWSER_PREFS_SCOPED_USER_PREF_UPDATE_H_ #pragma once +#include <string> + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "base/threading/non_thread_safe.h" +#include "base/values.h" #include "chrome/browser/prefs/pref_service.h" -class ScopedUserPrefUpdate { - public: - ScopedUserPrefUpdate(PrefService* service, const char* path); - ~ScopedUserPrefUpdate(); +class DictionaryValue; +class ListValue; +class PrefService; + +namespace subtle { + +// Base class for ScopedUserPrefUpdateTemplate that contains the parts +// that do not depend on ScopedUserPrefUpdateTemplate's template parameter. +// +// We need this base class mostly for making it a friend of PrefService +// and getting access to PrefService::GetMutableUserPref and +// PrefService::ReportUserPrefChanged. +class ScopedUserPrefUpdateBase : public base::NonThreadSafe { + protected: + ScopedUserPrefUpdateBase(PrefService* service, const char* path); + + // Calls Notify(). + virtual ~ScopedUserPrefUpdateBase(); + + // Sets |value_| to |service_|->GetMutableUserPref and returns it. + Value* Get(Value::ValueType type); private: + // If |value_| is not null, triggers a notification of PrefObservers and + // resets |value_|. + virtual void Notify(); + + // Weak pointer. PrefService* service_; + // Path of the preference being updated. std::string path_; + // Cache of value from user pref store (set between Get() and Notify() calls). + Value* value_; + + DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdateBase); }; +} // namespace subtle + +// Class to support modifications to DictionaryValues and ListValues while +// guaranteeing that PrefObservers are notified of changed values. +// +// This class may only be used on the UI thread as it requires access to the +// PrefService. +template <typename T, Value::ValueType type_enum_value> +class ScopedUserPrefUpdate : public subtle::ScopedUserPrefUpdateBase { + public: + ScopedUserPrefUpdate(PrefService* service, const char* path) + : ScopedUserPrefUpdateBase(service, path) {} + + // Triggers an update notification if Get() was called. + virtual ~ScopedUserPrefUpdate() {} + + // Returns a mutable |T| instance that + // - is already in the user pref store, or + // - is (silently) created and written to the user pref store if none existed + // before. + // + // Calling Get() implies that an update notification is necessary at + // destruction time. + // + // The ownership of the return value remains with the user pref store. + virtual T* Get() { + return static_cast<T*>( + subtle::ScopedUserPrefUpdateBase::Get(type_enum_value)); + } + + T& operator*() { + return *Get(); + } + + T* operator->() { + return Get(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdate); +}; + +typedef ScopedUserPrefUpdate<DictionaryValue, Value::TYPE_DICTIONARY> + DictionaryPrefUpdate; +typedef ScopedUserPrefUpdate<ListValue, Value::TYPE_LIST> ListPrefUpdate; + #endif // CHROME_BROWSER_PREFS_SCOPED_USER_PREF_UPDATE_H_ diff --git a/chrome/browser/prefs/scoped_user_pref_update_unittest.cc b/chrome/browser/prefs/scoped_user_pref_update_unittest.cc new file mode 100644 index 0000000..88faebe --- /dev/null +++ b/chrome/browser/prefs/scoped_user_pref_update_unittest.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2011 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/prefs/scoped_user_pref_update.h" +#include "chrome/browser/prefs/pref_change_registrar.h" +#include "chrome/browser/prefs/pref_observer_mock.h" +#include "chrome/test/testing_pref_service.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Mock; + +class ScopedUserPrefUpdateTest : public testing::Test { + public: + ~ScopedUserPrefUpdateTest() {} + + protected: + virtual void SetUp() { + prefs_.RegisterDictionaryPref(kPref); + registrar_.Init(&prefs_); + registrar_.Add(kPref, &observer_); + } + + static const char kPref[]; + static const char kKey[]; + static const char kValue[]; + + TestingPrefService prefs_; + PrefObserverMock observer_; + PrefChangeRegistrar registrar_; +}; + +const char ScopedUserPrefUpdateTest::kPref[] = "name"; +const char ScopedUserPrefUpdateTest::kKey[] = "key"; +const char ScopedUserPrefUpdateTest::kValue[] = "value"; + +TEST_F(ScopedUserPrefUpdateTest, RegularUse) { + // Dictionary that will be expected to be set at the end. + DictionaryValue expected_dictionary; + expected_dictionary.SetString(kKey, kValue); + + { + EXPECT_CALL(observer_, Observe(_, _, _)).Times(0); + DictionaryPrefUpdate update(&prefs_, kPref); + DictionaryValue* value = update.Get(); + ASSERT_TRUE(value); + value->SetString(kKey, kValue); + + // The dictionary was created for us but the creation should have happened + // silently without notifications. + Mock::VerifyAndClearExpectations(&observer_); + + // Modifications happen online and are instantly visible, though. + const DictionaryValue* current_value = prefs_.GetDictionary(kPref); + ASSERT_TRUE(current_value); + EXPECT_TRUE(expected_dictionary.Equals(current_value)); + + // Now we are leaving the scope of the update so we should be notified. + observer_.Expect(&prefs_, kPref, &expected_dictionary); + } + Mock::VerifyAndClearExpectations(&observer_); + + const DictionaryValue* current_value = prefs_.GetDictionary(kPref); + ASSERT_TRUE(current_value); + EXPECT_TRUE(expected_dictionary.Equals(current_value)); +} + +TEST_F(ScopedUserPrefUpdateTest, NeverTouchAnything) { + const DictionaryValue* old_value = prefs_.GetDictionary(kPref); + EXPECT_CALL(observer_, Observe(_, _, _)).Times(0); + { + DictionaryPrefUpdate update(&prefs_, kPref); + } + const DictionaryValue* new_value = prefs_.GetDictionary(kPref); + EXPECT_EQ(old_value, new_value); + Mock::VerifyAndClearExpectations(&observer_); +} diff --git a/chrome/browser/prefs/session_startup_pref.cc b/chrome/browser/prefs/session_startup_pref.cc index 8642018..de5cf76 100644 --- a/chrome/browser/prefs/session_startup_pref.cc +++ b/chrome/browser/prefs/session_startup_pref.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -70,9 +70,8 @@ void SessionStartupPref::SetStartupPref(PrefService* prefs, // Always save the URLs, that way the UI can remain consistent even if the // user changes the startup type pref. // Ownership of the ListValue retains with the pref service. - ScopedUserPrefUpdate update(prefs, prefs::kURLsToRestoreOnStartup); - ListValue* url_pref_list = - prefs->GetMutableList(prefs::kURLsToRestoreOnStartup); + ListPrefUpdate update(prefs, prefs::kURLsToRestoreOnStartup); + ListValue* url_pref_list = update.Get(); DCHECK(url_pref_list); url_pref_list->Clear(); for (size_t i = 0; i < pref.urls.size(); ++i) { diff --git a/chrome/browser/prefs/testing_pref_store.cc b/chrome/browser/prefs/testing_pref_store.cc index a3d33d8..e85a836 100644 --- a/chrome/browser/prefs/testing_pref_store.cc +++ b/chrome/browser/prefs/testing_pref_store.cc @@ -14,7 +14,12 @@ TestingPrefStore::TestingPrefStore() TestingPrefStore::~TestingPrefStore() {} PrefStore::ReadResult TestingPrefStore::GetValue(const std::string& key, - Value** value) const { + const Value** value) const { + return prefs_.GetValue(key, value) ? READ_OK : READ_NO_VALUE; +} + +PrefStore::ReadResult TestingPrefStore::GetMutableValue(const std::string& key, + Value** value) { return prefs_.GetValue(key, value) ? READ_OK : READ_NO_VALUE; } @@ -90,7 +95,7 @@ void TestingPrefStore::SetBoolean(const std::string& key, bool value) { bool TestingPrefStore::GetString(const std::string& key, std::string* value) const { - Value* stored_value; + const Value* stored_value; if (!prefs_.GetValue(key, &stored_value) || !stored_value) return false; @@ -98,7 +103,7 @@ bool TestingPrefStore::GetString(const std::string& key, } bool TestingPrefStore::GetInteger(const std::string& key, int* value) const { - Value* stored_value; + const Value* stored_value; if (!prefs_.GetValue(key, &stored_value) || !stored_value) return false; @@ -106,7 +111,7 @@ bool TestingPrefStore::GetInteger(const std::string& key, int* value) const { } bool TestingPrefStore::GetBoolean(const std::string& key, bool* value) const { - Value* stored_value; + const Value* stored_value; if (!prefs_.GetValue(key, &stored_value) || !stored_value) return false; diff --git a/chrome/browser/prefs/testing_pref_store.h b/chrome/browser/prefs/testing_pref_store.h index 79f1c59..048dcc7 100644 --- a/chrome/browser/prefs/testing_pref_store.h +++ b/chrome/browser/prefs/testing_pref_store.h @@ -7,8 +7,8 @@ #pragma once #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "base/observer_list.h" -#include "base/scoped_ptr.h" #include "chrome/browser/prefs/pref_value_map.h" #include "chrome/common/persistent_pref_store.h" @@ -23,12 +23,15 @@ class TestingPrefStore : public PersistentPrefStore { virtual ~TestingPrefStore(); // Overriden from PrefStore. - virtual ReadResult GetValue(const std::string& key, Value** result) const; + virtual ReadResult GetValue(const std::string& key, + const Value** result) const; virtual void AddObserver(PrefStore::Observer* observer); virtual void RemoveObserver(PrefStore::Observer* observer); virtual bool IsInitializationComplete() const; // PersistentPrefStore overrides: + virtual ReadResult GetMutableValue(const std::string& key, Value** result); + virtual void ReportValueChanged(const std::string& key); virtual void SetValue(const std::string& key, Value* value); virtual void SetValueSilently(const std::string& key, Value* value); virtual void RemoveValue(const std::string& key); @@ -36,8 +39,7 @@ class TestingPrefStore : public PersistentPrefStore { virtual PersistentPrefStore::PrefReadError ReadPrefs(); virtual bool WritePrefs(); virtual void ScheduleWritePrefs() {} - // TODO(battre) remove this function - virtual void ReportValueChanged(const std::string& key); + virtual void CommitPendingWrite() {} // Marks the store as having completed initialization. void SetInitializationCompleted(); diff --git a/chrome/browser/prefs/value_map_pref_store.cc b/chrome/browser/prefs/value_map_pref_store.cc index 58c4016..4d2c8ca 100644 --- a/chrome/browser/prefs/value_map_pref_store.cc +++ b/chrome/browser/prefs/value_map_pref_store.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -14,7 +14,7 @@ ValueMapPrefStore::ValueMapPrefStore() {} ValueMapPrefStore::~ValueMapPrefStore() {} PrefStore::ReadResult ValueMapPrefStore::GetValue(const std::string& key, - Value** value) const { + const Value** value) const { return prefs_.GetValue(key, value) ? READ_OK : READ_NO_VALUE; } diff --git a/chrome/browser/prefs/value_map_pref_store.h b/chrome/browser/prefs/value_map_pref_store.h index a8b66c4..c713156 100644 --- a/chrome/browser/prefs/value_map_pref_store.h +++ b/chrome/browser/prefs/value_map_pref_store.h @@ -22,7 +22,8 @@ class ValueMapPrefStore : public PrefStore { virtual ~ValueMapPrefStore(); // PrefStore overrides: - virtual ReadResult GetValue(const std::string& key, Value** value) const; + virtual ReadResult GetValue(const std::string& key, + const Value** value) const; virtual void AddObserver(PrefStore::Observer* observer); virtual void RemoveObserver(PrefStore::Observer* observer); |