Chromium Code Reviews| Index: services/preferences/public/cpp/pref_service_factory.cc |
| diff --git a/services/preferences/public/cpp/pref_service_factory.cc b/services/preferences/public/cpp/pref_service_factory.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..40112257d0471fd598b72cbb0525138f726c99c0 |
| --- /dev/null |
| +++ b/services/preferences/public/cpp/pref_service_factory.cc |
| @@ -0,0 +1,168 @@ |
| +// 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_service_factory.h" |
| + |
| +#include "base/callback_helpers.h" |
| +#include "components/prefs/persistent_pref_store.h" |
| +#include "components/prefs/pref_notifier_impl.h" |
| +#include "components/prefs/pref_registry.h" |
| +#include "components/prefs/pref_service.h" |
| +#include "components/prefs/pref_value_store.h" |
| +#include "services/preferences/public/cpp/persistent_pref_store_client.h" |
| +#include "services/preferences/public/cpp/pref_store_client.h" |
| +#include "services/preferences/public/interfaces/preferences.mojom.h" |
| +#include "services/service_manager/public/cpp/connector.h" |
| + |
| +namespace prefs { |
| +namespace { |
| + |
| +// Used to implement a "fire and forget" pattern where we call an interface |
| +// method, with an attached error handler, but don't care to hold on to the |
| +// InterfacePtr after. |
| +template <typename Interface> |
| +class RefCountedInterfacePtr |
| + : public base::RefCounted<RefCountedInterfacePtr<Interface>> { |
| + public: |
| + mojo::InterfacePtr<Interface>& get() { return ptr_; } |
| + void reset() { ptr_.reset(); } |
| + |
| + private: |
| + friend class base::RefCounted<RefCountedInterfacePtr<Interface>>; |
| + ~RefCountedInterfacePtr() = default; |
| + |
| + mojo::InterfacePtr<Interface> ptr_; |
| +}; |
| + |
| +void DoNothingHandleReadError(PersistentPrefStore::PrefReadError error) {} |
| + |
| +class ConnectionBarrier : public base::RefCounted<ConnectionBarrier> { |
| + public: |
| + static void Create(service_manager::Connector* connector, |
| + scoped_refptr<PrefRegistry> pref_registry, |
| + CreateCallback callback); |
| + |
| + private: |
| + friend class base::RefCounted<ConnectionBarrier>; |
| + ConnectionBarrier(scoped_refptr<PrefRegistry> pref_registry, |
| + scoped_refptr<PersistentPrefStore> persistent_pref_store, |
| + CreateCallback callback); |
| + ~ConnectionBarrier() = default; |
| + |
| + // |unused| exists so that the InterfacePtr won't go out of scope and close |
|
Sam McNally
2017/03/22 04:34:03
They aren't unused anymore.
tibell
2017/03/22 05:32:04
Done.
|
| + // the |pipe. |
| + void OnConnect( |
| + scoped_refptr<RefCountedInterfacePtr<mojom::PrefStoreConnector>> unused, |
| + scoped_refptr<PrefRegistry> pref_registry, |
| + std::unordered_map<PrefValueStore::PrefStoreType, |
| + mojom::PrefStoreConnectionPtr> connections); |
| + |
| + // |unused| exists so that the InterfacePtr won't go out of scope and close |
| + // the |pipe. |
| + void OnConnectError( |
| + scoped_refptr<RefCountedInterfacePtr<mojom::PrefStoreConnector>> unused); |
| + |
| + scoped_refptr<PrefRegistry> pref_registry_; |
| + scoped_refptr<PersistentPrefStore> persistent_pref_store_; |
| + CreateCallback callback_; |
| +}; |
| + |
| +ConnectionBarrier::ConnectionBarrier( |
| + scoped_refptr<PrefRegistry> pref_registry, |
| + scoped_refptr<PersistentPrefStore> persistent_pref_store, |
| + CreateCallback callback) |
| + : pref_registry_(std::move(pref_registry)), |
| + persistent_pref_store_(std::move(persistent_pref_store)), |
| + callback_(std::move(callback)) {} |
| + |
| +void ConnectionBarrier::OnConnect( |
| + scoped_refptr<RefCountedInterfacePtr<mojom::PrefStoreConnector>> |
| + connector_ptr, |
| + scoped_refptr<PrefRegistry> pref_registry, |
| + std::unordered_map<PrefValueStore::PrefStoreType, |
| + mojom::PrefStoreConnectionPtr> connections) { |
| + scoped_refptr<PrefStore> managed_prefs = |
| + connections.count(PrefValueStore::MANAGED_STORE) |
|
Sam McNally
2017/03/22 04:34:03
Could each of these be a function call instead? Th
tibell
2017/03/22 05:32:04
Done.
|
| + ? make_scoped_refptr(new PrefStoreClient(std::move( |
| + connections.find(PrefValueStore::MANAGED_STORE)->second))) |
| + : nullptr; |
| + scoped_refptr<PrefStore> supervised_user_prefs = |
| + connections.count(PrefValueStore::SUPERVISED_USER_STORE) |
| + ? make_scoped_refptr(new PrefStoreClient(std::move( |
| + connections.find(PrefValueStore::SUPERVISED_USER_STORE) |
| + ->second))) |
| + : nullptr; |
| + scoped_refptr<PrefStore> extension_prefs = |
| + connections.count(PrefValueStore::EXTENSION_STORE) |
| + ? make_scoped_refptr(new PrefStoreClient(std::move( |
| + connections.find(PrefValueStore::EXTENSION_STORE)->second))) |
| + : nullptr; |
| + scoped_refptr<PrefStore> command_line_prefs = |
| + connections.count(PrefValueStore::COMMAND_LINE_STORE) |
| + ? make_scoped_refptr(new PrefStoreClient(std::move( |
| + connections.find(PrefValueStore::COMMAND_LINE_STORE)->second))) |
| + : nullptr; |
| + scoped_refptr<PrefStore> recommended_prefs = |
| + connections.count(PrefValueStore::RECOMMENDED_STORE) |
| + ? make_scoped_refptr(new PrefStoreClient(std::move( |
| + connections.find(PrefValueStore::RECOMMENDED_STORE)->second))) |
| + : nullptr; |
| + scoped_refptr<PrefStore> default_prefs = |
| + connections.count(PrefValueStore::DEFAULT_STORE) |
| + ? make_scoped_refptr(new PrefStoreClient(std::move( |
| + connections.find(PrefValueStore::DEFAULT_STORE)->second))) |
| + : nullptr; |
| + PrefNotifierImpl* pref_notifier = new PrefNotifierImpl(); |
| + auto* pref_value_store = new PrefValueStore( |
| + managed_prefs.get(), supervised_user_prefs.get(), extension_prefs.get(), |
| + command_line_prefs.get(), persistent_pref_store_.get(), |
| + recommended_prefs.get(), default_prefs.get(), pref_notifier); |
| + base::ResetAndReturn(&callback_) |
| + .Run(base::MakeUnique<::PrefService>( |
| + pref_notifier, pref_value_store, persistent_pref_store_.get(), |
| + pref_registry_.get(), base::Bind(&DoNothingHandleReadError), true)); |
| + connector_ptr->reset(); |
| +} |
| + |
| +void ConnectionBarrier::OnConnectError( |
| + scoped_refptr<RefCountedInterfacePtr<mojom::PrefStoreConnector>> |
| + connector_ptr) { |
| + callback_.Run(nullptr); |
| + connector_ptr->reset(); |
| +} |
| + |
| +// static |
| +void ConnectionBarrier::Create(service_manager::Connector* connector, |
| + scoped_refptr<PrefRegistry> pref_registry, |
| + CreateCallback callback) { |
| + // Connect to user pref store. |
| + mojom::PersistentPrefStoreConnectorPtr persistent_connector_ptr; |
| + connector->BindInterface(mojom::kPrefStoreServiceName, |
| + &persistent_connector_ptr); |
| + auto barrier = make_scoped_refptr(new ConnectionBarrier( |
| + std::move(pref_registry), |
| + make_scoped_refptr( |
| + new PersistentPrefStoreClient(std::move(persistent_connector_ptr))), |
| + std::move(callback))); |
| + |
| + // Connect to all other pref stores. |
| + auto connector_ptr = make_scoped_refptr( |
| + new RefCountedInterfacePtr<mojom::PrefStoreConnector>()); |
| + connector->BindInterface(mojom::kPrefStoreServiceName, &connector_ptr->get()); |
| + connector_ptr->get().set_connection_error_handler( |
| + base::Bind(&ConnectionBarrier::OnConnectError, barrier, connector_ptr)); |
| + connector_ptr->get()->Connect(base::Bind(&ConnectionBarrier::OnConnect, |
| + barrier, connector_ptr, |
| + std::move(pref_registry))); |
| +} |
| + |
| +} // namespace |
| + |
| +void CreatePrefService(service_manager::Connector* connector, |
| + scoped_refptr<PrefRegistry> pref_registry, |
| + const CreateCallback& callback) { |
| + ConnectionBarrier::Create(connector, std::move(pref_registry), callback); |
| +} |
| + |
| +} // namespace prefs |