15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/prefs/overlay_user_pref_store.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OverlayUserPrefStore::OverlayUserPrefStore(
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PersistentPrefStore* underlay)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : underlay_(underlay) {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  underlay_->AddObserver(this);
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OverlayUserPrefStore::IsSetInOverlay(const std::string& key) const {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return overlay_.GetValue(key, NULL);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::AddObserver(PrefStore::Observer* observer) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::RemoveObserver(PrefStore::Observer* observer) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool OverlayUserPrefStore::HasObservers() const {
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return observers_.might_have_observers();
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OverlayUserPrefStore::IsInitializationComplete() const {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return underlay_->IsInitializationComplete();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OverlayUserPrefStore::GetValue(const std::string& key,
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    const base::Value** result) const {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the |key| shall NOT be stored in the overlay store, there must not
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be an entry.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ShallBeStoredInOverlay(key) || !overlay_.GetValue(key, NULL));
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (overlay_.GetValue(key, result))
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return underlay_->GetValue(GetUnderlayKey(key), result);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OverlayUserPrefStore::GetMutableValue(const std::string& key,
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                           base::Value** result) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShallBeStoredInOverlay(key))
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return underlay_->GetMutableValue(GetUnderlayKey(key), result);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (overlay_.GetValue(key, result))
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to create copy of underlay if the overlay does not contain a value.
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::Value* underlay_value = NULL;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!underlay_->GetMutableValue(GetUnderlayKey(key), &underlay_value))
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = underlay_value->DeepCopy();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overlay_.SetValue(key, *result);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::SetValue(const std::string& key,
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    base::Value* value) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShallBeStoredInOverlay(key)) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underlay_->SetValue(GetUnderlayKey(key), value);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (overlay_.SetValue(key, value))
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportValueChanged(key);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::SetValueSilently(const std::string& key,
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                            base::Value* value) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShallBeStoredInOverlay(key)) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underlay_->SetValueSilently(GetUnderlayKey(key), value);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overlay_.SetValue(key, value);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::RemoveValue(const std::string& key) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShallBeStoredInOverlay(key)) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underlay_->RemoveValue(GetUnderlayKey(key));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (overlay_.RemoveValue(key))
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportValueChanged(key);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OverlayUserPrefStore::ReadOnly() const {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PersistentPrefStore::PrefReadError OverlayUserPrefStore::GetReadError() const {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PersistentPrefStore::PREF_READ_ERROR_NONE;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PersistentPrefStore::PrefReadError OverlayUserPrefStore::ReadPrefs() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not read intentionally.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnInitializationCompleted(true);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PersistentPrefStore::PREF_READ_ERROR_NONE;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::ReadPrefsAsync(
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadErrorDelegate* error_delegate_raw) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not read intentionally.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnInitializationCompleted(true);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::CommitPendingWrite() {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  underlay_->CommitPendingWrite();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not write our content intentionally.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::ReportValueChanged(const std::string& key) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::OnPrefValueChanged(const std::string& key) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!overlay_.GetValue(GetOverlayKey(key), NULL))
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportValueChanged(GetOverlayKey(key));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::OnInitializationCompleted(bool succeeded) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OnInitializationCompleted(succeeded));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::RegisterOverlayPref(const std::string& key) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterOverlayPref(key, key);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverlayUserPrefStore::RegisterOverlayPref(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& overlay_key,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& underlay_key) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!overlay_key.empty()) << "Overlay key is empty";
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(overlay_to_underlay_names_map_.find(overlay_key) ==
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         overlay_to_underlay_names_map_.end()) <<
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Overlay key already registered";
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!underlay_key.empty()) << "Underlay key is empty";
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(underlay_to_overlay_names_map_.find(underlay_key) ==
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         underlay_to_overlay_names_map_.end()) <<
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Underlay key already registered";
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overlay_to_underlay_names_map_[overlay_key] = underlay_key;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  underlay_to_overlay_names_map_[underlay_key] = overlay_key;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OverlayUserPrefStore::~OverlayUserPrefStore() {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  underlay_->RemoveObserver(this);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& OverlayUserPrefStore::GetOverlayKey(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& underlay_key) const {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NamesMap::const_iterator i =
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      underlay_to_overlay_names_map_.find(underlay_key);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i != underlay_to_overlay_names_map_.end() ? i->second : underlay_key;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& OverlayUserPrefStore::GetUnderlayKey(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& overlay_key) const {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NamesMap::const_iterator i =
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overlay_to_underlay_names_map_.find(overlay_key);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i != overlay_to_underlay_names_map_.end() ? i->second : overlay_key;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OverlayUserPrefStore::ShallBeStoredInOverlay(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& key) const {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return overlay_to_underlay_names_map_.find(key) !=
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overlay_to_underlay_names_map_.end();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
178