| Index: chrome/browser/prefs/pref_value_store.cc
 | 
| diff --git a/chrome/browser/prefs/pref_value_store.cc b/chrome/browser/prefs/pref_value_store.cc
 | 
| index b327e33dcc9e77e505b297a33c38e262f50db810..3dcc813a666a66a036220bcd61705ca314372668 100644
 | 
| --- a/chrome/browser/prefs/pref_value_store.cc
 | 
| +++ b/chrome/browser/prefs/pref_value_store.cc
 | 
| @@ -6,62 +6,69 @@
 | 
|  
 | 
|  #include "chrome/browser/browser_thread.h"
 | 
|  #include "chrome/browser/policy/configuration_policy_pref_store.h"
 | 
| -#include "chrome/browser/prefs/command_line_pref_store.h"
 | 
| -#include "chrome/browser/prefs/in_memory_pref_store.h"
 | 
| -#include "chrome/common/json_pref_store.h"
 | 
| +#include "chrome/browser/prefs/pref_notifier.h"
 | 
|  #include "chrome/common/notification_service.h"
 | 
|  
 | 
| -namespace {
 | 
| +PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
 | 
| +    : pref_value_store_(NULL),
 | 
| +      type_(PrefValueStore::INVALID_STORE) {
 | 
| +}
 | 
|  
 | 
| -// Returns true if the actual value is a valid type for the expected type when
 | 
| -// found in the given store.
 | 
| -bool IsValidType(Value::ValueType expected, Value::ValueType actual,
 | 
| -                 PrefNotifier::PrefStoreType store) {
 | 
| -  if (expected == actual)
 | 
| -    return true;
 | 
| +PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
 | 
| +  if (pref_store_.get())
 | 
| +    pref_store_->RemoveObserver(this);
 | 
| +}
 | 
|  
 | 
| -  // Dictionaries and lists are allowed to hold TYPE_NULL values too, but only
 | 
| -  // in the default pref store.
 | 
| -  if (store == PrefNotifier::DEFAULT_STORE &&
 | 
| -      actual == Value::TYPE_NULL &&
 | 
| -      (expected == Value::TYPE_DICTIONARY || expected == Value::TYPE_LIST)) {
 | 
| -    return true;
 | 
| -  }
 | 
| -  return false;
 | 
| +void PrefValueStore::PrefStoreKeeper::Initialize(
 | 
| +    PrefValueStore* store,
 | 
| +    PrefStore* pref_store,
 | 
| +    PrefValueStore::PrefStoreType type) {
 | 
| +  if (pref_store_.get())
 | 
| +    pref_store_->RemoveObserver(this);
 | 
| +  type_ = type;
 | 
| +  pref_value_store_ = store;
 | 
| +  pref_store_.reset(pref_store);
 | 
| +  if (pref_store_.get())
 | 
| +    pref_store_->AddObserver(this);
 | 
|  }
 | 
|  
 | 
| -}  // namespace
 | 
| +void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
 | 
| +    const std::string& key) {
 | 
| +  pref_value_store_->OnPrefValueChanged(type_, key);
 | 
| +}
 | 
|  
 | 
| -// static
 | 
| -PrefValueStore* PrefValueStore::CreatePrefValueStore(
 | 
| -    const FilePath& pref_filename,
 | 
| -    Profile* profile,
 | 
| -    bool user_only) {
 | 
| -  using policy::ConfigurationPolicyPrefStore;
 | 
| -  ConfigurationPolicyPrefStore* managed = NULL;
 | 
| -  ConfigurationPolicyPrefStore* device_management = NULL;
 | 
| -  CommandLinePrefStore* command_line = NULL;
 | 
| -  ConfigurationPolicyPrefStore* recommended = NULL;
 | 
| -
 | 
| -  JsonPrefStore* user = new JsonPrefStore(
 | 
| -      pref_filename,
 | 
| -      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
 | 
| -  InMemoryPrefStore* extension = new InMemoryPrefStore();
 | 
| -  InMemoryPrefStore* default_store = new InMemoryPrefStore();
 | 
| -
 | 
| -  if (!user_only) {
 | 
| -    managed =
 | 
| -        ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore();
 | 
| -    device_management =
 | 
| -        ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(
 | 
| -            profile);
 | 
| -    command_line = new CommandLinePrefStore(CommandLine::ForCurrentProcess());
 | 
| -    recommended =
 | 
| -        ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore();
 | 
| -  }
 | 
| -  return new PrefValueStore(managed, device_management, extension,
 | 
| -                            command_line, user, recommended, default_store,
 | 
| -                            profile);
 | 
| +void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted() {
 | 
| +  pref_value_store_->OnInitializationCompleted(type_);
 | 
| +}
 | 
| +
 | 
| +PrefValueStore::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)
 | 
| +    : pref_notifier_(pref_notifier),
 | 
| +      profile_(profile) {
 | 
| +  // NULL default pref store is usually bad, but may be OK for some unit tests.
 | 
| +  if (!default_prefs)
 | 
| +    LOG(WARNING) << "default pref store is null";
 | 
| +  InitPrefStore(MANAGED_PLATFORM_STORE, managed_platform_prefs);
 | 
| +  InitPrefStore(DEVICE_MANAGEMENT_STORE, device_management_prefs);
 | 
| +  InitPrefStore(EXTENSION_STORE, extension_prefs);
 | 
| +  InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
 | 
| +  InitPrefStore(USER_STORE, user_prefs);
 | 
| +  InitPrefStore(RECOMMENDED_STORE, recommended_prefs);
 | 
| +  InitPrefStore(DEFAULT_STORE, default_prefs);
 | 
| +
 | 
| +  // TODO(mnissler): Remove after policy refresh cleanup.
 | 
| +  registrar_.Add(this,
 | 
| +                 NotificationType(NotificationType::POLICY_CHANGED),
 | 
| +                 NotificationService::AllSources());
 | 
| +
 | 
| +  CheckInitializationCompleted();
 | 
|  }
 | 
|  
 | 
|  PrefValueStore::~PrefValueStore() {}
 | 
| @@ -70,9 +77,8 @@ bool PrefValueStore::GetValue(const std::string& name,
 | 
|                                Value** out_value) const {
 | 
|    // 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.
 | 
| -  for (size_t i = 0; i <= PrefNotifier::PREF_STORE_TYPE_MAX; ++i) {
 | 
| -    if (GetValueFromStore(name.c_str(),
 | 
| -                          static_cast<PrefNotifier::PrefStoreType>(i),
 | 
| +  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
 | 
| +    if (GetValueFromStore(name.c_str(), static_cast<PrefStoreType>(i),
 | 
|                            out_value))
 | 
|        return true;
 | 
|    }
 | 
| @@ -81,7 +87,7 @@ bool PrefValueStore::GetValue(const std::string& name,
 | 
|  
 | 
|  bool PrefValueStore::GetUserValue(const std::string& name,
 | 
|                                    Value** out_value) const {
 | 
| -  return GetValueFromStore(name.c_str(), PrefNotifier::USER_STORE, out_value);
 | 
| +  return GetValueFromStore(name.c_str(), USER_STORE, out_value);
 | 
|  }
 | 
|  
 | 
|  void PrefValueStore::RegisterPreferenceType(const std::string& name,
 | 
| @@ -99,25 +105,28 @@ Value::ValueType PrefValueStore::GetRegisteredType(
 | 
|  
 | 
|  bool PrefValueStore::WritePrefs() {
 | 
|    bool success = true;
 | 
| -  for (size_t i = 0; i <= PrefNotifier::PREF_STORE_TYPE_MAX; ++i) {
 | 
| -    if (pref_stores_[i].get())
 | 
| -      success = pref_stores_[i]->WritePrefs() && success;
 | 
| +  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
 | 
| +    PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(i));
 | 
| +    if (store)
 | 
| +      success = store->WritePrefs() && success;
 | 
|    }
 | 
|    return success;
 | 
|  }
 | 
|  
 | 
|  void PrefValueStore::ScheduleWritePrefs() {
 | 
| -  for (size_t i = 0; i <= PrefNotifier::PREF_STORE_TYPE_MAX; ++i) {
 | 
| -    if (pref_stores_[i].get())
 | 
| -      pref_stores_[i]->ScheduleWritePrefs();
 | 
| +  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
 | 
| +    PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(i));
 | 
| +    if (store)
 | 
| +      store->ScheduleWritePrefs();
 | 
|    }
 | 
|  }
 | 
|  
 | 
|  PrefStore::PrefReadError PrefValueStore::ReadPrefs() {
 | 
|    PrefStore::PrefReadError result = PrefStore::PREF_READ_ERROR_NONE;
 | 
| -  for (size_t i = 0; i <= PrefNotifier::PREF_STORE_TYPE_MAX; ++i) {
 | 
| -    if (pref_stores_[i].get()) {
 | 
| -      PrefStore::PrefReadError this_error = pref_stores_[i]->ReadPrefs();
 | 
| +  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
 | 
| +    PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(i));
 | 
| +    if (store) {
 | 
| +      PrefStore::PrefReadError this_error = store->ReadPrefs();
 | 
|        if (result == PrefStore::PREF_READ_ERROR_NONE)
 | 
|          result = this_error;
 | 
|      }
 | 
| @@ -143,158 +152,188 @@ bool PrefValueStore::HasPrefPath(const char* path) const {
 | 
|    return rv && !PrefValueFromDefaultStore(path);
 | 
|  }
 | 
|  
 | 
| -bool PrefValueStore::PrefHasChanged(const char* path,
 | 
| -                                    PrefNotifier::PrefStoreType new_store) {
 | 
| -  DCHECK(new_store != PrefNotifier::INVALID_STORE);
 | 
| -  // If we get a change notification about an unregistered preference,
 | 
| -  // discard it silently because there cannot be any listeners.
 | 
| -  if (pref_types_.find(path) == pref_types_.end())
 | 
| -    return false;
 | 
| -
 | 
| -  // Replying that the pref has changed may cause problems, but it's the safer
 | 
| -  // choice.
 | 
| -  if (new_store == PrefNotifier::INVALID_STORE)
 | 
| -    return true;
 | 
| +void PrefValueStore::NotifyPrefChanged(
 | 
| +    const char* path,
 | 
| +    PrefValueStore::PrefStoreType new_store) {
 | 
| +  DCHECK(new_store != INVALID_STORE);
 | 
|  
 | 
| -  PrefNotifier::PrefStoreType controller = ControllingPrefStoreForPref(path);
 | 
| -  DCHECK(controller != PrefNotifier::INVALID_STORE)
 | 
| -      << "Invalid controller for path " << path;
 | 
| -  if (controller == PrefNotifier::INVALID_STORE)
 | 
| -    return true;
 | 
| +  // If this pref is not registered, just discard the notification.
 | 
| +  if (!pref_types_.count(path))
 | 
| +    return;
 | 
|  
 | 
| -  // If the pref is controlled by a higher-priority store, its effective value
 | 
| -  // cannot have changed.
 | 
| -  if (controller < new_store)
 | 
| -    return false;
 | 
| +  bool changed = true;
 | 
| +  // Replying that the pref has changed in case the new store is invalid may
 | 
| +  // cause problems, but it's the safer choice.
 | 
| +  if (new_store != INVALID_STORE) {
 | 
| +    PrefStoreType controller = ControllingPrefStoreForPref(path);
 | 
| +    DCHECK(controller != INVALID_STORE);
 | 
| +    // If the pref is controlled by a higher-priority store, its effective value
 | 
| +    // cannot have changed.
 | 
| +    if (controller != INVALID_STORE &&
 | 
| +        controller < new_store) {
 | 
| +      changed = false;
 | 
| +    }
 | 
| +  }
 | 
|  
 | 
| -  // Otherwise, we take the pref store's word that something changed.
 | 
| -  return true;
 | 
| +  if (changed)
 | 
| +    pref_notifier_->OnPreferenceChanged(path);
 | 
|  }
 | 
|  
 | 
| -// Note the |DictionaryValue| referenced by the |PrefStore| USER_STORE
 | 
| -// (returned by the method prefs()) takes the ownership of the Value referenced
 | 
| -// by in_value.
 | 
| -bool PrefValueStore::SetUserPrefValue(const char* name, Value* in_value) {
 | 
| +void PrefValueStore::SetUserPrefValue(const char* name, Value* in_value) {
 | 
| +  DCHECK(in_value);
 | 
|    Value* old_value = NULL;
 | 
| -  pref_stores_[PrefNotifier::USER_STORE]->prefs()->Get(name, &old_value);
 | 
| -  bool value_changed = !(old_value && old_value->Equals(in_value));
 | 
| +  GetPrefStore(USER_STORE)->prefs()->Get(name, &old_value);
 | 
| +  bool value_changed = !old_value || !old_value->Equals(in_value);
 | 
| +  GetPrefStore(USER_STORE)->prefs()->Set(name, in_value);
 | 
|  
 | 
| -  pref_stores_[PrefNotifier::USER_STORE]->prefs()->Set(name, in_value);
 | 
| -  return value_changed;
 | 
| +  if (value_changed)
 | 
| +    NotifyPrefChanged(name, USER_STORE);
 | 
|  }
 | 
|  
 | 
| -// Note the |DictionaryValue| referenced by the |PrefStore| DEFAULT_STORE
 | 
| -// (returned by the method prefs()) takes the ownership of the Value referenced
 | 
| -// by in_value.
 | 
| -void PrefValueStore::SetDefaultPrefValue(const char* name, Value* in_value) {
 | 
| -  pref_stores_[PrefNotifier::DEFAULT_STORE]->prefs()->Set(name, in_value);
 | 
| +void PrefValueStore::SetUserPrefValueSilently(const char* name,
 | 
| +                                              Value* in_value) {
 | 
| +  DCHECK(in_value);
 | 
| +  GetPrefStore(USER_STORE)->prefs()->Set(name, in_value);
 | 
|  }
 | 
|  
 | 
| -bool PrefValueStore::ReadOnly() {
 | 
| -  return pref_stores_[PrefNotifier::USER_STORE]->ReadOnly();
 | 
| +bool PrefValueStore::ReadOnly() const {
 | 
| +  return GetPrefStore(USER_STORE)->ReadOnly();
 | 
|  }
 | 
|  
 | 
| -bool PrefValueStore::RemoveUserPrefValue(const char* name) {
 | 
| -  if (pref_stores_[PrefNotifier::USER_STORE].get()) {
 | 
| -    return pref_stores_[PrefNotifier::USER_STORE]->prefs()->Remove(name, NULL);
 | 
| +void PrefValueStore::RemoveUserPrefValue(const char* name) {
 | 
| +  if (GetPrefStore(USER_STORE)) {
 | 
| +    if (GetPrefStore(USER_STORE)->prefs()->Remove(name, NULL))
 | 
| +      NotifyPrefChanged(name, USER_STORE);
 | 
|    }
 | 
| -  return false;
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueInManagedPlatformStore(const char* name) const {
 | 
| -  return PrefValueInStore(name, PrefNotifier::MANAGED_PLATFORM_STORE);
 | 
| +  return PrefValueInStore(name, MANAGED_PLATFORM_STORE);
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueInDeviceManagementStore(const char* name) const {
 | 
| -  return PrefValueInStore(name, PrefNotifier::DEVICE_MANAGEMENT_STORE);
 | 
| +  return PrefValueInStore(name, DEVICE_MANAGEMENT_STORE);
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueInExtensionStore(const char* name) const {
 | 
| -  return PrefValueInStore(name, PrefNotifier::EXTENSION_STORE);
 | 
| +  return PrefValueInStore(name, EXTENSION_STORE);
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueInUserStore(const char* name) const {
 | 
| -  return PrefValueInStore(name, PrefNotifier::USER_STORE);
 | 
| -}
 | 
| -
 | 
| -bool PrefValueStore::PrefValueInStoreRange(
 | 
| -    const char* name,
 | 
| -    PrefNotifier::PrefStoreType first_checked_store,
 | 
| -    PrefNotifier::PrefStoreType last_checked_store) {
 | 
| -  if (first_checked_store > last_checked_store) {
 | 
| -    NOTREACHED();
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  for (size_t i = first_checked_store;
 | 
| -       i <= static_cast<size_t>(last_checked_store); ++i) {
 | 
| -    if (PrefValueInStore(name, static_cast<PrefNotifier::PrefStoreType>(i)))
 | 
| -      return true;
 | 
| -  }
 | 
| -  return false;
 | 
| +  return PrefValueInStore(name, USER_STORE);
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueFromExtensionStore(const char* name) const {
 | 
| -  return ControllingPrefStoreForPref(name) == PrefNotifier::EXTENSION_STORE;
 | 
| +  return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueFromUserStore(const char* name) const {
 | 
| -  return ControllingPrefStoreForPref(name) == PrefNotifier::USER_STORE;
 | 
| +  return ControllingPrefStoreForPref(name) == USER_STORE;
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueFromDefaultStore(const char* name) const {
 | 
| -  return ControllingPrefStoreForPref(name) == PrefNotifier::DEFAULT_STORE;
 | 
| +  return ControllingPrefStoreForPref(name) == DEFAULT_STORE;
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueUserModifiable(const char* name) const {
 | 
| -  PrefNotifier::PrefStoreType effective_store =
 | 
| -      ControllingPrefStoreForPref(name);
 | 
| -  return effective_store >= PrefNotifier::USER_STORE ||
 | 
| -         effective_store == PrefNotifier::INVALID_STORE;
 | 
| +  PrefStoreType effective_store = ControllingPrefStoreForPref(name);
 | 
| +  return effective_store >= USER_STORE ||
 | 
| +         effective_store == INVALID_STORE;
 | 
|  }
 | 
|  
 | 
| -PrefNotifier::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
 | 
| -    const char* name) const {
 | 
| -  for (int i = 0; i <= PrefNotifier::PREF_STORE_TYPE_MAX; ++i) {
 | 
| -    if (PrefValueInStore(name, static_cast<PrefNotifier::PrefStoreType>(i)))
 | 
| -      return static_cast<PrefNotifier::PrefStoreType>(i);
 | 
| +bool PrefValueStore::HasPolicyConflictingUserProxySettings() const {
 | 
| +  using policy::ConfigurationPolicyPrefStore;
 | 
| +  ConfigurationPolicyPrefStore::ProxyPreferenceSet proxy_prefs;
 | 
| +  ConfigurationPolicyPrefStore::GetProxyPreferenceSet(&proxy_prefs);
 | 
| +  ConfigurationPolicyPrefStore::ProxyPreferenceSet::const_iterator i;
 | 
| +  for (i = proxy_prefs.begin(); i != proxy_prefs.end(); ++i) {
 | 
| +    if ((PrefValueInManagedPlatformStore(*i) ||
 | 
| +         PrefValueInDeviceManagementStore(*i)) &&
 | 
| +        PrefValueInStoreRange(*i,
 | 
| +                              COMMAND_LINE_STORE,
 | 
| +                              USER_STORE))
 | 
| +      return true;
 | 
| +  }
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
| +// Returns true if the actual value is a valid type for the expected type when
 | 
| +// found in the given store.
 | 
| +bool PrefValueStore::IsValidType(Value::ValueType expected,
 | 
| +                                 Value::ValueType actual,
 | 
| +                                 PrefValueStore::PrefStoreType store) {
 | 
| +  if (expected == actual)
 | 
| +    return true;
 | 
| +
 | 
| +  // Dictionaries and lists are allowed to hold TYPE_NULL values too, but only
 | 
| +  // in the default pref store.
 | 
| +  if (store == DEFAULT_STORE &&
 | 
| +      actual == Value::TYPE_NULL &&
 | 
| +      (expected == Value::TYPE_DICTIONARY || expected == Value::TYPE_LIST)) {
 | 
| +    return true;
 | 
|    }
 | 
| -  return PrefNotifier::INVALID_STORE;
 | 
| +  return false;
 | 
|  }
 | 
|  
 | 
|  bool PrefValueStore::PrefValueInStore(
 | 
|      const char* name,
 | 
| -    PrefNotifier::PrefStoreType store) const {
 | 
| +    PrefValueStore::PrefStoreType store) const {
 | 
|    // Declare a temp Value* and call GetValueFromStore,
 | 
|    // ignoring the output value.
 | 
|    Value* tmp_value = NULL;
 | 
|    return GetValueFromStore(name, store, &tmp_value);
 | 
|  }
 | 
|  
 | 
| -bool PrefValueStore::GetValueFromStore(
 | 
| +bool PrefValueStore::PrefValueInStoreRange(
 | 
|      const char* name,
 | 
| -    PrefNotifier::PrefStoreType store,
 | 
| -    Value** out_value) const {
 | 
| +    PrefValueStore::PrefStoreType first_checked_store,
 | 
| +    PrefValueStore::PrefStoreType last_checked_store) const {
 | 
| +  if (first_checked_store > last_checked_store) {
 | 
| +    NOTREACHED();
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  for (size_t i = first_checked_store;
 | 
| +       i <= static_cast<size_t>(last_checked_store); ++i) {
 | 
| +    if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
 | 
| +      return true;
 | 
| +  }
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
| +PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
 | 
| +    const char* name) const {
 | 
| +  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
 | 
| +    if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
 | 
| +      return static_cast<PrefStoreType>(i);
 | 
| +  }
 | 
| +  return INVALID_STORE;
 | 
| +}
 | 
| +
 | 
| +bool PrefValueStore::GetValueFromStore(const char* name,
 | 
| +                                       PrefValueStore::PrefStoreType store_type,
 | 
| +                                       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.
 | 
| -  if (pref_stores_[store].get() &&
 | 
| -      pref_stores_[store]->prefs()->Get(name, out_value)) {
 | 
| -    // If the value is the sentinel that redirects to the default
 | 
| -    // store, re-fetch the value from the default store explicitly.
 | 
| -    // Because the default values are not available when creating
 | 
| -    // stores, the default value must be fetched dynamically for every
 | 
| -    // redirect.
 | 
| +  const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
 | 
| +  if (store && store->prefs()->Get(name, out_value)) {
 | 
| +    // If the value is the sentinel that redirects to the default store,
 | 
| +    // re-fetch the value from the default store explicitly. Because the default
 | 
| +    // values are not available when creating stores, the default value must be
 | 
| +    // fetched dynamically for every redirect.
 | 
|      if (PrefStore::IsUseDefaultSentinelValue(*out_value)) {
 | 
| -      DCHECK(pref_stores_[PrefNotifier::DEFAULT_STORE].get());
 | 
| -      if (!pref_stores_[PrefNotifier::DEFAULT_STORE]->prefs()->Get(name,
 | 
| -                                                                   out_value)) {
 | 
| +      store = GetPrefStore(DEFAULT_STORE);
 | 
| +      if (!store || !store->prefs()->Get(name, out_value)) {
 | 
|          *out_value = NULL;
 | 
|          return false;
 | 
|        }
 | 
| -      store = PrefNotifier::DEFAULT_STORE;
 | 
| +      store_type = DEFAULT_STORE;
 | 
|      }
 | 
| -    if (IsValidType(GetRegisteredType(name), (*out_value)->GetType(), store))
 | 
| +    if (IsValidType(GetRegisteredType(name),
 | 
| +                    (*out_value)->GetType(),
 | 
| +                    store_type)) {
 | 
|        return true;
 | 
| +    }
 | 
|    }
 | 
|    // No valid value found for the given preference name: set the return false.
 | 
|    *out_value = NULL;
 | 
| @@ -305,9 +344,7 @@ void PrefValueStore::RefreshPolicyPrefsOnFileThread(
 | 
|      BrowserThread::ID calling_thread_id,
 | 
|      PrefStore* new_managed_platform_pref_store,
 | 
|      PrefStore* new_device_management_pref_store,
 | 
| -    PrefStore* new_recommended_pref_store,
 | 
| -    AfterRefreshCallback* callback_pointer) {
 | 
| -  scoped_ptr<AfterRefreshCallback> callback(callback_pointer);
 | 
| +    PrefStore* new_recommended_pref_store) {
 | 
|    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 | 
|    scoped_ptr<PrefStore> managed_platform_pref_store(
 | 
|        new_managed_platform_pref_store);
 | 
| @@ -343,30 +380,54 @@ void PrefValueStore::RefreshPolicyPrefsOnFileThread(
 | 
|                          &PrefValueStore::RefreshPolicyPrefsCompletion,
 | 
|                          managed_platform_pref_store.release(),
 | 
|                          device_management_pref_store.release(),
 | 
| -                        recommended_pref_store.release(),
 | 
| -                        callback.release()));
 | 
| +                        recommended_pref_store.release()));
 | 
| +}
 | 
| +
 | 
| +void PrefValueStore::RefreshPolicyPrefs() {
 | 
| +  using policy::ConfigurationPolicyPrefStore;
 | 
| +  // Because loading of policy information must happen on the FILE
 | 
| +  // thread, it's not possible to just replace the contents of the
 | 
| +  // managed and recommended stores in place due to possible
 | 
| +  // concurrent access from the UI thread. Instead, new stores are
 | 
| +  // created and the refreshed policy read into them. The new stores
 | 
| +  // are swapped with the old from a Task on the UI thread after the
 | 
| +  // load is complete.
 | 
| +  PrefStore* new_managed_platform_pref_store(
 | 
| +      ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore());
 | 
| +  PrefStore* new_device_management_pref_store(
 | 
| +      ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(
 | 
| +          profile_));
 | 
| +  PrefStore* new_recommended_pref_store(
 | 
| +      ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore());
 | 
| +  BrowserThread::ID current_thread_id;
 | 
| +  CHECK(BrowserThread::GetCurrentThreadIdentifier(¤t_thread_id));
 | 
| +  BrowserThread::PostTask(
 | 
| +      BrowserThread::FILE, FROM_HERE,
 | 
| +      NewRunnableMethod(this,
 | 
| +                        &PrefValueStore::RefreshPolicyPrefsOnFileThread,
 | 
| +                        current_thread_id,
 | 
| +                        new_managed_platform_pref_store,
 | 
| +                        new_device_management_pref_store,
 | 
| +                        new_recommended_pref_store));
 | 
|  }
 | 
|  
 | 
|  void PrefValueStore::RefreshPolicyPrefsCompletion(
 | 
|      PrefStore* new_managed_platform_pref_store,
 | 
|      PrefStore* new_device_management_pref_store,
 | 
| -    PrefStore* new_recommended_pref_store,
 | 
| -    AfterRefreshCallback* callback_pointer) {
 | 
| -  scoped_ptr<AfterRefreshCallback> callback(callback_pointer);
 | 
| -
 | 
| +    PrefStore* new_recommended_pref_store) {
 | 
|    // Determine the paths of all the changed preferences values in the three
 | 
|    // policy-related stores (managed platform, device management and
 | 
|    // recommended).
 | 
|    DictionaryValue* managed_platform_prefs_before(
 | 
| -      pref_stores_[PrefNotifier::MANAGED_PLATFORM_STORE]->prefs());
 | 
| +      GetPrefStore(MANAGED_PLATFORM_STORE)->prefs());
 | 
|    DictionaryValue* managed_platform_prefs_after(
 | 
|        new_managed_platform_pref_store->prefs());
 | 
|    DictionaryValue* device_management_prefs_before(
 | 
| -      pref_stores_[PrefNotifier::DEVICE_MANAGEMENT_STORE]->prefs());
 | 
| +      GetPrefStore(DEVICE_MANAGEMENT_STORE)->prefs());
 | 
|    DictionaryValue* device_management_prefs_after(
 | 
|        new_device_management_pref_store->prefs());
 | 
|    DictionaryValue* recommended_prefs_before(
 | 
| -      pref_stores_[PrefNotifier::RECOMMENDED_STORE]->prefs());
 | 
| +      GetPrefStore(RECOMMENDED_STORE)->prefs());
 | 
|    DictionaryValue* recommended_prefs_after(new_recommended_pref_store->prefs());
 | 
|  
 | 
|    std::vector<std::string> changed_managed_platform_paths;
 | 
| @@ -412,84 +473,45 @@ void PrefValueStore::RefreshPolicyPrefsCompletion(
 | 
|  
 | 
|    // Replace the old stores with the new and send notification of the changed
 | 
|    // preferences.
 | 
| -  pref_stores_[PrefNotifier::MANAGED_PLATFORM_STORE].reset(
 | 
| -      new_managed_platform_pref_store);
 | 
| -  pref_stores_[PrefNotifier::DEVICE_MANAGEMENT_STORE].reset(
 | 
| -      new_device_management_pref_store);
 | 
| -  pref_stores_[PrefNotifier::RECOMMENDED_STORE].reset(
 | 
| -      new_recommended_pref_store);
 | 
| -  callback->Run(changed_paths);
 | 
| +  InitPrefStore(MANAGED_PLATFORM_STORE, new_managed_platform_pref_store);
 | 
| +  InitPrefStore(DEVICE_MANAGEMENT_STORE, new_device_management_pref_store);
 | 
| +  InitPrefStore(RECOMMENDED_STORE, new_recommended_pref_store);
 | 
| +
 | 
| +  std::vector<std::string>::const_iterator current;
 | 
| +  for (current = changed_paths.begin();
 | 
| +       current != changed_paths.end();
 | 
| +       ++current) {
 | 
| +    pref_notifier_->OnPreferenceChanged(current->c_str());
 | 
| +  }
 | 
|  }
 | 
|  
 | 
| -void PrefValueStore::RefreshPolicyPrefs(
 | 
| -    AfterRefreshCallback* callback) {
 | 
| -  using policy::ConfigurationPolicyPrefStore;
 | 
| -  // Because loading of policy information must happen on the FILE
 | 
| -  // thread, it's not possible to just replace the contents of the
 | 
| -  // managed and recommended stores in place due to possible
 | 
| -  // concurrent access from the UI thread. Instead, new stores are
 | 
| -  // created and the refreshed policy read into them. The new stores
 | 
| -  // are swapped with the old from a Task on the UI thread after the
 | 
| -  // load is complete.
 | 
| -  PrefStore* new_managed_platform_pref_store(
 | 
| -      ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore());
 | 
| -  PrefStore* new_device_management_pref_store(
 | 
| -      ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(
 | 
| -          profile_));
 | 
| -  PrefStore* new_recommended_pref_store(
 | 
| -      ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore());
 | 
| -  BrowserThread::ID current_thread_id;
 | 
| -  CHECK(BrowserThread::GetCurrentThreadIdentifier(¤t_thread_id));
 | 
| -  BrowserThread::PostTask(
 | 
| -      BrowserThread::FILE, FROM_HERE,
 | 
| -      NewRunnableMethod(this,
 | 
| -                        &PrefValueStore::RefreshPolicyPrefsOnFileThread,
 | 
| -                        current_thread_id,
 | 
| -                        new_managed_platform_pref_store,
 | 
| -                        new_device_management_pref_store,
 | 
| -                        new_recommended_pref_store,
 | 
| -                        callback));
 | 
| +void PrefValueStore::Observe(NotificationType type,
 | 
| +                             const NotificationSource& source,
 | 
| +                             const NotificationDetails& details) {
 | 
| +  if (type == NotificationType::POLICY_CHANGED)
 | 
| +    RefreshPolicyPrefs();
 | 
|  }
 | 
|  
 | 
| -bool PrefValueStore::HasPolicyConflictingUserProxySettings() {
 | 
| -  using policy::ConfigurationPolicyPrefStore;
 | 
| -  ConfigurationPolicyPrefStore::ProxyPreferenceSet proxy_prefs;
 | 
| -  ConfigurationPolicyPrefStore::GetProxyPreferenceSet(&proxy_prefs);
 | 
| -  ConfigurationPolicyPrefStore::ProxyPreferenceSet::const_iterator i;
 | 
| -  for (i = proxy_prefs.begin(); i != proxy_prefs.end(); ++i) {
 | 
| -    if ((PrefValueInManagedPlatformStore(*i) ||
 | 
| -         PrefValueInDeviceManagementStore(*i)) &&
 | 
| -        PrefValueInStoreRange(*i,
 | 
| -                              PrefNotifier::COMMAND_LINE_STORE,
 | 
| -                              PrefNotifier::USER_STORE))
 | 
| -      return true;
 | 
| -  }
 | 
| -  return false;
 | 
| +void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
 | 
| +                                        const std::string& key) {
 | 
| +  NotifyPrefChanged(key.c_str(), type);
 | 
|  }
 | 
|  
 | 
| -PrefStore* PrefValueStore::GetExtensionPrefStore() const {
 | 
| -  return pref_stores_[PrefNotifier::EXTENSION_STORE].get();
 | 
| +void PrefValueStore::OnInitializationCompleted(
 | 
| +    PrefValueStore::PrefStoreType type) {
 | 
| +  CheckInitializationCompleted();
 | 
|  }
 | 
|  
 | 
| -PrefValueStore::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)
 | 
| -    : profile_(profile) {
 | 
| -  // NULL default pref store is usually bad, but may be OK for some unit tests.
 | 
| -  if (!default_prefs)
 | 
| -    LOG(WARNING) << "default pref store is null";
 | 
| -  pref_stores_[PrefNotifier::MANAGED_PLATFORM_STORE].reset(
 | 
| -      managed_platform_prefs);
 | 
| -  pref_stores_[PrefNotifier::DEVICE_MANAGEMENT_STORE].reset(
 | 
| -      device_management_prefs);
 | 
| -  pref_stores_[PrefNotifier::EXTENSION_STORE].reset(extension_prefs);
 | 
| -  pref_stores_[PrefNotifier::COMMAND_LINE_STORE].reset(command_line_prefs);
 | 
| -  pref_stores_[PrefNotifier::USER_STORE].reset(user_prefs);
 | 
| -  pref_stores_[PrefNotifier::RECOMMENDED_STORE].reset(recommended_prefs);
 | 
| -  pref_stores_[PrefNotifier::DEFAULT_STORE].reset(default_prefs);
 | 
| +void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
 | 
| +                                   PrefStore* pref_store) {
 | 
| +  pref_stores_[type].Initialize(this, pref_store, type);
 | 
| +}
 | 
| +
 | 
| +void PrefValueStore::CheckInitializationCompleted() {
 | 
| +  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
 | 
| +    PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(i));
 | 
| +    if (store && !store->IsInitializationComplete())
 | 
| +      return;
 | 
| +  }
 | 
| +  pref_notifier_->OnInitializationCompleted();
 | 
|  }
 | 
| 
 |