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/service_manager/background_shell_service_loader.h"
8 #include "base/run_loop.h"
9 #include "mojo/service_manager/service_manager.h"
13 class BackgroundShellServiceLoader::BackgroundLoader
{
15 explicit BackgroundLoader(ServiceLoader
* loader
) : loader_(loader
) {}
16 ~BackgroundLoader() {}
18 void LoadService(ServiceManager
* manager
,
20 ScopedMessagePipeHandle shell_handle
) {
21 loader_
->LoadService(manager
, url
, shell_handle
.Pass());
24 void OnServiceError(ServiceManager
* manager
, const GURL
& url
) {
25 loader_
->OnServiceError(manager
, url
);
29 ServiceLoader
* loader_
; // Owned by BackgroundShellServiceLoader
31 DISALLOW_COPY_AND_ASSIGN(BackgroundLoader
);
34 BackgroundShellServiceLoader::BackgroundShellServiceLoader(
35 scoped_ptr
<ServiceLoader
> real_loader
,
36 const std::string
& thread_name
,
37 base::MessageLoop::Type message_loop_type
)
38 : loader_(real_loader
.Pass()),
39 message_loop_type_(message_loop_type
),
40 thread_name_(thread_name
),
41 message_loop_created_(true, false),
42 background_loader_(NULL
) {
45 BackgroundShellServiceLoader::~BackgroundShellServiceLoader() {
50 void BackgroundShellServiceLoader::LoadService(
51 ServiceManager
* manager
,
53 ScopedMessagePipeHandle shell_handle
) {
55 // TODO(tim): It'd be nice if we could just have each LoadService call
56 // result in a new thread like DynamicService{Loader, Runner}. But some
57 // loaders are creating multiple ApplicationImpls (NetworkServiceLoader)
58 // sharing a delegate (etc). So we have to keep it single threaded, wait
59 // for the thread to initialize, and post to the TaskRunner for subsequent
60 // LoadService calls for now.
61 thread_
.reset(new base::DelegateSimpleThread(this, thread_name_
));
63 message_loop_created_
.Wait();
67 task_runner_
->PostTask(FROM_HERE
,
68 base::Bind(&BackgroundShellServiceLoader::LoadServiceOnBackgroundThread
,
69 base::Unretained(this), manager
, url
,
71 new ScopedMessagePipeHandle(shell_handle
.Pass()))));
74 void BackgroundShellServiceLoader::OnServiceError(
75 ServiceManager
* manager
, const GURL
& url
) {
76 task_runner_
->PostTask(FROM_HERE
,
78 &BackgroundShellServiceLoader::OnServiceErrorOnBackgroundThread
,
79 base::Unretained(this), manager
, url
));
82 void BackgroundShellServiceLoader::Run() {
83 base::MessageLoop
message_loop(message_loop_type_
);
85 task_runner_
= message_loop
.task_runner();
86 quit_closure_
= loop
.QuitClosure();
87 message_loop_created_
.Signal();
90 delete background_loader_
;
91 background_loader_
= NULL
;
92 // Destroy |loader_| on the thread it's actually used on.
96 void BackgroundShellServiceLoader::LoadServiceOnBackgroundThread(
97 ServiceManager
* manager
,
99 ScopedMessagePipeHandle
* shell_handle
) {
100 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
101 if (!background_loader_
)
102 background_loader_
= new BackgroundLoader(loader_
.get());
103 background_loader_
->LoadService(manager
, url
, shell_handle
->Pass());
106 void BackgroundShellServiceLoader::OnServiceErrorOnBackgroundThread(
107 ServiceManager
* manager
, const GURL
& url
) {
108 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
109 if (!background_loader_
)
110 background_loader_
= new BackgroundLoader(loader_
.get());
111 background_loader_
->OnServiceError(manager
, url
);