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

Side by Side Diff: mojo/shell/runner/child/runner_connection.cc

Issue 1793793002: Remove ShellConnection::WaitForInitialize (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/runner/child/runner_connection.h" 5 #include "mojo/shell/runner/child/runner_connection.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/callback.h" 12 #include "base/callback.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "base/threading/thread.h"
19 #include "base/threading/thread_checker.h"
20 #include "mojo/edk/embedder/embedder.h" 17 #include "mojo/edk/embedder/embedder.h"
21 #include "mojo/edk/embedder/platform_channel_pair.h" 18 #include "mojo/edk/embedder/platform_channel_pair.h"
22 #include "mojo/edk/embedder/scoped_platform_handle.h" 19 #include "mojo/edk/embedder/scoped_platform_handle.h"
23 #include "mojo/message_pump/message_pump_mojo.h"
24 #include "mojo/public/cpp/bindings/binding.h" 20 #include "mojo/public/cpp/bindings/binding.h"
25 #include "mojo/shell/public/interfaces/shell_client_factory.mojom.h" 21 #include "mojo/shell/public/interfaces/shell_client_factory.mojom.h"
26 #include "mojo/shell/runner/common/switches.h" 22 #include "mojo/shell/runner/common/switches.h"
27 23
28 namespace mojo { 24 namespace mojo {
29 namespace shell { 25 namespace shell {
30 namespace { 26 namespace {
31 27
32 // Blocks a thread until another thread unblocks it, at which point it unblocks 28 class RunnerConnectionImpl : public RunnerConnection,
33 // and runs a closure provided by that thread. 29 public mojom::ShellClientFactory {
34 class Blocker {
35 public: 30 public:
36 // Unblocks a Blocker. Safe to copy around to any thread, but must only be 31 RunnerConnectionImpl(mojo::ShellConnection* shell_connetion,
37 // used from a single thread. 32 mojom::ShellClientFactoryRequest client_factory_request,
38 class Unblocker { 33 bool exit_on_error)
39 public: 34 : shell_connection_(shell_connetion),
40 explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {} 35 binding_(this, std::move(client_factory_request)),
41 ~Unblocker() {} 36 exit_on_error_(exit_on_error) {
42 37 binding_.set_connection_error_handler([this] { OnConnectionError(); });
43 bool IsBlocking() const { return blocker_ != nullptr; }
44
45 void Unblock(base::Closure run_after) {
46 DCHECK(blocker_);
47 DCHECK(blocker_->run_after_.is_null());
48 blocker_->run_after_ = run_after;
49 blocker_->event_.Signal();
50 blocker_ = nullptr;
51 }
52
53 private:
54 Blocker* blocker_;
55
56 // Copy and assign allowed.
57 };
58
59 Blocker() : event_(true, false) {}
60 ~Blocker() {}
61
62 void Block() {
63 DCHECK(run_after_.is_null());
64 event_.Wait();
65 if (!run_after_.is_null())
66 run_after_.Run();
67 } 38 }
68 39
69 Unblocker GetUnblocker() { return Unblocker(this); } 40 ~RunnerConnectionImpl() override {}
70 41
71 private: 42 private:
72 base::WaitableEvent event_; 43 // mojom::ShellClientFactory:
73 base::Closure run_after_; 44 void CreateShellClient(mojom::ShellClientRequest client_request,
74 45 const String& name) override {
75 DISALLOW_COPY_AND_ASSIGN(Blocker); 46 shell_connection_->BindToRequest(std::move(client_request));
76 };
77
78 using GotApplicationRequestCallback =
79 base::Callback<void(InterfaceRequest<mojom::ShellClient>)>;
80
81 void OnGotApplicationRequest(InterfaceRequest<mojom::ShellClient>* out_request,
82 InterfaceRequest<mojom::ShellClient> request) {
83 *out_request = std::move(request);
84 }
85
86 class ChildControllerImpl;
87
88 class RunnerConnectionImpl : public RunnerConnection {
89 public:
90 RunnerConnectionImpl() : controller_thread_("controller_thread") {
91 StartControllerThread();
92 }
93 ~RunnerConnectionImpl() override {
94 controller_runner_->PostTask(
95 FROM_HERE, base::Bind(&RunnerConnectionImpl::ShutdownOnControllerThread,
96 base::Unretained(this)));
97 controller_thread_.Stop();
98 }
99
100 // Returns true if a connection to the runner has been established and
101 // |request| has been modified, false if no connection was established.
102 bool WaitForApplicationRequest(InterfaceRequest<mojom::ShellClient>* request,
103 ScopedMessagePipeHandle handle,
104 bool exit_on_error);
105
106 ChildControllerImpl* controller() const { return controller_.get(); }
107
108 void set_controller(scoped_ptr<ChildControllerImpl> controller) {
109 controller_ = std::move(controller);
110 }
111
112 private:
113 void StartControllerThread() {
114 base::Thread::Options controller_thread_options;
115 controller_thread_options.message_loop_type =
116 base::MessageLoop::TYPE_CUSTOM;
117 controller_thread_options.message_pump_factory =
118 base::Bind(&common::MessagePumpMojo::Create);
119 CHECK(controller_thread_.StartWithOptions(controller_thread_options));
120 controller_runner_ = controller_thread_.task_runner().get();
121 CHECK(controller_runner_.get());
122 }
123
124 void ShutdownOnControllerThread() { controller_.reset(); }
125
126 base::Thread controller_thread_;
127 scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
128
129 // Accessed only on the controller thread.
130 scoped_ptr<ChildControllerImpl> controller_;
131
132 DISALLOW_COPY_AND_ASSIGN(RunnerConnectionImpl);
133 };
134
135 class ChildControllerImpl : public mojom::ShellClientFactory {
136 public:
137 ~ChildControllerImpl() override {
138 DCHECK(thread_checker_.CalledOnValidThread());
139 }
140
141 // To be executed on the controller thread. Creates the |ChildController|,
142 // etc.
143 static void Create(RunnerConnectionImpl* connection,
144 const GotApplicationRequestCallback& callback,
145 ScopedMessagePipeHandle runner_handle,
146 const Blocker::Unblocker& unblocker,
147 bool exit_on_error) {
148 DCHECK(connection);
149 DCHECK(!connection->controller());
150
151 scoped_ptr<ChildControllerImpl> impl(
152 new ChildControllerImpl(connection, callback, unblocker,
153 exit_on_error));
154
155 impl->Bind(std::move(runner_handle));
156
157 connection->set_controller(std::move(impl));
158 }
159
160 void Bind(ScopedMessagePipeHandle handle) {
161 binding_.Bind(std::move(handle));
162 binding_.set_connection_error_handler([this]() { OnConnectionError(); });
163 } 47 }
164 48
165 void OnConnectionError() { 49 void OnConnectionError() {
166 // A connection error means the connection to the shell is lost. This is not 50 // A connection error means the connection to the shell is lost. This is not
167 // recoverable. 51 // recoverable.
168 DLOG(ERROR) << "Connection error to the shell."; 52 DLOG(ERROR) << "Connection error to the shell.";
169 if (exit_on_error_) 53 if (exit_on_error_)
170 _exit(1); 54 _exit(1);
171 else
172 UnblockConnection(nullptr);
173 } 55 }
174 56
175 // |mojom::ShellClientFactory| methods: 57 mojo::ShellConnection* const shell_connection_;
176 void CreateShellClient(mojom::ShellClientRequest request, 58 Binding<mojom::ShellClientFactory> binding_;
177 const String& name) override { 59 const bool exit_on_error_;
178 UnblockConnection(std::move(request));
179 }
180 60
181 private: 61 DISALLOW_COPY_AND_ASSIGN(RunnerConnectionImpl);
182 ChildControllerImpl(RunnerConnectionImpl* connection,
183 const GotApplicationRequestCallback& callback,
184 const Blocker::Unblocker& unblocker,
185 bool exit_on_error)
186 : connection_(connection),
187 callback_(callback),
188 unblocker_(unblocker),
189 binding_(this),
190 exit_on_error_(exit_on_error) {}
191
192 static void ReturnApplicationRequestOnMainThread(
193 const GotApplicationRequestCallback& callback,
194 InterfaceRequest<mojom::ShellClient> request) {
195 callback.Run(std::move(request));
196 }
197
198 void UnblockConnection(mojom::ShellClientRequest request) {
199 DCHECK(thread_checker_.CalledOnValidThread());
200 if (unblocker_.IsBlocking()) {
201 unblocker_.Unblock(
202 base::Bind(&ChildControllerImpl::ReturnApplicationRequestOnMainThread,
203 callback_, base::Passed(&request)));
204 }
205 }
206
207 base::ThreadChecker thread_checker_;
208 RunnerConnectionImpl* const connection_;
209 GotApplicationRequestCallback callback_;
210 Blocker::Unblocker unblocker_;
211
212 Binding<mojom::ShellClientFactory> binding_;
213
214 bool exit_on_error_;
215
216 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl);
217 }; 62 };
218 63
219 bool RunnerConnectionImpl::WaitForApplicationRequest(
220 InterfaceRequest<mojom::ShellClient>* request,
221 ScopedMessagePipeHandle handle,
222 bool exit_on_error) {
223 // If a valid message pipe to the runner was not provided, look for one on the
224 // command line.
225 if (!handle.is_valid()) {
226 edk::ScopedPlatformHandle platform_channel =
227 edk::PlatformChannelPair::PassClientHandleFromParentProcess(
228 *base::CommandLine::ForCurrentProcess());
229 if (!platform_channel.is_valid())
230 return false;
231 edk::SetParentPipeHandle(std::move(platform_channel));
232 std::string primordial_pipe_token =
233 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
234 switches::kPrimordialPipeToken);
235 handle = edk::CreateChildMessagePipe(primordial_pipe_token);
236 }
237
238 DCHECK(handle.is_valid());
239
240 Blocker blocker;
241 controller_runner_->PostTask(
242 FROM_HERE,
243 base::Bind(
244 &ChildControllerImpl::Create, base::Unretained(this),
245 base::Bind(&OnGotApplicationRequest, request), base::Passed(&handle),
246 blocker.GetUnblocker(), exit_on_error));
247 blocker.Block();
248
249 return request->is_pending();
250 }
251
252 } // namespace 64 } // namespace
253 65
254 RunnerConnection::~RunnerConnection() {} 66 RunnerConnection::~RunnerConnection() {}
255 67
256 // static 68 // static
257 RunnerConnection* RunnerConnection::ConnectToRunner( 69 scoped_ptr<RunnerConnection> RunnerConnection::Create(
258 InterfaceRequest<mojom::ShellClient>* request, 70 mojo::ShellConnection* shell_connection,
259 ScopedMessagePipeHandle handle,
260 bool exit_on_error) { 71 bool exit_on_error) {
261 RunnerConnectionImpl* connection = new RunnerConnectionImpl; 72 std::string primordial_pipe_token =
262 if (!connection->WaitForApplicationRequest( 73 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
263 request, std::move(handle), exit_on_error)) { 74 switches::kPrimordialPipeToken);
264 delete connection; 75 mojom::ShellClientFactoryRequest client_factory_request;
265 return nullptr; 76 client_factory_request.Bind(
266 } 77 edk::CreateChildMessagePipe(primordial_pipe_token));
267 return connection; 78
79 return make_scoped_ptr(new RunnerConnectionImpl(
80 shell_connection, std::move(client_factory_request), exit_on_error));
268 } 81 }
269 82
270 RunnerConnection::RunnerConnection() {} 83 RunnerConnection::RunnerConnection() {}
271 84
272 } // namespace shell 85 } // namespace shell
273 } // namespace mojo 86 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/shell/runner/child/runner_connection.h ('k') | mojo/shell/runner/child/test_native_main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698