| 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 "mojo/shell/shell.h" | 5 #include "mojo/shell/shell.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #include "url/gurl.h" | 32 #include "url/gurl.h" |
| 33 | 33 |
| 34 namespace mojo { | 34 namespace mojo { |
| 35 namespace shell { | 35 namespace shell { |
| 36 namespace { | 36 namespace { |
| 37 const char kCatalogName[] = "mojo:catalog"; | 37 const char kCatalogName[] = "mojo:catalog"; |
| 38 const char kShellName[] = "mojo:shell"; | 38 const char kShellName[] = "mojo:shell"; |
| 39 const char kCapabilityClass_UserID[] = "user_id"; | 39 const char kCapabilityClass_UserID[] = "user_id"; |
| 40 const char kCapabilityClass_ClientProcess[] = "client_process"; | 40 const char kCapabilityClass_ClientProcess[] = "client_process"; |
| 41 const char kCapabilityClass_InstanceName[] = "instance_name"; | 41 const char kCapabilityClass_InstanceName[] = "instance_name"; |
| 42 const char kCapabilityClass_AllUsers[] = "all_users"; |
| 42 | 43 |
| 43 void EmptyResolverCallback(const String& resolved_name, | 44 void EmptyResolverCallback(const String& resolved_name, |
| 44 const String& resolved_instance, | 45 const String& resolved_instance, |
| 45 mojom::CapabilitySpecPtr capabilities, | 46 mojom::CapabilitySpecPtr capabilities, |
| 46 const String& file_url) {} | 47 const String& file_url) {} |
| 47 | 48 |
| 48 } | 49 } |
| 49 | 50 |
| 50 Identity CreateShellIdentity() { | 51 Identity CreateShellIdentity() { |
| 51 return Identity(kShellName, mojom::kRootUserID); | 52 return Identity(kShellName, mojom::kRootUserID); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 for (const auto& class_name : request.classes) { | 90 for (const auto& class_name : request.classes) { |
| 90 auto it = target_spec.provided.find(class_name); | 91 auto it = target_spec.provided.find(class_name); |
| 91 if (it != target_spec.provided.end()) { | 92 if (it != target_spec.provided.end()) { |
| 92 for (const auto& interface_name : it->second) | 93 for (const auto& interface_name : it->second) |
| 93 request.interfaces.insert(interface_name); | 94 request.interfaces.insert(interface_name); |
| 94 } | 95 } |
| 95 } | 96 } |
| 96 return request; | 97 return request; |
| 97 } | 98 } |
| 98 | 99 |
| 100 bool HasClass(const CapabilitySpec& spec, const std::string& class_name) { |
| 101 auto it = spec.required.find(kShellName); |
| 102 if (it == spec.required.end()) |
| 103 return false; |
| 104 return it->second.classes.find(class_name) != it->second.classes.end(); |
| 105 } |
| 106 |
| 99 // Encapsulates a connection to an instance of an application, tracked by the | 107 // Encapsulates a connection to an instance of an application, tracked by the |
| 100 // shell's Shell. | 108 // shell's Shell. |
| 101 class Shell::Instance : public mojom::Connector, | 109 class Shell::Instance : public mojom::Connector, |
| 102 public mojom::PIDReceiver, | 110 public mojom::PIDReceiver, |
| 103 public ShellClient, | 111 public ShellClient, |
| 104 public InterfaceFactory<mojom::Shell>, | 112 public InterfaceFactory<mojom::Shell>, |
| 105 public mojom::Shell { | 113 public mojom::Shell { |
| 106 public: | 114 public: |
| 107 Instance(mojo::shell::Shell* shell, | 115 Instance(mojo::shell::Shell* shell, |
| 108 const Identity& identity, | 116 const Identity& identity, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 207 } |
| 200 | 208 |
| 201 mojom::InstanceInfoPtr CreateInstanceInfo() const { | 209 mojom::InstanceInfoPtr CreateInstanceInfo() const { |
| 202 mojom::InstanceInfoPtr info(mojom::InstanceInfo::New()); | 210 mojom::InstanceInfoPtr info(mojom::InstanceInfo::New()); |
| 203 info->id = id_; | 211 info->id = id_; |
| 204 info->identity = mojom::Identity::From(identity_); | 212 info->identity = mojom::Identity::From(identity_); |
| 205 info->pid = pid_; | 213 info->pid = pid_; |
| 206 return info; | 214 return info; |
| 207 } | 215 } |
| 208 | 216 |
| 217 const CapabilitySpec& capability_spec() const { |
| 218 return capability_spec_; |
| 219 } |
| 209 const Identity& identity() const { return identity_; } | 220 const Identity& identity() const { return identity_; } |
| 210 uint32_t id() const { return id_; } | 221 uint32_t id() const { return id_; } |
| 211 | 222 |
| 212 // ShellClient: | 223 // ShellClient: |
| 213 bool AcceptConnection(Connection* connection) override { | 224 bool AcceptConnection(Connection* connection) override { |
| 214 connection->AddInterface<mojom::Shell>(this); | 225 connection->AddInterface<mojom::Shell>(this); |
| 215 return true; | 226 return true; |
| 216 } | 227 } |
| 217 | 228 |
| 218 private: | 229 private: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 return false; | 293 return false; |
| 283 } | 294 } |
| 284 return true; | 295 return true; |
| 285 } | 296 } |
| 286 | 297 |
| 287 bool ValidateClientProcessConnection( | 298 bool ValidateClientProcessConnection( |
| 288 mojom::ClientProcessConnectionPtr* client_process_connection, | 299 mojom::ClientProcessConnectionPtr* client_process_connection, |
| 289 const Identity& target, | 300 const Identity& target, |
| 290 const ConnectCallback& callback) { | 301 const ConnectCallback& callback) { |
| 291 if (!client_process_connection->is_null()) { | 302 if (!client_process_connection->is_null()) { |
| 292 if (!HasClass(kCapabilityClass_ClientProcess)) { | 303 if (!HasClass(capability_spec_, kCapabilityClass_ClientProcess)) { |
| 293 LOG(ERROR) << "Error: Instance: " << identity_.name() << " attempting " | 304 LOG(ERROR) << "Error: Instance: " << identity_.name() << " attempting " |
| 294 << "to register an instance for a process it created for " | 305 << "to register an instance for a process it created for " |
| 295 << "target: " << target.name() << " without the " | 306 << "target: " << target.name() << " without the " |
| 296 << "mojo:shell{client_process} capability class."; | 307 << "mojo:shell{client_process} capability class."; |
| 297 callback.Run(mojom::ConnectResult::ACCESS_DENIED, | 308 callback.Run(mojom::ConnectResult::ACCESS_DENIED, |
| 298 mojom::kInheritUserID, mojom::kInvalidInstanceID); | 309 mojom::kInheritUserID, mojom::kInvalidInstanceID); |
| 299 return false; | 310 return false; |
| 300 } | 311 } |
| 301 | 312 |
| 302 if (!(*client_process_connection)->shell_client.is_valid() || | 313 if (!(*client_process_connection)->shell_client.is_valid() || |
| (...skipping 17 matching lines...) Expand all Loading... |
| 320 return true; | 331 return true; |
| 321 } | 332 } |
| 322 | 333 |
| 323 bool ValidateCapabilities(const Identity& target, | 334 bool ValidateCapabilities(const Identity& target, |
| 324 const ConnectCallback& callback) { | 335 const ConnectCallback& callback) { |
| 325 // TODO(beng): Need to do the following additional policy validation of | 336 // TODO(beng): Need to do the following additional policy validation of |
| 326 // whether this instance is allowed to connect using: | 337 // whether this instance is allowed to connect using: |
| 327 // - a non-null client_process_connection. | 338 // - a non-null client_process_connection. |
| 328 if (target.user_id() != identity_.user_id() && | 339 if (target.user_id() != identity_.user_id() && |
| 329 target.user_id() != mojom::kRootUserID && | 340 target.user_id() != mojom::kRootUserID && |
| 330 !HasClass(kCapabilityClass_UserID)) { | 341 !HasClass(capability_spec_, kCapabilityClass_UserID)) { |
| 331 LOG(ERROR) << "Instance: " << identity_.name() << " running as: " | 342 LOG(ERROR) << "Instance: " << identity_.name() << " running as: " |
| 332 << identity_.user_id() << " attempting to connect to: " | 343 << identity_.user_id() << " attempting to connect to: " |
| 333 << target.name() << " as: " << target.user_id() << " without " | 344 << target.name() << " as: " << target.user_id() << " without " |
| 334 << " the mojo:shell{user_id} capability class."; | 345 << " the mojo:shell{user_id} capability class."; |
| 335 callback.Run(mojom::ConnectResult::ACCESS_DENIED, | 346 callback.Run(mojom::ConnectResult::ACCESS_DENIED, |
| 336 mojom::kInheritUserID, mojom::kInvalidInstanceID); | 347 mojom::kInheritUserID, mojom::kInvalidInstanceID); |
| 337 return false; | 348 return false; |
| 338 } | 349 } |
| 339 if (!target.instance().empty() && | 350 if (!target.instance().empty() && |
| 340 target.instance() != GetNamePath(target.name()) && | 351 target.instance() != GetNamePath(target.name()) && |
| 341 !HasClass(kCapabilityClass_InstanceName)) { | 352 !HasClass(capability_spec_, kCapabilityClass_InstanceName)) { |
| 342 LOG(ERROR) << "Instance: " << identity_.name() << " attempting to " | 353 LOG(ERROR) << "Instance: " << identity_.name() << " attempting to " |
| 343 << "connect to " << target.name() << " using Instance name: " | 354 << "connect to " << target.name() << " using Instance name: " |
| 344 << target.instance() << " without the " | 355 << target.instance() << " without the " |
| 345 << "mojo:shell{instance_name} capability class."; | 356 << "mojo:shell{instance_name} capability class."; |
| 346 callback.Run(mojom::ConnectResult::ACCESS_DENIED, | 357 callback.Run(mojom::ConnectResult::ACCESS_DENIED, |
| 347 mojom::kInheritUserID, mojom::kInvalidInstanceID); | 358 mojom::kInheritUserID, mojom::kInvalidInstanceID); |
| 348 return false; | 359 return false; |
| 349 | 360 |
| 350 } | 361 } |
| 351 | 362 |
| 352 if (allow_any_application_ || | 363 if (allow_any_application_ || |
| 353 capability_spec_.required.find(target.name()) != | 364 capability_spec_.required.find(target.name()) != |
| 354 capability_spec_.required.end()) { | 365 capability_spec_.required.end()) { |
| 355 return true; | 366 return true; |
| 356 } | 367 } |
| 357 LOG(ERROR) << "Capabilities prevented connection from: " << | 368 LOG(ERROR) << "Capabilities prevented connection from: " << |
| 358 identity_.name() << " to: " << target.name(); | 369 identity_.name() << " to: " << target.name(); |
| 359 callback.Run(mojom::ConnectResult::ACCESS_DENIED, | 370 callback.Run(mojom::ConnectResult::ACCESS_DENIED, |
| 360 mojom::kInheritUserID, mojom::kInvalidInstanceID); | 371 mojom::kInheritUserID, mojom::kInvalidInstanceID); |
| 361 return false; | 372 return false; |
| 362 } | 373 } |
| 363 | 374 |
| 364 bool HasClass(const std::string& class_name) const { | |
| 365 auto it = capability_spec_.required.find(kShellName); | |
| 366 if (it == capability_spec_.required.end()) | |
| 367 return false; | |
| 368 return it->second.classes.find(class_name) != it->second.classes.end(); | |
| 369 } | |
| 370 | |
| 371 uint32_t GenerateUniqueID() const { | 375 uint32_t GenerateUniqueID() const { |
| 372 static uint32_t id = mojom::kInvalidInstanceID; | 376 static uint32_t id = mojom::kInvalidInstanceID; |
| 373 ++id; | 377 ++id; |
| 374 CHECK_NE(mojom::kInvalidInstanceID, id); | 378 CHECK_NE(mojom::kInvalidInstanceID, id); |
| 375 return id; | 379 return id; |
| 376 } | 380 } |
| 377 | 381 |
| 378 void PIDAvailable(base::ProcessId pid) { | 382 void PIDAvailable(base::ProcessId pid) { |
| 379 pid_ = pid; | 383 pid_ = pid; |
| 380 shell_->NotifyPIDAvailable(id_, pid_); | 384 shell_->NotifyPIDAvailable(id_, pid_); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 | 560 |
| 557 Shell::Instance* Shell::GetExistingInstance(const Identity& identity) const { | 561 Shell::Instance* Shell::GetExistingInstance(const Identity& identity) const { |
| 558 const auto& it = identity_to_instance_.find(identity); | 562 const auto& it = identity_to_instance_.find(identity); |
| 559 return it != identity_to_instance_.end() ? it->second : nullptr; | 563 return it != identity_to_instance_.end() ? it->second : nullptr; |
| 560 } | 564 } |
| 561 | 565 |
| 562 Shell::Instance* Shell::GetExistingOrRootInstance( | 566 Shell::Instance* Shell::GetExistingOrRootInstance( |
| 563 const Identity& identity) const { | 567 const Identity& identity) const { |
| 564 Instance* instance = GetExistingInstance(identity); | 568 Instance* instance = GetExistingInstance(identity); |
| 565 if (!instance) { | 569 if (!instance) { |
| 570 if (singletons_.find(identity.name()) != singletons_.end()) { |
| 571 for (auto entry : identity_to_instance_) { |
| 572 if (entry.first.name() == identity.name() && |
| 573 entry.first.instance() == identity.instance()) { |
| 574 return entry.second; |
| 575 } |
| 576 } |
| 577 } |
| 578 |
| 566 Identity root_identity = identity; | 579 Identity root_identity = identity; |
| 567 root_identity.set_user_id(mojom::kRootUserID); | 580 root_identity.set_user_id(mojom::kRootUserID); |
| 568 instance = GetExistingInstance(root_identity); | 581 instance = GetExistingInstance(root_identity); |
| 569 } | 582 } |
| 570 return instance; | 583 return instance; |
| 571 } | 584 } |
| 572 | 585 |
| 573 void Shell::NotifyPIDAvailable(uint32_t id, base::ProcessId pid) { | 586 void Shell::NotifyPIDAvailable(uint32_t id, base::ProcessId pid) { |
| 574 instance_listeners_.ForAllPtrs([id, pid](mojom::InstanceListener* listener) { | 587 instance_listeners_.ForAllPtrs([id, pid](mojom::InstanceListener* listener) { |
| 575 listener->InstancePIDAvailable(id, pid); | 588 listener->InstancePIDAvailable(id, pid); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 if (ConnectToExistingInstance(¶ms)) | 678 if (ConnectToExistingInstance(¶ms)) |
| 666 return; | 679 return; |
| 667 | 680 |
| 668 Identity source = params->source(); | 681 Identity source = params->source(); |
| 669 // |capabilities_ptr| can be null when there is no manifest, e.g. for URL | 682 // |capabilities_ptr| can be null when there is no manifest, e.g. for URL |
| 670 // types not resolvable by the resolver. | 683 // types not resolvable by the resolver. |
| 671 CapabilitySpec capabilities = GetPermissiveCapabilities(); | 684 CapabilitySpec capabilities = GetPermissiveCapabilities(); |
| 672 if (!capabilities_ptr.is_null()) | 685 if (!capabilities_ptr.is_null()) |
| 673 capabilities = capabilities_ptr.To<CapabilitySpec>(); | 686 capabilities = capabilities_ptr.To<CapabilitySpec>(); |
| 674 | 687 |
| 688 if (HasClass(capabilities, kCapabilityClass_AllUsers)) |
| 689 singletons_.insert(target.name()); |
| 690 |
| 675 mojom::ClientProcessConnectionPtr client_process_connection = | 691 mojom::ClientProcessConnectionPtr client_process_connection = |
| 676 params->TakeClientProcessConnection(); | 692 params->TakeClientProcessConnection(); |
| 677 Instance* instance = CreateInstance(target, capabilities); | 693 Instance* instance = CreateInstance(target, capabilities); |
| 678 | 694 |
| 679 // Below are various paths through which a new Instance can be bound to a | 695 // Below are various paths through which a new Instance can be bound to a |
| 680 // ShellClient proxy. | 696 // ShellClient proxy. |
| 681 if (client.is_bound()) { | 697 if (client.is_bound()) { |
| 682 // If a ShellClientPtr was provided, there's no more work to do: someone | 698 // If a ShellClientPtr was provided, there's no more work to do: someone |
| 683 // is already holding a corresponding ShellClientRequest. | 699 // is already holding a corresponding ShellClientRequest. |
| 684 instance->StartWithClient(std::move(client)); | 700 instance->StartWithClient(std::move(client)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 for (auto it = native_runners_.begin(); it != native_runners_.end(); ++it) { | 746 for (auto it = native_runners_.begin(); it != native_runners_.end(); ++it) { |
| 731 if (it->get() == runner) { | 747 if (it->get() == runner) { |
| 732 native_runners_.erase(it); | 748 native_runners_.erase(it); |
| 733 return; | 749 return; |
| 734 } | 750 } |
| 735 } | 751 } |
| 736 } | 752 } |
| 737 | 753 |
| 738 } // namespace shell | 754 } // namespace shell |
| 739 } // namespace mojo | 755 } // namespace mojo |
| OLD | NEW |