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.
5 #include "mojo/application_manager/background_shell_application_loader.h"
8 #include "base/run_loop.h"
9 #include "mojo/application_manager/application_manager.h"
13 class BackgroundShellApplicationLoader::BackgroundLoader
{
15 explicit BackgroundLoader(ApplicationLoader
* loader
) : loader_(loader
) {}
16 ~BackgroundLoader() {}
18 void Load(ApplicationManager
* manager
,
20 ScopedMessagePipeHandle shell_handle
) {
21 scoped_refptr
<LoadCallbacks
> callbacks(
22 new ApplicationLoader::SimpleLoadCallbacks(shell_handle
.Pass()));
23 loader_
->Load(manager
, url
, callbacks
);
26 void OnApplicationError(ApplicationManager
* manager
, const GURL
& url
) {
27 loader_
->OnApplicationError(manager
, url
);
31 ApplicationLoader
* loader_
; // Owned by BackgroundShellApplicationLoader
33 DISALLOW_COPY_AND_ASSIGN(BackgroundLoader
);
36 BackgroundShellApplicationLoader::BackgroundShellApplicationLoader(
37 scoped_ptr
<ApplicationLoader
> real_loader
,
38 const std::string
& thread_name
,
39 base::MessageLoop::Type message_loop_type
)
40 : loader_(real_loader
.Pass()),
41 message_loop_type_(message_loop_type
),
42 thread_name_(thread_name
),
43 message_loop_created_(true, false),
44 background_loader_(NULL
) {
47 BackgroundShellApplicationLoader::~BackgroundShellApplicationLoader() {
52 void BackgroundShellApplicationLoader::Load(
53 ApplicationManager
* manager
,
55 scoped_refptr
<LoadCallbacks
> callbacks
) {
56 ScopedMessagePipeHandle shell_handle
= callbacks
->RegisterApplication();
57 if (!shell_handle
.is_valid())
61 // TODO(tim): It'd be nice if we could just have each Load call
62 // result in a new thread like DynamicService{Loader, Runner}. But some
63 // loaders are creating multiple ApplicationImpls (NetworkApplicationLoader)
64 // sharing a delegate (etc). So we have to keep it single threaded, wait
65 // for the thread to initialize, and post to the TaskRunner for subsequent
66 // Load calls for now.
67 thread_
.reset(new base::DelegateSimpleThread(this, thread_name_
));
69 message_loop_created_
.Wait();
70 DCHECK(task_runner_
.get());
73 task_runner_
->PostTask(
76 &BackgroundShellApplicationLoader::LoadOnBackgroundThread
,
77 base::Unretained(this),
80 base::Owned(new ScopedMessagePipeHandle(shell_handle
.Pass()))));
83 void BackgroundShellApplicationLoader::OnApplicationError(
84 ApplicationManager
* manager
,
86 task_runner_
->PostTask(FROM_HERE
,
87 base::Bind(&BackgroundShellApplicationLoader::
88 OnApplicationErrorOnBackgroundThread
,
89 base::Unretained(this),
94 void BackgroundShellApplicationLoader::Run() {
95 base::MessageLoop
message_loop(message_loop_type_
);
97 task_runner_
= message_loop
.task_runner();
98 quit_closure_
= loop
.QuitClosure();
99 message_loop_created_
.Signal();
102 delete background_loader_
;
103 background_loader_
= NULL
;
104 // Destroy |loader_| on the thread it's actually used on.
108 void BackgroundShellApplicationLoader::LoadOnBackgroundThread(
109 ApplicationManager
* manager
,
111 ScopedMessagePipeHandle
* shell_handle
) {
112 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
113 if (!background_loader_
)
114 background_loader_
= new BackgroundLoader(loader_
.get());
115 background_loader_
->Load(manager
, url
, shell_handle
->Pass());
118 void BackgroundShellApplicationLoader::OnApplicationErrorOnBackgroundThread(
119 ApplicationManager
* manager
,
121 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
122 if (!background_loader_
)
123 background_loader_
= new BackgroundLoader(loader_
.get());
124 background_loader_
->OnApplicationError(manager
, url
);