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