Chromium Code Reviews| Index: services/preferences/public/cpp/pref_store_manager_impl.cc | 
| diff --git a/services/preferences/public/cpp/pref_store_manager_impl.cc b/services/preferences/public/cpp/pref_store_manager_impl.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..0eb00b99a347a1a9c15cad9887a36aa91ad6e9ee | 
| --- /dev/null | 
| +++ b/services/preferences/public/cpp/pref_store_manager_impl.cc | 
| @@ -0,0 +1,125 @@ | 
| +// 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/public/cpp/pref_store_manager_impl.h" | 
| + | 
| +#include "base/memory/ref_counted.h" | 
| +#include "components/prefs/pref_value_store.h" | 
| +#include "mojo/public/cpp/bindings/interface_request.h" | 
| +#include "services/service_manager/public/cpp/interface_registry.h" | 
| + | 
| +namespace prefs { | 
| + | 
| +class PrefStoreManagerImpl::ConnectionBarrier | 
| 
 
Sam McNally
2017/02/24 04:14:53
Why is this nested?
 
tibell
2017/02/27 00:02:54
Done.
 
 | 
| + : public base::RefCounted<ConnectionBarrier> { | 
| + public: | 
| + ConnectionBarrier(const PrefStorePtrs& pref_store_ptrs, | 
| + const ConnectCallback& callback); | 
| + | 
| + private: | 
| + friend class base::RefCounted<ConnectionBarrier>; | 
| + ~ConnectionBarrier(); | 
| + | 
| + void OnConnect(PrefValueStore::PrefStoreType type, | 
| + mojom::PrefStoreConnectionPtr connection_ptr); | 
| + | 
| + ConnectCallback callback_; | 
| + | 
| + std::unordered_map<PrefValueStore::PrefStoreType, | 
| + mojom::PrefStoreConnectionPtr> | 
| + connections_; | 
| + | 
| + const size_t expected_connections_; | 
| + | 
| + DISALLOW_COPY_AND_ASSIGN(ConnectionBarrier); | 
| +}; | 
| + | 
| +PrefStoreManagerImpl::ConnectionBarrier::ConnectionBarrier( | 
| + const PrefStorePtrs& pref_store_ptrs, | 
| + const ConnectCallback& callback) | 
| + : callback_(callback), expected_connections_(pref_store_ptrs.size()) { | 
| + for (const auto& ptr : pref_store_ptrs) { | 
| + ptr.second->AddObserver( | 
| 
 
Sam McNally
2017/02/24 04:14:53
This is perilous if the first ptr is closed. RefCo
 
tibell
2017/02/27 00:02:54
Done.
 
 | 
| + base::Bind(&ConnectionBarrier::OnConnect, this, ptr.first)); | 
| + } | 
| +} | 
| + | 
| +PrefStoreManagerImpl::ConnectionBarrier::~ConnectionBarrier() = default; | 
| + | 
| +// static | 
| +PrefStoreManagerImpl::PrefStoreTypes PrefStoreManagerImpl::DefaultStores() { | 
| + return {PrefValueStore::MANAGED_STORE}; | 
| 
 
Sam McNally
2017/02/24 04:14:53
Is this correct?
 
tibell
2017/02/27 00:02:54
It's temporary in two senses:
1) I'm messing with
 
 | 
| +} | 
| + | 
| +void PrefStoreManagerImpl::ConnectionBarrier::OnConnect( | 
| 
 
Sam McNally
2017/02/24 04:14:53
This should be above DefaultStores().
 
tibell
2017/02/27 00:02:54
Done.
 
 | 
| + PrefValueStore::PrefStoreType type, | 
| + mojom::PrefStoreConnectionPtr connection_ptr) { | 
| + connections_.insert(std::make_pair(type, std::move(connection_ptr))); | 
| + if (connections_.size() == expected_connections_) { | 
| + // After this method exits |this| will get destroyed so it's safe to move | 
| + // out the map. | 
| + callback_.Run(std::move(connections_)); | 
| + } | 
| +} | 
| + | 
| +PrefStoreManagerImpl::PrefStoreManagerImpl(PrefStoreTypes expected_pref_stores) | 
| + : expected_pref_stores_(std::move(expected_pref_stores)) {} | 
| + | 
| +PrefStoreManagerImpl::~PrefStoreManagerImpl() = default; | 
| + | 
| +void PrefStoreManagerImpl::Register(mojom::PrefStorePtr pref_store_ptr, | 
| + PrefValueStore::PrefStoreType type) { | 
| + if (expected_pref_stores_.count(type) == 0) { | 
| + LOG(WARNING) << "Not registering unexpected pref store: " << type; | 
| + return; | 
| + } | 
| + DVLOG(1) << "Registering pref store: " << type; | 
| + if (!pref_store_ptrs_.insert(std::make_pair(type, std::move(pref_store_ptr))) | 
| + .second) { | 
| + DLOG(FATAL) << "The same pref store registered twice: " << type; | 
| + } | 
| + if (AllConnected()) { | 
| + DVLOG(1) << "All pref stores registered."; | 
| + if (!pending_callbacks_.empty()) { | 
| + for (const auto& callback : pending_callbacks_) | 
| + make_scoped_refptr(new ConnectionBarrier(pref_store_ptrs_, callback)); | 
| + pending_callbacks_.clear(); | 
| + } | 
| + } | 
| +} | 
| + | 
| +void PrefStoreManagerImpl::Connect(const ConnectCallback& callback) { | 
| + if (AllConnected()) | 
| + make_scoped_refptr(new ConnectionBarrier(pref_store_ptrs_, callback)); | 
| + else | 
| + pending_callbacks_.push_back(callback); | 
| +} | 
| + | 
| +void PrefStoreManagerImpl::Create( | 
| + const service_manager::Identity& remote_identity, | 
| + prefs::mojom::PrefStoreConnectorRequest request) { | 
| + connector_bindings_.AddBinding(this, std::move(request)); | 
| +} | 
| + | 
| +void PrefStoreManagerImpl::Create( | 
| + const service_manager::Identity& remote_identity, | 
| + prefs::mojom::PrefStoreRegistryRequest request) { | 
| + registry_bindings_.AddBinding(this, std::move(request)); | 
| +} | 
| + | 
| +void PrefStoreManagerImpl::OnStart() {} | 
| + | 
| +bool PrefStoreManagerImpl::OnConnect( | 
| + const service_manager::ServiceInfo& remote_info, | 
| + service_manager::InterfaceRegistry* registry) { | 
| + registry->AddInterface<prefs::mojom::PrefStoreConnector>(this); | 
| + registry->AddInterface<prefs::mojom::PrefStoreRegistry>(this); | 
| + return true; | 
| +} | 
| + | 
| +bool PrefStoreManagerImpl::AllConnected() const { | 
| + return pref_store_ptrs_.size() == expected_pref_stores_.size(); | 
| +} | 
| + | 
| +} // namespace prefs |