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 |