| 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" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 it = source_spec.requires.find("*"); | 28 it = source_spec.requires.find("*"); |
| 29 if (it != source_spec.requires.end()) { | 29 if (it != source_spec.requires.end()) { |
| 30 std::copy(it->second.begin(), it->second.end(), | 30 std::copy(it->second.begin(), it->second.end(), |
| 31 std::inserter(capabilities, capabilities.begin())); | 31 std::inserter(capabilities, capabilities.begin())); |
| 32 } | 32 } |
| 33 return capabilities; | 33 return capabilities; |
| 34 } | 34 } |
| 35 | 35 |
| 36 // Generates a single set of interfaces that is the union of all interfaces | 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. | 37 // exposed by the target for the capabilities requested by the source. |
| 38 InterfaceSet GetAllowedInterfaces( | 38 InterfaceSet GetInterfacesToExpose( |
| 39 const InterfaceProviderSpec& source_spec, | 39 const InterfaceProviderSpec& source_spec, |
| 40 const Identity& target, | 40 const Identity& target, |
| 41 const InterfaceProviderSpec& target_spec) { | 41 const InterfaceProviderSpec& target_spec) { |
| 42 InterfaceSet allowed_interfaces; | 42 InterfaceSet exposed_interfaces; |
| 43 // TODO(beng): remove this once we can assert that an InterfaceRegistry must | 43 // TODO(beng): remove this once we can assert that an InterfaceRegistry must |
| 44 // always be constructed with a valid identity. | 44 // always be constructed with a valid identity. |
| 45 if (!target.IsValid()) { | 45 if (!target.IsValid()) { |
| 46 allowed_interfaces.insert("*"); | 46 exposed_interfaces.insert("*"); |
| 47 return allowed_interfaces; | 47 return exposed_interfaces; |
| 48 } | 48 } |
| 49 CapabilitySet capabilities = GetRequestedCapabilities(source_spec, target); | 49 CapabilitySet capabilities = GetRequestedCapabilities(source_spec, target); |
| 50 for (const auto& capability : capabilities) { | 50 for (const auto& capability : capabilities) { |
| 51 auto it = target_spec.provides.find(capability); | 51 auto it = target_spec.provides.find(capability); |
| 52 if (it != target_spec.provides.end()) { | 52 if (it != target_spec.provides.end()) { |
| 53 for (const auto& interface_name : it->second) | 53 for (const auto& interface_name : it->second) |
| 54 allowed_interfaces.insert(interface_name); | 54 exposed_interfaces.insert(interface_name); |
| 55 } | 55 } |
| 56 } | 56 } |
| 57 return allowed_interfaces; | 57 return exposed_interfaces; |
| 58 } | 58 } |
| 59 | 59 |
| 60 void SerializeIdentity(const Identity& identity, std::stringstream* stream) { |
| 61 *stream << identity.name() << "@" << identity.instance() << " run as: " |
| 62 << identity.user_id(); |
| 63 } |
| 64 |
| 65 void SerializeSpec(const InterfaceProviderSpec& spec, |
| 66 std::stringstream* stream) { |
| 67 *stream << " Providing:\n"; |
| 68 for (const auto& entry : spec.provides) { |
| 69 *stream << " capability: " << entry.first << " containing interfaces:\n"; |
| 70 for (const auto& interface_name : entry.second) |
| 71 *stream << " " << interface_name << "\n"; |
| 72 } |
| 73 *stream << "\n Requiring:\n"; |
| 74 for (const auto& entry : spec.requires) { |
| 75 *stream << " From: " << entry.first << ":\n"; |
| 76 for (const auto& capability_name : entry.second) |
| 77 *stream << " " << capability_name << "\n"; |
| 78 } |
| 79 } |
| 60 | 80 |
| 61 } // namespace | 81 } // namespace |
| 62 | 82 |
| 63 InterfaceRegistry::InterfaceRegistry(const std::string& name) | 83 InterfaceRegistry::InterfaceRegistry(const std::string& name) |
| 64 : binding_(this), | 84 : binding_(this), |
| 65 name_(name), | 85 name_(name), |
| 66 weak_factory_(this) {} | 86 weak_factory_(this) {} |
| 67 InterfaceRegistry::~InterfaceRegistry() {} | 87 InterfaceRegistry::~InterfaceRegistry() {} |
| 68 | 88 |
| 69 void InterfaceRegistry::Bind( | 89 void InterfaceRegistry::Bind( |
| 70 mojom::InterfaceProviderRequest local_interfaces_request, | 90 mojom::InterfaceProviderRequest local_interfaces_request, |
| 71 const Identity& local_identity, | 91 const Identity& local_identity, |
| 72 const InterfaceProviderSpec& local_interface_provider_spec, | 92 const InterfaceProviderSpec& local_interface_provider_spec, |
| 73 const Identity& remote_identity, | 93 const Identity& remote_identity, |
| 74 const InterfaceProviderSpec& remote_interface_provider_spec) { | 94 const InterfaceProviderSpec& remote_interface_provider_spec) { |
| 75 DCHECK(!binding_.is_bound()); | 95 DCHECK(!binding_.is_bound()); |
| 76 identity_ = local_identity; | 96 local_identity_ = local_identity; |
| 77 interface_provider_spec_ = local_interface_provider_spec; | 97 local_interface_provider_spec_ = local_interface_provider_spec; |
| 78 remote_identity_ = remote_identity; | 98 remote_identity_ = remote_identity; |
| 79 allowed_interfaces_ = GetAllowedInterfaces(remote_interface_provider_spec, | 99 remote_interface_provider_spec_ = remote_interface_provider_spec; |
| 80 identity_, | 100 RebuildExposedInterfaces(); |
| 81 interface_provider_spec_); | 101 binding_.Bind(std::move(local_interfaces_request)); |
| 82 allow_all_interfaces_ = | 102 } |
| 83 allowed_interfaces_.size() == 1 && allowed_interfaces_.count("*") == 1; | 103 |
| 84 if (!allow_all_interfaces_) { | 104 void InterfaceRegistry::Serialize(std::stringstream* stream) { |
| 85 for (auto it = name_to_binder_.begin(); it != name_to_binder_.end();) { | 105 *stream << "\n\nInterfaceRegistry(" << name_ << "):\n"; |
| 86 if (allowed_interfaces_.count(it->first) == 0) | 106 if (!binding_.is_bound()) { |
| 87 it = name_to_binder_.erase(it); | 107 *stream << "\n --> InterfaceRegistry is not yet bound to a pipe.\n\n"; |
| 88 else | 108 return; |
| 89 ++it; | |
| 90 } | |
| 91 } | 109 } |
| 92 binding_.Bind(std::move(local_interfaces_request)); | 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"; |
| 93 } | 136 } |
| 94 | 137 |
| 95 base::WeakPtr<InterfaceRegistry> InterfaceRegistry::GetWeakPtr() { | 138 base::WeakPtr<InterfaceRegistry> InterfaceRegistry::GetWeakPtr() { |
| 96 return weak_factory_.GetWeakPtr(); | 139 return weak_factory_.GetWeakPtr(); |
| 97 } | 140 } |
| 98 | 141 |
| 99 bool InterfaceRegistry::AddInterface( | 142 bool InterfaceRegistry::AddInterface( |
| 100 const std::string& name, | 143 const std::string& name, |
| 101 const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, | 144 const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, |
| 102 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { | 145 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 } | 183 } |
| 141 | 184 |
| 142 // mojom::InterfaceProvider: | 185 // mojom::InterfaceProvider: |
| 143 void InterfaceRegistry::GetInterface(const std::string& interface_name, | 186 void InterfaceRegistry::GetInterface(const std::string& interface_name, |
| 144 mojo::ScopedMessagePipeHandle handle) { | 187 mojo::ScopedMessagePipeHandle handle) { |
| 145 if (is_paused_) { | 188 if (is_paused_) { |
| 146 pending_interface_requests_.emplace(interface_name, std::move(handle)); | 189 pending_interface_requests_.emplace(interface_name, std::move(handle)); |
| 147 return; | 190 return; |
| 148 } | 191 } |
| 149 | 192 |
| 150 auto iter = name_to_binder_.find(interface_name); | 193 if (CanBindRequestForInterface(interface_name)) { |
| 151 if (iter != name_to_binder_.end()) { | 194 auto iter = name_to_binder_.find(interface_name); |
| 152 iter->second->BindInterface(remote_identity_, | 195 if (iter != name_to_binder_.end()) { |
| 153 interface_name, | 196 iter->second->BindInterface(remote_identity_, |
| 154 std::move(handle)); | 197 interface_name, |
| 155 } else if (!CanBindRequestForInterface(interface_name)) { | 198 std::move(handle)); |
| 199 } else if (!default_binder_.is_null()) { |
| 200 default_binder_.Run(interface_name, std::move(handle)); |
| 201 } else { |
| 202 std::stringstream ss; |
| 203 ss << "Failed to locate a binder for interface: " << interface_name |
| 204 << " requested by: " << remote_identity_.name() << " exposed by: " |
| 205 << local_identity_.name() << " via InterfaceProviderSpec \"" << name_ |
| 206 << "\"."; |
| 207 Serialize(&ss); |
| 208 LOG(ERROR) << ss.str(); |
| 209 } |
| 210 } else { |
| 156 std::stringstream ss; | 211 std::stringstream ss; |
| 157 ss << "InterfaceProviderSpec \"" << name_ << "\" prevented service: " | 212 ss << "InterfaceProviderSpec \"" << name_ << "\" prevented service: " |
| 158 << remote_identity_.name() << " from binding interface: " | 213 << remote_identity_.name() << " from binding interface: " |
| 159 << interface_name << " exposed by: " << identity_.name(); | 214 << interface_name << " exposed by: " << local_identity_.name(); |
| 215 Serialize(&ss); |
| 160 LOG(ERROR) << ss.str(); | 216 LOG(ERROR) << ss.str(); |
| 161 mojo::ReportBadMessage(ss.str()); | 217 mojo::ReportBadMessage(ss.str()); |
| 162 } else if (!default_binder_.is_null()) { | |
| 163 default_binder_.Run(interface_name, std::move(handle)); | |
| 164 } else { | |
| 165 LOG(ERROR) << "Failed to locate a binder for interface: " << interface_name | |
| 166 << " requested by: " << remote_identity_.name() | |
| 167 << " exposed by: " << identity_.name(); | |
| 168 } | 218 } |
| 169 } | 219 } |
| 170 | 220 |
| 171 bool InterfaceRegistry::SetInterfaceBinderForName( | 221 bool InterfaceRegistry::SetInterfaceBinderForName( |
| 172 std::unique_ptr<InterfaceBinder> binder, | 222 std::unique_ptr<InterfaceBinder> binder, |
| 173 const std::string& interface_name) { | 223 const std::string& interface_name) { |
| 174 if (CanBindRequestForInterface(interface_name)) { | 224 if (CanBindRequestForInterface(interface_name)) { |
| 175 RemoveInterface(interface_name); | 225 RemoveInterface(interface_name); |
| 176 name_to_binder_[interface_name] = std::move(binder); | 226 name_to_binder_[interface_name] = std::move(binder); |
| 177 return true; | 227 return true; |
| 178 } | 228 } |
| 179 return false; | 229 return false; |
| 180 } | 230 } |
| 181 | 231 |
| 182 bool InterfaceRegistry::CanBindRequestForInterface( | 232 bool InterfaceRegistry::CanBindRequestForInterface( |
| 183 const std::string& interface_name) const { | 233 const std::string& interface_name) const { |
| 184 // Any interface may be registered before the registry is bound to a pipe. At | 234 // Any interface may be registered before the registry is bound to a pipe. At |
| 185 // bind time, the interfaces exposed will be intersected with the requirements | 235 // bind time, the interfaces exposed will be intersected with the requirements |
| 186 // of the source. | 236 // of the source. |
| 187 if (!binding_.is_bound()) | 237 if (!binding_.is_bound()) |
| 188 return true; | 238 return true; |
| 189 return allow_all_interfaces_ || allowed_interfaces_.count(interface_name); | 239 return expose_all_interfaces_ || exposed_interfaces_.count(interface_name); |
| 240 } |
| 241 |
| 242 void InterfaceRegistry::RebuildExposedInterfaces() { |
| 243 exposed_interfaces_ = GetInterfacesToExpose(remote_interface_provider_spec_, |
| 244 local_identity_, |
| 245 local_interface_provider_spec_); |
| 246 expose_all_interfaces_ = |
| 247 exposed_interfaces_.size() == 1 && exposed_interfaces_.count("*") == 1; |
| 190 } | 248 } |
| 191 | 249 |
| 192 } // namespace service_manager | 250 } // namespace service_manager |
| OLD | NEW |