| Index: services/service_manager/service_manager.cc
|
| diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc
|
| index 63a0d7c487a7b22bf06e1f7708fed8e498a9d791..a7e11851647d31f8ea7a2ab724549b60a3edaaa8 100644
|
| --- a/services/service_manager/service_manager.cc
|
| +++ b/services/service_manager/service_manager.cc
|
| @@ -47,6 +47,34 @@ const char kCapability_InstancePerChild[] =
|
| "service_manager:instance_per_child";
|
| const char kCapability_ServiceManager[] = "service_manager:service_manager";
|
|
|
| +bool Succeeded(mojom::ConnectResult result) {
|
| + return result == mojom::ConnectResult::SUCCEEDED;
|
| +}
|
| +
|
| +bool RunConnectCallback(ConnectParams* params,
|
| + mojom::ConnectResult result,
|
| + const std::string& user_id) {
|
| + if (!params->connect_callback().is_null()) {
|
| + params->connect_callback().Run(result, user_id);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void RunBindInterfaceCallback(ConnectParams* params,
|
| + mojom::ConnectResult result,
|
| + const std::string& user_id) {
|
| + if (!params->bind_interface_callback().is_null())
|
| + params->bind_interface_callback().Run(result, user_id);
|
| +}
|
| +
|
| +void RunCallback(ConnectParams* params,
|
| + mojom::ConnectResult result,
|
| + const std::string& user_id) {
|
| + if (!RunConnectCallback(params, result, user_id))
|
| + RunBindInterfaceCallback(params, result, user_id);
|
| +}
|
| +
|
| } // namespace
|
|
|
| Identity CreateServiceManagerIdentity() {
|
| @@ -125,18 +153,20 @@ class ServiceManager::Instance
|
| Stop();
|
| }
|
|
|
| - bool ConnectToService(std::unique_ptr<ConnectParams>* connect_params) {
|
| - if (!service_.is_bound())
|
| + bool OnConnect(std::unique_ptr<ConnectParams>* in_params) {
|
| + if (!service_.is_bound()) {
|
| + RunConnectCallback(in_params->get(), mojom::ConnectResult::ACCESS_DENIED,
|
| + identity_.user_id());
|
| return false;
|
| -
|
| - std::unique_ptr<ConnectParams> params(std::move(*connect_params));
|
| - if (!params->connect_callback().is_null()) {
|
| - params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED,
|
| - identity_.user_id());
|
| }
|
|
|
| + std::unique_ptr<ConnectParams> params(std::move(*in_params));
|
| + RunConnectCallback(params.get(), mojom::ConnectResult::SUCCEEDED,
|
| + identity_.user_id());
|
| +
|
| InterfaceProviderSpecMap specs;
|
| - Instance* source = service_manager_->GetExistingInstance(params->source());
|
| + Instance* source =
|
| + service_manager_->GetExistingInstance(params->source());
|
| if (source)
|
| specs = source->interface_provider_specs_;
|
|
|
| @@ -148,6 +178,52 @@ class ServiceManager::Instance
|
| return true;
|
| }
|
|
|
| + bool OnBindInterface(std::unique_ptr<ConnectParams>* in_params) {
|
| + if (!service_.is_bound()) {
|
| + RunBindInterfaceCallback(in_params->get(),
|
| + mojom::ConnectResult::ACCESS_DENIED,
|
| + identity_.user_id());
|
| + return false;
|
| + }
|
| +
|
| + std::unique_ptr<ConnectParams> params(std::move(*in_params));
|
| + InterfaceProviderSpecMap source_specs;
|
| + InterfaceProviderSpec source_connection_spec;
|
| + Instance* source =
|
| + service_manager_->GetExistingInstance(params->source());
|
| + if (source) {
|
| + source_specs = source->interface_provider_specs_;
|
| + 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();
|
| + params->bind_interface_callback().Run(mojom::ConnectResult::ACCESS_DENIED,
|
| + identity_.user_id());
|
| + return false;
|
| + }
|
| +
|
| + params->bind_interface_callback().Run(mojom::ConnectResult::SUCCEEDED,
|
| + identity_.user_id());
|
| +
|
| + pending_service_connections_++;
|
| + service_->OnBindInterface(
|
| + ServiceInfo(params->source(), source_specs),
|
| + params->interface_name(),
|
| + params->TakeInterfaceRequestPipe(),
|
| + base::Bind(&Instance::OnConnectComplete, base::Unretained(this)));
|
| + return true;
|
| + }
|
| +
|
| void OnConnectComplete() {
|
| DCHECK_GT(pending_service_connections_, 0);
|
| pending_service_connections_--;
|
| @@ -229,72 +305,65 @@ class ServiceManager::Instance
|
|
|
| // mojom::Connector implementation:
|
| void StartService(
|
| - const Identity& target,
|
| + const Identity& in_target,
|
| mojo::ScopedMessagePipeHandle service_handle,
|
| mojom::PIDReceiverRequest pid_receiver_request) override {
|
| + Identity target = in_target;
|
| + mojom::ConnectResult result =
|
| + ValidateConnectParams(&target, nullptr, nullptr);
|
| + if (!Succeeded(result))
|
| + 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));
|
| - ConnectImpl(
|
| - target,
|
| - mojom::InterfaceProviderRequest(),
|
| - std::move(service),
|
| - std::move(pid_receiver_request),
|
| - base::Bind(
|
| - &service_manager::ServiceManager::Instance::EmptyConnectCallback,
|
| - weak_factory_.GetWeakPtr()));
|
| + params->set_client_process_info(std::move(service),
|
| + std::move(pid_receiver_request));
|
| + service_manager_->Connect(
|
| + std::move(params), nullptr, weak_factory_.GetWeakPtr());
|
| }
|
|
|
| - void Connect(const service_manager::Identity& target,
|
| + void Connect(const service_manager::Identity& in_target,
|
| mojom::InterfaceProviderRequest remote_interfaces,
|
| const ConnectCallback& callback) override {
|
| - ConnectImpl(target, std::move(remote_interfaces), mojom::ServicePtr(),
|
| - mojom::PIDReceiverRequest(), callback);
|
| + Identity target = in_target;
|
| + mojom::ConnectResult result =
|
| + ValidateConnectParams(&target, nullptr, nullptr);
|
| + if (!Succeeded(result)) {
|
| + callback.Run(result, mojom::kInheritUserID);
|
| + return;
|
| + }
|
| +
|
| + std::unique_ptr<ConnectParams> params(new ConnectParams);
|
| + params->set_source(identity_);
|
| + params->set_target(target);
|
| + params->set_remote_interfaces(std::move(remote_interfaces));
|
| + params->set_connect_callback(callback);
|
| + service_manager_->Connect(
|
| + std::move(params), nullptr, weak_factory_.GetWeakPtr());
|
| }
|
|
|
| - void BindInterface(const service_manager::Identity& target,
|
| + void BindInterface(const service_manager::Identity& in_target,
|
| const std::string& interface_name,
|
| mojo::ScopedMessagePipeHandle interface_pipe,
|
| const BindInterfaceCallback& callback) override {
|
| - mojom::InterfaceProviderPtr remote_interfaces;
|
| - ConnectImpl(
|
| - target,
|
| - MakeRequest(&remote_interfaces),
|
| - mojom::ServicePtr(),
|
| - mojom::PIDReceiverRequest(),
|
| - base::Bind(
|
| - &service_manager::ServiceManager::Instance::BindCallbackWrapper,
|
| - weak_factory_.GetWeakPtr(),
|
| - callback));
|
| - remote_interfaces->GetInterface(interface_name, std::move(interface_pipe));
|
| - // TODO(beng): Rather than just forwarding thru to InterfaceProvider, do
|
| - // manifest policy intersection here.
|
| - }
|
| -
|
| - void ConnectImpl(const service_manager::Identity& in_target,
|
| - mojom::InterfaceProviderRequest remote_interfaces,
|
| - mojom::ServicePtr service,
|
| - mojom::PIDReceiverRequest pid_receiver_request,
|
| - const ConnectCallback& callback) {
|
| Identity target = in_target;
|
| - if (target.user_id() == mojom::kInheritUserID)
|
| - target.set_user_id(identity_.user_id());
|
| -
|
| - if (!ValidateIdentity(target, callback))
|
| - return;
|
| - if (!ValidateClientProcessInfo(&service, &pid_receiver_request, target,
|
| - callback)) {
|
| + mojom::ConnectResult result =
|
| + ValidateConnectParams(&target, nullptr, nullptr);
|
| + if (!Succeeded(result)) {
|
| + callback.Run(result, mojom::kInheritUserID);
|
| return;
|
| }
|
| - if (!ValidateConnectionSpec(target, callback))
|
| - return;
|
|
|
| std::unique_ptr<ConnectParams> params(new ConnectParams);
|
| params->set_source(identity_);
|
| params->set_target(target);
|
| - params->set_remote_interfaces(std::move(remote_interfaces));
|
| - params->set_client_process_info(std::move(service),
|
| - std::move(pid_receiver_request));
|
| - params->set_connect_callback(callback);
|
| + params->set_interface_request_info(interface_name,
|
| + std::move(interface_pipe));
|
| + params->set_bind_interface_callback(callback);
|
| service_manager_->Connect(
|
| std::move(params), nullptr, weak_factory_.GetWeakPtr());
|
| }
|
| @@ -321,61 +390,66 @@ class ServiceManager::Instance
|
| service_manager_->AddListener(std::move(listener));
|
| }
|
|
|
| - bool ValidateIdentity(const Identity& identity,
|
| - const ConnectCallback& callback) {
|
| + mojom::ConnectResult ValidateConnectParams(
|
| + Identity* target,
|
| + mojom::ServicePtr* service,
|
| + mojom::PIDReceiverRequest* pid_receiver_request) {
|
| + if (target->user_id() == mojom::kInheritUserID)
|
| + target->set_user_id(identity_.user_id());
|
| +
|
| + mojom::ConnectResult result = ValidateIdentity(*target);
|
| + if (!Succeeded(result))
|
| + return result;
|
| +
|
| + result = ValidateClientProcessInfo(service, pid_receiver_request, *target);
|
| + if (!Succeeded(result))
|
| + return result;
|
| + return ValidateConnectionSpec(*target);
|
| + }
|
| +
|
| + mojom::ConnectResult ValidateIdentity(const Identity& identity) {
|
| if (identity.name().empty()) {
|
| LOG(ERROR) << "Error: empty service name.";
|
| - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT,
|
| - mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::INVALID_ARGUMENT;
|
| }
|
| if (!base::IsValidGUID(identity.user_id())) {
|
| LOG(ERROR) << "Error: invalid user_id: " << identity.user_id();
|
| - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT,
|
| - mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::INVALID_ARGUMENT;
|
| }
|
| - return true;
|
| + return mojom::ConnectResult::SUCCEEDED;
|
| }
|
|
|
| - bool ValidateClientProcessInfo(
|
| + mojom::ConnectResult ValidateClientProcessInfo(
|
| mojom::ServicePtr* service,
|
| mojom::PIDReceiverRequest* pid_receiver_request,
|
| - const Identity& target,
|
| - const ConnectCallback& callback) {
|
| - if (service->is_bound() || pid_receiver_request->is_pending()) {
|
| + const Identity& target) {
|
| + if (service && pid_receiver_request &&
|
| + (service->is_bound() || pid_receiver_request->is_pending())) {
|
| if (!HasCapability(GetConnectionSpec(), kCapability_ClientProcess)) {
|
| LOG(ERROR) << "Instance: " << identity_.name() << " attempting "
|
| << "to register an instance for a process it created for "
|
| << "target: " << target.name() << " without the "
|
| << "service_manager{client_process} capability "
|
| << "class.";
|
| - callback.Run(mojom::ConnectResult::ACCESS_DENIED,
|
| - mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::ACCESS_DENIED;
|
| }
|
|
|
| if (!service->is_bound() || !pid_receiver_request->is_pending()) {
|
| LOG(ERROR) << "Must supply both service AND "
|
| << "pid_receiver_request when sending client process info";
|
| - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT,
|
| - mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::INVALID_ARGUMENT;
|
| }
|
| if (service_manager_->GetExistingInstance(target)) {
|
| LOG(ERROR) << "Cannot client process matching existing identity:"
|
| << "Name: " << target.name() << " User: "
|
| << target.user_id() << " Instance: " << target.instance();
|
| - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT,
|
| - mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::INVALID_ARGUMENT;
|
| }
|
| }
|
| - return true;
|
| + return mojom::ConnectResult::SUCCEEDED;
|
| }
|
|
|
| - bool ValidateConnectionSpec(const Identity& target,
|
| - const ConnectCallback& callback) {
|
| + mojom::ConnectResult ValidateConnectionSpec(const Identity& target) {
|
| InterfaceProviderSpec connection_spec = GetConnectionSpec();
|
| // TODO(beng): Need to do the following additional policy validation of
|
| // whether this instance is allowed to connect using:
|
| @@ -388,9 +462,7 @@ class ServiceManager::Instance
|
| << " attempting to connect to: " << target.name()
|
| << " as: " << target.user_id() << " without "
|
| << " the service:service_manager{user_id} capability.";
|
| - callback.Run(mojom::ConnectResult::ACCESS_DENIED,
|
| - mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::ACCESS_DENIED;
|
| }
|
| if (!target.instance().empty() &&
|
| target.instance() != target.name() &&
|
| @@ -400,19 +472,17 @@ class ServiceManager::Instance
|
| << " using Instance name: " << target.instance()
|
| << " without the "
|
| << "service_manager{instance_name} capability.";
|
| - callback.Run(mojom::ConnectResult::ACCESS_DENIED, mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::ACCESS_DENIED;
|
| }
|
|
|
| if (allow_any_application_ ||
|
| connection_spec.requires.find(target.name()) !=
|
| connection_spec.requires.end()) {
|
| - return true;
|
| + return mojom::ConnectResult::SUCCEEDED;
|
| }
|
| LOG(ERROR) << "InterfaceProviderSpec prevented connection from: "
|
| << identity_.name() << " to: " << target.name();
|
| - callback.Run(mojom::ConnectResult::ACCESS_DENIED, mojom::kInheritUserID);
|
| - return false;
|
| + return mojom::ConnectResult::ACCESS_DENIED;
|
| }
|
|
|
| uint32_t GenerateUniqueID() const {
|
| @@ -782,7 +852,14 @@ void ServiceManager::NotifyServiceFailedToStart(const Identity& identity) {
|
| bool ServiceManager::ConnectToExistingInstance(
|
| std::unique_ptr<ConnectParams>* params) {
|
| Instance* instance = GetExistingInstance((*params)->target());
|
| - return instance && instance->ConnectToService(params);
|
| + if (instance) {
|
| + if ((*params)->HasInterfaceRequestInfo()) {
|
| + instance->OnBindInterface(params);
|
| + return true;
|
| + }
|
| + return instance->OnConnect(params);
|
| + }
|
| + return false;
|
| }
|
|
|
| ServiceManager::Instance* ServiceManager::CreateInstance(
|
| @@ -868,10 +945,7 @@ void ServiceManager::OnGotResolvedName(std::unique_ptr<ConnectParams> params,
|
| // If name resolution failed, we drop the connection.
|
| if (!result) {
|
| LOG(ERROR) << "Failed to resolve service name: " << params->target().name();
|
| - if (!params->connect_callback().is_null()) {
|
| - params->connect_callback().Run(
|
| - mojom::ConnectResult::INVALID_ARGUMENT, "");
|
| - }
|
| + RunCallback(params.get(), mojom::ConnectResult::INVALID_ARGUMENT, "");
|
| return;
|
| }
|
|
|
| @@ -941,8 +1015,7 @@ void ServiceManager::OnGotResolvedName(std::unique_ptr<ConnectParams> params,
|
| LOG(ERROR)
|
| << "Error: The catalog was unable to read a manifest for service \""
|
| << result->name << "\".";
|
| - if (!params->connect_callback().is_null())
|
| - params->connect_callback().Run(mojom::ConnectResult::ACCESS_DENIED, "");
|
| + RunCallback(params.get(), mojom::ConnectResult::ACCESS_DENIED, "");
|
| return;
|
| }
|
|
|
| @@ -980,18 +1053,19 @@ void ServiceManager::OnGotResolvedName(std::unique_ptr<ConnectParams> params,
|
|
|
| if (!instance->StartWithFilePath(package_path)) {
|
| OnInstanceError(instance);
|
| - if (!params->connect_callback().is_null()) {
|
| - params->connect_callback().Run(
|
| - mojom::ConnectResult::INVALID_ARGUMENT, "");
|
| - }
|
| + RunCallback(params.get(), mojom::ConnectResult::INVALID_ARGUMENT, "");
|
| return;
|
| }
|
| }
|
| }
|
|
|
| // Now that the instance has a Service, we can connect to it.
|
| - bool connected = instance->ConnectToService(¶ms);
|
| - DCHECK(connected);
|
| + if (params->HasInterfaceRequestInfo()) {
|
| + instance->OnBindInterface(¶ms);
|
| + } else {
|
| + bool connected = instance->OnConnect(¶ms);
|
| + DCHECK(connected);
|
| + }
|
| }
|
|
|
| base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() {
|
|
|