OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "services/service_manager/public/cpp/interface_registry.h" | 5 #include "services/service_manager/public/cpp/interface_registry.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "mojo/public/cpp/bindings/message.h" | 9 #include "mojo/public/cpp/bindings/message.h" |
10 #include "services/service_manager/public/cpp/connection.h" | 10 #include "services/service_manager/public/cpp/connection.h" |
11 | 11 |
12 namespace service_manager { | 12 namespace service_manager { |
| 13 namespace { |
13 | 14 |
14 InterfaceRegistry::InterfaceRegistry() | 15 // Returns the set of capabilities required from the target. |
15 : binding_(this), allow_all_interfaces_(true), weak_factory_(this) {} | 16 CapabilitySet GetRequestedCapabilities(const InterfaceProviderSpec& source_spec, |
| 17 const Identity& target) { |
| 18 CapabilitySet capabilities; |
| 19 |
| 20 // Start by looking for specs specific to the supplied identity. |
| 21 auto it = source_spec.requires.find(target.name()); |
| 22 if (it != source_spec.requires.end()) { |
| 23 std::copy(it->second.begin(), it->second.end(), |
| 24 std::inserter(capabilities, capabilities.begin())); |
| 25 } |
| 26 |
| 27 // Apply wild card rules too. |
| 28 it = source_spec.requires.find("*"); |
| 29 if (it != source_spec.requires.end()) { |
| 30 std::copy(it->second.begin(), it->second.end(), |
| 31 std::inserter(capabilities, capabilities.begin())); |
| 32 } |
| 33 return capabilities; |
| 34 } |
| 35 |
| 36 // Generates a single set of interfaces that is the union of all interfaces |
| 37 // exposed by the target for the capabilities requested by the source. |
| 38 InterfaceSet GetAllowedInterfaces( |
| 39 const InterfaceProviderSpec& source_spec, |
| 40 const Identity& target, |
| 41 const InterfaceProviderSpec& target_spec) { |
| 42 InterfaceSet allowed_interfaces; |
| 43 // TODO(beng): remove this once we can assert that an InterfaceRegistry must |
| 44 // always be constructed with a valid identity. |
| 45 if (!target.IsValid()) { |
| 46 allowed_interfaces.insert("*"); |
| 47 return allowed_interfaces; |
| 48 } |
| 49 CapabilitySet capabilities = GetRequestedCapabilities(source_spec, target); |
| 50 for (const auto& capability : capabilities) { |
| 51 auto it = target_spec.provides.find(capability); |
| 52 if (it != target_spec.provides.end()) { |
| 53 for (const auto& interface_name : it->second) |
| 54 allowed_interfaces.insert(interface_name); |
| 55 } |
| 56 } |
| 57 return allowed_interfaces; |
| 58 } |
| 59 |
| 60 |
| 61 } // namespace |
16 | 62 |
17 InterfaceRegistry::InterfaceRegistry( | 63 InterfaceRegistry::InterfaceRegistry( |
18 const Identity& local_identity, | 64 const Identity& identity, |
19 const Identity& remote_identity, | 65 const InterfaceProviderSpec& interface_provider_spec) |
20 const InterfaceSet& allowed_interfaces) | |
21 : binding_(this), | 66 : binding_(this), |
22 local_identity_(local_identity), | 67 identity_(identity), |
23 remote_identity_(remote_identity), | 68 interface_provider_spec_(interface_provider_spec), |
24 allowed_interfaces_(allowed_interfaces), | |
25 allow_all_interfaces_(allowed_interfaces_.size() == 1 && | |
26 allowed_interfaces_.count("*") == 1), | |
27 weak_factory_(this) {} | 69 weak_factory_(this) {} |
28 | 70 |
29 InterfaceRegistry::~InterfaceRegistry() {} | 71 InterfaceRegistry::~InterfaceRegistry() {} |
30 | 72 |
31 void InterfaceRegistry::Bind( | 73 void InterfaceRegistry::Bind( |
32 mojom::InterfaceProviderRequest local_interfaces_request) { | 74 mojom::InterfaceProviderRequest local_interfaces_request, |
| 75 const Identity& remote_identity, |
| 76 const InterfaceProviderSpec& remote_interface_provider_spec) { |
33 DCHECK(!binding_.is_bound()); | 77 DCHECK(!binding_.is_bound()); |
| 78 remote_identity_ = remote_identity; |
| 79 allowed_interfaces_ = GetAllowedInterfaces(remote_interface_provider_spec, |
| 80 identity_, |
| 81 interface_provider_spec_); |
| 82 allow_all_interfaces_ = |
| 83 allowed_interfaces_.size() == 1 && allowed_interfaces_.count("*") == 1; |
| 84 if (!allow_all_interfaces_) { |
| 85 for (auto it = name_to_binder_.begin(); it != name_to_binder_.end(); ++it) { |
| 86 if (allowed_interfaces_.count(it->first) == 0) |
| 87 name_to_binder_.erase(it); |
| 88 } |
| 89 } |
34 binding_.Bind(std::move(local_interfaces_request)); | 90 binding_.Bind(std::move(local_interfaces_request)); |
35 } | 91 } |
36 | 92 |
37 base::WeakPtr<InterfaceRegistry> InterfaceRegistry::GetWeakPtr() { | 93 base::WeakPtr<InterfaceRegistry> InterfaceRegistry::GetWeakPtr() { |
38 return weak_factory_.GetWeakPtr(); | 94 return weak_factory_.GetWeakPtr(); |
39 } | 95 } |
40 | 96 |
41 bool InterfaceRegistry::AddInterface( | 97 bool InterfaceRegistry::AddInterface( |
42 const std::string& name, | 98 const std::string& name, |
43 const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, | 99 const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 | 147 |
92 auto iter = name_to_binder_.find(interface_name); | 148 auto iter = name_to_binder_.find(interface_name); |
93 if (iter != name_to_binder_.end()) { | 149 if (iter != name_to_binder_.end()) { |
94 iter->second->BindInterface(remote_identity_, | 150 iter->second->BindInterface(remote_identity_, |
95 interface_name, | 151 interface_name, |
96 std::move(handle)); | 152 std::move(handle)); |
97 } else if (!CanBindRequestForInterface(interface_name)) { | 153 } else if (!CanBindRequestForInterface(interface_name)) { |
98 std::stringstream ss; | 154 std::stringstream ss; |
99 ss << "Capability spec prevented service " << remote_identity_.name() | 155 ss << "Capability spec prevented service " << remote_identity_.name() |
100 << " from binding interface: " << interface_name | 156 << " from binding interface: " << interface_name |
101 << " exposed by: " << local_identity_.name(); | 157 << " exposed by: " << identity_.name(); |
102 LOG(ERROR) << ss.str(); | 158 LOG(ERROR) << ss.str(); |
103 mojo::ReportBadMessage(ss.str()); | 159 mojo::ReportBadMessage(ss.str()); |
104 } else if (!default_binder_.is_null()) { | 160 } else if (!default_binder_.is_null()) { |
105 default_binder_.Run(interface_name, std::move(handle)); | 161 default_binder_.Run(interface_name, std::move(handle)); |
106 } else { | 162 } else { |
107 LOG(ERROR) << "Failed to locate a binder for interface: " << interface_name | 163 LOG(ERROR) << "Failed to locate a binder for interface: " << interface_name |
108 << " requested by: " << remote_identity_.name() | 164 << " requested by: " << remote_identity_.name() |
109 << " exposed by: " << local_identity_.name(); | 165 << " exposed by: " << identity_.name(); |
110 } | 166 } |
111 } | 167 } |
112 | 168 |
113 bool InterfaceRegistry::SetInterfaceBinderForName( | 169 bool InterfaceRegistry::SetInterfaceBinderForName( |
114 std::unique_ptr<InterfaceBinder> binder, | 170 std::unique_ptr<InterfaceBinder> binder, |
115 const std::string& interface_name) { | 171 const std::string& interface_name) { |
116 if (CanBindRequestForInterface(interface_name)) { | 172 if (CanBindRequestForInterface(interface_name)) { |
117 RemoveInterface(interface_name); | 173 RemoveInterface(interface_name); |
118 name_to_binder_[interface_name] = std::move(binder); | 174 name_to_binder_[interface_name] = std::move(binder); |
119 return true; | 175 return true; |
120 } | 176 } |
121 return false; | 177 return false; |
122 } | 178 } |
123 | 179 |
124 bool InterfaceRegistry::CanBindRequestForInterface( | 180 bool InterfaceRegistry::CanBindRequestForInterface( |
125 const std::string& interface_name) const { | 181 const std::string& interface_name) const { |
| 182 // Any interface may be registered before the registry is bound to a pipe. At |
| 183 // bind time, the interfaces exposed will be intersected with the requirements |
| 184 // of the source. |
| 185 if (!binding_.is_bound()) |
| 186 return true; |
126 return allow_all_interfaces_ || allowed_interfaces_.count(interface_name); | 187 return allow_all_interfaces_ || allowed_interfaces_.count(interface_name); |
127 } | 188 } |
128 | 189 |
129 } // namespace service_manager | 190 } // namespace service_manager |
OLD | NEW |