| OLD | NEW |
| (Empty) |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "services/preferences/public/cpp/pref_store_manager_impl.h" | |
| 6 | |
| 7 #include <utility> | |
| 8 | |
| 9 #include "base/memory/ref_counted.h" | |
| 10 #include "base/threading/sequenced_worker_pool.h" | |
| 11 #include "components/prefs/pref_value_store.h" | |
| 12 #include "mojo/public/cpp/bindings/interface_request.h" | |
| 13 #include "services/preferences/persistent_pref_store_factory.h" | |
| 14 #include "services/preferences/persistent_pref_store_impl.h" | |
| 15 #include "services/service_manager/public/cpp/interface_registry.h" | |
| 16 | |
| 17 namespace prefs { | |
| 18 namespace { | |
| 19 | |
| 20 using ConnectCallback = mojom::PrefStoreConnector::ConnectCallback; | |
| 21 using PrefStorePtrs = | |
| 22 std::unordered_map<PrefValueStore::PrefStoreType, mojom::PrefStorePtr>; | |
| 23 | |
| 24 // Used to make sure all pref stores have been registered before replying to any | |
| 25 // Connect calls. | |
| 26 class ConnectionBarrier : public base::RefCounted<ConnectionBarrier> { | |
| 27 public: | |
| 28 static void Create(const PrefStorePtrs& pref_store_ptrs, | |
| 29 const ConnectCallback& callback); | |
| 30 | |
| 31 void Init(const PrefStorePtrs& pref_store_ptrs); | |
| 32 | |
| 33 private: | |
| 34 friend class base::RefCounted<ConnectionBarrier>; | |
| 35 ConnectionBarrier(const PrefStorePtrs& pref_store_ptrs, | |
| 36 const ConnectCallback& callback); | |
| 37 ~ConnectionBarrier() = default; | |
| 38 | |
| 39 void OnConnect(PrefValueStore::PrefStoreType type, | |
| 40 mojom::PrefStoreConnectionPtr connection_ptr); | |
| 41 | |
| 42 ConnectCallback callback_; | |
| 43 | |
| 44 std::unordered_map<PrefValueStore::PrefStoreType, | |
| 45 mojom::PrefStoreConnectionPtr> | |
| 46 connections_; | |
| 47 | |
| 48 const size_t expected_connections_; | |
| 49 | |
| 50 DISALLOW_COPY_AND_ASSIGN(ConnectionBarrier); | |
| 51 }; | |
| 52 | |
| 53 // static | |
| 54 void ConnectionBarrier::Create(const PrefStorePtrs& pref_store_ptrs, | |
| 55 const ConnectCallback& callback) { | |
| 56 make_scoped_refptr(new ConnectionBarrier(pref_store_ptrs, callback)) | |
| 57 ->Init(pref_store_ptrs); | |
| 58 } | |
| 59 | |
| 60 void ConnectionBarrier::Init(const PrefStorePtrs& pref_store_ptrs) { | |
| 61 if (expected_connections_ == 0) { | |
| 62 // Degenerate case. We don't expect this, but it could happen in | |
| 63 // e.g. testing. | |
| 64 callback_.Run(std::move(connections_)); | |
| 65 return; | |
| 66 } | |
| 67 for (const auto& ptr : pref_store_ptrs) { | |
| 68 ptr.second->AddObserver( | |
| 69 base::Bind(&ConnectionBarrier::OnConnect, this, ptr.first)); | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 ConnectionBarrier::ConnectionBarrier(const PrefStorePtrs& pref_store_ptrs, | |
| 74 const ConnectCallback& callback) | |
| 75 : callback_(callback), expected_connections_(pref_store_ptrs.size()) {} | |
| 76 | |
| 77 void ConnectionBarrier::OnConnect( | |
| 78 PrefValueStore::PrefStoreType type, | |
| 79 mojom::PrefStoreConnectionPtr connection_ptr) { | |
| 80 connections_.insert(std::make_pair(type, std::move(connection_ptr))); | |
| 81 if (connections_.size() == expected_connections_) { | |
| 82 // After this method exits |this| will get destroyed so it's safe to move | |
| 83 // out the map. | |
| 84 callback_.Run(std::move(connections_)); | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 } // namespace | |
| 89 | |
| 90 PrefStoreManagerImpl::PrefStoreManagerImpl( | |
| 91 PrefStoreTypes expected_pref_stores, | |
| 92 scoped_refptr<base::SequencedWorkerPool> worker_pool) | |
| 93 : expected_pref_stores_(std::move(expected_pref_stores)), | |
| 94 init_binding_(this), | |
| 95 worker_pool_(std::move(worker_pool)) {} | |
| 96 | |
| 97 PrefStoreManagerImpl::~PrefStoreManagerImpl() = default; | |
| 98 | |
| 99 void PrefStoreManagerImpl::Register(PrefValueStore::PrefStoreType type, | |
| 100 mojom::PrefStorePtr pref_store_ptr) { | |
| 101 if (expected_pref_stores_.count(type) == 0) { | |
| 102 LOG(WARNING) << "Not registering unexpected pref store: " << type; | |
| 103 return; | |
| 104 } | |
| 105 DVLOG(1) << "Registering pref store: " << type; | |
| 106 pref_store_ptr.set_connection_error_handler( | |
| 107 base::Bind(&PrefStoreManagerImpl::OnPrefStoreDisconnect, | |
| 108 base::Unretained(this), type)); | |
| 109 const bool success = | |
| 110 pref_store_ptrs_.insert(std::make_pair(type, std::move(pref_store_ptr))) | |
| 111 .second; | |
| 112 DCHECK(success) << "The same pref store registered twice: " << type; | |
| 113 if (AllConnected()) { | |
| 114 DVLOG(1) << "All pref stores registered."; | |
| 115 for (const auto& callback : pending_callbacks_) | |
| 116 ConnectionBarrier::Create(pref_store_ptrs_, callback); | |
| 117 pending_callbacks_.clear(); | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 void PrefStoreManagerImpl::Connect(const ConnectCallback& callback) { | |
| 122 if (AllConnected()) | |
| 123 ConnectionBarrier::Create(pref_store_ptrs_, callback); | |
| 124 else | |
| 125 pending_callbacks_.push_back(callback); | |
| 126 } | |
| 127 | |
| 128 void PrefStoreManagerImpl::Create( | |
| 129 const service_manager::Identity& remote_identity, | |
| 130 prefs::mojom::PrefStoreConnectorRequest request) { | |
| 131 connector_bindings_.AddBinding(this, std::move(request)); | |
| 132 } | |
| 133 | |
| 134 void PrefStoreManagerImpl::Create( | |
| 135 const service_manager::Identity& remote_identity, | |
| 136 prefs::mojom::PrefStoreRegistryRequest request) { | |
| 137 registry_bindings_.AddBinding(this, std::move(request)); | |
| 138 } | |
| 139 | |
| 140 void PrefStoreManagerImpl::Create( | |
| 141 const service_manager::Identity& remote_identity, | |
| 142 prefs::mojom::PersistentPrefStoreConnectorRequest request) { | |
| 143 if (!persistent_pref_store_) { | |
| 144 pending_persistent_pref_store_requests_.push_back(std::move(request)); | |
| 145 return; | |
| 146 } | |
| 147 persistent_pref_store_bindings_.AddBinding(persistent_pref_store_.get(), | |
| 148 std::move(request)); | |
| 149 } | |
| 150 | |
| 151 void PrefStoreManagerImpl::Create( | |
| 152 const service_manager::Identity& remote_identity, | |
| 153 prefs::mojom::PrefServiceControlRequest request) { | |
| 154 if (init_binding_.is_bound()) { | |
| 155 LOG(ERROR) | |
| 156 << "Pref service received unexpected control interface connection from " | |
| 157 << remote_identity.name(); | |
| 158 return; | |
| 159 } | |
| 160 | |
| 161 init_binding_.Bind(std::move(request)); | |
| 162 } | |
| 163 | |
| 164 void PrefStoreManagerImpl::Init( | |
| 165 mojom::PersistentPrefStoreConfigurationPtr configuration) { | |
| 166 DCHECK(!persistent_pref_store_); | |
| 167 | |
| 168 persistent_pref_store_ = | |
| 169 CreatePersistentPrefStore(std::move(configuration), worker_pool_.get()); | |
| 170 DCHECK(persistent_pref_store_); | |
| 171 for (auto& request : pending_persistent_pref_store_requests_) { | |
| 172 persistent_pref_store_bindings_.AddBinding(persistent_pref_store_.get(), | |
| 173 std::move(request)); | |
| 174 } | |
| 175 pending_persistent_pref_store_requests_.clear(); | |
| 176 } | |
| 177 | |
| 178 void PrefStoreManagerImpl::OnStart() {} | |
| 179 | |
| 180 bool PrefStoreManagerImpl::OnConnect( | |
| 181 const service_manager::ServiceInfo& remote_info, | |
| 182 service_manager::InterfaceRegistry* registry) { | |
| 183 registry->AddInterface<prefs::mojom::PrefStoreConnector>(this); | |
| 184 registry->AddInterface<prefs::mojom::PrefStoreRegistry>(this); | |
| 185 registry->AddInterface<prefs::mojom::PersistentPrefStoreConnector>(this); | |
| 186 registry->AddInterface<prefs::mojom::PrefServiceControl>(this); | |
| 187 return true; | |
| 188 } | |
| 189 | |
| 190 void PrefStoreManagerImpl::OnPrefStoreDisconnect( | |
| 191 PrefValueStore::PrefStoreType type) { | |
| 192 DVLOG(1) << "Deregistering pref store: " << type; | |
| 193 pref_store_ptrs_.erase(type); | |
| 194 } | |
| 195 | |
| 196 bool PrefStoreManagerImpl::AllConnected() const { | |
| 197 return pref_store_ptrs_.size() == expected_pref_stores_.size(); | |
| 198 } | |
| 199 | |
| 200 } // namespace prefs | |
| OLD | NEW |