Index: mojo/shell/shell.cc |
diff --git a/mojo/shell/shell.cc b/mojo/shell/shell.cc |
index 4cefbc3708e2a31fa68a36c0528d0211780c6459..1fb16b62795e4f3b52ce354f7316887f2ebecd09 100644 |
--- a/mojo/shell/shell.cc |
+++ b/mojo/shell/shell.cc |
@@ -129,28 +129,25 @@ class Shell::Instance : public mojom::Connector, |
DCHECK_NE(mojom::kInvalidInstanceID, id_); |
} |
- ~Instance() override {} |
- |
- void OnShellClientLost() { |
- shell_client_.reset(); |
- OnConnectionLost(); |
+ ~Instance() override { |
+ if (parent_) |
+ parent_->RemoveChild(this); |
+ // |children_| will be modified during destruction. |
+ std::set<Instance*> children = children_; |
+ for (auto child : children) |
+ shell_->OnInstanceError(child); |
} |
- void OnConnectionLost() { |
- // Any time a Connector is lost or we lose the ShellClient connection, it |
- // may have been the last pipe using this Instance. If so, clean up. |
- if (connectors_.empty() && !shell_client_) { |
- // Deletes |this|. |
- shell_->OnInstanceError(this); |
- } |
+ Instance* parent() { return parent_; } |
+ void AddChild(Instance* child) { |
+ children_.insert(child); |
+ child->parent_ = this; |
} |
- |
- void OnInitializeResponse(mojom::ConnectorRequest connector_request) { |
- if (connector_request.is_pending()) { |
- connectors_.AddBinding(this, std::move(connector_request)); |
- connectors_.set_connection_error_handler( |
- base::Bind(&Instance::OnConnectionLost, base::Unretained(this))); |
- } |
+ void RemoveChild(Instance* child) { |
+ auto it = children_.find(child); |
+ DCHECK(it != children_.end()); |
+ children_.erase(it); |
+ child->parent_ = nullptr; |
} |
void ConnectToClient(scoped_ptr<ConnectParams> params) { |
@@ -176,7 +173,8 @@ class Shell::Instance : public mojom::Connector, |
CHECK(!shell_client_); |
shell_client_ = std::move(client); |
shell_client_.set_connection_error_handler( |
- base::Bind(&Instance::OnShellClientLost, base::Unretained(this))); |
+ base::Bind(&Instance::OnShellClientLost, base::Unretained(this), |
+ shell_->GetWeakPtr())); |
shell_client_->Initialize(mojom::Identity::From(identity_), id_, |
base::Bind(&Instance::OnInitializeResponse, |
base::Unretained(this))); |
@@ -384,6 +382,29 @@ class Shell::Instance : public mojom::Connector, |
shell_->NotifyPIDAvailable(id_, pid_); |
} |
+ void OnShellClientLost(base::WeakPtr<mojo::shell::Shell> shell) { |
+ shell_client_.reset(); |
+ OnConnectionLost(shell); |
+ } |
+ |
+ void OnConnectionLost(base::WeakPtr<mojo::shell::Shell> shell) { |
+ // Any time a Connector is lost or we lose the ShellClient connection, it |
+ // may have been the last pipe using this Instance. If so, clean up. |
+ if (shell && connectors_.empty() && !shell_client_) { |
+ // Deletes |this|. |
+ shell->OnInstanceError(this); |
+ } |
+ } |
+ |
+ void OnInitializeResponse(mojom::ConnectorRequest connector_request) { |
+ if (connector_request.is_pending()) { |
+ connectors_.AddBinding(this, std::move(connector_request)); |
+ connectors_.set_connection_error_handler( |
+ base::Bind(&Instance::OnConnectionLost, base::Unretained(this), |
+ shell_->GetWeakPtr())); |
+ } |
+ } |
+ |
mojo::shell::Shell* const shell_; |
// An id that identifies this instance. Distinct from pid, as a single process |
@@ -399,6 +420,8 @@ class Shell::Instance : public mojom::Connector, |
BindingSet<mojom::Shell> shell_bindings_; |
NativeRunner* runner_ = nullptr; |
base::ProcessId pid_ = base::kNullProcessId; |
+ Instance* parent_ = nullptr; |
+ std::set<Instance*> children_; |
base::WeakPtrFactory<Instance> weak_factory_; |
DISALLOW_COPY_AND_ASSIGN(Instance); |
@@ -425,9 +448,10 @@ Shell::Shell(scoped_ptr<NativeRunnerFactory> native_runner_factory, |
weak_ptr_factory_(this) { |
mojom::ShellClientPtr client; |
mojom::ShellClientRequest request = GetProxy(&client); |
- Instance* instance = CreateInstance(CreateShellIdentity(), |
+ Instance* instance = CreateInstance(Identity(), CreateShellIdentity(), |
GetPermissiveCapabilities()); |
instance->StartWithClient(std::move(client)); |
+ singletons_.insert(kShellName); |
shell_connection_.reset(new ShellConnection(this, std::move(request))); |
if (catalog) |
@@ -467,7 +491,7 @@ mojom::ShellClientRequest Shell::InitInstanceForEmbedder( |
void Shell::SetLoaderForName(scoped_ptr<Loader> loader, |
const std::string& name) { |
- NameToLoaderMap::iterator it = name_to_loader_.find(name); |
+ auto it = name_to_loader_.find(name); |
if (it != name_to_loader_.end()) |
delete it->second; |
name_to_loader_[name] = loader.release(); |
@@ -496,8 +520,10 @@ bool Shell::AcceptConnection(Connection* connection) { |
// Shell, private: |
void Shell::InitCatalog(mojom::ShellClientPtr catalog) { |
- Instance* instance = |
- CreateInstance(CreateCatalogIdentity(), CapabilitySpec()); |
+ Instance* instance = CreateInstance(CreateShellIdentity(), |
+ CreateCatalogIdentity(), |
+ CapabilitySpec()); |
+ singletons_.insert(kCatalogName); |
instance->StartWithClient(std::move(catalog)); |
// TODO(beng): this doesn't work anymore. |
@@ -509,7 +535,9 @@ void Shell::InitCatalog(mojom::ShellClientPtr catalog) { |
} |
void Shell::TerminateShellConnections() { |
- STLDeleteValues(&identity_to_instance_); |
+ Instance* instance = GetExistingInstance(CreateShellIdentity()); |
+ DCHECK(instance); |
+ OnInstanceError(instance); |
} |
void Shell::OnInstanceError(Instance* instance) { |
@@ -588,12 +616,16 @@ bool Shell::ConnectToExistingInstance(scoped_ptr<ConnectParams>* params) { |
return !!instance; |
} |
-Shell::Instance* Shell::CreateInstance(const Identity& target, |
+Shell::Instance* Shell::CreateInstance(const Identity& source, |
+ const Identity& target, |
const CapabilitySpec& spec) { |
CHECK(target.user_id() != mojom::kInheritUserID); |
Instance* instance = new Instance(this, target, spec); |
DCHECK(identity_to_instance_.find(target) == |
identity_to_instance_.end()); |
+ Instance* source_instance = GetExistingInstance(source); |
+ if (source_instance) |
+ source_instance->AddChild(instance); |
identity_to_instance_[target] = instance; |
mojom::InstanceInfoPtr info = instance->CreateInstanceInfo(); |
instance_listeners_.ForAllPtrs( |
@@ -678,13 +710,16 @@ void Shell::OnGotResolvedName(mojom::ShellResolverPtr resolver, |
capabilities = capabilities_ptr.To<CapabilitySpec>(); |
// Clients that request "all_users" class from the shell are allowed to |
- // field connection requests from any user. |
- if (HasClass(capabilities, kCapabilityClass_AllUsers)) |
+ // field connection requests from any user. They also run with a synthetic |
+ // user id generated here. The user id provided via Connect() is ignored. |
+ if (HasClass(capabilities, kCapabilityClass_AllUsers)) { |
singletons_.insert(target.name()); |
+ target.set_user_id(base::GenerateGUID()); |
+ } |
mojom::ClientProcessConnectionPtr client_process_connection = |
params->TakeClientProcessConnection(); |
- Instance* instance = CreateInstance(target, capabilities); |
+ Instance* instance = CreateInstance(params->source(), target, capabilities); |
// Below are various paths through which a new Instance can be bound to a |
// ShellClient proxy. |
@@ -736,6 +771,10 @@ Loader* Shell::GetLoaderForName(const std::string& name) { |
return default_loader_.get(); |
} |
+base::WeakPtr<Shell> Shell::GetWeakPtr() { |
+ return weak_ptr_factory_.GetWeakPtr(); |
+} |
+ |
void Shell::CleanupRunner(NativeRunner* runner) { |
for (auto it = native_runners_.begin(); it != native_runners_.end(); ++it) { |
if (it->get() == runner) { |