OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "mojo/shell/application_manager.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <utility> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/command_line.h" | |
13 #include "base/logging.h" | |
14 #include "base/macros.h" | |
15 #include "base/process/process.h" | |
16 #include "base/process/process_handle.h" | |
17 #include "base/stl_util.h" | |
18 #include "base/strings/string_util.h" | |
19 #include "base/trace_event/trace_event.h" | |
20 #include "mojo/common/url_type_converters.h" | |
21 #include "mojo/public/cpp/bindings/binding.h" | |
22 #include "mojo/public/cpp/bindings/binding_set.h" | |
23 #include "mojo/services/package_manager/loader.h" | |
24 #include "mojo/shell/connect_util.h" | |
25 #include "mojo/shell/public/cpp/connect.h" | |
26 #include "mojo/shell/public/cpp/names.h" | |
27 #include "mojo/shell/public/cpp/shell_connection.h" | |
28 #include "mojo/shell/public/interfaces/application_manager.mojom.h" | |
29 #include "mojo/shell/public/interfaces/shell.mojom.h" | |
30 #include "mojo/shell/public/interfaces/shell_client.mojom.h" | |
31 #include "mojo/util/filename_util.h" | |
32 | |
33 namespace mojo { | |
34 namespace shell { | |
35 namespace { | |
36 const char kPackageManagerName[] = "mojo:package_manager"; | |
37 | |
38 void EmptyResolverCallback(const String& resolved_name, | |
39 const String& resolved_qualifier, | |
40 mojom::CapabilityFilterPtr base_filter, | |
41 const String& file_url) {} | |
42 | |
43 } | |
44 | |
45 // Encapsulates a connection to an instance of an application, tracked by the | |
46 // shell's ApplicationManager. | |
47 class ApplicationManager::Instance | |
48 : public mojom::Connector, | |
49 public mojom::PIDReceiver, | |
50 public ShellClient, | |
51 public InterfaceFactory<mojom::ApplicationManager>, | |
52 public mojom::ApplicationManager { | |
53 public: | |
54 Instance(mojom::ShellClientPtr shell_client, | |
55 mojo::shell::ApplicationManager* manager, | |
56 const Identity& identity) | |
57 : manager_(manager), | |
58 id_(GenerateUniqueID()), | |
59 identity_(identity), | |
60 allow_any_application_(identity.filter().size() == 1 && | |
61 identity.filter().count("*") == 1), | |
62 shell_client_(std::move(shell_client)), | |
63 pid_receiver_binding_(this), | |
64 weak_factory_(this) { | |
65 if (identity_.name() == "mojo:shell" || | |
66 manager_->GetLoaderForName(identity_.name())) { | |
67 pid_ = base::Process::Current().Pid(); | |
68 } | |
69 DCHECK_NE(kInvalidApplicationID, id_); | |
70 } | |
71 | |
72 ~Instance() override {} | |
73 | |
74 void InitializeClient() { | |
75 shell_client_->Initialize(connectors_.CreateInterfacePtrAndBind(this), | |
76 identity_.name(), id_, identity_.user_id()); | |
77 connectors_.set_connection_error_handler( | |
78 base::Bind(&mojo::shell::ApplicationManager::OnInstanceError, | |
79 base::Unretained(manager_), base::Unretained(this))); | |
80 } | |
81 | |
82 void ConnectToClient(scoped_ptr<ConnectParams> params) { | |
83 params->connect_callback().Run(id_, identity_.user_id()); | |
84 AllowedInterfaces interfaces; | |
85 interfaces.insert("*"); | |
86 if (!params->source().is_null()) | |
87 interfaces = GetAllowedInterfaces(params->source().filter(), identity_); | |
88 | |
89 Instance* source = manager_->GetExistingInstance(params->source()); | |
90 uint32_t source_id = source ? source->id() : kInvalidApplicationID; | |
91 shell_client_->AcceptConnection( | |
92 params->source().name(), source_id, params->source().user_id(), | |
93 params->TakeRemoteInterfaces(), params->TakeLocalInterfaces(), | |
94 Array<String>::From(interfaces), params->target().name()); | |
95 } | |
96 | |
97 scoped_ptr<NativeRunner> StartWithFileURL(const GURL& file_url, | |
98 mojom::ShellClientRequest request, | |
99 bool start_sandboxed, | |
100 NativeRunnerFactory* factory) { | |
101 base::FilePath path = util::UrlToFilePath(file_url); | |
102 scoped_ptr<NativeRunner> runner = factory->Create(path); | |
103 runner_ = runner.get(); | |
104 runner_->Start(path, identity_, start_sandboxed, std::move(request), | |
105 base::Bind(&Instance::PIDAvailable, | |
106 weak_factory_.GetWeakPtr()), | |
107 base::Bind(&mojo::shell::ApplicationManager::CleanupRunner, | |
108 manager_->weak_ptr_factory_.GetWeakPtr(), | |
109 runner_)); | |
110 return runner; | |
111 } | |
112 | |
113 scoped_ptr<NativeRunner> StartWithFactory( | |
114 mojom::ShellClientFactoryPtr shell_client_factory, | |
115 const String& name, | |
116 mojom::ShellClientRequest request, | |
117 mojom::PIDReceiverRequest pid_receiver_request, | |
118 NativeRunnerFactory* factory) { | |
119 pid_receiver_binding_.Bind(std::move(pid_receiver_request)); | |
120 scoped_ptr<NativeRunner> runner = factory->Create(base::FilePath()); | |
121 runner_ = runner.get(); | |
122 runner_->InitHost(std::move(shell_client_factory), name, | |
123 std::move(request)); | |
124 return runner; | |
125 } | |
126 | |
127 mojom::InstanceInfoPtr CreateInstanceInfo() const { | |
128 mojom::InstanceInfoPtr info(mojom::InstanceInfo::New()); | |
129 info->id = id_; | |
130 info->name = identity_.name(); | |
131 info->qualifier = identity_.qualifier(); | |
132 info->pid = pid_; | |
133 return info; | |
134 } | |
135 | |
136 const Identity& identity() const { return identity_; } | |
137 uint32_t id() const { return id_; } | |
138 | |
139 // ShellClient: | |
140 bool AcceptConnection(Connection* connection) override { | |
141 connection->AddInterface<mojom::ApplicationManager>(this); | |
142 return true; | |
143 } | |
144 | |
145 private: | |
146 // mojom::Connector implementation: | |
147 void Connect(const String& app_name, | |
148 uint32_t user_id, | |
149 shell::mojom::InterfaceProviderRequest remote_interfaces, | |
150 shell::mojom::InterfaceProviderPtr local_interfaces, | |
151 const ConnectCallback& callback) override { | |
152 // TODO(beng): perform checking on policy of whether this instance is | |
153 // allowed to pass different user_ids. | |
154 if (!IsValidName(app_name)) { | |
155 LOG(ERROR) << "Error: invalid Name: " << app_name; | |
156 callback.Run(kInvalidApplicationID, kUserInherit); | |
157 return; | |
158 } | |
159 if (allow_any_application_ || | |
160 identity_.filter().find(app_name) != identity_.filter().end()) { | |
161 scoped_ptr<ConnectParams> params(new ConnectParams); | |
162 params->set_source(identity_); | |
163 params->set_target(Identity(app_name, std::string(), user_id)); | |
164 params->set_remote_interfaces(std::move(remote_interfaces)); | |
165 params->set_local_interfaces(std::move(local_interfaces)); | |
166 params->set_connect_callback(callback); | |
167 manager_->Connect(std::move(params)); | |
168 } | |
169 else { | |
170 LOG(WARNING) << "CapabilityFilter prevented connection from: " << | |
171 identity_.name() << " to: " << app_name; | |
172 callback.Run(kInvalidApplicationID, kUserInherit); | |
173 } | |
174 } | |
175 void Clone(mojom::ConnectorRequest request) override { | |
176 connectors_.AddBinding(this, std::move(request)); | |
177 } | |
178 | |
179 // mojom::PIDReceiver: | |
180 void SetPID(uint32_t pid) override { | |
181 PIDAvailable(pid); | |
182 } | |
183 | |
184 // InterfaceFactory<mojom::ApplicationManager>: | |
185 void Create(Connection* connection, | |
186 mojom::ApplicationManagerRequest request) override { | |
187 application_manager_bindings_.AddBinding(this, std::move(request)); | |
188 } | |
189 | |
190 // mojom::ApplicationManager implementation: | |
191 void CreateInstanceForFactory( | |
192 mojom::ShellClientFactoryPtr factory, | |
193 const String& name, | |
194 uint32_t user_id, | |
195 mojom::CapabilityFilterPtr filter, | |
196 mojom::PIDReceiverRequest pid_receiver) override { | |
197 // TODO(beng): perform checking on policy of whether this instance is | |
198 // allowed to pass different user_ids. | |
199 if (user_id == mojom::Connector::kUserInherit) | |
200 user_id = identity_.user_id(); | |
201 manager_->CreateInstanceForFactory(std::move(factory), name, user_id, | |
202 std::move(filter), | |
203 std::move(pid_receiver)); | |
204 } | |
205 void AddInstanceListener(mojom::InstanceListenerPtr listener) override { | |
206 // TODO(beng): this should only track the instances matching this user, and | |
207 // root. | |
208 manager_->AddInstanceListener(std::move(listener)); | |
209 } | |
210 | |
211 uint32_t GenerateUniqueID() const { | |
212 static uint32_t id = kInvalidApplicationID; | |
213 ++id; | |
214 CHECK_NE(kInvalidApplicationID, id); | |
215 return id; | |
216 } | |
217 | |
218 void PIDAvailable(base::ProcessId pid) { | |
219 pid_ = pid; | |
220 manager_->NotifyPIDAvailable(id_, pid_); | |
221 } | |
222 | |
223 mojo::shell::ApplicationManager* const manager_; | |
224 // An id that identifies this instance. Distinct from pid, as a single process | |
225 // may vend multiple application instances, and this object may exist before a | |
226 // process is launched. | |
227 const uint32_t id_; | |
228 const Identity identity_; | |
229 const bool allow_any_application_; | |
230 mojom::ShellClientPtr shell_client_; | |
231 Binding<mojom::PIDReceiver> pid_receiver_binding_; | |
232 BindingSet<mojom::Connector> connectors_; | |
233 BindingSet<mojom::ApplicationManager> application_manager_bindings_; | |
234 NativeRunner* runner_ = nullptr; | |
235 base::ProcessId pid_ = base::kNullProcessId; | |
236 base::WeakPtrFactory<Instance> weak_factory_; | |
237 | |
238 DISALLOW_COPY_AND_ASSIGN(Instance); | |
239 }; | |
240 | |
241 // static | |
242 ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager) | |
243 : manager_(manager) { | |
244 } | |
245 | |
246 ApplicationManager::TestAPI::~TestAPI() { | |
247 } | |
248 | |
249 bool ApplicationManager::TestAPI::HasRunningInstanceForName( | |
250 const std::string& name) const { | |
251 return manager_->identity_to_instance_.find(Identity(name)) != | |
252 manager_->identity_to_instance_.end(); | |
253 } | |
254 | |
255 //////////////////////////////////////////////////////////////////////////////// | |
256 // ApplicationManager, public: | |
257 | |
258 ApplicationManager::ApplicationManager( | |
259 scoped_ptr<NativeRunnerFactory> native_runner_factory, | |
260 base::TaskRunner* file_task_runner, | |
261 scoped_ptr<package_manager::ApplicationCatalogStore> app_catalog) | |
262 : file_task_runner_(file_task_runner), | |
263 native_runner_factory_(std::move(native_runner_factory)), | |
264 weak_ptr_factory_(this) { | |
265 mojom::ShellClientRequest request; | |
266 CreateInstance(CreateShellIdentity(), &request); | |
267 shell_connection_.reset(new ShellConnection(this, std::move(request))); | |
268 | |
269 InitPackageManager(std::move(app_catalog)); | |
270 } | |
271 | |
272 ApplicationManager::~ApplicationManager() { | |
273 TerminateShellConnections(); | |
274 STLDeleteValues(&name_to_loader_); | |
275 for (auto& runner : native_runners_) | |
276 runner.reset(); | |
277 } | |
278 | |
279 void ApplicationManager::SetInstanceQuitCallback( | |
280 base::Callback<void(const Identity&)> callback) { | |
281 instance_quit_callback_ = callback; | |
282 } | |
283 | |
284 void ApplicationManager::Connect(scoped_ptr<ConnectParams> params) { | |
285 TRACE_EVENT_INSTANT1("mojo_shell", "ApplicationManager::Connect", | |
286 TRACE_EVENT_SCOPE_THREAD, "original_name", | |
287 params->target().name()); | |
288 DCHECK(IsValidName(params->target().name())); | |
289 | |
290 if (params->target().user_id() == mojom::Connector::kUserInherit) { | |
291 Instance* source = GetExistingInstance(params->source()); | |
292 Identity target = params->target(); | |
293 // TODO(beng): we should CHECK source. | |
294 target.set_user_id(source ? source->identity().user_id() | |
295 : mojom::Connector::kUserRoot); | |
296 params->set_target(target); | |
297 } | |
298 | |
299 // Connect to an existing matching instance, if possible. | |
300 if (ConnectToExistingInstance(¶ms)) | |
301 return; | |
302 | |
303 std::string name = params->target().name(); | |
304 shell_resolver_->ResolveMojoName( | |
305 name, | |
306 base::Bind(&ApplicationManager::OnGotResolvedName, | |
307 weak_ptr_factory_.GetWeakPtr(), base::Passed(¶ms))); | |
308 } | |
309 | |
310 mojom::ShellClientRequest ApplicationManager::InitInstanceForEmbedder( | |
311 const std::string& name) { | |
312 DCHECK(!embedder_instance_); | |
313 | |
314 mojo::shell::Identity target(name, std::string(), | |
315 mojom::Connector::kUserRoot); | |
316 target.set_filter(GetPermissiveCapabilityFilter()); | |
317 DCHECK(!GetExistingInstance(target)); | |
318 | |
319 mojom::ShellClientRequest request; | |
320 embedder_instance_ = CreateInstance(target, &request); | |
321 DCHECK(embedder_instance_); | |
322 | |
323 return request; | |
324 } | |
325 | |
326 void ApplicationManager::SetLoaderForName(scoped_ptr<Loader> loader, | |
327 const std::string& name) { | |
328 NameToLoaderMap::iterator it = name_to_loader_.find(name); | |
329 if (it != name_to_loader_.end()) | |
330 delete it->second; | |
331 name_to_loader_[name] = loader.release(); | |
332 } | |
333 | |
334 //////////////////////////////////////////////////////////////////////////////// | |
335 // ApplicationManager, ShellClient implementation: | |
336 | |
337 bool ApplicationManager::AcceptConnection(Connection* connection) { | |
338 // The only interface we expose is mojom::ApplicationManager, and access to | |
339 // this interface is brokered by a policy specific to each caller, managed by | |
340 // the caller's instance. Here we look to see who's calling, and forward to | |
341 // the caller's instance to continue. | |
342 uint32_t caller_instance_id = mojom::Connector::kInvalidApplicationID; | |
343 CHECK(connection->GetRemoteApplicationID(&caller_instance_id)); | |
344 Instance* instance = nullptr; | |
345 for (const auto& entry : identity_to_instance_) { | |
346 if (entry.second->id() == caller_instance_id) { | |
347 instance = entry.second; | |
348 break; | |
349 } | |
350 } | |
351 DCHECK(instance); | |
352 return instance->AcceptConnection(connection); | |
353 } | |
354 | |
355 //////////////////////////////////////////////////////////////////////////////// | |
356 // ApplicationManager, private: | |
357 | |
358 void ApplicationManager::InitPackageManager( | |
359 scoped_ptr<package_manager::ApplicationCatalogStore> app_catalog) { | |
360 scoped_ptr<Loader> loader( | |
361 new package_manager::Loader(file_task_runner_, std::move(app_catalog))); | |
362 Loader* loader_raw = loader.get(); | |
363 std::string name = kPackageManagerName; | |
364 SetLoaderForName(std::move(loader), name); | |
365 | |
366 mojom::ShellClientRequest request; | |
367 CreateInstance(Identity(name), &request); | |
368 loader_raw->Load(name, std::move(request)); | |
369 | |
370 ConnectToInterface(this, CreateShellIdentity(), name, &shell_resolver_); | |
371 | |
372 // Seed the catalog with manifest info for the shell & package manager. | |
373 if (file_task_runner_) { | |
374 shell_resolver_->ResolveMojoName(name, base::Bind(&EmptyResolverCallback)); | |
375 shell_resolver_->ResolveMojoName("mojo:shell", | |
376 base::Bind(&EmptyResolverCallback)); | |
377 } | |
378 } | |
379 | |
380 void ApplicationManager::TerminateShellConnections() { | |
381 STLDeleteValues(&identity_to_instance_); | |
382 } | |
383 | |
384 void ApplicationManager::OnInstanceError(Instance* instance) { | |
385 const Identity identity = instance->identity(); | |
386 // Remove the shell. | |
387 auto it = identity_to_instance_.find(identity); | |
388 DCHECK(it != identity_to_instance_.end()); | |
389 int id = instance->id(); | |
390 delete it->second; | |
391 identity_to_instance_.erase(it); | |
392 instance_listeners_.ForAllPtrs([this, id](mojom::InstanceListener* listener) { | |
393 listener->InstanceDestroyed(id); | |
394 }); | |
395 if (!instance_quit_callback_.is_null()) | |
396 instance_quit_callback_.Run(identity); | |
397 } | |
398 | |
399 ApplicationManager::Instance* ApplicationManager::GetExistingInstance( | |
400 const Identity& identity) const { | |
401 const auto& it = identity_to_instance_.find(identity); | |
402 return it != identity_to_instance_.end() ? it->second : nullptr; | |
403 } | |
404 | |
405 void ApplicationManager::NotifyPIDAvailable(uint32_t id, base::ProcessId pid) { | |
406 instance_listeners_.ForAllPtrs([id, pid](mojom::InstanceListener* listener) { | |
407 listener->InstancePIDAvailable(id, pid); | |
408 }); | |
409 } | |
410 | |
411 bool ApplicationManager::ConnectToExistingInstance( | |
412 scoped_ptr<ConnectParams>* params) { | |
413 Instance* instance = GetExistingInstance((*params)->target()); | |
414 if (!instance) { | |
415 Identity root_identity = (*params)->target(); | |
416 root_identity.set_user_id(mojom::Connector::kUserRoot); | |
417 instance = GetExistingInstance(root_identity); | |
418 if (!instance) return false; | |
419 } | |
420 instance->ConnectToClient(std::move(*params)); | |
421 return true; | |
422 } | |
423 | |
424 ApplicationManager::Instance* ApplicationManager::CreateInstance( | |
425 const Identity& target_id, | |
426 mojom::ShellClientRequest* request) { | |
427 mojom::ShellClientPtr shell_client; | |
428 *request = GetProxy(&shell_client); | |
429 Instance* instance = new Instance(std::move(shell_client), this, target_id); | |
430 DCHECK(identity_to_instance_.find(target_id) == | |
431 identity_to_instance_.end()); | |
432 identity_to_instance_[target_id] = instance; | |
433 mojom::InstanceInfoPtr info = instance->CreateInstanceInfo(); | |
434 instance_listeners_.ForAllPtrs( | |
435 [this, &info](mojom::InstanceListener* listener) { | |
436 listener->InstanceCreated(info.Clone()); | |
437 }); | |
438 instance->InitializeClient(); | |
439 return instance; | |
440 } | |
441 | |
442 void ApplicationManager::CreateInstanceForFactory( | |
443 mojom::ShellClientFactoryPtr factory, | |
444 const String& name, | |
445 uint32_t user_id, | |
446 mojom::CapabilityFilterPtr filter, | |
447 mojom::PIDReceiverRequest pid_receiver) { | |
448 DCHECK(user_id != mojom::Connector::kUserInherit); | |
449 // We don't call ConnectToClient() here since the instance was created | |
450 // manually by other code, not in response to a Connect() request. The newly | |
451 // created instance is identified by |name| and may be subsequently reached by | |
452 // client code using this identity. | |
453 Identity target_id(name, std::string(), mojom::Connector::kUserRoot); | |
454 target_id.set_filter(filter->filter.To<CapabilityFilter>()); | |
455 mojom::ShellClientRequest request; | |
456 Instance* instance = CreateInstance(target_id, &request); | |
457 native_runners_.push_back( | |
458 instance->StartWithFactory(std::move(factory), name, std::move(request), | |
459 std::move(pid_receiver), | |
460 native_runner_factory_.get())); | |
461 } | |
462 | |
463 void ApplicationManager::AddInstanceListener( | |
464 mojom::InstanceListenerPtr listener) { | |
465 // TODO(beng): filter instances provided by those visible to this client. | |
466 Array<mojom::InstanceInfoPtr> instances; | |
467 for (auto& instance : identity_to_instance_) | |
468 instances.push_back(instance.second->CreateInstanceInfo()); | |
469 listener->SetExistingInstances(std::move(instances)); | |
470 | |
471 instance_listeners_.AddInterfacePtr(std::move(listener)); | |
472 } | |
473 | |
474 void ApplicationManager::CreateShellClient( | |
475 const Identity& source, | |
476 const Identity& shell_client_factory, | |
477 const std::string& name, | |
478 mojom::ShellClientRequest request) { | |
479 mojom::ShellClientFactory* factory = | |
480 GetShellClientFactory(shell_client_factory, source); | |
481 factory->CreateShellClient(std::move(request), name); | |
482 } | |
483 | |
484 mojom::ShellClientFactory* ApplicationManager::GetShellClientFactory( | |
485 const Identity& shell_client_factory_identity, | |
486 const Identity& source_identity) { | |
487 auto it = shell_client_factories_.find(shell_client_factory_identity); | |
488 if (it != shell_client_factories_.end()) | |
489 return it->second.get(); | |
490 | |
491 mojom::ShellClientFactoryPtr factory; | |
492 // TODO(beng): we should forward the original source identity! | |
493 ConnectToInterface(this, source_identity, shell_client_factory_identity, | |
494 &factory); | |
495 mojom::ShellClientFactory* factory_interface = factory.get(); | |
496 factory.set_connection_error_handler( | |
497 base::Bind(&ApplicationManager::OnShellClientFactoryLost, | |
498 weak_ptr_factory_.GetWeakPtr(), | |
499 shell_client_factory_identity)); | |
500 shell_client_factories_[shell_client_factory_identity] = std::move(factory); | |
501 return factory_interface; | |
502 } | |
503 | |
504 void ApplicationManager::OnShellClientFactoryLost(const Identity& which) { | |
505 // Remove the mapping. | |
506 auto it = shell_client_factories_.find(which); | |
507 DCHECK(it != shell_client_factories_.end()); | |
508 shell_client_factories_.erase(it); | |
509 } | |
510 | |
511 void ApplicationManager::OnGotResolvedName( | |
512 scoped_ptr<ConnectParams> params, | |
513 const String& resolved_name, | |
514 const String& resolved_qualifier, | |
515 mojom::CapabilityFilterPtr base_filter, | |
516 const String& file_url) { | |
517 std::string qualifier = params->target().qualifier(); | |
518 if (qualifier == GetNamePath(params->target().name())) | |
519 qualifier = resolved_qualifier; | |
520 Identity target(params->target().name(), qualifier, | |
521 params->target().user_id()); | |
522 params->set_target(target); | |
523 | |
524 // It's possible that when this manifest request was issued, another one was | |
525 // already in-progress and completed by the time this one did, and so the | |
526 // requested application may already be running. | |
527 if (ConnectToExistingInstance(¶ms)) | |
528 return; | |
529 | |
530 Identity source = params->source(); | |
531 // |base_filter| can be null when there is no manifest, e.g. for URL types | |
532 // not resolvable by the resolver. | |
533 CapabilityFilter filter = GetPermissiveCapabilityFilter(); | |
534 if (!base_filter.is_null()) | |
535 filter = base_filter->filter.To<CapabilityFilter>(); | |
536 target.set_filter(filter); | |
537 | |
538 mojom::ShellClientRequest request; | |
539 Instance* instance = CreateInstance(target, &request); | |
540 instance->ConnectToClient(std::move(params)); | |
541 | |
542 if (LoadWithLoader(target, &request)) | |
543 return; | |
544 | |
545 CHECK(!file_url.is_null() && !base_filter.is_null()); | |
546 | |
547 if (target.name() != resolved_name) { | |
548 // In cases where a package alias is resolved, we have to use the qualifier | |
549 // from the original request rather than for the package itself, which will | |
550 // always be the same. | |
551 CreateShellClient( | |
552 source, Identity(resolved_name, resolved_qualifier, target.user_id()), | |
553 target.name(), std::move(request)); | |
554 } else { | |
555 bool start_sandboxed = false; | |
556 native_runners_.push_back( | |
557 instance->StartWithFileURL(file_url.To<GURL>(), std::move(request), | |
558 start_sandboxed, | |
559 native_runner_factory_.get())); | |
560 } | |
561 } | |
562 | |
563 bool ApplicationManager::LoadWithLoader(const Identity& target, | |
564 mojom::ShellClientRequest* request) { | |
565 Loader* loader = GetLoaderForName(target.name()); | |
566 if (!loader) | |
567 return false; | |
568 loader->Load(target.name(), std::move(*request)); | |
569 return true; | |
570 } | |
571 | |
572 Loader* ApplicationManager::GetLoaderForName(const std::string& name) { | |
573 auto name_it = name_to_loader_.find(name); | |
574 if (name_it != name_to_loader_.end()) | |
575 return name_it->second; | |
576 return default_loader_.get(); | |
577 } | |
578 | |
579 void ApplicationManager::CleanupRunner(NativeRunner* runner) { | |
580 for (auto it = native_runners_.begin(); it != native_runners_.end(); ++it) { | |
581 if (it->get() == runner) { | |
582 native_runners_.erase(it); | |
583 return; | |
584 } | |
585 } | |
586 } | |
587 | |
588 } // namespace shell | |
589 } // namespace mojo | |
OLD | NEW |