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 "base/memory/ref_counted.h" | |
8 #include "components/prefs/pref_value_store.h" | |
9 #include "mojo/public/cpp/bindings/interface_request.h" | |
10 #include "services/service_manager/public/cpp/interface_registry.h" | |
11 | |
12 namespace prefs { | |
13 | |
14 using ConnectCallback = mojom::PrefStoreConnector::ConnectCallback; | |
15 using PrefStorePtrs = | |
16 std::unordered_map<PrefValueStore::PrefStoreType, mojom::PrefStorePtr>; | |
17 | |
18 // Used to make sure all pref stores have been registered before replying to any | |
19 // Connect calls. | |
20 class ConnectionBarrier : public base::RefCounted<ConnectionBarrier> { | |
21 public: | |
22 static void Create(const PrefStorePtrs& pref_store_ptrs, | |
23 const ConnectCallback& callback); | |
24 | |
25 ConnectionBarrier(const PrefStorePtrs& pref_store_ptrs, | |
26 const ConnectCallback& callback); | |
27 | |
28 void Init(const PrefStorePtrs& pref_store_ptrs); | |
29 | |
30 private: | |
31 friend class base::RefCounted<ConnectionBarrier>; | |
32 ~ConnectionBarrier() = default; | |
33 | |
34 void OnConnect(PrefValueStore::PrefStoreType type, | |
35 mojom::PrefStoreConnectionPtr connection_ptr); | |
36 | |
37 ConnectCallback callback_; | |
38 | |
39 std::unordered_map<PrefValueStore::PrefStoreType, | |
40 mojom::PrefStoreConnectionPtr> | |
41 connections_; | |
42 | |
43 const size_t expected_connections_; | |
44 | |
45 DISALLOW_COPY_AND_ASSIGN(ConnectionBarrier); | |
46 }; | |
47 | |
48 // static | |
49 void Create(const PrefStorePtrs& pref_store_ptrs, | |
50 const ConnectCallback& callback) { | |
51 make_scoped_refptr(new ConnectionBarrier(pref_store_ptrs, callback)) | |
52 ->Init(pref_store_ptrs); | |
53 } | |
54 | |
55 ConnectionBarrier::ConnectionBarrier(const PrefStorePtrs& pref_store_ptrs, | |
56 const ConnectCallback& callback) | |
57 : callback_(callback), expected_connections_(pref_store_ptrs.size()) {} | |
58 | |
59 void ConnectionBarrier::Init(const PrefStorePtrs& pref_store_ptrs) { | |
60 for (const auto& ptr : pref_store_ptrs) { | |
61 ptr.second->AddObserver( | |
62 base::Bind(&ConnectionBarrier::OnConnect, this, ptr.first)); | |
63 } | |
64 } | |
65 | |
66 void ConnectionBarrier::OnConnect( | |
67 PrefValueStore::PrefStoreType type, | |
68 mojom::PrefStoreConnectionPtr connection_ptr) { | |
69 connections_.insert(std::make_pair(type, std::move(connection_ptr))); | |
70 if (connections_.size() == expected_connections_) { | |
71 // After this method exits |this| will get destroyed so it's safe to move | |
72 // out the map. | |
73 callback_.Run(std::move(connections_)); | |
74 } | |
75 } | |
76 | |
77 PrefStoreManagerImpl::PrefStoreManagerImpl(PrefStoreTypes expected_pref_stores) | |
78 : expected_pref_stores_(std::move(expected_pref_stores)) {} | |
79 | |
80 PrefStoreManagerImpl::~PrefStoreManagerImpl() = default; | |
81 | |
82 // static | |
83 PrefStoreManagerImpl::PrefStoreTypes PrefStoreManagerImpl::DefaultStores() { | |
84 // TODO(tibell): Complete this list. | |
85 return {PrefValueStore::MANAGED_STORE}; | |
86 } | |
87 | |
88 void PrefStoreManagerImpl::Register(PrefValueStore::PrefStoreType type, | |
89 mojom::PrefStorePtr pref_store_ptr) { | |
90 if (expected_pref_stores_.count(type) == 0) { | |
91 LOG(WARNING) << "Not registering unexpected pref store: " << type; | |
92 return; | |
93 } | |
94 DVLOG(1) << "Registering pref store: " << type; | |
95 pref_store_ptr.set_connection_error_handler( | |
96 base::Bind(&PrefStoreManagerImpl::OnPrefStoreDisconnect, | |
97 base::Unretained(this), type)); | |
98 if (!pref_store_ptrs_.insert(std::make_pair(type, std::move(pref_store_ptr))) | |
Sam McNally
2017/03/03 03:47:58
I think
bool success = pref_store_ptrs_.insert(...
tibell
2017/03/07 00:52:52
Done.
| |
99 .second) { | |
100 DLOG(FATAL) << "The same pref store registered twice: " << type; | |
101 } | |
102 if (AllConnected()) { | |
103 DVLOG(1) << "All pref stores registered."; | |
104 if (!pending_callbacks_.empty()) { | |
Sam McNally
2017/03/03 03:47:58
Remove this?
tibell
2017/03/07 00:52:52
Done.
| |
105 for (const auto& callback : pending_callbacks_) | |
106 make_scoped_refptr(new ConnectionBarrier(pref_store_ptrs_, callback)); | |
107 pending_callbacks_.clear(); | |
108 } | |
109 } | |
110 } | |
111 | |
112 void PrefStoreManagerImpl::Connect(const ConnectCallback& callback) { | |
113 if (AllConnected()) | |
114 make_scoped_refptr(new ConnectionBarrier(pref_store_ptrs_, callback)); | |
115 else | |
116 pending_callbacks_.push_back(callback); | |
117 } | |
118 | |
119 void PrefStoreManagerImpl::Create( | |
120 const service_manager::Identity& remote_identity, | |
121 prefs::mojom::PrefStoreConnectorRequest request) { | |
122 connector_bindings_.AddBinding(this, std::move(request)); | |
123 } | |
124 | |
125 void PrefStoreManagerImpl::Create( | |
126 const service_manager::Identity& remote_identity, | |
127 prefs::mojom::PrefStoreRegistryRequest request) { | |
128 registry_bindings_.AddBinding(this, std::move(request)); | |
129 } | |
130 | |
131 void PrefStoreManagerImpl::OnStart() {} | |
132 | |
133 bool PrefStoreManagerImpl::OnConnect( | |
134 const service_manager::ServiceInfo& remote_info, | |
135 service_manager::InterfaceRegistry* registry) { | |
136 registry->AddInterface<prefs::mojom::PrefStoreConnector>(this); | |
137 registry->AddInterface<prefs::mojom::PrefStoreRegistry>(this); | |
138 return true; | |
139 } | |
140 | |
141 void PrefStoreManagerImpl::OnPrefStoreDisconnect( | |
142 PrefValueStore::PrefStoreType type) { | |
143 DVLOG(1) << "Deregistering pref store: " << type; | |
144 pref_store_ptrs_.erase(type); | |
145 } | |
146 | |
147 bool PrefStoreManagerImpl::AllConnected() const { | |
148 return pref_store_ptrs_.size() == expected_pref_stores_.size(); | |
149 } | |
150 | |
151 } // namespace prefs | |
OLD | NEW |