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

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

Issue 2436763004: More graceful shutdown for ArcSession. (Closed)
Patch Set: Add StopArcInstance 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
« no previous file with comments | « components/arc/arc_session.h ('k') | components/arc/test/fake_arc_bridge_service.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(
202 const scoped_refptr<base::TaskRunner>& blocking_task_runner);
203 ~ArcSessionImpl() override; 203 ~ArcSessionImpl() override;
204 204
205 // ArcSession overrides: 205 // ArcSession overrides:
206 void Start() override; 206 void Start() override;
207 void Stop() override; 207 void Stop() override;
208 void OnShutdown() override;
208 209
209 private: 210 private:
210 // Creates the UNIX socket on a worker pool and then processes its file 211 // Creates the UNIX socket on a worker pool and then processes its file
211 // descriptor. 212 // descriptor.
212 static base::ScopedFD CreateSocket(); 213 static base::ScopedFD CreateSocket();
213 void OnSocketCreated(base::ScopedFD fd); 214 void OnSocketCreated(base::ScopedFD fd);
214 215
215 // DBus callback for StartArcInstance(). 216 // DBus callback for StartArcInstance().
216 void OnInstanceStarted(base::ScopedFD socket_fd, 217 void OnInstanceStarted(base::ScopedFD socket_fd,
217 StartArcInstanceResult result); 218 StartArcInstanceResult result);
218 219
219 // Synchronously accepts a connection on |socket_fd| and then processes the 220 // Synchronously accepts a connection on |socket_fd| and then processes the
220 // connected socket's file descriptor. 221 // connected socket's file descriptor.
221 static base::ScopedFD ConnectMojo(base::ScopedFD socket_fd, 222 static base::ScopedFD ConnectMojo(base::ScopedFD socket_fd,
222 base::ScopedFD cancel_fd); 223 base::ScopedFD cancel_fd);
223 void OnMojoConnected(base::ScopedFD fd); 224 void OnMojoConnected(base::ScopedFD fd);
224 225
225 // Request to stop ARC instance via DBus. 226 // Request to stop ARC instance via DBus.
226 void StopArcInstance(); 227 void StopArcInstance();
227 228
228 // chromeos::SessionManagerClient::Observer: 229 // chromeos::SessionManagerClient::Observer:
229 void ArcInstanceStopped(bool clean) override; 230 void ArcInstanceStopped(bool clean) override;
230 231
231 // Completes the termination procedure. 232 // Completes the termination procedure.
232 void OnStopped(ArcBridgeService::StopReason reason); 233 void OnStopped(ArcBridgeService::StopReason reason);
233 234
235 // Checks whether a function runs on the thread where the instance is
236 // created.
237 base::ThreadChecker thread_checker_;
238
239 // Task runner to run a blocking tasks.
240 scoped_refptr<base::TaskRunner> blocking_task_runner_;
241
234 // The state of the session. 242 // The state of the session.
235 State state_ = State::NOT_STARTED; 243 State state_ = State::NOT_STARTED;
236 244
237 // When Stop() is called, this flag is set. 245 // When Stop() is called, this flag is set.
238 bool stop_requested_ = false; 246 bool stop_requested_ = false;
239 247
240 // In CONNECTING_MOJO state, this is set to the write side of the pipe 248 // In CONNECTING_MOJO state, this is set to the write side of the pipe
241 // to notify cancelling of the procedure. 249 // to notify cancelling of the procedure.
242 base::ScopedFD accept_cancel_pipe_; 250 base::ScopedFD accept_cancel_pipe_;
243 251
244 // Mojo endpoint. 252 // Mojo endpoint.
245 std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_; 253 std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_;
246 254
247 base::ThreadChecker thread_checker_;
248
249 // WeakPtrFactory to use callbacks. 255 // WeakPtrFactory to use callbacks.
250 base::WeakPtrFactory<ArcSessionImpl> weak_factory_; 256 base::WeakPtrFactory<ArcSessionImpl> weak_factory_;
251 257
252 private: 258 private:
253 DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl); 259 DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl);
254 }; 260 };
255 261
256 ArcSessionImpl::ArcSessionImpl() : weak_factory_(this) { 262 ArcSessionImpl::ArcSessionImpl(
263 const scoped_refptr<base::TaskRunner>& blocking_task_runner)
264 : blocking_task_runner_(blocking_task_runner), weak_factory_(this) {
257 chromeos::SessionManagerClient* client = GetSessionManagerClient(); 265 chromeos::SessionManagerClient* client = GetSessionManagerClient();
258 if (client == nullptr) 266 if (client == nullptr)
259 return; 267 return;
260 client->AddObserver(this); 268 client->AddObserver(this);
261 } 269 }
262 270
263 ArcSessionImpl::~ArcSessionImpl() { 271 ArcSessionImpl::~ArcSessionImpl() {
264 DCHECK(thread_checker_.CalledOnValidThread()); 272 DCHECK(thread_checker_.CalledOnValidThread());
265 // TODO(hidehiko): CHECK if |state_| is in NOT_STARTED or STOPPED. 273 DCHECK(state_ == State::NOT_STARTED || state_ == State::STOPPED);
266 // Currently, specifically on shutdown, the state_ can be any value.
267 chromeos::SessionManagerClient* client = GetSessionManagerClient(); 274 chromeos::SessionManagerClient* client = GetSessionManagerClient();
268 if (client == nullptr) 275 if (client == nullptr)
269 return; 276 return;
270 client->RemoveObserver(this); 277 client->RemoveObserver(this);
271 } 278 }
272 279
273 void ArcSessionImpl::Start() { 280 void ArcSessionImpl::Start() {
274 DCHECK(thread_checker_.CalledOnValidThread()); 281 DCHECK(thread_checker_.CalledOnValidThread());
275 DCHECK_EQ(state_, State::NOT_STARTED); 282 DCHECK_EQ(state_, State::NOT_STARTED);
276 VLOG(2) << "Starting ARC session."; 283 VLOG(2) << "Starting ARC session.";
277 VLOG(2) << "Creating socket..."; 284 VLOG(2) << "Creating socket...";
278 285
279 state_ = State::CREATING_SOCKET; 286 state_ = State::CREATING_SOCKET;
280 base::PostTaskAndReplyWithResult( 287 base::PostTaskAndReplyWithResult(
281 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 288 blocking_task_runner_.get(), FROM_HERE,
282 base::Bind(&ArcSessionImpl::CreateSocket), 289 base::Bind(&ArcSessionImpl::CreateSocket),
283 base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr())); 290 base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr()));
284 } 291 }
285 292
286 // static 293 // static
287 base::ScopedFD ArcSessionImpl::CreateSocket() { 294 base::ScopedFD ArcSessionImpl::CreateSocket() {
288 base::FilePath socket_path(kArcBridgeSocketPath); 295 base::FilePath socket_path(kArcBridgeSocketPath);
289 296
290 int raw_fd = -1; 297 int raw_fd = -1;
291 if (!IPC::CreateServerUnixDomainSocket(socket_path, &raw_fd)) 298 if (!IPC::CreateServerUnixDomainSocket(socket_path, &raw_fd))
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 397
391 // Prepare a pipe so that AcceptInstanceConnection can be interrupted on 398 // Prepare a pipe so that AcceptInstanceConnection can be interrupted on
392 // Stop(). 399 // Stop().
393 base::ScopedFD cancel_fd; 400 base::ScopedFD cancel_fd;
394 if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) { 401 if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) {
395 OnStopped(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); 402 OnStopped(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
396 return; 403 return;
397 } 404 }
398 405
399 base::PostTaskAndReplyWithResult( 406 base::PostTaskAndReplyWithResult(
400 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 407 blocking_task_runner_.get(), FROM_HERE,
401 base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd), 408 base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd),
402 base::Passed(&cancel_fd)), 409 base::Passed(&cancel_fd)),
403 base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr())); 410 base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr()));
404 } 411 }
405 412
406 // static 413 // static
407 base::ScopedFD ArcSessionImpl::ConnectMojo(base::ScopedFD socket_fd, 414 base::ScopedFD ArcSessionImpl::ConnectMojo(base::ScopedFD socket_fd,
408 base::ScopedFD cancel_fd) { 415 base::ScopedFD cancel_fd) {
409 if (!WaitForSocketReadable(socket_fd.get(), cancel_fd.get())) { 416 if (!WaitForSocketReadable(socket_fd.get(), cancel_fd.get())) {
410 VLOG(1) << "Mojo connection was cancelled."; 417 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 514 // On Chrome shutdown, it is not the case because the message loop is
508 // already stopped here. Practically, it is not a problem because; 515 // already stopped here. Practically, it is not a problem because;
509 // - On socket creating, it is ok to simply ignore such cases, 516 // - On socket creating, it is ok to simply ignore such cases,
510 // because we no-longer continue the bootstrap procedure. 517 // because we no-longer continue the bootstrap procedure.
511 // - On starting instance, the container instance can be leaked. 518 // - On starting instance, the container instance can be leaked.
512 // Practically it is not problematic because the session manager will 519 // Practically it is not problematic because the session manager will
513 // clean it up. 520 // clean it up.
514 return; 521 return;
515 522
516 case State::CONNECTING_MOJO: 523 case State::CONNECTING_MOJO:
517 // Mojo connection is being waited on a WorkerPool thread. 524 // Mojo connection is being waited on a BlockingPool thread.
518 // Request to cancel it. Following stopping procedure will run 525 // Request to cancel it. Following stopping procedure will run
519 // in its callback. 526 // in its callback.
520 DCHECK(accept_cancel_pipe_.get());
521 accept_cancel_pipe_.reset(); 527 accept_cancel_pipe_.reset();
522 return; 528 return;
523 529
524 case State::RUNNING: 530 case State::RUNNING:
525 // Now ARC instance is running. Request to stop it. 531 // Now ARC instance is running. Request to stop it.
526 StopArcInstance(); 532 StopArcInstance();
527 return; 533 return;
528 534
529 case State::STOPPED: 535 case State::STOPPED:
530 // The instance is already stopped. Do nothing. 536 // The instance is already stopped. Do nothing.
(...skipping 13 matching lines...) Expand all
544 session_manager_client->StopArcInstance( 550 session_manager_client->StopArcInstance(
545 base::Bind(&DoNothingInstanceStopped)); 551 base::Bind(&DoNothingInstanceStopped));
546 } 552 }
547 553
548 void ArcSessionImpl::ArcInstanceStopped(bool clean) { 554 void ArcSessionImpl::ArcInstanceStopped(bool clean) {
549 DCHECK(thread_checker_.CalledOnValidThread()); 555 DCHECK(thread_checker_.CalledOnValidThread());
550 VLOG(1) << "Notified that ARC instance is stopped " 556 VLOG(1) << "Notified that ARC instance is stopped "
551 << (clean ? "cleanly" : "uncleanly"); 557 << (clean ? "cleanly" : "uncleanly");
552 558
553 // In case that crash happens during before the Mojo channel is connected, 559 // In case that crash happens during before the Mojo channel is connected,
554 // unlock the WorkerPool thread. 560 // unlock the BlockingPool thread.
555 accept_cancel_pipe_.reset(); 561 accept_cancel_pipe_.reset();
556 562
557 ArcBridgeService::StopReason reason; 563 ArcBridgeService::StopReason reason;
558 if (stop_requested_) { 564 if (stop_requested_) {
559 // If the ARC instance is stopped after its explicit request, 565 // If the ARC instance is stopped after its explicit request,
560 // return SHUTDOWN. 566 // return SHUTDOWN.
561 reason = ArcBridgeService::StopReason::SHUTDOWN; 567 reason = ArcBridgeService::StopReason::SHUTDOWN;
562 } else if (clean) { 568 } else if (clean) {
563 // If the ARC instance is stopped, but it is not explicitly requested, 569 // If the ARC instance is stopped, but it is not explicitly requested,
564 // then this is triggered by some failure during the starting procedure. 570 // then this is triggered by some failure during the starting procedure.
(...skipping 10 matching lines...) Expand all
575 DCHECK(thread_checker_.CalledOnValidThread()); 581 DCHECK(thread_checker_.CalledOnValidThread());
576 // OnStopped() should be called once per instance. 582 // OnStopped() should be called once per instance.
577 DCHECK_NE(state_, State::STOPPED); 583 DCHECK_NE(state_, State::STOPPED);
578 VLOG(2) << "ARC session is stopped."; 584 VLOG(2) << "ARC session is stopped.";
579 arc_bridge_host_.reset(); 585 arc_bridge_host_.reset();
580 state_ = State::STOPPED; 586 state_ = State::STOPPED;
581 for (auto& observer : observer_list_) 587 for (auto& observer : observer_list_)
582 observer.OnStopped(reason); 588 observer.OnStopped(reason);
583 } 589 }
584 590
591 void ArcSessionImpl::OnShutdown() {
592 DCHECK(thread_checker_.CalledOnValidThread());
593 stop_requested_ = true;
594 if (state_ == State::STOPPED)
595 return;
596
597 // Here, the message loop is already stopped, and the Chrome will be soon
598 // shutdown. Thus, it is not necessary to take care about restarting case.
599 // If ArcSession is waiting for mojo connection, cancels it. The BlockingPool
600 // will be joined later.
601 accept_cancel_pipe_.reset();
602
603 // Stops the ARC instance to let it graceful shutdown.
604 // Note that this may fail if ARC container is not actually running, but
605 // ignore an error as described below.
606 if (state_ == State::STARTING_INSTANCE ||
607 state_ == State::CONNECTING_MOJO || state_ == State::RUNNING)
608 StopArcInstance();
609
610 // Directly set to the STOPPED stateby OnStopped(). Note that calling
611 // StopArcInstance() may not work well. At least, because the UI thread is
612 // already stopped here, ArcInstanceStopped() callback cannot be invoked.
613 OnStopped(ArcBridgeService::StopReason::SHUTDOWN);
614 }
615
585 } // namespace 616 } // namespace
586 617
587 ArcSession::ArcSession() = default; 618 ArcSession::ArcSession() = default;
588 ArcSession::~ArcSession() = default; 619 ArcSession::~ArcSession() = default;
589 620
590 void ArcSession::AddObserver(Observer* observer) { 621 void ArcSession::AddObserver(Observer* observer) {
591 observer_list_.AddObserver(observer); 622 observer_list_.AddObserver(observer);
592 } 623 }
593 624
594 void ArcSession::RemoveObserver(Observer* observer) { 625 void ArcSession::RemoveObserver(Observer* observer) {
595 observer_list_.RemoveObserver(observer); 626 observer_list_.RemoveObserver(observer);
596 } 627 }
597 628
598 // static 629 // static
599 std::unique_ptr<ArcSession> ArcSession::Create() { 630 std::unique_ptr<ArcSession> ArcSession::Create(
600 return base::MakeUnique<ArcSessionImpl>(); 631 const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
632 return base::MakeUnique<ArcSessionImpl>(blocking_task_runner);
601 } 633 }
602 634
603 } // namespace arc 635 } // namespace arc
OLDNEW
« no previous file with comments | « components/arc/arc_session.h ('k') | components/arc/test/fake_arc_bridge_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698