| 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_bridge_bootstrap.h" | 5 #include "components/arc/arc_bridge_bootstrap.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" | 24 #include "base/threading/worker_pool.h" |
| 25 #include "chromeos/cryptohome/cryptohome_parameters.h" | 25 #include "chromeos/cryptohome/cryptohome_parameters.h" |
| 26 #include "chromeos/dbus/dbus_method_call_status.h" | 26 #include "chromeos/dbus/dbus_method_call_status.h" |
| 27 #include "chromeos/dbus/dbus_thread_manager.h" | 27 #include "chromeos/dbus/dbus_thread_manager.h" |
| 28 #include "chromeos/dbus/session_manager_client.h" | 28 #include "chromeos/dbus/session_manager_client.h" |
| 29 #include "components/arc/arc_bridge_host_impl.h" |
| 29 #include "components/arc/arc_features.h" | 30 #include "components/arc/arc_features.h" |
| 30 #include "components/user_manager/user_manager.h" | 31 #include "components/user_manager/user_manager.h" |
| 31 #include "ipc/unix_domain_socket_util.h" | 32 #include "ipc/unix_domain_socket_util.h" |
| 32 #include "mojo/edk/embedder/embedder.h" | 33 #include "mojo/edk/embedder/embedder.h" |
| 33 #include "mojo/edk/embedder/platform_channel_pair.h" | 34 #include "mojo/edk/embedder/platform_channel_pair.h" |
| 34 #include "mojo/edk/embedder/platform_channel_utils_posix.h" | 35 #include "mojo/edk/embedder/platform_channel_utils_posix.h" |
| 35 #include "mojo/edk/embedder/platform_handle_vector.h" | 36 #include "mojo/edk/embedder/platform_handle_vector.h" |
| 36 #include "mojo/edk/embedder/scoped_platform_handle.h" | 37 #include "mojo/edk/embedder/scoped_platform_handle.h" |
| 37 #include "mojo/public/cpp/bindings/binding.h" | 38 #include "mojo/public/cpp/bindings/binding.h" |
| 38 | 39 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 // CREATING_SOCKET | 120 // CREATING_SOCKET |
| 120 // CreateSocket() -> OnSocketCreated() -> | 121 // CreateSocket() -> OnSocketCreated() -> |
| 121 // STARTING_INSTANCE | 122 // STARTING_INSTANCE |
| 122 // -> OnInstanceStarted() -> | 123 // -> OnInstanceStarted() -> |
| 123 // CONNECTING_MOJO | 124 // CONNECTING_MOJO |
| 124 // ConnectMojo() -> OnMojoConnected() -> | 125 // ConnectMojo() -> OnMojoConnected() -> |
| 125 // RUNNING | 126 // RUNNING |
| 126 // | 127 // |
| 127 // At any state, Stop() can be called. It does not immediately stop the | 128 // At any state, Stop() can be called. It does not immediately stop the |
| 128 // instance, but will eventually stop it. | 129 // instance, but will eventually stop it. |
| 129 // The actual stop will be notified via OnStopped() of the |delegate_|. | 130 // The actual stop will be notified via Observer::OnStopped(). |
| 130 // | 131 // |
| 131 // When Stop() is called, it makes various behavior based on the current | 132 // When Stop() is called, it makes various behavior based on the current |
| 132 // phase. | 133 // phase. |
| 133 // | 134 // |
| 134 // NOT_STARTED: | 135 // NOT_STARTED: |
| 135 // Do nothing. Immediately transition to the STOPPED state. | 136 // Do nothing. Immediately transition to the STOPPED state. |
| 136 // CHECKING_DISK_SPACE, CREATING_SOCKET: | 137 // CHECKING_DISK_SPACE, CREATING_SOCKET: |
| 137 // The main task of those phases runs on WorkerPool thread. So, Stop() | 138 // The main task of those phases runs on WorkerPool thread. So, Stop() |
| 138 // just sets the flag and return. On the main task completion, a callback | 139 // just sets the flag and return. On the main task completion, a callback |
| 139 // will run on the main (practically UI) thread, and the flag is checked | 140 // will run on the main (practically UI) thread, and the flag is checked |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 // The state of the bootstrap connection. | 242 // The state of the bootstrap connection. |
| 242 State state_ = State::NOT_STARTED; | 243 State state_ = State::NOT_STARTED; |
| 243 | 244 |
| 244 // When Stop() is called, this flag is set. | 245 // When Stop() is called, this flag is set. |
| 245 bool stop_requested_ = false; | 246 bool stop_requested_ = false; |
| 246 | 247 |
| 247 // 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 |
| 248 // to notify cancelling of the procedure. | 249 // to notify cancelling of the procedure. |
| 249 base::ScopedFD accept_cancel_pipe_; | 250 base::ScopedFD accept_cancel_pipe_; |
| 250 | 251 |
| 252 // Mojo endpoint. |
| 253 std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_; |
| 254 |
| 251 base::ThreadChecker thread_checker_; | 255 base::ThreadChecker thread_checker_; |
| 252 | 256 |
| 253 // WeakPtrFactory to use callbacks. | 257 // WeakPtrFactory to use callbacks. |
| 254 base::WeakPtrFactory<ArcBridgeBootstrapImpl> weak_factory_; | 258 base::WeakPtrFactory<ArcBridgeBootstrapImpl> weak_factory_; |
| 255 | 259 |
| 256 private: | 260 private: |
| 257 DISALLOW_COPY_AND_ASSIGN(ArcBridgeBootstrapImpl); | 261 DISALLOW_COPY_AND_ASSIGN(ArcBridgeBootstrapImpl); |
| 258 }; | 262 }; |
| 259 | 263 |
| 260 ArcBridgeBootstrapImpl::ArcBridgeBootstrapImpl() | 264 ArcBridgeBootstrapImpl::ArcBridgeBootstrapImpl() |
| 261 : weak_factory_(this) { | 265 : weak_factory_(this) { |
| 262 chromeos::SessionManagerClient* client = GetSessionManagerClient(); | 266 chromeos::SessionManagerClient* client = GetSessionManagerClient(); |
| 263 if (client == nullptr) | 267 if (client == nullptr) |
| 264 return; | 268 return; |
| 265 client->AddObserver(this); | 269 client->AddObserver(this); |
| 266 } | 270 } |
| 267 | 271 |
| 268 ArcBridgeBootstrapImpl::~ArcBridgeBootstrapImpl() { | 272 ArcBridgeBootstrapImpl::~ArcBridgeBootstrapImpl() { |
| 269 DCHECK(thread_checker_.CalledOnValidThread()); | 273 DCHECK(thread_checker_.CalledOnValidThread()); |
| 270 // TODO(hidehiko): CHECK if |state_| is in NOT_STARTED or STOPPED. | 274 // TODO(hidehiko): CHECK if |state_| is in NOT_STARTED or STOPPED. |
| 271 // Currently, specifically on shutdown, the state_ can be any value. | 275 // Currently, specifically on shutdown, the state_ can be any value. |
| 272 chromeos::SessionManagerClient* client = GetSessionManagerClient(); | 276 chromeos::SessionManagerClient* client = GetSessionManagerClient(); |
| 273 if (client == nullptr) | 277 if (client == nullptr) |
| 274 return; | 278 return; |
| 275 client->RemoveObserver(this); | 279 client->RemoveObserver(this); |
| 276 } | 280 } |
| 277 | 281 |
| 278 void ArcBridgeBootstrapImpl::Start() { | 282 void ArcBridgeBootstrapImpl::Start() { |
| 279 DCHECK(thread_checker_.CalledOnValidThread()); | 283 DCHECK(thread_checker_.CalledOnValidThread()); |
| 280 DCHECK(delegate_); | |
| 281 DCHECK_EQ(state_, State::NOT_STARTED); | 284 DCHECK_EQ(state_, State::NOT_STARTED); |
| 282 VLOG(2) << "Starting ARC session."; | 285 VLOG(2) << "Starting ARC session."; |
| 283 VLOG(2) << "Checking disk space..."; | 286 VLOG(2) << "Checking disk space..."; |
| 284 state_ = State::CHECKING_DISK_SPACE; | 287 state_ = State::CHECKING_DISK_SPACE; |
| 285 | 288 |
| 286 // TODO(crbug.com/628124): Move disk space checking logic to session_manager. | 289 // TODO(crbug.com/628124): Move disk space checking logic to session_manager. |
| 287 base::PostTaskAndReplyWithResult( | 290 base::PostTaskAndReplyWithResult( |
| 288 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, | 291 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, |
| 289 base::Bind(&base::SysInfo::AmountOfFreeDiskSpace, | 292 base::Bind(&base::SysInfo::AmountOfFreeDiskSpace, |
| 290 base::FilePath(kDiskCheckPath)), | 293 base::FilePath(kDiskCheckPath)), |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release()))); | 510 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release()))); |
| 508 if (!server_pipe.is_valid()) { | 511 if (!server_pipe.is_valid()) { |
| 509 LOG(ERROR) << "Invalid pipe"; | 512 LOG(ERROR) << "Invalid pipe"; |
| 510 StopArcInstance(); | 513 StopArcInstance(); |
| 511 return; | 514 return; |
| 512 } | 515 } |
| 513 | 516 |
| 514 mojom::ArcBridgeInstancePtr instance; | 517 mojom::ArcBridgeInstancePtr instance; |
| 515 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>( | 518 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>( |
| 516 std::move(server_pipe), 0u)); | 519 std::move(server_pipe), 0u)); |
| 517 // TODO(hidehiko): Move to creating ArcBridgeHost here to fix the twisted | 520 arc_bridge_host_.reset(new ArcBridgeHostImpl(std::move(instance))); |
| 518 // state change. | |
| 519 | 521 |
| 520 VLOG(2) << "Mojo is connected. ARC is running."; | 522 VLOG(2) << "Mojo is connected. ARC is running."; |
| 521 state_ = State::RUNNING; | 523 state_ = State::RUNNING; |
| 522 delegate_->OnConnectionEstablished(std::move(instance)); | 524 FOR_EACH_OBSERVER(ArcBridgeBootstrap::Observer, observer_list_, OnReady()); |
| 523 } | 525 } |
| 524 | 526 |
| 525 void ArcBridgeBootstrapImpl::Stop() { | 527 void ArcBridgeBootstrapImpl::Stop() { |
| 526 DCHECK(thread_checker_.CalledOnValidThread()); | 528 DCHECK(thread_checker_.CalledOnValidThread()); |
| 527 DCHECK(delegate_); | |
| 528 VLOG(2) << "Stopping ARC session is requested."; | 529 VLOG(2) << "Stopping ARC session is requested."; |
| 529 | 530 |
| 530 // For second time or later, just do nothing. | 531 // For second time or later, just do nothing. |
| 531 // It is already in the stopping phase. | 532 // It is already in the stopping phase. |
| 532 if (stop_requested_) | 533 if (stop_requested_) |
| 533 return; | 534 return; |
| 534 | 535 |
| 535 stop_requested_ = true; | 536 stop_requested_ = true; |
| 537 arc_bridge_host_.reset(); |
| 536 switch (state_) { | 538 switch (state_) { |
| 537 case State::NOT_STARTED: | 539 case State::NOT_STARTED: |
| 538 OnStopped(ArcBridgeService::StopReason::SHUTDOWN); | 540 OnStopped(ArcBridgeService::StopReason::SHUTDOWN); |
| 539 return; | 541 return; |
| 540 | 542 |
| 541 case State::CHECKING_DISK_SPACE: | 543 case State::CHECKING_DISK_SPACE: |
| 542 case State::CREATING_SOCKET: | 544 case State::CREATING_SOCKET: |
| 543 case State::STARTING_INSTANCE: | 545 case State::STARTING_INSTANCE: |
| 544 // Before starting the ARC instance, we do nothing here. | 546 // Before starting the ARC instance, we do nothing here. |
| 545 // At some point, a callback will be invoked on UI thread, | 547 // At some point, a callback will be invoked on UI thread, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 reason = ArcBridgeService::StopReason::CRASH; | 612 reason = ArcBridgeService::StopReason::CRASH; |
| 611 } | 613 } |
| 612 OnStopped(reason); | 614 OnStopped(reason); |
| 613 } | 615 } |
| 614 | 616 |
| 615 void ArcBridgeBootstrapImpl::OnStopped(ArcBridgeService::StopReason reason) { | 617 void ArcBridgeBootstrapImpl::OnStopped(ArcBridgeService::StopReason reason) { |
| 616 DCHECK(thread_checker_.CalledOnValidThread()); | 618 DCHECK(thread_checker_.CalledOnValidThread()); |
| 617 // OnStopped() should be called once per instance. | 619 // OnStopped() should be called once per instance. |
| 618 DCHECK_NE(state_, State::STOPPED); | 620 DCHECK_NE(state_, State::STOPPED); |
| 619 VLOG(2) << "ARC session is stopped."; | 621 VLOG(2) << "ARC session is stopped."; |
| 622 arc_bridge_host_.reset(); |
| 620 state_ = State::STOPPED; | 623 state_ = State::STOPPED; |
| 621 delegate_->OnStopped(reason); | 624 FOR_EACH_OBSERVER(ArcBridgeBootstrap::Observer, observer_list_, |
| 625 OnStopped(reason)); |
| 622 } | 626 } |
| 623 | 627 |
| 624 } // namespace | 628 } // namespace |
| 625 | 629 |
| 630 ArcBridgeBootstrap::ArcBridgeBootstrap() = default; |
| 631 ArcBridgeBootstrap::~ArcBridgeBootstrap() = default; |
| 632 |
| 633 void ArcBridgeBootstrap::AddObserver(Observer* observer) { |
| 634 observer_list_.AddObserver(observer); |
| 635 } |
| 636 |
| 637 void ArcBridgeBootstrap::RemoveObserver(Observer* observer) { |
| 638 observer_list_.RemoveObserver(observer); |
| 639 } |
| 640 |
| 626 // static | 641 // static |
| 627 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() { | 642 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() { |
| 628 return base::MakeUnique<ArcBridgeBootstrapImpl>(); | 643 return base::MakeUnique<ArcBridgeBootstrapImpl>(); |
| 629 } | 644 } |
| 630 | 645 |
| 631 } // namespace arc | 646 } // namespace arc |
| OLD | NEW |