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

Side by Side Diff: components/arc/arc_session.cc

Issue 2436763004: More graceful shutdown for ArcSession. (Closed)
Patch Set: Created 4 years, 2 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 "components/arc/arc_session.h" 5 #include "components/arc/arc_session.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <grp.h> 8 #include <grp.h>
9 #include <poll.h> 9 #include <poll.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 11
12 #include <utility> 12 #include <utility>
13 13
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
16 #include "base/location.h" 16 #include "base/location.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/memory/ptr_util.h" 18 #include "base/memory/ptr_util.h"
19 #include "base/posix/eintr_wrapper.h" 19 #include "base/posix/eintr_wrapper.h"
20 #include "base/sys_info.h" 20 #include "base/sys_info.h"
21 #include "base/task_runner_util.h" 21 #include "base/task_runner_util.h"
22 #include "base/threading/thread_checker.h" 22 #include "base/threading/thread_checker.h"
23 #include "base/threading/thread_task_runner_handle.h" 23 #include "base/threading/thread_task_runner_handle.h"
24 #include "base/threading/worker_pool.h"
25 #include "chromeos/cryptohome/cryptohome_parameters.h" 24 #include "chromeos/cryptohome/cryptohome_parameters.h"
26 #include "chromeos/dbus/dbus_method_call_status.h" 25 #include "chromeos/dbus/dbus_method_call_status.h"
27 #include "chromeos/dbus/dbus_thread_manager.h" 26 #include "chromeos/dbus/dbus_thread_manager.h"
28 #include "chromeos/dbus/session_manager_client.h" 27 #include "chromeos/dbus/session_manager_client.h"
29 #include "components/arc/arc_bridge_host_impl.h" 28 #include "components/arc/arc_bridge_host_impl.h"
30 #include "components/arc/arc_features.h" 29 #include "components/arc/arc_features.h"
31 #include "components/user_manager/user_manager.h" 30 #include "components/user_manager/user_manager.h"
32 #include "ipc/unix_domain_socket_util.h" 31 #include "ipc/unix_domain_socket_util.h"
33 #include "mojo/edk/embedder/embedder.h" 32 #include "mojo/edk/embedder/embedder.h"
34 #include "mojo/edk/embedder/platform_channel_pair.h" 33 #include "mojo/edk/embedder/platform_channel_pair.h"
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 // At any state, Stop() can be called. It does not immediately stop the 124 // At any state, Stop() can be called. It does not immediately stop the
126 // instance, but will eventually stop it. 125 // instance, but will eventually stop it.
127 // The actual stop will be notified via Observer::OnStopped(). 126 // The actual stop will be notified via Observer::OnStopped().
128 // 127 //
129 // When Stop() is called, it makes various behavior based on the current 128 // When Stop() is called, it makes various behavior based on the current
130 // phase. 129 // phase.
131 // 130 //
132 // NOT_STARTED: 131 // NOT_STARTED:
133 // Do nothing. Immediately transition to the STOPPED state. 132 // Do nothing. Immediately transition to the STOPPED state.
134 // CREATING_SOCKET: 133 // CREATING_SOCKET:
135 // The main task of the phase runs on WorkerPool thread. So, Stop() just 134 // The main task of the phase runs on BlockingPool thread. So, Stop() just
136 // sets the flag and return. On the main task completion, a callback 135 // sets the flag and return. On the main task completion, a callback
137 // will run on the main (practically UI) thread, and the flag is checked 136 // will run on the main (practically UI) thread, and the flag is checked
138 // at the beginning of them. This should work under the assumption that 137 // at the beginning of them. This should work under the assumption that
139 // the main tasks do not block indefinitely. 138 // the main tasks do not block indefinitely.
140 // STARTING_INSTANCE: 139 // STARTING_INSTANCE:
141 // The ARC instance is starting via SessionManager. So, similar to 140 // The ARC instance is starting via SessionManager. So, similar to
142 // CREATING_SOCKET case, Stop() just sets the flag and return. In its 141 // CREATING_SOCKET case, Stop() just sets the flag and return. In its
143 // callback, it checks if ARC instance is successfully started or not. 142 // callback, it checks if ARC instance is successfully started or not.
144 // In case of success, a request to stop the ARC instance is sent to 143 // In case of success, a request to stop the ARC instance is sent to
145 // SessionManager. Its completion will be notified via ArcInstanceStopped. 144 // SessionManager. Its completion will be notified via ArcInstanceStopped.
146 // Otherwise, it just turns into STOPPED state. 145 // Otherwise, it just turns into STOPPED state.
147 // CONNECTING_MOJO: 146 // CONNECTING_MOJO:
148 // The main task runs on WorkerPool thread, but it is blocking call. 147 // The main task runs on BlockingPool thread, but it is blocking call.
149 // So, Stop() sends a request to cancel the blocking by closing the pipe 148 // So, Stop() sends a request to cancel the blocking by closing the pipe
150 // whose read side is also polled. Then, in its callback, similar to 149 // whose read side is also polled. Then, in its callback, similar to
151 // STARTING_INSTANCE, a request to stop the ARC instance is sent to 150 // STARTING_INSTANCE, a request to stop the ARC instance is sent to
152 // SessionManager, and ArcInstanceStopped handles remaining procedure. 151 // SessionManager, and ArcInstanceStopped handles remaining procedure.
153 // RUNNING: 152 // RUNNING:
154 // There is no more callback which runs on normal flow, so Stop() requests 153 // There is no more callback which runs on normal flow, so Stop() requests
155 // to stop the ARC instance via SessionManager. 154 // to stop the ARC instance via SessionManager.
156 // 155 //
157 // Another trigger to change the state coming from outside of this class 156 // Another trigger to change the state coming from outside of this class
158 // is an event ArcInstanceStopped() sent from SessionManager, when ARC 157 // is an event ArcInstanceStopped() sent from SessionManager, when ARC
159 // instace unexpectedly terminates. ArcInstanceStopped() turns the state into 158 // instace unexpectedly terminates. ArcInstanceStopped() turns the state into
160 // STOPPED immediately. 159 // STOPPED immediately.
161 // This happens only when STARTING_INSTANCE, CONNECTING_MOJO or RUNNING 160 // This happens only when STARTING_INSTANCE, CONNECTING_MOJO or RUNNING
162 // state. 161 // state.
163 // 162 //
164 // STARTING_INSTANCE: 163 // STARTING_INSTANCE:
165 // In OnInstanceStarted(), |state_| is checked at the beginning. If it is 164 // In OnInstanceStarted(), |state_| is checked at the beginning. If it is
166 // STOPPED, then ArcInstanceStopped() is called. Do nothing in that case. 165 // STOPPED, then ArcInstanceStopped() is called. Do nothing in that case.
167 // CONNECTING_MOJO: 166 // CONNECTING_MOJO:
168 // Similar to Stop() case above, ArcInstanceStopped() also notifies to 167 // Similar to Stop() case above, ArcInstanceStopped() also notifies to
169 // WorkerPool() thread to cancel it to unblock the thread. In 168 // BlockingPool thread to cancel it to unblock the thread. In
170 // OnMojoConnected(), similar to OnInstanceStarted(), check if |state_| is 169 // OnMojoConnected(), similar to OnInstanceStarted(), check if |state_| is
171 // STOPPED, then do nothing. 170 // STOPPED, then do nothing.
172 // RUNNING: 171 // RUNNING:
173 // It is not necessary to do anything special here. 172 // It is not necessary to do anything special here.
174 // 173 //
175 // In NOT_STARTED or STOPPED state, the instance can be safely destructed. 174 // In NOT_STARTED or STOPPED state, the instance can be safely destructed.
176 // Specifically, in STOPPED state, there may be inflight operations or 175 // Specifically, in STOPPED state, there may be inflight operations or
177 // pending callbacks. Though, what they do is just do-nothing conceptually 176 // pending callbacks. Though, what they do is just do-nothing conceptually
178 // and they can be safely ignored. 177 // and they can be safely ignored.
179 // 178 //
(...skipping 12 matching lines...) Expand all
192 // The instance has started. Waiting for it to connect to the IPC bridge. 191 // The instance has started. Waiting for it to connect to the IPC bridge.
193 CONNECTING_MOJO, 192 CONNECTING_MOJO,
194 193
195 // The instance is fully set up. 194 // The instance is fully set up.
196 RUNNING, 195 RUNNING,
197 196
198 // ARC is terminated. 197 // ARC is terminated.
199 STOPPED, 198 STOPPED,
200 }; 199 };
201 200
202 ArcSessionImpl(); 201 explicit ArcSessionImpl(scoped_refptr<base::TaskRunner> blocking_task_runner);
Luis Héctor Chávez 2016/10/21 00:43:41 nit: const scoped_refptr<...>&
hidehiko 2016/10/21 04:34:03 Done.
203 ~ArcSessionImpl() override; 202 ~ArcSessionImpl() override;
204 203
205 // ArcSession overrides: 204 // ArcSession overrides:
206 void Start() override; 205 void Start() override;
207 void Stop() override; 206 void Stop() override;
207 void OnShutdown() override;
208 208
209 private: 209 private:
210 // Creates the UNIX socket on a worker pool and then processes its file 210 // Creates the UNIX socket on a worker pool and then processes its file
211 // descriptor. 211 // descriptor.
212 static base::ScopedFD CreateSocket(); 212 static base::ScopedFD CreateSocket();
213 void OnSocketCreated(base::ScopedFD fd); 213 void OnSocketCreated(base::ScopedFD fd);
214 214
215 // DBus callback for StartArcInstance(). 215 // DBus callback for StartArcInstance().
216 void OnInstanceStarted(base::ScopedFD socket_fd, 216 void OnInstanceStarted(base::ScopedFD socket_fd,
217 StartArcInstanceResult result); 217 StartArcInstanceResult result);
218 218
219 // Synchronously accepts a connection on |socket_fd| and then processes the 219 // Synchronously accepts a connection on |socket_fd| and then processes the
220 // connected socket's file descriptor. 220 // connected socket's file descriptor.
221 static base::ScopedFD ConnectMojo(base::ScopedFD socket_fd, 221 static base::ScopedFD ConnectMojo(base::ScopedFD socket_fd,
222 base::ScopedFD cancel_fd); 222 base::ScopedFD cancel_fd);
223 void OnMojoConnected(base::ScopedFD fd); 223 void OnMojoConnected(base::ScopedFD fd);
224 224
225 // Request to stop ARC instance via DBus. 225 // Request to stop ARC instance via DBus.
226 void StopArcInstance(); 226 void StopArcInstance();
227 227
228 // chromeos::SessionManagerClient::Observer: 228 // chromeos::SessionManagerClient::Observer:
229 void ArcInstanceStopped(bool clean) override; 229 void ArcInstanceStopped(bool clean) override;
230 230
231 // Completes the termination procedure. 231 // Completes the termination procedure.
232 void OnStopped(ArcBridgeService::StopReason reason); 232 void OnStopped(ArcBridgeService::StopReason reason);
233 233
234 // Checks whether a function runs on the thread where the instance is
235 // created.
236 base::ThreadChecker thread_checker_;
237
238 // Task runner to run a blocking tasks.
239 scoped_refptr<base::TaskRunner> blocking_task_runner_;
240
234 // The state of the session. 241 // The state of the session.
235 State state_ = State::NOT_STARTED; 242 State state_ = State::NOT_STARTED;
236 243
237 // When Stop() is called, this flag is set. 244 // When Stop() is called, this flag is set.
238 bool stop_requested_ = false; 245 bool stop_requested_ = false;
239 246
240 // In CONNECTING_MOJO state, this is set to the write side of the pipe 247 // In CONNECTING_MOJO state, this is set to the write side of the pipe
241 // to notify cancelling of the procedure. 248 // to notify cancelling of the procedure.
242 base::ScopedFD accept_cancel_pipe_; 249 base::ScopedFD accept_cancel_pipe_;
243 250
244 // Mojo endpoint. 251 // Mojo endpoint.
245 std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_; 252 std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_;
246 253
247 base::ThreadChecker thread_checker_;
248
249 // WeakPtrFactory to use callbacks. 254 // WeakPtrFactory to use callbacks.
250 base::WeakPtrFactory<ArcSessionImpl> weak_factory_; 255 base::WeakPtrFactory<ArcSessionImpl> weak_factory_;
251 256
252 private: 257 private:
253 DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl); 258 DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl);
254 }; 259 };
255 260
256 ArcSessionImpl::ArcSessionImpl() : weak_factory_(this) { 261 ArcSessionImpl::ArcSessionImpl(
262 scoped_refptr<base::TaskRunner> blocking_task_runner)
263 : blocking_task_runner_(blocking_task_runner), weak_factory_(this) {
257 chromeos::SessionManagerClient* client = GetSessionManagerClient(); 264 chromeos::SessionManagerClient* client = GetSessionManagerClient();
258 if (client == nullptr) 265 if (client == nullptr)
259 return; 266 return;
260 client->AddObserver(this); 267 client->AddObserver(this);
261 } 268 }
262 269
263 ArcSessionImpl::~ArcSessionImpl() { 270 ArcSessionImpl::~ArcSessionImpl() {
264 DCHECK(thread_checker_.CalledOnValidThread()); 271 DCHECK(thread_checker_.CalledOnValidThread());
265 // TODO(hidehiko): CHECK if |state_| is in NOT_STARTED or STOPPED. 272 DCHECK(state_ == State::NOT_STARTED || state_ == State::STOPPED);
266 // Currently, specifically on shutdown, the state_ can be any value.
267 chromeos::SessionManagerClient* client = GetSessionManagerClient(); 273 chromeos::SessionManagerClient* client = GetSessionManagerClient();
268 if (client == nullptr) 274 if (client == nullptr)
269 return; 275 return;
270 client->RemoveObserver(this); 276 client->RemoveObserver(this);
271 } 277 }
272 278
273 void ArcSessionImpl::Start() { 279 void ArcSessionImpl::Start() {
274 DCHECK(thread_checker_.CalledOnValidThread()); 280 DCHECK(thread_checker_.CalledOnValidThread());
275 DCHECK_EQ(state_, State::NOT_STARTED); 281 DCHECK_EQ(state_, State::NOT_STARTED);
276 VLOG(2) << "Starting ARC session."; 282 VLOG(2) << "Starting ARC session.";
277 VLOG(2) << "Creating socket..."; 283 VLOG(2) << "Creating socket...";
278 284
279 state_ = State::CREATING_SOCKET; 285 state_ = State::CREATING_SOCKET;
280 base::PostTaskAndReplyWithResult( 286 base::PostTaskAndReplyWithResult(
281 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 287 blocking_task_runner_.get(), FROM_HERE,
282 base::Bind(&ArcSessionImpl::CreateSocket), 288 base::Bind(&ArcSessionImpl::CreateSocket),
283 base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr())); 289 base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr()));
284 } 290 }
285 291
286 // static 292 // static
287 base::ScopedFD ArcSessionImpl::CreateSocket() { 293 base::ScopedFD ArcSessionImpl::CreateSocket() {
288 base::FilePath socket_path(kArcBridgeSocketPath); 294 base::FilePath socket_path(kArcBridgeSocketPath);
289 295
290 int raw_fd = -1; 296 int raw_fd = -1;
291 if (!IPC::CreateServerUnixDomainSocket(socket_path, &raw_fd)) 297 if (!IPC::CreateServerUnixDomainSocket(socket_path, &raw_fd))
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 396
391 // Prepare a pipe so that AcceptInstanceConnection can be interrupted on 397 // Prepare a pipe so that AcceptInstanceConnection can be interrupted on
392 // Stop(). 398 // Stop().
393 base::ScopedFD cancel_fd; 399 base::ScopedFD cancel_fd;
394 if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) { 400 if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) {
395 OnStopped(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); 401 OnStopped(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
396 return; 402 return;
397 } 403 }
398 404
399 base::PostTaskAndReplyWithResult( 405 base::PostTaskAndReplyWithResult(
400 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 406 blocking_task_runner_.get(), FROM_HERE,
401 base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd), 407 base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd),
402 base::Passed(&cancel_fd)), 408 base::Passed(&cancel_fd)),
403 base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr())); 409 base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr()));
404 } 410 }
405 411
406 // static 412 // static
407 base::ScopedFD ArcSessionImpl::ConnectMojo(base::ScopedFD socket_fd, 413 base::ScopedFD ArcSessionImpl::ConnectMojo(base::ScopedFD socket_fd,
408 base::ScopedFD cancel_fd) { 414 base::ScopedFD cancel_fd) {
409 if (!WaitForSocketReadable(socket_fd.get(), cancel_fd.get())) { 415 if (!WaitForSocketReadable(socket_fd.get(), cancel_fd.get())) {
410 VLOG(1) << "Mojo connection was cancelled."; 416 VLOG(1) << "Mojo connection was cancelled.";
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 // On Chrome shutdown, it is not the case because the message loop is 513 // On Chrome shutdown, it is not the case because the message loop is
508 // already stopped here. Practically, it is not a problem because; 514 // already stopped here. Practically, it is not a problem because;
509 // - On socket creating, it is ok to simply ignore such cases, 515 // - On socket creating, it is ok to simply ignore such cases,
510 // because we no-longer continue the bootstrap procedure. 516 // because we no-longer continue the bootstrap procedure.
511 // - On starting instance, the container instance can be leaked. 517 // - On starting instance, the container instance can be leaked.
512 // Practically it is not problematic because the session manager will 518 // Practically it is not problematic because the session manager will
513 // clean it up. 519 // clean it up.
514 return; 520 return;
515 521
516 case State::CONNECTING_MOJO: 522 case State::CONNECTING_MOJO:
517 // Mojo connection is being waited on a WorkerPool thread. 523 // Mojo connection is being waited on a BlockingPool thread.
518 // Request to cancel it. Following stopping procedure will run 524 // Request to cancel it. Following stopping procedure will run
519 // in its callback. 525 // in its callback.
520 DCHECK(accept_cancel_pipe_.get());
hidehiko 2016/10/20 10:09:08 Note: I found that there is a case that this is tr
Luis Héctor Chávez 2016/10/21 00:43:41 Acknowledged.
521 accept_cancel_pipe_.reset(); 526 accept_cancel_pipe_.reset();
522 return; 527 return;
523 528
524 case State::RUNNING: 529 case State::RUNNING:
525 // Now ARC instance is running. Request to stop it. 530 // Now ARC instance is running. Request to stop it.
526 StopArcInstance(); 531 StopArcInstance();
527 return; 532 return;
528 533
529 case State::STOPPED: 534 case State::STOPPED:
530 // The instance is already stopped. Do nothing. 535 // The instance is already stopped. Do nothing.
(...skipping 13 matching lines...) Expand all
544 session_manager_client->StopArcInstance( 549 session_manager_client->StopArcInstance(
545 base::Bind(&DoNothingInstanceStopped)); 550 base::Bind(&DoNothingInstanceStopped));
546 } 551 }
547 552
548 void ArcSessionImpl::ArcInstanceStopped(bool clean) { 553 void ArcSessionImpl::ArcInstanceStopped(bool clean) {
549 DCHECK(thread_checker_.CalledOnValidThread()); 554 DCHECK(thread_checker_.CalledOnValidThread());
550 VLOG(1) << "Notified that ARC instance is stopped " 555 VLOG(1) << "Notified that ARC instance is stopped "
551 << (clean ? "cleanly" : "uncleanly"); 556 << (clean ? "cleanly" : "uncleanly");
552 557
553 // In case that crash happens during before the Mojo channel is connected, 558 // In case that crash happens during before the Mojo channel is connected,
554 // unlock the WorkerPool thread. 559 // unlock the BlockingPool thread.
555 accept_cancel_pipe_.reset(); 560 accept_cancel_pipe_.reset();
556 561
557 ArcBridgeService::StopReason reason; 562 ArcBridgeService::StopReason reason;
558 if (stop_requested_) { 563 if (stop_requested_) {
559 // If the ARC instance is stopped after its explicit request, 564 // If the ARC instance is stopped after its explicit request,
560 // return SHUTDOWN. 565 // return SHUTDOWN.
561 reason = ArcBridgeService::StopReason::SHUTDOWN; 566 reason = ArcBridgeService::StopReason::SHUTDOWN;
562 } else if (clean) { 567 } else if (clean) {
563 // If the ARC instance is stopped, but it is not explicitly requested, 568 // If the ARC instance is stopped, but it is not explicitly requested,
564 // then this is triggered by some failure during the starting procedure. 569 // then this is triggered by some failure during the starting procedure.
(...skipping 10 matching lines...) Expand all
575 DCHECK(thread_checker_.CalledOnValidThread()); 580 DCHECK(thread_checker_.CalledOnValidThread());
576 // OnStopped() should be called once per instance. 581 // OnStopped() should be called once per instance.
577 DCHECK_NE(state_, State::STOPPED); 582 DCHECK_NE(state_, State::STOPPED);
578 VLOG(2) << "ARC session is stopped."; 583 VLOG(2) << "ARC session is stopped.";
579 arc_bridge_host_.reset(); 584 arc_bridge_host_.reset();
580 state_ = State::STOPPED; 585 state_ = State::STOPPED;
581 for (auto& observer : observer_list_) 586 for (auto& observer : observer_list_)
582 observer.OnStopped(reason); 587 observer.OnStopped(reason);
583 } 588 }
584 589
590 void ArcSessionImpl::OnShutdown() {
591 DCHECK(thread_checker_.CalledOnValidThread());
592 stop_requested_ = true;
593 if (state_ == State::STOPPED)
594 return;
595
596 // Here, the message loop is already stopped, and the Chrome will be soon
597 // shutdown. Thus, it is not necessary to take care about restarting case.
598 // If ArcSession is waiting for mojo connection, cancels it. The BlockingPool
599 // will be joined later.
600 accept_cancel_pipe_.reset();
601
602 // After Chrome's shutdown, SessionManager shuts down the ARC instance,
Luis Héctor Chávez 2016/10/21 00:43:41 I'd still want this code to be robust by itself an
hidehiko 2016/10/21 04:34:03 Could you tell me what more robustness do you want
Luis Héctor Chávez 2016/10/21 06:34:20 We can rely on SessionManager's _current_ behavior
hashimoto 2016/10/21 07:20:27 IIUC unclean shutdown is also covered by SessionMa
Luis Héctor Chávez 2016/10/21 07:53:43 Oh that was unintentional :/ we should swap the ti
603 // so we do not need to worry about it here.
604 // Directly set to the STOPPED stateby OnStopped(). Note that callsing
Luis Héctor Chávez 2016/10/21 00:43:41 nit: s/callsing/calling/
hidehiko 2016/10/21 04:34:03 Done.
605 // StopArcInstance() may not work well. At least, because the UI thread is
606 // already stopped here, ArcInstanceStopped() callback cannot be invoked.
607 OnStopped(ArcBridgeService::StopReason::SHUTDOWN);
608 }
609
585 } // namespace 610 } // namespace
586 611
587 ArcSession::ArcSession() = default; 612 ArcSession::ArcSession() = default;
588 ArcSession::~ArcSession() = default; 613 ArcSession::~ArcSession() = default;
589 614
590 void ArcSession::AddObserver(Observer* observer) { 615 void ArcSession::AddObserver(Observer* observer) {
591 observer_list_.AddObserver(observer); 616 observer_list_.AddObserver(observer);
592 } 617 }
593 618
594 void ArcSession::RemoveObserver(Observer* observer) { 619 void ArcSession::RemoveObserver(Observer* observer) {
595 observer_list_.RemoveObserver(observer); 620 observer_list_.RemoveObserver(observer);
596 } 621 }
597 622
598 // static 623 // static
599 std::unique_ptr<ArcSession> ArcSession::Create() { 624 std::unique_ptr<ArcSession> ArcSession::Create(
600 return base::MakeUnique<ArcSessionImpl>(); 625 scoped_refptr<base::TaskRunner> blocking_task_runner) {
626 return base::MakeUnique<ArcSessionImpl>(blocking_task_runner);
601 } 627 }
602 628
603 } // namespace arc 629 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698