| Index: mojo/shell/shell.cc
|
| diff --git a/mojo/shell/shell.cc b/mojo/shell/shell.cc
|
| index 17e912b64dcba59f1203bc189fe10929cf0b2c4f..4955c971721df8be895d22ca468c8f947bf068a1 100644
|
| --- a/mojo/shell/shell.cc
|
| +++ b/mojo/shell/shell.cc
|
| @@ -37,12 +37,40 @@ namespace {
|
| const char kPackageManagerName[] = "mojo:package_manager";
|
|
|
| void EmptyResolverCallback(const String& resolved_name,
|
| - const String& resolved_qualifier,
|
| + const String& resolved_instance,
|
| mojom::CapabilityFilterPtr base_filter,
|
| const String& file_url) {}
|
|
|
| }
|
|
|
| +Identity CreateShellIdentity() {
|
| + return Identity("mojo:shell", mojom::kRootUserID);
|
| +}
|
| +
|
| +CapabilityFilter GetPermissiveCapabilityFilter() {
|
| + CapabilityFilter filter;
|
| + AllowedInterfaces interfaces;
|
| + interfaces.insert("*");
|
| + filter["*"] = interfaces;
|
| + return filter;
|
| +}
|
| +
|
| +AllowedInterfaces GetAllowedInterfaces(const CapabilityFilter& filter,
|
| + const Identity& identity) {
|
| + // Start by looking for interfaces specific to the supplied identity.
|
| + auto it = filter.find(identity.name());
|
| + if (it != filter.end())
|
| + return it->second;
|
| +
|
| + // Fall back to looking for a wildcard rule.
|
| + it = filter.find("*");
|
| + if (filter.size() == 1 && it != filter.end())
|
| + return it->second;
|
| +
|
| + // Finally, nothing is allowed.
|
| + return AllowedInterfaces();
|
| +}
|
| +
|
| // Encapsulates a connection to an instance of an application, tracked by the
|
| // shell's Shell.
|
| class Shell::Instance : public mojom::Connector,
|
| @@ -53,12 +81,13 @@ class Shell::Instance : public mojom::Connector,
|
| public:
|
| Instance(mojom::ShellClientPtr shell_client,
|
| mojo::shell::Shell* shell,
|
| - const Identity& identity)
|
| + const Identity& identity,
|
| + const CapabilityFilter& filter)
|
| : shell_(shell),
|
| id_(GenerateUniqueID()),
|
| identity_(identity),
|
| - allow_any_application_(identity.filter().size() == 1 &&
|
| - identity.filter().count("*") == 1),
|
| + filter_(filter),
|
| + allow_any_application_(filter.size() == 1 && filter.count("*") == 1),
|
| shell_client_(std::move(shell_client)),
|
| pid_receiver_binding_(this),
|
| weak_factory_(this) {
|
| @@ -73,7 +102,7 @@ class Shell::Instance : public mojom::Connector,
|
|
|
| void InitializeClient() {
|
| shell_client_->Initialize(connectors_.CreateInterfacePtrAndBind(this),
|
| - identity_.name(), identity_.user_id(), id_);
|
| + mojom::Identity::From(identity_), id_);
|
| connectors_.set_connection_error_handler(
|
| base::Bind(&mojo::shell::Shell::OnInstanceError,
|
| base::Unretained(shell_), base::Unretained(this)));
|
| @@ -82,15 +111,16 @@ class Shell::Instance : public mojom::Connector,
|
| void ConnectToClient(scoped_ptr<ConnectParams> params) {
|
| params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED,
|
| identity_.user_id(), id_);
|
| + uint32_t source_id = mojom::kInvalidInstanceID;
|
| AllowedInterfaces interfaces;
|
| interfaces.insert("*");
|
| - if (!params->source().is_null())
|
| - interfaces = GetAllowedInterfaces(params->source().filter(), identity_);
|
| -
|
| Instance* source = shell_->GetExistingInstance(params->source());
|
| - uint32_t source_id = source ? source->id() : mojom::kInvalidInstanceID;
|
| + if (source) {
|
| + interfaces = GetAllowedInterfaces(source->filter_, identity_);
|
| + source_id = source->id();
|
| + }
|
| shell_client_->AcceptConnection(
|
| - params->source().name(), params->source().user_id(), source_id,
|
| + mojom::Identity::From(params->source()), source_id,
|
| params->TakeRemoteInterfaces(), params->TakeLocalInterfaces(),
|
| Array<String>::From(interfaces), params->target().name());
|
| }
|
| @@ -114,8 +144,7 @@ class Shell::Instance : public mojom::Connector,
|
| mojom::InstanceInfoPtr CreateInstanceInfo() const {
|
| mojom::InstanceInfoPtr info(mojom::InstanceInfo::New());
|
| info->id = id_;
|
| - info->name = identity_.name();
|
| - info->qualifier = identity_.qualifier();
|
| + info->identity = mojom::Identity::From(identity_);
|
| info->pid = pid_;
|
| return info;
|
| }
|
| @@ -131,37 +160,37 @@ class Shell::Instance : public mojom::Connector,
|
|
|
| private:
|
| // mojom::Connector implementation:
|
| - void Connect(const String& app_name,
|
| - const String& user_id,
|
| - shell::mojom::InterfaceProviderRequest remote_interfaces,
|
| - shell::mojom::InterfaceProviderPtr local_interfaces,
|
| + void Connect(mojom::IdentityPtr target,
|
| + mojom::InterfaceProviderRequest remote_interfaces,
|
| + mojom::InterfaceProviderPtr local_interfaces,
|
| const ConnectCallback& callback) override {
|
| - if (!IsValidName(app_name)) {
|
| - LOG(ERROR) << "Error: invalid Name: " << app_name;
|
| + if (!IsValidName(target->name)) {
|
| + LOG(ERROR) << "Error: invalid Name: " << target->name;
|
| callback.Run(mojom::ConnectResult::INVALID_ARGUMENT,
|
| mojom::kInheritUserID, mojom::kInvalidInstanceID);
|
| return;
|
| }
|
| - if (!base::IsValidGUID(user_id)) {
|
| - LOG(ERROR) << "Error: invalid user_id: " << user_id;
|
| + if (!base::IsValidGUID(target->user_id)) {
|
| + LOG(ERROR) << "Error: invalid user_id: " << target->user_id;
|
| callback.Run(mojom::ConnectResult::INVALID_ARGUMENT,
|
| mojom::kInheritUserID, mojom::kInvalidInstanceID);
|
| return;
|
| }
|
| // TODO(beng): perform checking on policy of whether this instance is
|
| // allowed to pass different user_ids.
|
| - if (allow_any_application_ ||
|
| - identity_.filter().find(app_name) != identity_.filter().end()) {
|
| + // TODO(beng): perform checking on policy of whether this instance is
|
| + // allowed to pass non-empty instance identifiers.
|
| + if (allow_any_application_ || filter_.find(target->name) != filter_.end()) {
|
| scoped_ptr<ConnectParams> params(new ConnectParams);
|
| params->set_source(identity_);
|
| - params->set_target(Identity(app_name, std::string(), user_id));
|
| + params->set_target(target.To<Identity>());
|
| params->set_remote_interfaces(std::move(remote_interfaces));
|
| params->set_local_interfaces(std::move(local_interfaces));
|
| params->set_connect_callback(callback);
|
| shell_->Connect(std::move(params));
|
| } else {
|
| LOG(WARNING) << "CapabilityFilter prevented connection from: " <<
|
| - identity_.name() << " to: " << app_name;
|
| + identity_.name() << " to: " << target->name;
|
| callback.Run(mojom::ConnectResult::ACCESS_DENIED,
|
| mojom::kInheritUserID, mojom::kInvalidInstanceID);
|
| }
|
| @@ -183,31 +212,31 @@ class Shell::Instance : public mojom::Connector,
|
|
|
| // mojom::Shell implementation:
|
| void CreateInstance(mojom::ShellClientFactoryPtr factory,
|
| - const String& name,
|
| - const String& user_id,
|
| + mojom::IdentityPtr target,
|
| mojom::CapabilityFilterPtr filter,
|
| mojom::PIDReceiverRequest pid_receiver,
|
| const CreateInstanceCallback& callback) override {
|
| - if (!base::IsValidGUID(user_id))
|
| + if (!base::IsValidGUID(target->user_id))
|
| callback.Run(mojom::ConnectResult::INVALID_ARGUMENT);
|
| +
|
| + Identity target_id = target.To<Identity>();
|
| +
|
| // TODO(beng): perform checking on policy of whether this instance is
|
| // allowed to pass different user_ids.
|
| - std::string user_id_string = user_id;
|
| - if (user_id_string == mojom::kInheritUserID)
|
| - user_id_string = identity_.user_id();
|
| + if (target_id.user_id() == mojom::kInheritUserID)
|
| + target_id.set_user_id(identity_.user_id());
|
|
|
| - // We don't call ConnectToClient() here since the instance was created
|
| - // manually by other code, not in response to a Connect() request. The newly
|
| - // created instance is identified by |name| and may be subsequently reached
|
| - // by client code using this identity.
|
| - Identity target_id(name, std::string(), user_id_string);
|
| - target_id.set_filter(filter->filter.To<CapabilityFilter>());
|
| mojom::ShellClientRequest request;
|
| - Instance* instance = shell_->CreateInstance(target_id, &request);
|
| + Instance* instance = shell_->CreateInstance(
|
| + target_id, filter->filter.To<CapabilityFilter>(), &request);
|
| instance->pid_receiver_binding_.Bind(std::move(pid_receiver));
|
| instance->factory_ = std::move(factory);
|
| - instance->factory_->CreateShellClient(std::move(request), name);
|
| + instance->factory_->CreateShellClient(std::move(request), target->name);
|
| callback.Run(mojom::ConnectResult::SUCCEEDED);
|
| + // We don't call ConnectToClient() here since the instance was created
|
| + // manually by other code, not in response to a Connect() request. The newly
|
| + // created instance is identified by |name| and may be subsequently reached
|
| + // by client code using this identity.
|
| }
|
| void AddInstanceListener(mojom::InstanceListenerPtr listener) override {
|
| // TODO(beng): this should only track the instances matching this user, and
|
| @@ -233,6 +262,7 @@ class Shell::Instance : public mojom::Connector,
|
| // process is launched.
|
| const uint32_t id_;
|
| const Identity identity_;
|
| + const CapabilityFilter filter_;
|
| const bool allow_any_application_;
|
| mojom::ShellClientPtr shell_client_;
|
| Binding<mojom::PIDReceiver> pid_receiver_binding_;
|
| @@ -251,8 +281,11 @@ Shell::TestAPI::TestAPI(Shell* shell) : shell_(shell) {}
|
| Shell::TestAPI::~TestAPI() {}
|
|
|
| bool Shell::TestAPI::HasRunningInstanceForName(const std::string& name) const {
|
| - return shell_->identity_to_instance_.find(Identity(name)) !=
|
| - shell_->identity_to_instance_.end();
|
| + for (const auto& entry : shell_->identity_to_instance_) {
|
| + if (entry.first.name() == name)
|
| + return true;
|
| + }
|
| + return false;
|
| }
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
| @@ -265,7 +298,8 @@ Shell::Shell(scoped_ptr<NativeRunnerFactory> native_runner_factory,
|
| native_runner_factory_(std::move(native_runner_factory)),
|
| weak_ptr_factory_(this) {
|
| mojom::ShellClientRequest request;
|
| - CreateInstance(CreateShellIdentity(), &request);
|
| + CreateInstance(CreateShellIdentity(), GetPermissiveCapabilityFilter(),
|
| + &request);
|
| shell_connection_.reset(new ShellConnection(this, std::move(request)));
|
|
|
| InitPackageManager(std::move(app_catalog));
|
| @@ -298,6 +332,8 @@ void Shell::Connect(scoped_ptr<ConnectParams> params) {
|
| params->set_target(target);
|
| }
|
|
|
| + CHECK(params->target().user_id() != mojom::kInheritUserID);
|
| +
|
| // Connect to an existing matching instance, if possible.
|
| if (ConnectToExistingInstance(¶ms))
|
| return;
|
| @@ -313,12 +349,12 @@ mojom::ShellClientRequest Shell::InitInstanceForEmbedder(
|
| const std::string& name) {
|
| DCHECK(!embedder_instance_);
|
|
|
| - mojo::shell::Identity target(name, std::string(), mojom::kRootUserID);
|
| - target.set_filter(GetPermissiveCapabilityFilter());
|
| + Identity target(name, mojom::kRootUserID);
|
| DCHECK(!GetExistingInstance(target));
|
|
|
| mojom::ShellClientRequest request;
|
| - embedder_instance_ = CreateInstance(target, &request);
|
| + embedder_instance_ = CreateInstance(
|
| + target, GetPermissiveCapabilityFilter(), &request);
|
| DCHECK(embedder_instance_);
|
|
|
| return request;
|
| @@ -363,7 +399,10 @@ void Shell::InitPackageManager(
|
| SetLoaderForName(std::move(loader), name);
|
|
|
| mojom::ShellClientRequest request;
|
| - CreateInstance(Identity(name), &request);
|
| + // TODO(beng): Does the package manager actually have to be run with a
|
| + // permissive filter?
|
| + Identity identity(name, mojom::kRootUserID);
|
| + CreateInstance(identity, GetPermissiveCapabilityFilter(), &request);
|
| loader_raw->Load(name, std::move(request));
|
|
|
| ConnectToInterface(this, CreateShellIdentity(), name, &shell_resolver_);
|
| @@ -419,10 +458,13 @@ bool Shell::ConnectToExistingInstance(scoped_ptr<ConnectParams>* params) {
|
| }
|
|
|
| Shell::Instance* Shell::CreateInstance(const Identity& target_id,
|
| + const CapabilityFilter& filter,
|
| mojom::ShellClientRequest* request) {
|
| + CHECK(target_id.user_id() != mojom::kInheritUserID);
|
| mojom::ShellClientPtr shell_client;
|
| *request = GetProxy(&shell_client);
|
| - Instance* instance = new Instance(std::move(shell_client), this, target_id);
|
| + Instance* instance =
|
| + new Instance(std::move(shell_client), this, target_id, filter);
|
| DCHECK(identity_to_instance_.find(target_id) ==
|
| identity_to_instance_.end());
|
| identity_to_instance_[target_id] = instance;
|
| @@ -483,14 +525,14 @@ void Shell::OnShellClientFactoryLost(const Identity& which) {
|
|
|
| void Shell::OnGotResolvedName(scoped_ptr<ConnectParams> params,
|
| const String& resolved_name,
|
| - const String& resolved_qualifier,
|
| + const String& resolved_instance,
|
| mojom::CapabilityFilterPtr base_filter,
|
| const String& file_url) {
|
| - std::string qualifier = params->target().qualifier();
|
| - if (qualifier == GetNamePath(params->target().name()))
|
| - qualifier = resolved_qualifier;
|
| - Identity target(params->target().name(), qualifier,
|
| - params->target().user_id());
|
| + std::string instance_name = params->target().instance();
|
| + if (instance_name == GetNamePath(params->target().name()))
|
| + instance_name = resolved_instance;
|
| + Identity target(params->target().name(), params->target().user_id(),
|
| + instance_name);
|
| params->set_target(target);
|
|
|
| // It's possible that when this manifest request was issued, another one was
|
| @@ -505,10 +547,9 @@ void Shell::OnGotResolvedName(scoped_ptr<ConnectParams> params,
|
| CapabilityFilter filter = GetPermissiveCapabilityFilter();
|
| if (!base_filter.is_null())
|
| filter = base_filter->filter.To<CapabilityFilter>();
|
| - target.set_filter(filter);
|
|
|
| mojom::ShellClientRequest request;
|
| - Instance* instance = CreateInstance(target, &request);
|
| + Instance* instance = CreateInstance(target, filter, &request);
|
| instance->ConnectToClient(std::move(params));
|
|
|
| if (LoadWithLoader(target, &request))
|
| @@ -517,11 +558,11 @@ void Shell::OnGotResolvedName(scoped_ptr<ConnectParams> params,
|
| CHECK(!file_url.is_null() && !base_filter.is_null());
|
|
|
| if (target.name() != resolved_name) {
|
| - // In cases where a package alias is resolved, we have to use the qualifier
|
| + // In cases where a package alias is resolved, we have to use the instance
|
| // from the original request rather than for the package itself, which will
|
| // always be the same.
|
| CreateShellClient(
|
| - source, Identity(resolved_name, resolved_qualifier, target.user_id()),
|
| + source, Identity(resolved_name, target.user_id(), resolved_instance),
|
| target.name(), std::move(request));
|
| } else {
|
| bool start_sandboxed = false;
|
|
|