| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |