| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/shell/shell.h" | 5 #include "services/shell/shell.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/guid.h" | 13 #include "base/guid.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/process/process.h" | 16 #include "base/process/process.h" |
| 17 #include "base/process/process_handle.h" | 17 #include "base/process/process_handle.h" |
| 18 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 20 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
| 21 #include "mojo/public/cpp/bindings/binding.h" | 21 #include "mojo/public/cpp/bindings/binding.h" |
| 22 #include "mojo/public/cpp/bindings/binding_set.h" | 22 #include "mojo/public/cpp/bindings/binding_set.h" |
| 23 #include "services/shell/connect_util.h" | 23 #include "services/shell/connect_util.h" |
| 24 #include "services/shell/public/cpp/connector.h" | 24 #include "services/shell/public/cpp/connector.h" |
| 25 #include "services/shell/public/cpp/names.h" | 25 #include "services/shell/public/cpp/names.h" |
| 26 #include "services/shell/public/cpp/shell_connection.h" | 26 #include "services/shell/public/cpp/shell_connection.h" |
| 27 #include "services/shell/public/interfaces/connector.mojom.h" | 27 #include "services/shell/public/interfaces/connector.mojom.h" |
| 28 #include "services/shell/public/interfaces/service.mojom.h" |
| 28 #include "services/shell/public/interfaces/shell.mojom.h" | 29 #include "services/shell/public/interfaces/shell.mojom.h" |
| 29 #include "services/shell/public/interfaces/shell_client.mojom.h" | |
| 30 | 30 |
| 31 namespace shell { | 31 namespace shell { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 const char kCatalogName[] = "mojo:catalog"; | 35 const char kCatalogName[] = "mojo:catalog"; |
| 36 const char kShellName[] = "mojo:shell"; | 36 const char kShellName[] = "mojo:shell"; |
| 37 const char kCapabilityClass_UserID[] = "shell:user_id"; | 37 const char kCapabilityClass_UserID[] = "shell:user_id"; |
| 38 const char kCapabilityClass_ClientProcess[] = "shell:client_process"; | 38 const char kCapabilityClass_ClientProcess[] = "shell:client_process"; |
| 39 const char kCapabilityClass_InstanceName[] = "shell:instance_name"; | 39 const char kCapabilityClass_InstanceName[] = "shell:instance_name"; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 auto it = spec.required.find(kShellName); | 103 auto it = spec.required.find(kShellName); |
| 104 if (it == spec.required.end()) | 104 if (it == spec.required.end()) |
| 105 return false; | 105 return false; |
| 106 return it->second.classes.find(class_name) != it->second.classes.end(); | 106 return it->second.classes.find(class_name) != it->second.classes.end(); |
| 107 } | 107 } |
| 108 | 108 |
| 109 // Encapsulates a connection to an instance of an application, tracked by the | 109 // Encapsulates a connection to an instance of an application, tracked by the |
| 110 // shell's Shell. | 110 // shell's Shell. |
| 111 class Shell::Instance : public mojom::Connector, | 111 class Shell::Instance : public mojom::Connector, |
| 112 public mojom::PIDReceiver, | 112 public mojom::PIDReceiver, |
| 113 public ShellClient, | 113 public Service, |
| 114 public InterfaceFactory<mojom::Shell>, | 114 public InterfaceFactory<mojom::Shell>, |
| 115 public mojom::Shell { | 115 public mojom::Shell { |
| 116 public: | 116 public: |
| 117 Instance(shell::Shell* shell, | 117 Instance(shell::Shell* shell, |
| 118 const Identity& identity, | 118 const Identity& identity, |
| 119 const CapabilitySpec& capability_spec) | 119 const CapabilitySpec& capability_spec) |
| 120 : shell_(shell), | 120 : shell_(shell), |
| 121 id_(GenerateUniqueID()), | 121 id_(GenerateUniqueID()), |
| 122 identity_(identity), | 122 identity_(identity), |
| 123 capability_spec_(capability_spec), | 123 capability_spec_(capability_spec), |
| 124 allow_any_application_(capability_spec.required.count("*") == 1), | 124 allow_any_application_(capability_spec.required.count("*") == 1), |
| 125 pid_receiver_binding_(this), | 125 pid_receiver_binding_(this), |
| 126 weak_factory_(this) { | 126 weak_factory_(this) { |
| 127 if (identity_.name() == kShellName || identity_.name() == kCatalogName) | 127 if (identity_.name() == kShellName || identity_.name() == kCatalogName) |
| 128 pid_ = base::Process::Current().Pid(); | 128 pid_ = base::Process::Current().Pid(); |
| 129 DCHECK_NE(mojom::kInvalidInstanceID, id_); | 129 DCHECK_NE(mojom::kInvalidInstanceID, id_); |
| 130 } | 130 } |
| 131 | 131 |
| 132 ~Instance() override { | 132 ~Instance() override { |
| 133 if (parent_) | 133 if (parent_) |
| 134 parent_->RemoveChild(this); | 134 parent_->RemoveChild(this); |
| 135 // |children_| will be modified during destruction. | 135 // |children_| will be modified during destruction. |
| 136 std::set<Instance*> children = children_; | 136 std::set<Instance*> children = children_; |
| 137 for (auto child : children) | 137 for (auto child : children) |
| 138 shell_->OnInstanceError(child); | 138 shell_->OnInstanceError(child); |
| 139 | 139 |
| 140 // Shutdown all bindings before we close the runner. This way the process | 140 // Shutdown all bindings before we close the runner. This way the process |
| 141 // should see the pipes closed and exit, as well as waking up any potential | 141 // should see the pipes closed and exit, as well as waking up any potential |
| 142 // sync/WaitForIncomingResponse(). | 142 // sync/WaitForIncomingResponse(). |
| 143 shell_client_.reset(); | 143 service_.reset(); |
| 144 if (pid_receiver_binding_.is_bound()) | 144 if (pid_receiver_binding_.is_bound()) |
| 145 pid_receiver_binding_.Close(); | 145 pid_receiver_binding_.Close(); |
| 146 connectors_.CloseAllBindings(); | 146 connectors_.CloseAllBindings(); |
| 147 shell_bindings_.CloseAllBindings(); | 147 shell_bindings_.CloseAllBindings(); |
| 148 // Release |runner_| so that if we are called back to OnRunnerCompleted() | 148 // Release |runner_| so that if we are called back to OnRunnerCompleted() |
| 149 // we know we're in the destructor. | 149 // we know we're in the destructor. |
| 150 std::unique_ptr<NativeRunner> runner = std::move(runner_); | 150 std::unique_ptr<NativeRunner> runner = std::move(runner_); |
| 151 runner.reset(); | 151 runner.reset(); |
| 152 } | 152 } |
| 153 | 153 |
| 154 Instance* parent() { return parent_; } | 154 Instance* parent() { return parent_; } |
| 155 | 155 |
| 156 void AddChild(Instance* child) { | 156 void AddChild(Instance* child) { |
| 157 children_.insert(child); | 157 children_.insert(child); |
| 158 child->parent_ = this; | 158 child->parent_ = this; |
| 159 } | 159 } |
| 160 | 160 |
| 161 void RemoveChild(Instance* child) { | 161 void RemoveChild(Instance* child) { |
| 162 auto it = children_.find(child); | 162 auto it = children_.find(child); |
| 163 DCHECK(it != children_.end()); | 163 DCHECK(it != children_.end()); |
| 164 children_.erase(it); | 164 children_.erase(it); |
| 165 child->parent_ = nullptr; | 165 child->parent_ = nullptr; |
| 166 } | 166 } |
| 167 | 167 |
| 168 bool ConnectToClient(std::unique_ptr<ConnectParams>* connect_params) { | 168 bool ConnectToClient(std::unique_ptr<ConnectParams>* connect_params) { |
| 169 if (!shell_client_.is_bound()) | 169 if (!service_.is_bound()) |
| 170 return false; | 170 return false; |
| 171 | 171 |
| 172 std::unique_ptr<ConnectParams> params(std::move(*connect_params)); | 172 std::unique_ptr<ConnectParams> params(std::move(*connect_params)); |
| 173 if (!params->connect_callback().is_null()) { | 173 if (!params->connect_callback().is_null()) { |
| 174 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED, | 174 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED, |
| 175 identity_.user_id(), id_); | 175 identity_.user_id(), id_); |
| 176 } | 176 } |
| 177 uint32_t source_id = mojom::kInvalidInstanceID; | 177 uint32_t source_id = mojom::kInvalidInstanceID; |
| 178 CapabilityRequest request; | 178 CapabilityRequest request; |
| 179 request.interfaces.insert("*"); | 179 request.interfaces.insert("*"); |
| 180 Instance* source = shell_->GetExistingInstance(params->source()); | 180 Instance* source = shell_->GetExistingInstance(params->source()); |
| 181 if (source) { | 181 if (source) { |
| 182 request = GenerateCapabilityRequestForConnection( | 182 request = GenerateCapabilityRequestForConnection( |
| 183 source->capability_spec_, identity_, capability_spec_); | 183 source->capability_spec_, identity_, capability_spec_); |
| 184 source_id = source->id(); | 184 source_id = source->id(); |
| 185 } | 185 } |
| 186 | 186 |
| 187 // The target has specified that sources must request one of its provided | 187 // The target has specified that sources must request one of its provided |
| 188 // classes instead of specifying a wild-card for interfaces. | 188 // classes instead of specifying a wild-card for interfaces. |
| 189 if (HasClass(capability_spec_, kCapabilityClass_ExplicitClass) && | 189 if (HasClass(capability_spec_, kCapabilityClass_ExplicitClass) && |
| 190 (request.interfaces.count("*") != 0)) { | 190 (request.interfaces.count("*") != 0)) { |
| 191 request.interfaces.erase("*"); | 191 request.interfaces.erase("*"); |
| 192 } | 192 } |
| 193 | 193 |
| 194 shell_client_->AcceptConnection( | 194 service_->OnConnect( |
| 195 mojom::Identity::From(params->source()), source_id, | 195 mojom::Identity::From(params->source()), source_id, |
| 196 params->TakeRemoteInterfaces(), params->TakeLocalInterfaces(), | 196 params->TakeRemoteInterfaces(), params->TakeLocalInterfaces(), |
| 197 mojom::CapabilityRequest::From(request), params->target().name()); | 197 mojom::CapabilityRequest::From(request), params->target().name()); |
| 198 | 198 |
| 199 return true; | 199 return true; |
| 200 } | 200 } |
| 201 | 201 |
| 202 void StartWithClient(mojom::ShellClientPtr client) { | 202 void StartWithClient(mojom::ServicePtr client) { |
| 203 CHECK(!shell_client_); | 203 CHECK(!service_); |
| 204 shell_client_ = std::move(client); | 204 service_ = std::move(client); |
| 205 shell_client_.set_connection_error_handler( | 205 service_.set_connection_error_handler( |
| 206 base::Bind(&Instance::OnShellClientLost, base::Unretained(this), | 206 base::Bind(&Instance::OnServiceLost, base::Unretained(this), |
| 207 shell_->GetWeakPtr())); | 207 shell_->GetWeakPtr())); |
| 208 shell_client_->Initialize(mojom::Identity::From(identity_), id_, | 208 service_->OnStart(mojom::Identity::From(identity_), id_, |
| 209 base::Bind(&Instance::OnInitializeResponse, | 209 base::Bind(&Instance::OnInitializeResponse, |
| 210 base::Unretained(this))); | 210 base::Unretained(this))); |
| 211 } | 211 } |
| 212 | 212 |
| 213 void StartWithClientProcessConnection( | 213 void StartWithClientProcessConnection( |
| 214 mojom::ClientProcessConnectionPtr client_process_connection) { | 214 mojom::ClientProcessConnectionPtr client_process_connection) { |
| 215 mojom::ShellClientPtr client; | 215 mojom::ServicePtr client; |
| 216 client.Bind(mojom::ShellClientPtrInfo( | 216 client.Bind(mojom::ServicePtrInfo( |
| 217 std::move(client_process_connection->shell_client), 0)); | 217 std::move(client_process_connection->service), 0)); |
| 218 pid_receiver_binding_.Bind( | 218 pid_receiver_binding_.Bind( |
| 219 std::move(client_process_connection->pid_receiver_request)); | 219 std::move(client_process_connection->pid_receiver_request)); |
| 220 StartWithClient(std::move(client)); | 220 StartWithClient(std::move(client)); |
| 221 } | 221 } |
| 222 | 222 |
| 223 void StartWithFilePath(const base::FilePath& path) { | 223 void StartWithFilePath(const base::FilePath& path) { |
| 224 CHECK(!shell_client_); | 224 CHECK(!service_); |
| 225 runner_ = shell_->native_runner_factory_->Create(path); | 225 runner_ = shell_->native_runner_factory_->Create(path); |
| 226 bool start_sandboxed = false; | 226 bool start_sandboxed = false; |
| 227 mojom::ShellClientPtr client = runner_->Start( | 227 mojom::ServicePtr client = runner_->Start( |
| 228 path, identity_, start_sandboxed, | 228 path, identity_, start_sandboxed, |
| 229 base::Bind(&Instance::PIDAvailable, weak_factory_.GetWeakPtr()), | 229 base::Bind(&Instance::PIDAvailable, weak_factory_.GetWeakPtr()), |
| 230 base::Bind(&Instance::OnRunnerCompleted, weak_factory_.GetWeakPtr())); | 230 base::Bind(&Instance::OnRunnerCompleted, weak_factory_.GetWeakPtr())); |
| 231 StartWithClient(std::move(client)); | 231 StartWithClient(std::move(client)); |
| 232 } | 232 } |
| 233 | 233 |
| 234 mojom::InstanceInfoPtr CreateInstanceInfo() const { | 234 mojom::InstanceInfoPtr CreateInstanceInfo() const { |
| 235 mojom::InstanceInfoPtr info(mojom::InstanceInfo::New()); | 235 mojom::InstanceInfoPtr info(mojom::InstanceInfo::New()); |
| 236 info->id = id_; | 236 info->id = id_; |
| 237 info->identity = mojom::Identity::From(identity_); | 237 info->identity = mojom::Identity::From(identity_); |
| 238 info->pid = pid_; | 238 info->pid = pid_; |
| 239 return info; | 239 return info; |
| 240 } | 240 } |
| 241 | 241 |
| 242 const CapabilitySpec& capability_spec() const { | 242 const CapabilitySpec& capability_spec() const { |
| 243 return capability_spec_; | 243 return capability_spec_; |
| 244 } | 244 } |
| 245 const Identity& identity() const { return identity_; } | 245 const Identity& identity() const { return identity_; } |
| 246 uint32_t id() const { return id_; } | 246 uint32_t id() const { return id_; } |
| 247 | 247 |
| 248 // ShellClient: | 248 // Service: |
| 249 bool AcceptConnection(Connection* connection) override { | 249 bool OnConnect(Connection* connection) override { |
| 250 connection->AddInterface<mojom::Shell>(this); | 250 connection->AddInterface<mojom::Shell>(this); |
| 251 return true; | 251 return true; |
| 252 } | 252 } |
| 253 | 253 |
| 254 private: | 254 private: |
| 255 // mojom::Connector implementation: | 255 // mojom::Connector implementation: |
| 256 void Connect(mojom::IdentityPtr target_ptr, | 256 void Connect(mojom::IdentityPtr target_ptr, |
| 257 mojom::InterfaceProviderRequest remote_interfaces, | 257 mojom::InterfaceProviderRequest remote_interfaces, |
| 258 mojom::InterfaceProviderPtr local_interfaces, | 258 mojom::InterfaceProviderPtr local_interfaces, |
| 259 mojom::ClientProcessConnectionPtr client_process_connection, | 259 mojom::ClientProcessConnectionPtr client_process_connection, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 if (!HasClass(capability_spec_, kCapabilityClass_ClientProcess)) { | 328 if (!HasClass(capability_spec_, kCapabilityClass_ClientProcess)) { |
| 329 LOG(ERROR) << "Instance: " << identity_.name() << " attempting " | 329 LOG(ERROR) << "Instance: " << identity_.name() << " attempting " |
| 330 << "to register an instance for a process it created for " | 330 << "to register an instance for a process it created for " |
| 331 << "target: " << target.name() << " without the " | 331 << "target: " << target.name() << " without the " |
| 332 << "mojo:shell{client_process} capability class."; | 332 << "mojo:shell{client_process} capability class."; |
| 333 callback.Run(mojom::ConnectResult::ACCESS_DENIED, | 333 callback.Run(mojom::ConnectResult::ACCESS_DENIED, |
| 334 mojom::kInheritUserID, mojom::kInvalidInstanceID); | 334 mojom::kInheritUserID, mojom::kInvalidInstanceID); |
| 335 return false; | 335 return false; |
| 336 } | 336 } |
| 337 | 337 |
| 338 if (!(*client_process_connection)->shell_client.is_valid() || | 338 if (!(*client_process_connection)->service.is_valid() || |
| 339 !(*client_process_connection)->pid_receiver_request.is_valid()) { | 339 !(*client_process_connection)->pid_receiver_request.is_valid()) { |
| 340 LOG(ERROR) << "Must supply both shell_client AND " | 340 LOG(ERROR) << "Must supply both service AND " |
| 341 << "pid_receiver_request when sending " | 341 << "pid_receiver_request when sending " |
| 342 << "client_process_connection."; | 342 << "client_process_connection."; |
| 343 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, | 343 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, |
| 344 mojom::kInheritUserID, mojom::kInvalidInstanceID); | 344 mojom::kInheritUserID, mojom::kInvalidInstanceID); |
| 345 return false; | 345 return false; |
| 346 } | 346 } |
| 347 if (shell_->GetExistingInstance(target)) { | 347 if (shell_->GetExistingInstance(target)) { |
| 348 LOG(ERROR) << "Cannot client process matching existing identity:" | 348 LOG(ERROR) << "Cannot client process matching existing identity:" |
| 349 << "Name: " << target.name() << " User: " | 349 << "Name: " << target.name() << " User: " |
| 350 << target.user_id() << " Instance: " << target.instance(); | 350 << target.user_id() << " Instance: " << target.instance(); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 | 406 |
| 407 void PIDAvailable(base::ProcessId pid) { | 407 void PIDAvailable(base::ProcessId pid) { |
| 408 if (pid == base::kNullProcessId) { | 408 if (pid == base::kNullProcessId) { |
| 409 shell_->OnInstanceError(this); | 409 shell_->OnInstanceError(this); |
| 410 return; | 410 return; |
| 411 } | 411 } |
| 412 pid_ = pid; | 412 pid_ = pid; |
| 413 shell_->NotifyPIDAvailable(id_, pid_); | 413 shell_->NotifyPIDAvailable(id_, pid_); |
| 414 } | 414 } |
| 415 | 415 |
| 416 void OnShellClientLost(base::WeakPtr<shell::Shell> shell) { | 416 void OnServiceLost(base::WeakPtr<shell::Shell> shell) { |
| 417 shell_client_.reset(); | 417 service_.reset(); |
| 418 OnConnectionLost(shell); | 418 OnConnectionLost(shell); |
| 419 } | 419 } |
| 420 | 420 |
| 421 void OnConnectionLost(base::WeakPtr<shell::Shell> shell) { | 421 void OnConnectionLost(base::WeakPtr<shell::Shell> shell) { |
| 422 // Any time a Connector is lost or we lose the ShellClient connection, it | 422 // Any time a Connector is lost or we lose the Service connection, it |
| 423 // may have been the last pipe using this Instance. If so, clean up. | 423 // may have been the last pipe using this Instance. If so, clean up. |
| 424 if (shell && connectors_.empty() && !shell_client_) { | 424 if (shell && connectors_.empty() && !service_) { |
| 425 // Deletes |this|. | 425 // Deletes |this|. |
| 426 shell->OnInstanceError(this); | 426 shell->OnInstanceError(this); |
| 427 } | 427 } |
| 428 } | 428 } |
| 429 | 429 |
| 430 void OnInitializeResponse(mojom::ConnectorRequest connector_request) { | 430 void OnInitializeResponse(mojom::ConnectorRequest connector_request) { |
| 431 if (connector_request.is_pending()) { | 431 if (connector_request.is_pending()) { |
| 432 connectors_.AddBinding(this, std::move(connector_request)); | 432 connectors_.AddBinding(this, std::move(connector_request)); |
| 433 connectors_.set_connection_error_handler( | 433 connectors_.set_connection_error_handler( |
| 434 base::Bind(&Instance::OnConnectionLost, base::Unretained(this), | 434 base::Bind(&Instance::OnConnectionLost, base::Unretained(this), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 447 shell::Shell* const shell_; | 447 shell::Shell* const shell_; |
| 448 | 448 |
| 449 // An id that identifies this instance. Distinct from pid, as a single process | 449 // An id that identifies this instance. Distinct from pid, as a single process |
| 450 // may vend multiple application instances, and this object may exist before a | 450 // may vend multiple application instances, and this object may exist before a |
| 451 // process is launched. | 451 // process is launched. |
| 452 const uint32_t id_; | 452 const uint32_t id_; |
| 453 const Identity identity_; | 453 const Identity identity_; |
| 454 const CapabilitySpec capability_spec_; | 454 const CapabilitySpec capability_spec_; |
| 455 const bool allow_any_application_; | 455 const bool allow_any_application_; |
| 456 std::unique_ptr<NativeRunner> runner_; | 456 std::unique_ptr<NativeRunner> runner_; |
| 457 mojom::ShellClientPtr shell_client_; | 457 mojom::ServicePtr service_; |
| 458 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; | 458 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; |
| 459 mojo::BindingSet<mojom::Connector> connectors_; | 459 mojo::BindingSet<mojom::Connector> connectors_; |
| 460 mojo::BindingSet<mojom::Shell> shell_bindings_; | 460 mojo::BindingSet<mojom::Shell> shell_bindings_; |
| 461 base::ProcessId pid_ = base::kNullProcessId; | 461 base::ProcessId pid_ = base::kNullProcessId; |
| 462 Instance* parent_ = nullptr; | 462 Instance* parent_ = nullptr; |
| 463 std::set<Instance*> children_; | 463 std::set<Instance*> children_; |
| 464 base::WeakPtrFactory<Instance> weak_factory_; | 464 base::WeakPtrFactory<Instance> weak_factory_; |
| 465 | 465 |
| 466 DISALLOW_COPY_AND_ASSIGN(Instance); | 466 DISALLOW_COPY_AND_ASSIGN(Instance); |
| 467 }; | 467 }; |
| 468 | 468 |
| 469 // static | 469 // static |
| 470 Shell::TestAPI::TestAPI(Shell* shell) : shell_(shell) {} | 470 Shell::TestAPI::TestAPI(Shell* shell) : shell_(shell) {} |
| 471 Shell::TestAPI::~TestAPI() {} | 471 Shell::TestAPI::~TestAPI() {} |
| 472 | 472 |
| 473 bool Shell::TestAPI::HasRunningInstanceForName(const std::string& name) const { | 473 bool Shell::TestAPI::HasRunningInstanceForName(const std::string& name) const { |
| 474 for (const auto& entry : shell_->identity_to_instance_) { | 474 for (const auto& entry : shell_->identity_to_instance_) { |
| 475 if (entry.first.name() == name) | 475 if (entry.first.name() == name) |
| 476 return true; | 476 return true; |
| 477 } | 477 } |
| 478 return false; | 478 return false; |
| 479 } | 479 } |
| 480 | 480 |
| 481 //////////////////////////////////////////////////////////////////////////////// | 481 //////////////////////////////////////////////////////////////////////////////// |
| 482 // Shell, public: | 482 // Shell, public: |
| 483 | 483 |
| 484 Shell::Shell(std::unique_ptr<NativeRunnerFactory> native_runner_factory, | 484 Shell::Shell(std::unique_ptr<NativeRunnerFactory> native_runner_factory, |
| 485 mojom::ShellClientPtr catalog) | 485 mojom::ServicePtr catalog) |
| 486 : native_runner_factory_(std::move(native_runner_factory)), | 486 : native_runner_factory_(std::move(native_runner_factory)), |
| 487 weak_ptr_factory_(this) { | 487 weak_ptr_factory_(this) { |
| 488 mojom::ShellClientPtr client; | 488 mojom::ServicePtr client; |
| 489 mojom::ShellClientRequest request = mojo::GetProxy(&client); | 489 mojom::ServiceRequest request = mojo::GetProxy(&client); |
| 490 Instance* instance = CreateInstance(Identity(), CreateShellIdentity(), | 490 Instance* instance = CreateInstance(Identity(), CreateShellIdentity(), |
| 491 GetPermissiveCapabilities()); | 491 GetPermissiveCapabilities()); |
| 492 instance->StartWithClient(std::move(client)); | 492 instance->StartWithClient(std::move(client)); |
| 493 singletons_.insert(kShellName); | 493 singletons_.insert(kShellName); |
| 494 shell_connection_.reset(new ShellConnection(this, std::move(request))); | 494 shell_connection_.reset(new ShellConnection(this, std::move(request))); |
| 495 | 495 |
| 496 if (catalog) | 496 if (catalog) |
| 497 InitCatalog(std::move(catalog)); | 497 InitCatalog(std::move(catalog)); |
| 498 } | 498 } |
| 499 | 499 |
| 500 Shell::~Shell() { | 500 Shell::~Shell() { |
| 501 TerminateShellConnections(); | 501 TerminateShellConnections(); |
| 502 // Terminate any remaining instances. | 502 // Terminate any remaining instances. |
| 503 while (!identity_to_instance_.empty()) | 503 while (!identity_to_instance_.empty()) |
| 504 OnInstanceError(identity_to_instance_.begin()->second); | 504 OnInstanceError(identity_to_instance_.begin()->second); |
| 505 identity_to_resolver_.clear(); | 505 identity_to_resolver_.clear(); |
| 506 } | 506 } |
| 507 | 507 |
| 508 void Shell::SetInstanceQuitCallback( | 508 void Shell::SetInstanceQuitCallback( |
| 509 base::Callback<void(const Identity&)> callback) { | 509 base::Callback<void(const Identity&)> callback) { |
| 510 instance_quit_callback_ = callback; | 510 instance_quit_callback_ = callback; |
| 511 } | 511 } |
| 512 | 512 |
| 513 void Shell::Connect(std::unique_ptr<ConnectParams> params) { | 513 void Shell::Connect(std::unique_ptr<ConnectParams> params) { |
| 514 Connect(std::move(params), nullptr); | 514 Connect(std::move(params), nullptr); |
| 515 } | 515 } |
| 516 | 516 |
| 517 mojom::ShellClientRequest Shell::InitInstanceForEmbedder( | 517 mojom::ServiceRequest Shell::InitInstanceForEmbedder( |
| 518 const std::string& name) { | 518 const std::string& name) { |
| 519 std::unique_ptr<ConnectParams> params(new ConnectParams); | 519 std::unique_ptr<ConnectParams> params(new ConnectParams); |
| 520 | 520 |
| 521 Identity embedder_identity(name, mojom::kRootUserID); | 521 Identity embedder_identity(name, mojom::kRootUserID); |
| 522 params->set_source(embedder_identity); | 522 params->set_source(embedder_identity); |
| 523 params->set_target(embedder_identity); | 523 params->set_target(embedder_identity); |
| 524 | 524 |
| 525 mojom::ShellClientPtr client; | 525 mojom::ServicePtr client; |
| 526 mojom::ShellClientRequest request = mojo::GetProxy(&client); | 526 mojom::ServiceRequest request = mojo::GetProxy(&client); |
| 527 Connect(std::move(params), std::move(client)); | 527 Connect(std::move(params), std::move(client)); |
| 528 | 528 |
| 529 return request; | 529 return request; |
| 530 } | 530 } |
| 531 | 531 |
| 532 //////////////////////////////////////////////////////////////////////////////// | 532 //////////////////////////////////////////////////////////////////////////////// |
| 533 // Shell, ShellClient implementation: | 533 // Shell, Service implementation: |
| 534 | 534 |
| 535 bool Shell::AcceptConnection(Connection* connection) { | 535 bool Shell::OnConnect(Connection* connection) { |
| 536 // The only interface we expose is mojom::Shell, and access to this interface | 536 // The only interface we expose is mojom::Shell, and access to this interface |
| 537 // is brokered by a policy specific to each caller, managed by the caller's | 537 // is brokered by a policy specific to each caller, managed by the caller's |
| 538 // instance. Here we look to see who's calling, and forward to the caller's | 538 // instance. Here we look to see who's calling, and forward to the caller's |
| 539 // instance to continue. | 539 // instance to continue. |
| 540 Instance* instance = nullptr; | 540 Instance* instance = nullptr; |
| 541 for (const auto& entry : identity_to_instance_) { | 541 for (const auto& entry : identity_to_instance_) { |
| 542 if (entry.second->id() == connection->GetRemoteInstanceID()) { | 542 if (entry.second->id() == connection->GetRemoteInstanceID()) { |
| 543 instance = entry.second; | 543 instance = entry.second; |
| 544 break; | 544 break; |
| 545 } | 545 } |
| 546 } | 546 } |
| 547 DCHECK(instance); | 547 DCHECK(instance); |
| 548 return instance->AcceptConnection(connection); | 548 return instance->OnConnect(connection); |
| 549 } | 549 } |
| 550 | 550 |
| 551 //////////////////////////////////////////////////////////////////////////////// | 551 //////////////////////////////////////////////////////////////////////////////// |
| 552 // Shell, private: | 552 // Shell, private: |
| 553 | 553 |
| 554 void Shell::InitCatalog(mojom::ShellClientPtr catalog) { | 554 void Shell::InitCatalog(mojom::ServicePtr catalog) { |
| 555 // TODO(beng): It'd be great to build this from the manifest, however there's | 555 // TODO(beng): It'd be great to build this from the manifest, however there's |
| 556 // a bit of a chicken-and-egg problem. | 556 // a bit of a chicken-and-egg problem. |
| 557 CapabilitySpec spec; | 557 CapabilitySpec spec; |
| 558 Interfaces interfaces; | 558 Interfaces interfaces; |
| 559 interfaces.insert("filesystem::mojom::Directory"); | 559 interfaces.insert("filesystem::mojom::Directory"); |
| 560 spec.provided["app"] = interfaces; | 560 spec.provided["app"] = interfaces; |
| 561 Instance* instance = CreateInstance(CreateShellIdentity(), | 561 Instance* instance = CreateInstance(CreateShellIdentity(), |
| 562 CreateCatalogIdentity(), | 562 CreateCatalogIdentity(), |
| 563 spec); | 563 spec); |
| 564 singletons_.insert(kCatalogName); | 564 singletons_.insert(kCatalogName); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 592 identity_to_instance_.erase(it); | 592 identity_to_instance_.erase(it); |
| 593 instance_listeners_.ForAllPtrs([this, id](mojom::InstanceListener* listener) { | 593 instance_listeners_.ForAllPtrs([this, id](mojom::InstanceListener* listener) { |
| 594 listener->InstanceDestroyed(id); | 594 listener->InstanceDestroyed(id); |
| 595 }); | 595 }); |
| 596 delete instance; | 596 delete instance; |
| 597 if (!instance_quit_callback_.is_null()) | 597 if (!instance_quit_callback_.is_null()) |
| 598 instance_quit_callback_.Run(identity); | 598 instance_quit_callback_.Run(identity); |
| 599 } | 599 } |
| 600 | 600 |
| 601 void Shell::Connect(std::unique_ptr<ConnectParams> params, | 601 void Shell::Connect(std::unique_ptr<ConnectParams> params, |
| 602 mojom::ShellClientPtr client) { | 602 mojom::ServicePtr client) { |
| 603 TRACE_EVENT_INSTANT1("mojo_shell", "Shell::Connect", | 603 TRACE_EVENT_INSTANT1("mojo_shell", "Shell::Connect", |
| 604 TRACE_EVENT_SCOPE_THREAD, "original_name", | 604 TRACE_EVENT_SCOPE_THREAD, "original_name", |
| 605 params->target().name()); | 605 params->target().name()); |
| 606 DCHECK(IsValidName(params->target().name())); | 606 DCHECK(IsValidName(params->target().name())); |
| 607 DCHECK(base::IsValidGUID(params->target().user_id())); | 607 DCHECK(base::IsValidGUID(params->target().user_id())); |
| 608 DCHECK_NE(mojom::kInheritUserID, params->target().user_id()); | 608 DCHECK_NE(mojom::kInheritUserID, params->target().user_id()); |
| 609 DCHECK(!client.is_bound() || !identity_to_instance_.count(params->target())); | 609 DCHECK(!client.is_bound() || !identity_to_instance_.count(params->target())); |
| 610 | 610 |
| 611 // Connect to an existing matching instance, if possible. | 611 // Connect to an existing matching instance, if possible. |
| 612 if (!client.is_bound() && ConnectToExistingInstance(¶ms)) | 612 if (!client.is_bound() && ConnectToExistingInstance(¶ms)) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 void Shell::AddInstanceListener(mojom::InstanceListenerPtr listener) { | 675 void Shell::AddInstanceListener(mojom::InstanceListenerPtr listener) { |
| 676 // TODO(beng): filter instances provided by those visible to this client. | 676 // TODO(beng): filter instances provided by those visible to this client. |
| 677 mojo::Array<mojom::InstanceInfoPtr> instances; | 677 mojo::Array<mojom::InstanceInfoPtr> instances; |
| 678 for (auto& instance : identity_to_instance_) | 678 for (auto& instance : identity_to_instance_) |
| 679 instances.push_back(instance.second->CreateInstanceInfo()); | 679 instances.push_back(instance.second->CreateInstanceInfo()); |
| 680 listener->SetExistingInstances(std::move(instances)); | 680 listener->SetExistingInstances(std::move(instances)); |
| 681 | 681 |
| 682 instance_listeners_.AddPtr(std::move(listener)); | 682 instance_listeners_.AddPtr(std::move(listener)); |
| 683 } | 683 } |
| 684 | 684 |
| 685 void Shell::CreateShellClientWithFactory(const Identity& shell_client_factory, | 685 void Shell::CreateServiceWithFactory(const Identity& service_factory, |
| 686 const std::string& name, | 686 const std::string& name, |
| 687 mojom::ShellClientRequest request) { | 687 mojom::ServiceRequest request) { |
| 688 mojom::ShellClientFactory* factory = | 688 mojom::ServiceFactory* factory = GetServiceFactory(service_factory); |
| 689 GetShellClientFactory(shell_client_factory); | 689 factory->CreateService(std::move(request), name); |
| 690 factory->CreateShellClient(std::move(request), name); | |
| 691 } | 690 } |
| 692 | 691 |
| 693 mojom::ShellClientFactory* Shell::GetShellClientFactory( | 692 mojom::ServiceFactory* Shell::GetServiceFactory( |
| 694 const Identity& shell_client_factory_identity) { | 693 const Identity& service_factory_identity) { |
| 695 auto it = shell_client_factories_.find(shell_client_factory_identity); | 694 auto it = service_factories_.find(service_factory_identity); |
| 696 if (it != shell_client_factories_.end()) | 695 if (it != service_factories_.end()) |
| 697 return it->second.get(); | 696 return it->second.get(); |
| 698 | 697 |
| 699 Identity source_identity(kShellName, mojom::kInheritUserID); | 698 Identity source_identity(kShellName, mojom::kInheritUserID); |
| 700 mojom::ShellClientFactoryPtr factory; | 699 mojom::ServiceFactoryPtr factory; |
| 701 ConnectToInterface(this, source_identity, shell_client_factory_identity, | 700 ConnectToInterface(this, source_identity, service_factory_identity, |
| 702 &factory); | 701 &factory); |
| 703 mojom::ShellClientFactory* factory_interface = factory.get(); | 702 mojom::ServiceFactory* factory_interface = factory.get(); |
| 704 factory.set_connection_error_handler(base::Bind( | 703 factory.set_connection_error_handler(base::Bind( |
| 705 &shell::Shell::OnShellClientFactoryLost, weak_ptr_factory_.GetWeakPtr(), | 704 &shell::Shell::OnServiceFactoryLost, weak_ptr_factory_.GetWeakPtr(), |
| 706 shell_client_factory_identity)); | 705 service_factory_identity)); |
| 707 shell_client_factories_[shell_client_factory_identity] = std::move(factory); | 706 service_factories_[service_factory_identity] = std::move(factory); |
| 708 return factory_interface; | 707 return factory_interface; |
| 709 } | 708 } |
| 710 | 709 |
| 711 void Shell::OnShellClientFactoryLost(const Identity& which) { | 710 void Shell::OnServiceFactoryLost(const Identity& which) { |
| 712 // Remove the mapping. | 711 // Remove the mapping. |
| 713 auto it = shell_client_factories_.find(which); | 712 auto it = service_factories_.find(which); |
| 714 DCHECK(it != shell_client_factories_.end()); | 713 DCHECK(it != service_factories_.end()); |
| 715 shell_client_factories_.erase(it); | 714 service_factories_.erase(it); |
| 716 } | 715 } |
| 717 | 716 |
| 718 void Shell::OnGotResolvedName(std::unique_ptr<ConnectParams> params, | 717 void Shell::OnGotResolvedName(std::unique_ptr<ConnectParams> params, |
| 719 mojom::ShellClientPtr client, | 718 mojom::ServicePtr client, |
| 720 mojom::ResolveResultPtr result) { | 719 mojom::ResolveResultPtr result) { |
| 721 std::string instance_name = params->target().instance(); | 720 std::string instance_name = params->target().instance(); |
| 722 if (instance_name == GetNamePath(params->target().name()) && | 721 if (instance_name == GetNamePath(params->target().name()) && |
| 723 result->qualifier != GetNamePath(result->resolved_name)) { | 722 result->qualifier != GetNamePath(result->resolved_name)) { |
| 724 instance_name = result->qualifier; | 723 instance_name = result->qualifier; |
| 725 } | 724 } |
| 726 Identity target(params->target().name(), params->target().user_id(), | 725 Identity target(params->target().name(), params->target().user_id(), |
| 727 instance_name); | 726 instance_name); |
| 728 params->set_target(target); | 727 params->set_target(target); |
| 729 | 728 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 753 } else { | 752 } else { |
| 754 source_identity_for_creation = params->source(); | 753 source_identity_for_creation = params->source(); |
| 755 } | 754 } |
| 756 | 755 |
| 757 mojom::ClientProcessConnectionPtr client_process_connection = | 756 mojom::ClientProcessConnectionPtr client_process_connection = |
| 758 params->TakeClientProcessConnection(); | 757 params->TakeClientProcessConnection(); |
| 759 Instance* instance = CreateInstance(source_identity_for_creation, | 758 Instance* instance = CreateInstance(source_identity_for_creation, |
| 760 target, capabilities); | 759 target, capabilities); |
| 761 | 760 |
| 762 // Below are various paths through which a new Instance can be bound to a | 761 // Below are various paths through which a new Instance can be bound to a |
| 763 // ShellClient proxy. | 762 // Service proxy. |
| 764 if (client.is_bound()) { | 763 if (client.is_bound()) { |
| 765 // If a ShellClientPtr was provided, there's no more work to do: someone | 764 // If a ServicePtr was provided, there's no more work to do: someone |
| 766 // is already holding a corresponding ShellClientRequest. | 765 // is already holding a corresponding ServiceRequest. |
| 767 instance->StartWithClient(std::move(client)); | 766 instance->StartWithClient(std::move(client)); |
| 768 } else if (!client_process_connection.is_null()) { | 767 } else if (!client_process_connection.is_null()) { |
| 769 // Likewise if a ClientProcessConnection was given via Connect(), it | 768 // Likewise if a ClientProcessConnection was given via Connect(), it |
| 770 // provides the ShellClient proxy to use. | 769 // provides the Service proxy to use. |
| 771 instance->StartWithClientProcessConnection( | 770 instance->StartWithClientProcessConnection( |
| 772 std::move(client_process_connection)); | 771 std::move(client_process_connection)); |
| 773 } else { | 772 } else { |
| 774 // Otherwise we create a new ShellClient pipe. | 773 // Otherwise we create a new Service pipe. |
| 775 mojom::ShellClientRequest request = GetProxy(&client); | 774 mojom::ServiceRequest request = GetProxy(&client); |
| 776 CHECK(!result->package_path.empty() && !result->capabilities.is_null()); | 775 CHECK(!result->package_path.empty() && !result->capabilities.is_null()); |
| 777 | 776 |
| 778 if (target.name() != result->resolved_name) { | 777 if (target.name() != result->resolved_name) { |
| 779 instance->StartWithClient(std::move(client)); | 778 instance->StartWithClient(std::move(client)); |
| 780 Identity factory(result->resolved_name, target.user_id(), | 779 Identity factory(result->resolved_name, target.user_id(), |
| 781 instance_name); | 780 instance_name); |
| 782 CreateShellClientWithFactory(factory, target.name(), | 781 CreateServiceWithFactory(factory, target.name(), |
| 783 std::move(request)); | 782 std::move(request)); |
| 784 } else { | 783 } else { |
| 785 instance->StartWithFilePath(result->package_path); | 784 instance->StartWithFilePath(result->package_path); |
| 786 } | 785 } |
| 787 } | 786 } |
| 788 | 787 |
| 789 // Now that the instance has a ShellClient, we can connect to it. | 788 // Now that the instance has a Service, we can connect to it. |
| 790 bool connected = instance->ConnectToClient(¶ms); | 789 bool connected = instance->ConnectToClient(¶ms); |
| 791 DCHECK(connected); | 790 DCHECK(connected); |
| 792 } | 791 } |
| 793 | 792 |
| 794 base::WeakPtr<Shell> Shell::GetWeakPtr() { | 793 base::WeakPtr<Shell> Shell::GetWeakPtr() { |
| 795 return weak_ptr_factory_.GetWeakPtr(); | 794 return weak_ptr_factory_.GetWeakPtr(); |
| 796 } | 795 } |
| 797 | 796 |
| 798 } // namespace shell | 797 } // namespace shell |
| OLD | NEW |