Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: mojo/service_manager/background_shell_service_loader.cc

Issue 437493002: mojo: allow BackgroundServiceLoader-loaded apps to Quit themselves. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/service_manager/background_service_loader.h" 5 #include "mojo/service_manager/background_shell_service_loader.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/run_loop.h"
8 #include "mojo/service_manager/service_manager.h" 9 #include "mojo/service_manager/service_manager.h"
9 10
10 namespace mojo { 11 namespace mojo {
11 12
12 class BackgroundServiceLoader::BackgroundLoader { 13 class BackgroundShellServiceLoader::BackgroundLoader {
13 public: 14 public:
14 explicit BackgroundLoader(ServiceLoader* loader) : loader_(loader) {} 15 explicit BackgroundLoader(ServiceLoader* loader) : loader_(loader) {}
15 ~BackgroundLoader() {} 16 ~BackgroundLoader() {}
16 17
17 void LoadService(ServiceManager* manager, 18 void LoadService(ServiceManager* manager,
18 const GURL& url, 19 const GURL& url,
19 ScopedMessagePipeHandle shell_handle) { 20 ScopedMessagePipeHandle shell_handle) {
20 loader_->LoadService(manager, url, shell_handle.Pass()); 21 loader_->LoadService(manager, url, shell_handle.Pass());
21 } 22 }
22 23
23 void OnServiceError(ServiceManager* manager, const GURL& url) { 24 void OnServiceError(ServiceManager* manager, const GURL& url) {
24 loader_->OnServiceError(manager, url); 25 loader_->OnServiceError(manager, url);
25 } 26 }
26 27
27 private: 28 private:
28 base::MessageLoop::Type message_loop_type_; 29 ServiceLoader* loader_; // Owned by BackgroundShellServiceLoader
29 ServiceLoader* loader_; // Owned by BackgroundServiceLoader
30 30
31 DISALLOW_COPY_AND_ASSIGN(BackgroundLoader); 31 DISALLOW_COPY_AND_ASSIGN(BackgroundLoader);
32 }; 32 };
33 33
34 BackgroundServiceLoader::BackgroundServiceLoader( 34 BackgroundShellServiceLoader::BackgroundShellServiceLoader(
35 scoped_ptr<ServiceLoader> real_loader, 35 scoped_ptr<ServiceLoader> real_loader,
36 const char* thread_name, 36 const std::string& thread_name,
37 base::MessageLoop::Type message_loop_type) 37 base::MessageLoop::Type message_loop_type)
38 : loader_(real_loader.Pass()), 38 : quit_on_shutdown_(false),
39 thread_(thread_name), 39 loader_(real_loader.Pass()),
40 message_loop_type_(message_loop_type), 40 message_loop_type_(message_loop_type),
41 thread_name_(thread_name),
42 message_loop_created_(true, false),
41 background_loader_(NULL) { 43 background_loader_(NULL) {
42 } 44 }
43 45
44 BackgroundServiceLoader::~BackgroundServiceLoader() { 46 BackgroundShellServiceLoader::~BackgroundShellServiceLoader() {
45 if (thread_.IsRunning()) { 47 if (thread_) {
46 thread_.message_loop()->PostTask( 48 if (quit_on_shutdown_)
47 FROM_HERE, 49 task_runner_->PostTask(FROM_HERE, quit_closure_);
48 base::Bind(&BackgroundServiceLoader::ShutdownOnBackgroundThread, 50 thread_->Join();
49 base::Unretained(this)));
50 } 51 }
51 thread_.Stop();
52 } 52 }
53 53
54 void BackgroundServiceLoader::LoadService( 54 void BackgroundShellServiceLoader::LoadService(
55 ServiceManager* manager, 55 ServiceManager* manager,
56 const GURL& url, 56 const GURL& url,
57 ScopedMessagePipeHandle shell_handle) { 57 ScopedMessagePipeHandle shell_handle) {
58 const int kDefaultStackSize = 0; 58 if (!thread_) {
59 if (!thread_.IsRunning()) { 59 // TODO(tim): It'd be nice if we could just have each LoadService call
60 thread_.StartWithOptions( 60 // result in a new thread like DynamicService{Loader, Runner}. But some
61 base::Thread::Options(message_loop_type_, kDefaultStackSize)); 61 // loaders are creating multiple ApplicationImpls (NetworkServiceLoader)
62 // sharing a delegate (etc). So we have to keep it single threaded, wait
63 // for the thread to initialize, and post to the TaskRunner for subsequent
64 // LoadService calls for now.
65 thread_.reset(new base::DelegateSimpleThread(this, thread_name_));
66 thread_->Start();
67 message_loop_created_.Wait();
68 DCHECK(task_runner_);
62 } 69 }
63 thread_.message_loop()->PostTask( 70
64 FROM_HERE, 71 task_runner_->PostTask(FROM_HERE,
65 base::Bind(&BackgroundServiceLoader::LoadServiceOnBackgroundThread, 72 base::Bind(&BackgroundShellServiceLoader::LoadServiceOnBackgroundThread,
66 base::Unretained(this), manager, url, 73 base::Unretained(this), manager, url,
67 base::Owned( 74 base::Owned(
68 new ScopedMessagePipeHandle(shell_handle.Pass())))); 75 new ScopedMessagePipeHandle(shell_handle.Pass()))));
69 } 76 }
70 77
71 void BackgroundServiceLoader::OnServiceError(ServiceManager* manager, 78 void BackgroundShellServiceLoader::OnServiceError(
72 const GURL& url) { 79 ServiceManager* manager, const GURL& url) {
73 if (!thread_.IsRunning()) 80 task_runner_->PostTask(FROM_HERE,
74 thread_.Start(); 81 base::Bind(
75 thread_.message_loop()->PostTask( 82 &BackgroundShellServiceLoader::OnServiceErrorOnBackgroundThread,
76 FROM_HERE, 83 base::Unretained(this), manager, url));
77 base::Bind(&BackgroundServiceLoader::OnServiceErrorOnBackgroundThread,
78 base::Unretained(this), manager, url));
79 } 84 }
80 85
81 void BackgroundServiceLoader::LoadServiceOnBackgroundThread( 86 void BackgroundShellServiceLoader::Run() {
82 ServiceManager* manager, 87 base::MessageLoop message_loop(message_loop_type_);
83 const GURL& url, 88 base::RunLoop loop;
84 ScopedMessagePipeHandle* shell_handle) { 89 task_runner_ = message_loop.task_runner();
90 quit_closure_ = loop.QuitClosure();
91 message_loop_created_.Signal();
92 loop.Run();
93
94 delete background_loader_;
95 background_loader_ = NULL;
96 // Destroy |loader_| on the thread it's actually used on.
97 loader_.reset();
98 }
99
100 void BackgroundShellServiceLoader::LoadServiceOnBackgroundThread(
101 ServiceManager* manager,
102 const GURL& url,
103 ScopedMessagePipeHandle* shell_handle) {
104 DCHECK(task_runner_->RunsTasksOnCurrentThread());
85 if (!background_loader_) 105 if (!background_loader_)
86 background_loader_ = new BackgroundLoader(loader_.get()); 106 background_loader_ = new BackgroundLoader(loader_.get());
87 background_loader_->LoadService( 107 background_loader_->LoadService(manager, url, shell_handle->Pass());
88 manager, url, shell_handle->Pass());
89 } 108 }
90 109
91 void BackgroundServiceLoader::OnServiceErrorOnBackgroundThread( 110 void BackgroundShellServiceLoader::OnServiceErrorOnBackgroundThread(
92 ServiceManager* manager, 111 ServiceManager* manager, const GURL& url) {
93 const GURL& url) { 112 DCHECK(task_runner_->RunsTasksOnCurrentThread());
94 if (!background_loader_) 113 if (!background_loader_)
95 background_loader_ = new BackgroundLoader(loader_.get()); 114 background_loader_ = new BackgroundLoader(loader_.get());
96 background_loader_->OnServiceError(manager, url); 115 background_loader_->OnServiceError(manager, url);
97 } 116 }
98 117
99 void BackgroundServiceLoader::ShutdownOnBackgroundThread() {
100 delete background_loader_;
101 // Destroy |loader_| on the thread it's actually used on.
102 loader_.reset();
103 }
104
105 } // namespace mojo 118 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698