| 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 |
| 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/logging.h" | 14 #include "base/logging.h" |
| 14 #include "base/macros.h" | 15 #include "base/macros.h" |
| 15 #include "base/process/process.h" | 16 #include "base/process/process.h" |
| 16 #include "base/process/process_handle.h" | 17 #include "base/process/process_handle.h" |
| 17 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 18 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 19 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
| 20 #include "mojo/common/url_type_converters.h" | 21 #include "mojo/common/url_type_converters.h" |
| 21 #include "mojo/public/cpp/bindings/binding.h" | 22 #include "mojo/public/cpp/bindings/binding.h" |
| 22 #include "mojo/public/cpp/bindings/binding_set.h" | 23 #include "mojo/public/cpp/bindings/binding_set.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 shell_->GetLoaderForName(identity_.name())) { | 66 shell_->GetLoaderForName(identity_.name())) { |
| 66 pid_ = base::Process::Current().Pid(); | 67 pid_ = base::Process::Current().Pid(); |
| 67 } | 68 } |
| 68 DCHECK_NE(kInvalidApplicationID, id_); | 69 DCHECK_NE(kInvalidApplicationID, id_); |
| 69 } | 70 } |
| 70 | 71 |
| 71 ~Instance() override {} | 72 ~Instance() override {} |
| 72 | 73 |
| 73 void InitializeClient() { | 74 void InitializeClient() { |
| 74 shell_client_->Initialize(connectors_.CreateInterfacePtrAndBind(this), | 75 shell_client_->Initialize(connectors_.CreateInterfacePtrAndBind(this), |
| 75 identity_.name(), id_, identity_.user_id()); | 76 identity_.name(), identity_.user_id(), id_); |
| 76 connectors_.set_connection_error_handler( | 77 connectors_.set_connection_error_handler( |
| 77 base::Bind(&mojo::shell::Shell::OnInstanceError, | 78 base::Bind(&mojo::shell::Shell::OnInstanceError, |
| 78 base::Unretained(shell_), base::Unretained(this))); | 79 base::Unretained(shell_), base::Unretained(this))); |
| 79 } | 80 } |
| 80 | 81 |
| 81 void ConnectToClient(scoped_ptr<ConnectParams> params) { | 82 void ConnectToClient(scoped_ptr<ConnectParams> params) { |
| 82 params->connect_callback().Run(id_, identity_.user_id()); | 83 params->connect_callback().Run(identity_.user_id(), id_); |
| 83 AllowedInterfaces interfaces; | 84 AllowedInterfaces interfaces; |
| 84 interfaces.insert("*"); | 85 interfaces.insert("*"); |
| 85 if (!params->source().is_null()) | 86 if (!params->source().is_null()) |
| 86 interfaces = GetAllowedInterfaces(params->source().filter(), identity_); | 87 interfaces = GetAllowedInterfaces(params->source().filter(), identity_); |
| 87 | 88 |
| 88 Instance* source = shell_->GetExistingInstance(params->source()); | 89 Instance* source = shell_->GetExistingInstance(params->source()); |
| 89 uint32_t source_id = source ? source->id() : kInvalidApplicationID; | 90 uint32_t source_id = source ? source->id() : kInvalidApplicationID; |
| 90 shell_client_->AcceptConnection( | 91 shell_client_->AcceptConnection( |
| 91 params->source().name(), source_id, params->source().user_id(), | 92 params->source().name(), params->source().user_id(), source_id, |
| 92 params->TakeRemoteInterfaces(), params->TakeLocalInterfaces(), | 93 params->TakeRemoteInterfaces(), params->TakeLocalInterfaces(), |
| 93 Array<String>::From(interfaces), params->target().name()); | 94 Array<String>::From(interfaces), params->target().name()); |
| 94 } | 95 } |
| 95 | 96 |
| 96 scoped_ptr<NativeRunner> StartWithFileURL(const GURL& file_url, | 97 scoped_ptr<NativeRunner> StartWithFileURL(const GURL& file_url, |
| 97 mojom::ShellClientRequest request, | 98 mojom::ShellClientRequest request, |
| 98 bool start_sandboxed, | 99 bool start_sandboxed, |
| 99 NativeRunnerFactory* factory) { | 100 NativeRunnerFactory* factory) { |
| 100 base::FilePath path = util::UrlToFilePath(file_url); | 101 base::FilePath path = util::UrlToFilePath(file_url); |
| 101 scoped_ptr<NativeRunner> runner = factory->Create(path); | 102 scoped_ptr<NativeRunner> runner = factory->Create(path); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 | 138 |
| 138 // ShellClient: | 139 // ShellClient: |
| 139 bool AcceptConnection(Connection* connection) override { | 140 bool AcceptConnection(Connection* connection) override { |
| 140 connection->AddInterface<mojom::Shell>(this); | 141 connection->AddInterface<mojom::Shell>(this); |
| 141 return true; | 142 return true; |
| 142 } | 143 } |
| 143 | 144 |
| 144 private: | 145 private: |
| 145 // mojom::Connector implementation: | 146 // mojom::Connector implementation: |
| 146 void Connect(const String& app_name, | 147 void Connect(const String& app_name, |
| 147 uint32_t user_id, | 148 const String& user_id, |
| 148 shell::mojom::InterfaceProviderRequest remote_interfaces, | 149 shell::mojom::InterfaceProviderRequest remote_interfaces, |
| 149 shell::mojom::InterfaceProviderPtr local_interfaces, | 150 shell::mojom::InterfaceProviderPtr local_interfaces, |
| 150 const ConnectCallback& callback) override { | 151 const ConnectCallback& callback) override { |
| 152 // TODO(beng): Might not want to CHECK here, but rather run the callback |
| 153 // with an error code. |
| 154 CHECK(base::IsValidGUID(user_id)); |
| 155 |
| 151 // TODO(beng): perform checking on policy of whether this instance is | 156 // TODO(beng): perform checking on policy of whether this instance is |
| 152 // allowed to pass different user_ids. | 157 // allowed to pass different user_ids. |
| 153 if (!IsValidName(app_name)) { | 158 if (!IsValidName(app_name)) { |
| 154 LOG(ERROR) << "Error: invalid Name: " << app_name; | 159 LOG(ERROR) << "Error: invalid Name: " << app_name; |
| 155 callback.Run(kInvalidApplicationID, kUserInherit); | 160 callback.Run(mojom::kInheritUserID, kInvalidApplicationID); |
| 156 return; | 161 return; |
| 157 } | 162 } |
| 158 if (allow_any_application_ || | 163 if (allow_any_application_ || |
| 159 identity_.filter().find(app_name) != identity_.filter().end()) { | 164 identity_.filter().find(app_name) != identity_.filter().end()) { |
| 160 scoped_ptr<ConnectParams> params(new ConnectParams); | 165 scoped_ptr<ConnectParams> params(new ConnectParams); |
| 161 params->set_source(identity_); | 166 params->set_source(identity_); |
| 162 params->set_target(Identity(app_name, std::string(), user_id)); | 167 params->set_target(Identity(app_name, std::string(), user_id)); |
| 163 params->set_remote_interfaces(std::move(remote_interfaces)); | 168 params->set_remote_interfaces(std::move(remote_interfaces)); |
| 164 params->set_local_interfaces(std::move(local_interfaces)); | 169 params->set_local_interfaces(std::move(local_interfaces)); |
| 165 params->set_connect_callback(callback); | 170 params->set_connect_callback(callback); |
| 166 shell_->Connect(std::move(params)); | 171 shell_->Connect(std::move(params)); |
| 167 } | 172 } |
| 168 else { | 173 else { |
| 169 LOG(WARNING) << "CapabilityFilter prevented connection from: " << | 174 LOG(WARNING) << "CapabilityFilter prevented connection from: " << |
| 170 identity_.name() << " to: " << app_name; | 175 identity_.name() << " to: " << app_name; |
| 171 callback.Run(kInvalidApplicationID, kUserInherit); | 176 callback.Run(mojom::kInheritUserID, kInvalidApplicationID); |
| 172 } | 177 } |
| 173 } | 178 } |
| 174 void Clone(mojom::ConnectorRequest request) override { | 179 void Clone(mojom::ConnectorRequest request) override { |
| 175 connectors_.AddBinding(this, std::move(request)); | 180 connectors_.AddBinding(this, std::move(request)); |
| 176 } | 181 } |
| 177 | 182 |
| 178 // mojom::PIDReceiver: | 183 // mojom::PIDReceiver: |
| 179 void SetPID(uint32_t pid) override { | 184 void SetPID(uint32_t pid) override { |
| 180 PIDAvailable(pid); | 185 PIDAvailable(pid); |
| 181 } | 186 } |
| 182 | 187 |
| 183 // InterfaceFactory<mojom::Shell>: | 188 // InterfaceFactory<mojom::Shell>: |
| 184 void Create(Connection* connection, | 189 void Create(Connection* connection, |
| 185 mojom::ShellRequest request) override { | 190 mojom::ShellRequest request) override { |
| 186 shell_bindings_.AddBinding(this, std::move(request)); | 191 shell_bindings_.AddBinding(this, std::move(request)); |
| 187 } | 192 } |
| 188 | 193 |
| 189 // mojom::Shell implementation: | 194 // mojom::Shell implementation: |
| 190 void CreateInstanceForFactory( | 195 void CreateInstanceForFactory( |
| 191 mojom::ShellClientFactoryPtr factory, | 196 mojom::ShellClientFactoryPtr factory, |
| 192 const String& name, | 197 const String& name, |
| 193 uint32_t user_id, | 198 const String& user_id, |
| 194 mojom::CapabilityFilterPtr filter, | 199 mojom::CapabilityFilterPtr filter, |
| 195 mojom::PIDReceiverRequest pid_receiver) override { | 200 mojom::PIDReceiverRequest pid_receiver) override { |
| 196 // TODO(beng): perform checking on policy of whether this instance is | 201 // TODO(beng): perform checking on policy of whether this instance is |
| 197 // allowed to pass different user_ids. | 202 // allowed to pass different user_ids. |
| 198 if (user_id == mojom::Connector::kUserInherit) | 203 std::string user_id_string = user_id; |
| 199 user_id = identity_.user_id(); | 204 if (user_id_string == mojom::kInheritUserID) |
| 200 shell_->CreateInstanceForFactory(std::move(factory), name, user_id, | 205 user_id_string = identity_.user_id(); |
| 206 shell_->CreateInstanceForFactory(std::move(factory), name, user_id_string, |
| 201 std::move(filter), | 207 std::move(filter), |
| 202 std::move(pid_receiver)); | 208 std::move(pid_receiver)); |
| 203 } | 209 } |
| 204 void AddInstanceListener(mojom::InstanceListenerPtr listener) override { | 210 void AddInstanceListener(mojom::InstanceListenerPtr listener) override { |
| 205 // TODO(beng): this should only track the instances matching this user, and | 211 // TODO(beng): this should only track the instances matching this user, and |
| 206 // root. | 212 // root. |
| 207 shell_->AddInstanceListener(std::move(listener)); | 213 shell_->AddInstanceListener(std::move(listener)); |
| 208 } | 214 } |
| 209 | 215 |
| 210 uint32_t GenerateUniqueID() const { | 216 uint32_t GenerateUniqueID() const { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 base::Callback<void(const Identity&)> callback) { | 279 base::Callback<void(const Identity&)> callback) { |
| 274 instance_quit_callback_ = callback; | 280 instance_quit_callback_ = callback; |
| 275 } | 281 } |
| 276 | 282 |
| 277 void Shell::Connect(scoped_ptr<ConnectParams> params) { | 283 void Shell::Connect(scoped_ptr<ConnectParams> params) { |
| 278 TRACE_EVENT_INSTANT1("mojo_shell", "Shell::Connect", | 284 TRACE_EVENT_INSTANT1("mojo_shell", "Shell::Connect", |
| 279 TRACE_EVENT_SCOPE_THREAD, "original_name", | 285 TRACE_EVENT_SCOPE_THREAD, "original_name", |
| 280 params->target().name()); | 286 params->target().name()); |
| 281 DCHECK(IsValidName(params->target().name())); | 287 DCHECK(IsValidName(params->target().name())); |
| 282 | 288 |
| 283 if (params->target().user_id() == mojom::Connector::kUserInherit) { | 289 if (params->target().user_id() == mojom::kInheritUserID) { |
| 284 Instance* source = GetExistingInstance(params->source()); | 290 Instance* source = GetExistingInstance(params->source()); |
| 285 Identity target = params->target(); | 291 Identity target = params->target(); |
| 286 // TODO(beng): we should CHECK source. | 292 // TODO(beng): we should CHECK source. |
| 287 target.set_user_id(source ? source->identity().user_id() | 293 target.set_user_id(source ? source->identity().user_id() |
| 288 : mojom::Connector::kUserRoot); | 294 : mojom::kRootUserID); |
| 289 params->set_target(target); | 295 params->set_target(target); |
| 290 } | 296 } |
| 291 | 297 |
| 292 // Connect to an existing matching instance, if possible. | 298 // Connect to an existing matching instance, if possible. |
| 293 if (ConnectToExistingInstance(¶ms)) | 299 if (ConnectToExistingInstance(¶ms)) |
| 294 return; | 300 return; |
| 295 | 301 |
| 296 std::string name = params->target().name(); | 302 std::string name = params->target().name(); |
| 297 shell_resolver_->ResolveMojoName( | 303 shell_resolver_->ResolveMojoName( |
| 298 name, | 304 name, |
| 299 base::Bind(&Shell::OnGotResolvedName, | 305 base::Bind(&Shell::OnGotResolvedName, |
| 300 weak_ptr_factory_.GetWeakPtr(), base::Passed(¶ms))); | 306 weak_ptr_factory_.GetWeakPtr(), base::Passed(¶ms))); |
| 301 } | 307 } |
| 302 | 308 |
| 303 mojom::ShellClientRequest Shell::InitInstanceForEmbedder( | 309 mojom::ShellClientRequest Shell::InitInstanceForEmbedder( |
| 304 const std::string& name) { | 310 const std::string& name) { |
| 305 DCHECK(!embedder_instance_); | 311 DCHECK(!embedder_instance_); |
| 306 | 312 |
| 307 mojo::shell::Identity target(name, std::string(), | 313 mojo::shell::Identity target(name, std::string(), mojom::kRootUserID); |
| 308 mojom::Connector::kUserRoot); | |
| 309 target.set_filter(GetPermissiveCapabilityFilter()); | 314 target.set_filter(GetPermissiveCapabilityFilter()); |
| 310 DCHECK(!GetExistingInstance(target)); | 315 DCHECK(!GetExistingInstance(target)); |
| 311 | 316 |
| 312 mojom::ShellClientRequest request; | 317 mojom::ShellClientRequest request; |
| 313 embedder_instance_ = CreateInstance(target, &request); | 318 embedder_instance_ = CreateInstance(target, &request); |
| 314 DCHECK(embedder_instance_); | 319 DCHECK(embedder_instance_); |
| 315 | 320 |
| 316 return request; | 321 return request; |
| 317 } | 322 } |
| 318 | 323 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 void Shell::NotifyPIDAvailable(uint32_t id, base::ProcessId pid) { | 402 void Shell::NotifyPIDAvailable(uint32_t id, base::ProcessId pid) { |
| 398 instance_listeners_.ForAllPtrs([id, pid](mojom::InstanceListener* listener) { | 403 instance_listeners_.ForAllPtrs([id, pid](mojom::InstanceListener* listener) { |
| 399 listener->InstancePIDAvailable(id, pid); | 404 listener->InstancePIDAvailable(id, pid); |
| 400 }); | 405 }); |
| 401 } | 406 } |
| 402 | 407 |
| 403 bool Shell::ConnectToExistingInstance(scoped_ptr<ConnectParams>* params) { | 408 bool Shell::ConnectToExistingInstance(scoped_ptr<ConnectParams>* params) { |
| 404 Instance* instance = GetExistingInstance((*params)->target()); | 409 Instance* instance = GetExistingInstance((*params)->target()); |
| 405 if (!instance) { | 410 if (!instance) { |
| 406 Identity root_identity = (*params)->target(); | 411 Identity root_identity = (*params)->target(); |
| 407 root_identity.set_user_id(mojom::Connector::kUserRoot); | 412 root_identity.set_user_id(mojom::kRootUserID); |
| 408 instance = GetExistingInstance(root_identity); | 413 instance = GetExistingInstance(root_identity); |
| 409 if (!instance) return false; | 414 if (!instance) return false; |
| 410 } | 415 } |
| 411 instance->ConnectToClient(std::move(*params)); | 416 instance->ConnectToClient(std::move(*params)); |
| 412 return true; | 417 return true; |
| 413 } | 418 } |
| 414 | 419 |
| 415 Shell::Instance* Shell::CreateInstance(const Identity& target_id, | 420 Shell::Instance* Shell::CreateInstance(const Identity& target_id, |
| 416 mojom::ShellClientRequest* request) { | 421 mojom::ShellClientRequest* request) { |
| 417 mojom::ShellClientPtr shell_client; | 422 mojom::ShellClientPtr shell_client; |
| 418 *request = GetProxy(&shell_client); | 423 *request = GetProxy(&shell_client); |
| 419 Instance* instance = new Instance(std::move(shell_client), this, target_id); | 424 Instance* instance = new Instance(std::move(shell_client), this, target_id); |
| 420 DCHECK(identity_to_instance_.find(target_id) == | 425 DCHECK(identity_to_instance_.find(target_id) == |
| 421 identity_to_instance_.end()); | 426 identity_to_instance_.end()); |
| 422 identity_to_instance_[target_id] = instance; | 427 identity_to_instance_[target_id] = instance; |
| 423 mojom::InstanceInfoPtr info = instance->CreateInstanceInfo(); | 428 mojom::InstanceInfoPtr info = instance->CreateInstanceInfo(); |
| 424 instance_listeners_.ForAllPtrs( | 429 instance_listeners_.ForAllPtrs( |
| 425 [this, &info](mojom::InstanceListener* listener) { | 430 [this, &info](mojom::InstanceListener* listener) { |
| 426 listener->InstanceCreated(info.Clone()); | 431 listener->InstanceCreated(info.Clone()); |
| 427 }); | 432 }); |
| 428 instance->InitializeClient(); | 433 instance->InitializeClient(); |
| 429 return instance; | 434 return instance; |
| 430 } | 435 } |
| 431 | 436 |
| 432 void Shell::CreateInstanceForFactory( | 437 void Shell::CreateInstanceForFactory( |
| 433 mojom::ShellClientFactoryPtr factory, | 438 mojom::ShellClientFactoryPtr factory, |
| 434 const String& name, | 439 const std::string& name, |
| 435 uint32_t user_id, | 440 const std::string& user_id, |
| 436 mojom::CapabilityFilterPtr filter, | 441 mojom::CapabilityFilterPtr filter, |
| 437 mojom::PIDReceiverRequest pid_receiver) { | 442 mojom::PIDReceiverRequest pid_receiver) { |
| 438 DCHECK(user_id != mojom::Connector::kUserInherit); | 443 DCHECK(user_id != mojom::kInheritUserID); |
| 439 // We don't call ConnectToClient() here since the instance was created | 444 // We don't call ConnectToClient() here since the instance was created |
| 440 // manually by other code, not in response to a Connect() request. The newly | 445 // manually by other code, not in response to a Connect() request. The newly |
| 441 // created instance is identified by |name| and may be subsequently reached by | 446 // created instance is identified by |name| and may be subsequently reached by |
| 442 // client code using this identity. | 447 // client code using this identity. |
| 443 Identity target_id(name, std::string(), mojom::Connector::kUserRoot); | 448 Identity target_id(name, std::string(), mojom::kRootUserID); |
| 444 target_id.set_filter(filter->filter.To<CapabilityFilter>()); | 449 target_id.set_filter(filter->filter.To<CapabilityFilter>()); |
| 445 mojom::ShellClientRequest request; | 450 mojom::ShellClientRequest request; |
| 446 Instance* instance = CreateInstance(target_id, &request); | 451 Instance* instance = CreateInstance(target_id, &request); |
| 447 native_runners_.push_back( | 452 native_runners_.push_back( |
| 448 instance->StartWithFactory(std::move(factory), name, std::move(request), | 453 instance->StartWithFactory(std::move(factory), name, std::move(request), |
| 449 std::move(pid_receiver), | 454 std::move(pid_receiver), |
| 450 native_runner_factory_.get())); | 455 native_runner_factory_.get())); |
| 451 } | 456 } |
| 452 | 457 |
| 453 void Shell::AddInstanceListener(mojom::InstanceListenerPtr listener) { | 458 void Shell::AddInstanceListener(mojom::InstanceListenerPtr listener) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 for (auto it = native_runners_.begin(); it != native_runners_.end(); ++it) { | 572 for (auto it = native_runners_.begin(); it != native_runners_.end(); ++it) { |
| 568 if (it->get() == runner) { | 573 if (it->get() == runner) { |
| 569 native_runners_.erase(it); | 574 native_runners_.erase(it); |
| 570 return; | 575 return; |
| 571 } | 576 } |
| 572 } | 577 } |
| 573 } | 578 } |
| 574 | 579 |
| 575 } // namespace shell | 580 } // namespace shell |
| 576 } // namespace mojo | 581 } // namespace mojo |
| OLD | NEW |