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

Unified Diff: chrome/browser/prefs/pref_value_store.h

Issue 5441002: Clean up pref change notification handling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix extension prefs breakage Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/prefs/pref_service_unittest.cc ('k') | chrome/browser/prefs/pref_value_store.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/prefs/pref_value_store.h
diff --git a/chrome/browser/prefs/pref_value_store.h b/chrome/browser/prefs/pref_value_store.h
index f4884e26edcd779a402fd41b8fde0f5273b2ea31..1724bbc4b48f0d0a8ed3efffe13f6aac0461c109 100644
--- a/chrome/browser/prefs/pref_value_store.h
+++ b/chrome/browser/prefs/pref_value_store.h
@@ -17,10 +17,12 @@
#include "base/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_notifier.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
#include "chrome/common/pref_store.h"
class FilePath;
+class PrefNotifier;
class PrefStore;
class Profile;
@@ -28,26 +30,47 @@ class Profile;
// (e.g., configuration policies, extensions, and user settings). It returns
// the value of a Preference from the source with the highest priority, and
// allows setting user-defined values for preferences that are not managed.
-// See PrefNotifier for a list of the available preference sources (PrefStores)
-// and their descriptions.
//
// Unless otherwise explicitly noted, all of the methods of this class must
// be called on the UI thread.
-class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
+class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore>,
+ public NotificationObserver {
public:
- // Returns a new PrefValueStore with all applicable PrefStores. The
- // |pref_filename| points to the user preference file. The |profile| is the
- // one to which these preferences apply; it may be NULL if we're dealing
- // with the local state. If |pref_filename| is empty, the user PrefStore will
- // not be created. If |user_only| is true, no PrefStores will be created
- // other than the user and default PrefStores. This should not normally be
- // called directly: the usual way to create a PrefValueStore is by creating a
- // PrefService.
- static PrefValueStore* CreatePrefValueStore(const FilePath& pref_filename,
- Profile* profile,
- bool user_only);
-
- ~PrefValueStore();
+ // In decreasing order of precedence:
+ // |managed_platform_prefs| contains all managed platform (non-cloud policy)
+ // preference values.
+ // |device_management_prefs| contains all device management (cloud policy)
+ // preference values.
+ // |extension_prefs| contains preference values set by extensions.
+ // |command_line_prefs| contains preference values set by command-line
+ // switches.
+ // |user_prefs| contains all user-set preference values.
+ // |recommended_prefs| contains all recommended (policy) preference values.
+ // |default_prefs| contains application-default preference values. It must
+ // be non-null if any preferences are to be registered.
+ //
+ // |pref_notifier| facilitates broadcasting preference change notifications
+ // to the world.
+ //
+ // The |profile| parameter is used to construct a replacement device
+ // management pref store. This is done after policy refresh when we swap out
+ // the policy pref stores for new ones, so the |profile| pointer needs to be
+ // kept around for then. It is safe to pass a NULL pointer for local state
+ // preferences.
+ //
+ // TODO(mnissler, danno): Refactor the pref store interface and refresh logic
+ // so refreshes can be handled by the pref store itself without swapping
+ // stores. This way we can get rid of the profile pointer here.
+ PrefValueStore(PrefStore* managed_platform_prefs,
+ PrefStore* device_management_prefs,
+ PrefStore* extension_prefs,
+ PrefStore* command_line_prefs,
+ PrefStore* user_prefs,
+ PrefStore* recommended_prefs,
+ PrefStore* default_prefs,
+ PrefNotifier* pref_notifier,
+ Profile* profile);
+ virtual ~PrefValueStore();
// Gets the value for the given preference name that has a valid value type;
// that is, the same type the preference was registered with, or NULL for
@@ -56,7 +79,7 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
// Preference::GetValue() instead of calling this method directly.
bool GetValue(const std::string& name, Value** out_value) const;
- // Same as GetValue but only searches USER_STORE.
+ // Same as GetValue but only searches the user store.
bool GetUserValue(const std::string& name, Value** out_value) const;
// Adds a preference to the mapping of names to types.
@@ -74,10 +97,12 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
// Persists prefs (to disk or elsewhere). Returns true if writing values was
// successful. In practice, only the user prefs are expected to be written
// out.
+ // TODO(mnissler, danno): Handle writes through PrefService and remove.
bool WritePrefs();
// Calls the method ScheduleWritePrefs on the PrefStores. In practice, only
// the user prefs are expected to be written out.
+ // TODO(mnissler, danno): Handle writes through PrefService and remove.
void ScheduleWritePrefs();
// Returns true if the PrefValueStore contains the given preference (i.e.,
@@ -87,37 +112,35 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
// store setting a value that happens to be equal to the default does.
bool HasPrefPath(const char* name) const;
- // Called by the PrefNotifier when the value of the preference at |path| has
- // changed, been added, or been removed in one of the PrefStores. The
- // |new_store| is the PrefStoreType of the caller. Returns true if the
- // effective value of the preference has changed, or if the store controlling
- // the pref has changed. Virtual so it can be mocked for a unit test.
- virtual bool PrefHasChanged(const char* path,
- PrefNotifier::PrefStoreType new_store);
-
// Returns true if the PrefValueStore is read-only. Because the managed
// platform, device management and recommended PrefStores are always
// read-only, the PrefValueStore as a whole is read-only if the PrefStore
// containing the user preferences is read-only.
- bool ReadOnly();
+ bool ReadOnly() const;
// Alters the user-defined value of a preference. Even if the preference is
// managed this method allows the user-defined value of the preference to be
- // set. But GetValue calls will not return this value as long as the
- // preference is managed. Instead GetValue will return the managed value
- // of the preference. Note that the PrefValueStore takes the ownership of
- // the value referenced by |in_value|. It is an error to call this when no
- // user PrefStore has been set. Returns true if the user-set value of the
- // preference was newly added or changed.
- bool SetUserPrefValue(const char* name, Value* in_value);
-
- // Removes a value from the user PrefStore. If a preference is managed
- // this function should have no visible effect. Returns true if there was a
- // user-set value to be removed.
- bool RemoveUserPrefValue(const char* name);
-
- // Sets a value in the DefaultPrefStore, which takes ownership of the Value.
- void SetDefaultPrefValue(const char* name, Value* in_value);
+ // set. However, GetValue calls will not return this value as long as the
+ // preference is overriden by a store of higher precedence. Note that the
+ // PrefValueStore takes the ownership of the value referenced by |in_value|.
+ // It is an error to call this when no user PrefStore has been set. Triggers
+ // notifications if the user-visible value changes.
+ // TODO(mnissler, danno): Handle writes in PrefService and notifications in
+ // the pref store implementation, so we can remove this call.
+ void SetUserPrefValue(const char* name, Value* in_value);
+
+ // Like SetUserPrefValue, but silently puts the value without triggering
+ // notifications.
+ // TODO(mnissler, danno): Handle writes in PrefService and notifications in
+ // the pref store implementation, so we can remove this call.
+ void SetUserPrefValueSilently(const char* name, Value* in_value);
+
+ // Removes a value from the user PrefStore. If a preference is overriden by a
+ // store of higher precedence, this function will have no immediately visible
+ // effect. Triggers notifications if the user-visible value changes.
+ // TODO(mnissler, danno): Handle writes in PrefService and notifications in
+ // the pref store implementation, so we can remove this call.
+ void RemoveUserPrefValue(const char* name);
// 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
@@ -127,14 +150,6 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
bool PrefValueInExtensionStore(const char* name) const;
bool PrefValueInUserStore(const char* name) const;
- // Returns true if a preference has an explicit value in any of the
- // stores in the range specified by |first_checked_store| and
- // |last_checked_store|, even if that value is currently being
- // overridden by a higher-priority store.
- bool PrefValueInStoreRange(const char* name,
- PrefNotifier::PrefStoreType first_checked_store,
- PrefNotifier::PrefStoreType last_checked_store);
-
// These methods return true if a preference with the given name is actually
// being controlled by the indicated pref store and not being overridden by
// a higher-priority source.
@@ -146,98 +161,129 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
// there is no higher-priority source controlling it.
bool PrefValueUserModifiable(const char* name) const;
- // Returns the pref store type identifying the source that controls the
- // Preference identified by |name|. If none of the sources has a value,
- // PrefNotifier::INVALID_STORE is returned. In practice, the default PrefStore
- // should always have a value for any registered preferencem, so INVALID_STORE
- // indicates an error.
- PrefNotifier::PrefStoreType ControllingPrefStoreForPref(
- const char* name) const;
-
- // Signature of callback triggered after policy refresh. Parameter is not
- // passed as reference to prevent passing along a pointer to a set whose
- // lifecycle is managed in another thread.
- typedef Callback1<std::vector<std::string> >::Type AfterRefreshCallback;
-
- // Called as a result of a notification of policy change. Triggers a reload of
- // managed platform, device management and recommended preferences from policy
- // from a Task on the FILE thread. The Task will take ownership of the
- // |callback|. |callback| is called with the set of preferences changed by the
- // policy refresh. |callback| is called on the caller's thread as a Task
- // after RefreshPolicyPrefs has returned.
- void RefreshPolicyPrefs(AfterRefreshCallback* callback);
-
// Returns true if there are proxy preferences in user-modifiable
// preference stores (e.g. CommandLinePrefStore, ExtensionPrefStore)
// that conflict with proxy settings specified by proxy policy.
- bool HasPolicyConflictingUserProxySettings();
-
- // TODO(mnissler) delete after applying your patch.
- // This is only called only by PrefService.
- PrefStore* GetExtensionPrefStore() const;
-
- protected:
- // In decreasing order of precedence:
- // |managed_platform_prefs| contains all managed platform (non-cloud policy)
- // preference values.
- // |device_management_prefs| contains all device management (cloud policy)
- // preference values.
- // |extension_prefs| contains preference values set by extensions.
- // |command_line_prefs| contains preference values set by command-line
- // switches.
- // |user_prefs| contains all user-set preference values.
- // |recommended_prefs| contains all recommended (policy) preference values.
- // |default_prefs| contains application-default preference values. It must
- // be non-null if any preferences are to be registered.
- //
- // The |profile| parameter is used to construct a replacement device
- // management pref store. This is done after policy refresh when we swap out
- // the policy pref stores for new ones, so the |profile| pointer needs to be
- // kept around for then. It is safe to pass a NULL pointer for local state
- // preferences.
- //
- // TODO(mnissler, danno): Refactor the pref store interface and refresh logic
- // so refreshes can be handled by the pref store itself without swapping
- // stores. This way we can get rid of the profile pointer here.
- //
- // This constructor should only be used internally, or by subclasses in
- // testing. The usual way to create a PrefValueStore is by creating a
- // PrefService.
- PrefValueStore(PrefStore* managed_platform_prefs,
- PrefStore* device_management_prefs,
- PrefStore* extension_prefs,
- PrefStore* command_line_prefs,
- PrefStore* user_prefs,
- PrefStore* recommended_prefs,
- PrefStore* default_prefs,
- Profile* profile);
+ bool HasPolicyConflictingUserProxySettings() const;
private:
+ // PrefStores must be listed here in order from highest to lowest priority.
+ // 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
+ // 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.
+ // DEFAULT contains all application default preference values.
+ enum PrefStoreType {
+ // INVALID_STORE is not associated with an actual PrefStore but used as
+ // an invalid marker, e.g. as a return value.
+ INVALID_STORE = -1,
+ MANAGED_PLATFORM_STORE = 0,
+ DEVICE_MANAGEMENT_STORE,
+ EXTENSION_STORE,
+ COMMAND_LINE_STORE,
+ USER_STORE,
+ RECOMMENDED_STORE,
+ DEFAULT_STORE,
+ PREF_STORE_TYPE_MAX = DEFAULT_STORE
+ };
+
+ // Keeps a PrefStore reference on behalf of the PrefValueStore and monitors
+ // the PrefStore for changes, forwarding notifications to PrefValueStore. This
+ // indirection is here for the sake of disambiguating notifications from the
+ // individual PrefStores.
+ class PrefStoreKeeper : public PrefStore::ObserverInterface {
+ public:
+ PrefStoreKeeper();
+ virtual ~PrefStoreKeeper();
+
+ // Takes ownership of |pref_store|.
+ void Initialize(PrefValueStore* store,
+ PrefStore* pref_store,
+ PrefStoreType type);
+
+ PrefStore* store() { return pref_store_.get(); }
+ const PrefStore* store() const { return pref_store_.get(); }
+
+ private:
+ // PrefStore::ObserverInterface implementation.
+ virtual void OnPrefValueChanged(const std::string& key);
+ virtual void OnInitializationCompleted();
+
+ // PrefValueStore this keeper is part of.
+ PrefValueStore* pref_value_store_;
+
+ // The PrefStore managed by this keeper.
+ scoped_ptr<PrefStore> pref_store_;
+
+ // Type of the pref store.
+ PrefStoreType type_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefStoreKeeper);
+ };
+
typedef std::map<std::string, Value::ValueType> PrefTypeMap;
friend class PrefValueStoreTest;
+ FRIEND_TEST_ALL_PREFIXES(PrefValueStoreTest, TestPolicyRefresh);
FRIEND_TEST_ALL_PREFIXES(PrefValueStoreTest,
TestRefreshPolicyPrefsCompletion);
+ FRIEND_TEST_ALL_PREFIXES(PrefValueStoreTest,
+ TestConcurrentPolicyRefresh);
+
+ // Returns true if the actual type is a valid type for the expected type when
+ // found in the given store.
+ static bool IsValidType(Value::ValueType expected,
+ Value::ValueType actual,
+ PrefStoreType store);
// Returns true if the preference with the given name has a value in the
// given PrefStoreType, of the same value type as the preference was
// registered with.
- bool PrefValueInStore(const char* name,
- PrefNotifier::PrefStoreType store) const;
+ bool PrefValueInStore(const char* name, PrefStoreType store) const;
+
+ // Returns true if a preference has an explicit value in any of the
+ // stores in the range specified by |first_checked_store| and
+ // |last_checked_store|, even if that value is currently being
+ // overridden by a higher-priority store.
+ bool PrefValueInStoreRange(const char* name,
+ PrefStoreType first_checked_store,
+ PrefStoreType last_checked_store) const;
+
+ // Returns the pref store type identifying the source that controls the
+ // Preference identified by |name|. If none of the sources has a value,
+ // INVALID_STORE is returned. In practice, the default PrefStore
+ // should always have a value for any registered preferencem, so INVALID_STORE
+ // indicates an error.
+ PrefStoreType ControllingPrefStoreForPref(const char* name) const;
// Get a value from the specified store type.
bool GetValueFromStore(const char* name,
- PrefNotifier::PrefStoreType store,
+ PrefStoreType store,
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
+ // if the effective value of the preference has changed, or if the store
+ // controlling the pref has changed.
+ void NotifyPrefChanged(const char* path, PrefStoreType new_store);
+
+ // Called as a result of a notification of policy change. Triggers a reload of
+ // managed platform, device management and recommended preferences from policy
+ // from a Task on the FILE thread.
+ void RefreshPolicyPrefs();
+
// Called during policy refresh after ReadPrefs completes on the thread
// that initiated the policy refresh. RefreshPolicyPrefsCompletion takes
// ownership of the |callback| object.
void RefreshPolicyPrefsCompletion(
PrefStore* new_managed_platform_pref_store,
PrefStore* new_device_management_pref_store,
- PrefStore* new_recommended_pref_store,
- AfterRefreshCallback* callback);
+ PrefStore* new_recommended_pref_store);
// Called during policy refresh to do the ReadPrefs on the FILE thread.
// RefreshPolicyPrefsOnFileThread takes ownership of the |callback| object.
@@ -245,10 +291,44 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
BrowserThread::ID calling_thread_id,
PrefStore* new_managed_platform_pref_store,
PrefStore* new_device_management_pref_store,
- PrefStore* new_recommended_pref_store,
- AfterRefreshCallback* callback);
+ PrefStore* new_recommended_pref_store);
+
+ // NotificationObserver methods:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Called from the PrefStoreKeeper implementation when a pref value for |key|
+ // changed in the pref store for |type|.
+ void OnPrefValueChanged(PrefStoreType type, const std::string& key);
- scoped_ptr<PrefStore> pref_stores_[PrefNotifier::PREF_STORE_TYPE_MAX + 1];
+ // Handle the event that the store for |type| has completed initialization.
+ void OnInitializationCompleted(PrefStoreType type);
+
+ // Initializes a pref store keeper. Sets up a PrefStoreKeeper that will take
+ // ownership of the passed |pref_store|.
+ void InitPrefStore(PrefStoreType type, PrefStore* pref_store);
+
+ // Checks whether initialization is completed and tells the notifier if that
+ // is the case.
+ void CheckInitializationCompleted();
+
+ // Get the PrefStore pointer for the given type. May return NULL if there is
+ // no PrefStore for that type.
+ PrefStore* GetPrefStore(PrefStoreType type) {
+ return pref_stores_[type].store();
+ }
+ const PrefStore* GetPrefStore(PrefStoreType type) const {
+ return pref_stores_[type].store();
+ }
+
+ // Keeps the PrefStore references in order of precedence.
+ PrefStoreKeeper pref_stores_[PREF_STORE_TYPE_MAX + 1];
+
+ // Used for generating PREF_CHANGED and PREF_INITIALIZATION_COMPLETED
+ // notifications. This is a weak reference, since the notifier is owned by the
+ // corresponding PrefService.
+ PrefNotifier* pref_notifier_;
// A mapping of preference names to their registered types.
PrefTypeMap pref_types_;
@@ -258,6 +338,9 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
// upon policy refresh.
Profile* profile_;
+ // TODO(mnissler): Remove this after cleaning up policy refresh handling.
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(PrefValueStore);
};
« no previous file with comments | « chrome/browser/prefs/pref_service_unittest.cc ('k') | chrome/browser/prefs/pref_value_store.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698