Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: services/service_manager/public/cpp/lib/interface_registry.cc

Issue 2847743003: Eliminate InterfaceRegistry (Closed)
Patch Set: . Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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/service_manager/public/cpp/interface_registry.h"
6
7 #include <iterator>
8 #include <sstream>
9
10 #include "base/memory/ptr_util.h"
11 #include "mojo/public/cpp/bindings/message.h"
12
13 namespace service_manager {
14 namespace {
15
16 void SerializeIdentity(const Identity& identity, std::stringstream* stream) {
17 *stream << identity.name() << "@" << identity.instance() << " run as: "
18 << identity.user_id();
19 }
20
21 void SerializeSpec(const InterfaceProviderSpec& spec,
22 std::stringstream* stream) {
23 *stream << " Providing:\n";
24 for (const auto& entry : spec.provides) {
25 *stream << " capability: " << entry.first << " containing interfaces:\n";
26 for (const auto& interface_name : entry.second)
27 *stream << " " << interface_name << "\n";
28 }
29 *stream << "\n Requiring:\n";
30 for (const auto& entry : spec.requires) {
31 *stream << " From: " << entry.first << ":\n";
32 for (const auto& capability_name : entry.second)
33 *stream << " " << capability_name << "\n";
34 }
35 }
36
37 } // namespace
38
39 CapabilitySet GetRequestedCapabilities(const InterfaceProviderSpec& source_spec,
40 const Identity& target) {
41 CapabilitySet capabilities;
42
43 // Start by looking for specs specific to the supplied identity.
44 auto it = source_spec.requires.find(target.name());
45 if (it != source_spec.requires.end()) {
46 std::copy(it->second.begin(), it->second.end(),
47 std::inserter(capabilities, capabilities.begin()));
48 }
49
50 // Apply wild card rules too.
51 it = source_spec.requires.find("*");
52 if (it != source_spec.requires.end()) {
53 std::copy(it->second.begin(), it->second.end(),
54 std::inserter(capabilities, capabilities.begin()));
55 }
56 return capabilities;
57 }
58
59 InterfaceSet GetInterfacesToExpose(
60 const InterfaceProviderSpec& source_spec,
61 const Identity& target,
62 const InterfaceProviderSpec& target_spec) {
63 InterfaceSet exposed_interfaces;
64 // TODO(beng): remove this once we can assert that an InterfaceRegistry must
65 // always be constructed with a valid identity.
66 if (!target.IsValid()) {
67 exposed_interfaces.insert("*");
68 return exposed_interfaces;
69 }
70 CapabilitySet capabilities = GetRequestedCapabilities(source_spec, target);
71 for (const auto& capability : capabilities) {
72 auto it = target_spec.provides.find(capability);
73 if (it != target_spec.provides.end()) {
74 for (const auto& interface_name : it->second)
75 exposed_interfaces.insert(interface_name);
76 }
77 }
78 return exposed_interfaces;
79 }
80
81 InterfaceRegistry::InterfaceRegistry(const std::string& name)
82 : binding_(this),
83 name_(name),
84 weak_factory_(this) {}
85 InterfaceRegistry::~InterfaceRegistry() {}
86
87 void InterfaceRegistry::Bind(
88 mojom::InterfaceProviderRequest local_interfaces_request,
89 const Identity& local_identity,
90 const InterfaceProviderSpec& local_interface_provider_spec,
91 const Identity& remote_identity,
92 const InterfaceProviderSpec& remote_interface_provider_spec) {
93 DCHECK(!binding_.is_bound());
94 local_identity_ = local_identity;
95 local_interface_provider_spec_ = local_interface_provider_spec;
96 remote_identity_ = remote_identity;
97 remote_interface_provider_spec_ = remote_interface_provider_spec;
98 RebuildExposedInterfaces();
99 binding_.Bind(std::move(local_interfaces_request));
100 binding_.set_connection_error_handler(base::Bind(
101 &InterfaceRegistry::OnConnectionError, base::Unretained(this)));
102 }
103
104 void InterfaceRegistry::Serialize(std::stringstream* stream) {
105 *stream << "\n\nInterfaceRegistry(" << name_ << "):\n";
106 if (!binding_.is_bound()) {
107 *stream << "\n --> InterfaceRegistry is not yet bound to a pipe.\n\n";
108 return;
109 }
110
111 *stream << "Owned by:\n ";
112 SerializeIdentity(local_identity_, stream);
113 *stream << "\n\n";
114 SerializeSpec(local_interface_provider_spec_, stream);
115
116 *stream << "\n";
117
118 *stream << "Bound to:\n ";
119 SerializeIdentity(remote_identity_, stream);
120 *stream << "\n\n";
121 SerializeSpec(remote_interface_provider_spec_, stream);
122
123 *stream << "\nBinders registered for:\n";
124 bool found_exposed = false;
125 for (const auto& entry : name_to_binder_) {
126 bool exposed = exposed_interfaces_.count(entry.first) > 0;
127 found_exposed |= exposed;
128 *stream << " " << (exposed ? "* " : " ") << entry.first << "\n";
129 }
130 if (found_exposed)
131 *stream << "\n * - denotes an interface exposed to remote per policy.\n";
132
133 *stream << "\n\n";
134 if (expose_all_interfaces_)
135 *stream << "All interfaces exposed.\n\n";
136 }
137
138 base::WeakPtr<InterfaceRegistry> InterfaceRegistry::GetWeakPtr() {
139 return weak_factory_.GetWeakPtr();
140 }
141
142 bool InterfaceRegistry::AddInterface(
143 const std::string& name,
144 const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback,
145 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
146 return SetInterfaceBinderForName(
147 base::MakeUnique<internal::GenericCallbackBinder>(callback, task_runner),
148 name);
149 }
150
151 void InterfaceRegistry::RemoveInterface(const std::string& name) {
152 auto it = name_to_binder_.find(name);
153 if (it != name_to_binder_.end())
154 name_to_binder_.erase(it);
155 }
156
157 void InterfaceRegistry::PauseBinding() {
158 DCHECK(!is_paused_);
159 is_paused_ = true;
160 }
161
162 void InterfaceRegistry::ResumeBinding() {
163 DCHECK(is_paused_);
164 is_paused_ = false;
165
166 while (!pending_interface_requests_.empty()) {
167 auto& request = pending_interface_requests_.front();
168 GetInterface(request.first, std::move(request.second));
169 pending_interface_requests_.pop();
170 }
171 }
172
173 void InterfaceRegistry::GetInterfaceNames(
174 std::set<std::string>* interface_names) {
175 DCHECK(interface_names);
176 for (auto& entry : name_to_binder_)
177 interface_names->insert(entry.first);
178 }
179
180 void InterfaceRegistry::AddConnectionLostClosure(
181 const base::Closure& connection_lost_closure) {
182 connection_lost_closures_.push_back(connection_lost_closure);
183 }
184
185 void InterfaceRegistry::BindInterface(const std::string& name,
186 mojo::ScopedMessagePipeHandle handle) {
187 // NOTE: We don't expose GetInterface() publicly so as to avoid confusion
188 // with local and remote binding requests.
189 GetInterface(name, std::move(handle));
190 }
191
192 // mojom::InterfaceProvider:
193 void InterfaceRegistry::GetInterface(const std::string& interface_name,
194 mojo::ScopedMessagePipeHandle handle) {
195 if (is_paused_) {
196 pending_interface_requests_.emplace(interface_name, std::move(handle));
197 return;
198 }
199
200 if (CanBindRequestForInterface(interface_name)) {
201 auto iter = name_to_binder_.find(interface_name);
202 if (iter != name_to_binder_.end()) {
203 iter->second->BindInterface(remote_identity_,
204 interface_name,
205 std::move(handle));
206 } else if (!default_binder_.is_null()) {
207 default_binder_.Run(interface_name, std::move(handle));
208 } else {
209 LOG(ERROR) << "Failed to locate a binder for interface: "
210 << interface_name << " requested by: " << remote_identity_.name()
211 << " exposed by: " << local_identity_.name()
212 << " via InterfaceProviderSpec \"" << name_ << "\".";
213
214 std::stringstream details;
215 Serialize(&details);
216 DVLOG(1) << details.str();
217 }
218 } else {
219 std::stringstream error;
220 error << "InterfaceProviderSpec \"" << name_ << "\" prevented service: "
221 << remote_identity_.name() << " from binding interface: "
222 << interface_name << " exposed by: " << local_identity_.name();
223 mojo::ReportBadMessage(error.str());
224 LOG(ERROR) << error.str();
225
226 std::stringstream details;
227 Serialize(&details);
228 DVLOG(1) << details.str();
229 }
230 }
231
232 bool InterfaceRegistry::SetInterfaceBinderForName(
233 std::unique_ptr<InterfaceBinder> binder,
234 const std::string& interface_name) {
235 if (CanBindRequestForInterface(interface_name)) {
236 RemoveInterface(interface_name);
237 name_to_binder_[interface_name] = std::move(binder);
238 return true;
239 }
240 return false;
241 }
242
243 bool InterfaceRegistry::CanBindRequestForInterface(
244 const std::string& interface_name) const {
245 // Any interface may be registered before the registry is bound to a pipe. At
246 // bind time, the interfaces exposed will be intersected with the requirements
247 // of the source.
248 if (!binding_.is_bound())
249 return true;
250 return expose_all_interfaces_ || exposed_interfaces_.count(interface_name);
251 }
252
253 void InterfaceRegistry::RebuildExposedInterfaces() {
254 exposed_interfaces_ = GetInterfacesToExpose(remote_interface_provider_spec_,
255 local_identity_,
256 local_interface_provider_spec_);
257 expose_all_interfaces_ =
258 exposed_interfaces_.size() == 1 && exposed_interfaces_.count("*") == 1;
259 }
260
261 void InterfaceRegistry::OnConnectionError() {
262 std::list<base::Closure> closures = connection_lost_closures_;
263 for (const auto& closure : closures)
264 closure.Run();
265 }
266
267 } // namespace service_manager
OLDNEW
« no previous file with comments | « services/service_manager/public/cpp/interface_registry.h ('k') | services/service_manager/public/cpp/tests/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698