| // Copyright 2017 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 "services/preferences/pref_store_impl.h" |
| |
| #include <memory> |
| #include <set> |
| #include <utility> |
| |
| #include "base/stl_util.h" |
| #include "base/values.h" |
| #include "services/preferences/public/cpp/lib/util.h" |
| |
| namespace prefs { |
| |
| class PrefStoreImpl::Observer { |
| public: |
| Observer(mojom::PrefStoreObserverPtr observer, std::set<std::string> prefs) |
| : observer_(std::move(observer)), prefs_(std::move(prefs)) {} |
| |
| void OnInitializationCompleted(bool succeeded) { |
| observer_->OnInitializationCompleted(succeeded); |
| } |
| |
| void OnPrefChanged(const std::string& key, const base::Value& value) const { |
| if (!base::ContainsKey(prefs_, key)) |
| return; |
| |
| std::vector<mojom::PrefUpdatePtr> updates; |
| updates.push_back(mojom::PrefUpdate::New( |
| key, mojom::PrefUpdateValue::NewAtomicUpdate(value.Clone()), 0)); |
| observer_->OnPrefsChanged(std::move(updates)); |
| } |
| |
| void OnPrefRemoved(const std::string& key) const { |
| if (!base::ContainsKey(prefs_, key)) |
| return; |
| |
| std::vector<mojom::PrefUpdatePtr> updates; |
| updates.push_back(mojom::PrefUpdate::New( |
| key, mojom::PrefUpdateValue::NewAtomicUpdate(base::nullopt), 0)); |
| observer_->OnPrefsChanged(std::move(updates)); |
| } |
| |
| private: |
| mojom::PrefStoreObserverPtr observer_; |
| const std::set<std::string> prefs_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Observer); |
| }; |
| |
| PrefStoreImpl::PrefStoreImpl(scoped_refptr<::PrefStore> pref_store) |
| : backing_pref_store_(std::move(pref_store)), |
| backing_pref_store_initialized_(false) { |
| DCHECK(backing_pref_store_); |
| if (backing_pref_store_->IsInitializationComplete()) |
| OnInitializationCompleted(true); |
| backing_pref_store_->AddObserver(this); |
| } |
| |
| PrefStoreImpl::~PrefStoreImpl() { |
| backing_pref_store_->RemoveObserver(this); |
| } |
| |
| void PrefStoreImpl::OnPrefValueChanged(const std::string& key) { |
| auto dictionary = std::make_unique<base::DictionaryValue>(); |
| const base::Value* value = nullptr; |
| if (backing_pref_store_->GetValue(key, &value)) { |
| for (const auto& observer : observers_) |
| observer->OnPrefChanged(key, *value); |
| } else { |
| for (const auto& observer : observers_) |
| observer->OnPrefRemoved(key); |
| } |
| } |
| |
| void PrefStoreImpl::OnInitializationCompleted(bool succeeded) { |
| // Some pref stores call this more than once. We just ignore all calls after |
| // the first. |
| if (backing_pref_store_initialized_) |
| DCHECK(succeeded); |
| backing_pref_store_initialized_ = succeeded; |
| for (const auto& observer : observers_) |
| observer->OnInitializationCompleted(succeeded); |
| } |
| |
| mojom::PrefStoreConnectionPtr PrefStoreImpl::AddObserver( |
| const std::vector<std::string>& prefs_to_observe) { |
| mojom::PrefStoreObserverPtr observer_ptr; |
| auto request = mojo::MakeRequest(&observer_ptr); |
| std::set<std::string> observed_prefs(prefs_to_observe.begin(), |
| prefs_to_observe.end()); |
| auto result = mojom::PrefStoreConnection::New( |
| std::move(request), |
| base::Value::FromUniquePtrValue( |
| FilterPrefs(backing_pref_store_->GetValues(), observed_prefs)), |
| backing_pref_store_->IsInitializationComplete()); |
| observers_.push_back(std::make_unique<Observer>(std::move(observer_ptr), |
| std::move(observed_prefs))); |
| return result; |
| } |
| |
| } // namespace prefs |