Index: services/service_manager/service_manager.cc |
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc |
index d29b0c9ad960ddaa0ecf2844270e479d7cef74a5..5db7cae74290010d4619fbaf71d0b3a0ad410444 100644 |
--- a/services/service_manager/service_manager.cc |
+++ b/services/service_manager/service_manager.cc |
@@ -22,6 +22,7 @@ |
#include "mojo/public/cpp/bindings/associated_binding.h" |
#include "mojo/public/cpp/bindings/binding.h" |
#include "mojo/public/cpp/bindings/binding_set.h" |
+#include "mojo/public/cpp/bindings/strong_binding.h" |
#include "services/catalog/public/interfaces/constants.mojom.h" |
#include "services/service_manager/connect_util.h" |
#include "services/service_manager/public/cpp/connector.h" |
@@ -77,6 +78,25 @@ bool HasCapability(const InterfaceProviderSpec& spec, |
return it->second.find(capability) != it->second.end(); |
} |
+bool AllowsInterface(const Identity& source, |
+ const InterfaceProviderSpec& source_spec, |
+ const Identity& target, |
+ const InterfaceProviderSpec& target_spec, |
+ const std::string& interface_name) { |
+ InterfaceSet exposed = |
+ GetInterfacesToExpose(source_spec, target, target_spec); |
+ bool allowed = (exposed.size() == 1 && exposed.count("*") == 1) || |
+ exposed.count(interface_name) > 0; |
+ if (!allowed) { |
+ std::stringstream ss; |
+ ss << "Connection InterfaceProviderSpec prevented service: " |
+ << source.name() << " from binding interface: " << interface_name |
+ << " exposed by: " << target.name(); |
+ LOG(ERROR) << ss.str(); |
+ } |
+ return allowed; |
+} |
+ |
// Encapsulates a connection to an instance of a service, tracked by the |
// Service Manager. |
class ServiceManager::Instance |
@@ -145,17 +165,8 @@ class ServiceManager::Instance |
source_connection_spec = source->GetConnectionSpec(); |
} |
- InterfaceSet exposed = GetInterfacesToExpose(source_connection_spec, |
- identity_, |
- GetConnectionSpec()); |
- bool allowed = (exposed.size() == 1 && exposed.count("*") == 1) || |
- exposed.count(params->interface_name()) > 0; |
- if (!allowed) { |
- std::stringstream ss; |
- ss << "Connection InterfaceProviderSpec prevented service: " |
- << params->source().name() << " from binding interface: " |
- << params->interface_name() << " exposed by: " << identity_.name(); |
- LOG(ERROR) << ss.str(); |
+ if (!AllowsInterface(params->source(), source_connection_spec, identity_, |
+ GetConnectionSpec(), params->interface_name())) { |
params->set_response_data(mojom::ConnectResult::ACCESS_DENIED, identity_); |
return false; |
} |
@@ -215,10 +226,17 @@ class ServiceManager::Instance |
} |
const InterfaceProviderSpec& GetConnectionSpec() const { |
- auto it = interface_provider_specs_.find( |
- mojom::kServiceManager_ConnectorSpec); |
+ return GetSpecNamed(mojom::kServiceManager_ConnectorSpec); |
+ } |
+ bool HasSpecNamed(const std::string& spec) const { |
Ken Rockot(use gerrit already)
2017/04/26 04:32:48
nits: GetSpec and HasSpec? And vertical whitespace
|
+ auto it = interface_provider_specs_.find(spec); |
+ return it != interface_provider_specs_.end(); |
+ } |
+ const InterfaceProviderSpec& GetSpecNamed(const std::string& spec) const { |
+ auto it = interface_provider_specs_.find(spec); |
return it != interface_provider_specs_.end() ? it->second : empty_spec_; |
} |
+ |
const Identity& identity() const { return identity_; } |
void set_identity(const Identity& identity) { identity_ = identity; } |
uint32_t id() const { return id_; } |
@@ -240,7 +258,7 @@ class ServiceManager::Instance |
} |
private: |
- enum class State { |
+ enum class State { |
// The service was not started yet. |
IDLE, |
@@ -252,74 +270,137 @@ class ServiceManager::Instance |
STARTED |
}; |
+ class InterfaceProviderImpl : public mojom::InterfaceProvider { |
+ public: |
+ InterfaceProviderImpl(const std::string& spec, |
+ const Identity& source_identity, |
+ const Identity& target_identity, |
+ service_manager::ServiceManager* service_manager, |
+ mojom::InterfaceProviderPtr target) |
+ : spec_(spec), |
+ source_identity_(source_identity), |
+ target_identity_(target_identity), |
+ service_manager_(service_manager), |
+ target_(std::move(target)) {} |
+ ~InterfaceProviderImpl() override {} |
+ |
+ private: |
+ // mojom::InterfaceProvider: |
+ void GetInterface(const std::string& interface_name, |
+ mojo::ScopedMessagePipeHandle interface_pipe) override { |
+ Instance* source = |
+ service_manager_->GetExistingInstance(source_identity_); |
+ Instance* target = |
+ service_manager_->GetExistingInstance(target_identity_); |
+ if (!source || !target) |
+ return; |
+ if (!ValidateSpec(source) || !ValidateSpec(target)) |
+ return; |
+ |
+ if (AllowsInterface(source_identity_, source->GetSpecNamed(spec_), |
+ target_identity_, target->GetSpecNamed(spec_), |
+ interface_name)) { |
+ target_->GetInterface(interface_name, std::move(interface_pipe)); |
+ } |
+ } |
+ |
+ bool ValidateSpec(Instance* instance) const { |
+ if (!instance->HasSpecNamed(spec_)) { |
+ LOG(ERROR) << "Instance for: " << instance->identity().name() |
+ << " did not have spec named: " << spec_; |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ const std::string spec_; |
+ const Identity source_identity_; |
+ const Identity target_identity_; |
+ service_manager::ServiceManager* service_manager_; |
Ken Rockot(use gerrit already)
2017/04/26 04:32:48
nit: this could be const too (service_manager::Ser
|
+ |
+ mojom::InterfaceProviderPtr target_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(InterfaceProviderImpl); |
+ }; |
+ |
// mojom::Connector implementation: |
- void BindInterface(const service_manager::Identity& in_target, |
- const std::string& interface_name, |
- mojo::ScopedMessagePipeHandle interface_pipe, |
- const BindInterfaceCallback& callback) override { |
- Identity target = in_target; |
- mojom::ConnectResult result = |
- ValidateConnectParams(&target, nullptr, nullptr); |
- if (!Succeeded(result)) { |
- callback.Run(result, Identity()); |
- return; |
- } |
- |
- std::unique_ptr<ConnectParams> params(new ConnectParams); |
- params->set_source(identity_); |
- params->set_target(target); |
- params->set_interface_request_info(interface_name, |
- std::move(interface_pipe)); |
- params->set_start_service_callback(callback); |
- service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
- } |
- |
- void StartService(const Identity& in_target, |
- const StartServiceCallback& callback) override { |
- Identity target = in_target; |
- mojom::ConnectResult result = |
- ValidateConnectParams(&target, nullptr, nullptr); |
- if (!Succeeded(result)) { |
- callback.Run(result, Identity()); |
- return; |
- } |
- |
- std::unique_ptr<ConnectParams> params(new ConnectParams); |
- params->set_source(identity_); |
- params->set_target(target); |
- params->set_start_service_callback(callback); |
- service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
- } |
- |
- void StartServiceWithProcess( |
- const Identity& in_target, |
- mojo::ScopedMessagePipeHandle service_handle, |
- mojom::PIDReceiverRequest pid_receiver_request, |
- const StartServiceWithProcessCallback& callback) override { |
- Identity target = in_target; |
- mojom::ConnectResult result = |
- ValidateConnectParams(&target, nullptr, nullptr); |
- if (!Succeeded(result)) { |
- callback.Run(result, Identity()); |
- return; |
- } |
- |
- std::unique_ptr<ConnectParams> params(new ConnectParams); |
- params->set_source(identity_); |
- params->set_target(target); |
- |
- mojom::ServicePtr service; |
- service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0)); |
- params->set_client_process_info(std::move(service), |
- std::move(pid_receiver_request)); |
- params->set_start_service_callback(callback); |
- service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
+ void BindInterface(const service_manager::Identity& in_target, |
+ const std::string& interface_name, |
+ mojo::ScopedMessagePipeHandle interface_pipe, |
+ const BindInterfaceCallback& callback) override { |
+ Identity target = in_target; |
+ mojom::ConnectResult result = |
+ ValidateConnectParams(&target, nullptr, nullptr); |
+ if (!Succeeded(result)) { |
+ callback.Run(result, Identity()); |
+ return; |
+ } |
+ |
+ std::unique_ptr<ConnectParams> params(new ConnectParams); |
+ params->set_source(identity_); |
+ params->set_target(target); |
+ params->set_interface_request_info(interface_name, |
+ std::move(interface_pipe)); |
+ params->set_start_service_callback(callback); |
+ service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
+ } |
+ |
+ void StartService(const Identity& in_target, |
+ const StartServiceCallback& callback) override { |
+ Identity target = in_target; |
+ mojom::ConnectResult result = |
+ ValidateConnectParams(&target, nullptr, nullptr); |
+ if (!Succeeded(result)) { |
+ callback.Run(result, Identity()); |
+ return; |
+ } |
+ |
+ std::unique_ptr<ConnectParams> params(new ConnectParams); |
+ params->set_source(identity_); |
+ params->set_target(target); |
+ params->set_start_service_callback(callback); |
+ service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
+ } |
+ |
+ void StartServiceWithProcess( |
+ const Identity& in_target, |
+ mojo::ScopedMessagePipeHandle service_handle, |
+ mojom::PIDReceiverRequest pid_receiver_request, |
+ const StartServiceWithProcessCallback& callback) override { |
+ Identity target = in_target; |
+ mojom::ConnectResult result = |
+ ValidateConnectParams(&target, nullptr, nullptr); |
+ if (!Succeeded(result)) { |
+ callback.Run(result, Identity()); |
+ return; |
+ } |
+ |
+ std::unique_ptr<ConnectParams> params(new ConnectParams); |
+ params->set_source(identity_); |
+ params->set_target(target); |
+ |
+ mojom::ServicePtr service; |
+ service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0)); |
+ params->set_client_process_info(std::move(service), |
+ std::move(pid_receiver_request)); |
+ params->set_start_service_callback(callback); |
+ service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
} |
void Clone(mojom::ConnectorRequest request) override { |
connectors_.AddBinding(this, std::move(request)); |
} |
+ void ApplySpec(const std::string& spec, |
+ const Identity& source, |
+ mojom::InterfaceProviderRequest source_request, |
+ mojom::InterfaceProviderPtr target) override { |
+ mojo::MakeStrongBinding( |
Ken Rockot(use gerrit already)
2017/04/26 04:32:48
It's not safe to use StrongBinding here if you're
|
+ base::MakeUnique<InterfaceProviderImpl>( |
+ spec, source, identity_, service_manager_, std::move(target)), |
+ std::move(source_request)); |
+ } |
+ |
// mojom::PIDReceiver: |
void SetPID(uint32_t pid) override { |
PIDAvailable(pid); |