| 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 "chromeos/cryptohome/cryptohome_parameters.h" | 24 #include "chromeos/cryptohome/cryptohome_parameters.h" | 
| 25 #include "chromeos/dbus/dbus_method_call_status.h" | 25 #include "chromeos/dbus/dbus_method_call_status.h" | 
| 26 #include "chromeos/dbus/dbus_thread_manager.h" | 26 #include "chromeos/dbus/dbus_thread_manager.h" | 
| 27 #include "chromeos/dbus/session_manager_client.h" | 27 #include "chromeos/dbus/session_manager_client.h" | 
| 28 #include "components/arc/arc_bridge_host_impl.h" | 28 #include "components/arc/arc_bridge_host_impl.h" | 
| 29 #include "components/arc/arc_features.h" | 29 #include "components/arc/arc_features.h" | 
|  | 30 #include "components/arc/arc_session_observer.h" | 
| 30 #include "components/user_manager/user_manager.h" | 31 #include "components/user_manager/user_manager.h" | 
| 31 #include "mojo/edk/embedder/embedder.h" | 32 #include "mojo/edk/embedder/embedder.h" | 
| 32 #include "mojo/edk/embedder/named_platform_handle.h" | 33 #include "mojo/edk/embedder/named_platform_handle.h" | 
| 33 #include "mojo/edk/embedder/named_platform_handle_utils.h" | 34 #include "mojo/edk/embedder/named_platform_handle_utils.h" | 
| 34 #include "mojo/edk/embedder/platform_channel_pair.h" | 35 #include "mojo/edk/embedder/platform_channel_pair.h" | 
| 35 #include "mojo/edk/embedder/platform_channel_utils_posix.h" | 36 #include "mojo/edk/embedder/platform_channel_utils_posix.h" | 
| 36 #include "mojo/edk/embedder/platform_handle_vector.h" | 37 #include "mojo/edk/embedder/platform_handle_vector.h" | 
| 37 #include "mojo/edk/embedder/scoped_platform_handle.h" | 38 #include "mojo/edk/embedder/scoped_platform_handle.h" | 
| 38 #include "mojo/public/cpp/bindings/binding.h" | 39 #include "mojo/public/cpp/bindings/binding.h" | 
| 39 | 40 | 
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 117   // CREATING_SOCKET | 118   // CREATING_SOCKET | 
| 118   //   CreateSocket() -> OnSocketCreated() -> | 119   //   CreateSocket() -> OnSocketCreated() -> | 
| 119   // STARTING_INSTANCE | 120   // STARTING_INSTANCE | 
| 120   //   -> OnInstanceStarted() -> | 121   //   -> OnInstanceStarted() -> | 
| 121   // CONNECTING_MOJO | 122   // CONNECTING_MOJO | 
| 122   //   ConnectMojo() -> OnMojoConnected() -> | 123   //   ConnectMojo() -> OnMojoConnected() -> | 
| 123   // RUNNING | 124   // RUNNING | 
| 124   // | 125   // | 
| 125   // At any state, Stop() can be called. It does not immediately stop the | 126   // At any state, Stop() can be called. It does not immediately stop the | 
| 126   // instance, but will eventually stop it. | 127   // instance, but will eventually stop it. | 
| 127   // The actual stop will be notified via Observer::OnStopped(). | 128   // The actual stop will be notified via ArcSessionObserver::OnStopped(). | 
| 128   // | 129   // | 
| 129   // When Stop() is called, it makes various behavior based on the current | 130   // When Stop() is called, it makes various behavior based on the current | 
| 130   // phase. | 131   // phase. | 
| 131   // | 132   // | 
| 132   // NOT_STARTED: | 133   // NOT_STARTED: | 
| 133   //   Do nothing. Immediately transition to the STOPPED state. | 134   //   Do nothing. Immediately transition to the STOPPED state. | 
| 134   // CREATING_SOCKET: | 135   // CREATING_SOCKET: | 
| 135   //   The main task of the phase runs on BlockingPool thread. So, Stop() just | 136   //   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 | 137   //   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 | 138   //   will run on the main (practically UI) thread, and the flag is checked | 
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 225       base::ScopedFD cancel_fd); | 226       base::ScopedFD cancel_fd); | 
| 226   void OnMojoConnected(mojo::edk::ScopedPlatformHandle fd); | 227   void OnMojoConnected(mojo::edk::ScopedPlatformHandle fd); | 
| 227 | 228 | 
| 228   // Request to stop ARC instance via DBus. | 229   // Request to stop ARC instance via DBus. | 
| 229   void StopArcInstance(); | 230   void StopArcInstance(); | 
| 230 | 231 | 
| 231   // chromeos::SessionManagerClient::Observer: | 232   // chromeos::SessionManagerClient::Observer: | 
| 232   void ArcInstanceStopped(bool clean) override; | 233   void ArcInstanceStopped(bool clean) override; | 
| 233 | 234 | 
| 234   // Completes the termination procedure. | 235   // Completes the termination procedure. | 
| 235   void OnStopped(ArcBridgeService::StopReason reason); | 236   void OnStopped(ArcSessionObserver::StopReason reason); | 
| 236 | 237 | 
| 237   // Checks whether a function runs on the thread where the instance is | 238   // Checks whether a function runs on the thread where the instance is | 
| 238   // created. | 239   // created. | 
| 239   base::ThreadChecker thread_checker_; | 240   base::ThreadChecker thread_checker_; | 
| 240 | 241 | 
| 241   // Owned by ArcServiceManager. | 242   // Owned by ArcServiceManager. | 
| 242   ArcBridgeService* const arc_bridge_service_; | 243   ArcBridgeService* const arc_bridge_service_; | 
| 243 | 244 | 
| 244   // Task runner to run a blocking tasks. | 245   // Task runner to run a blocking tasks. | 
| 245   scoped_refptr<base::TaskRunner> blocking_task_runner_; | 246   scoped_refptr<base::TaskRunner> blocking_task_runner_; | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 336   return socket_fd; | 337   return socket_fd; | 
| 337 } | 338 } | 
| 338 | 339 | 
| 339 void ArcSessionImpl::OnSocketCreated( | 340 void ArcSessionImpl::OnSocketCreated( | 
| 340     mojo::edk::ScopedPlatformHandle socket_fd) { | 341     mojo::edk::ScopedPlatformHandle socket_fd) { | 
| 341   DCHECK(thread_checker_.CalledOnValidThread()); | 342   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 342   DCHECK_EQ(state_, State::CREATING_SOCKET); | 343   DCHECK_EQ(state_, State::CREATING_SOCKET); | 
| 343 | 344 | 
| 344   if (stop_requested_) { | 345   if (stop_requested_) { | 
| 345     VLOG(1) << "Stop() called while connecting"; | 346     VLOG(1) << "Stop() called while connecting"; | 
| 346     OnStopped(ArcBridgeService::StopReason::SHUTDOWN); | 347     OnStopped(ArcSessionObserver::StopReason::SHUTDOWN); | 
| 347     return; | 348     return; | 
| 348   } | 349   } | 
| 349 | 350 | 
| 350   if (!socket_fd.is_valid()) { | 351   if (!socket_fd.is_valid()) { | 
| 351     LOG(ERROR) << "ARC: Error creating socket"; | 352     LOG(ERROR) << "ARC: Error creating socket"; | 
| 352     OnStopped(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); | 353     OnStopped(ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE); | 
| 353     return; | 354     return; | 
| 354   } | 355   } | 
| 355 | 356 | 
| 356   VLOG(2) << "Socket is created. Starting ARC instance..."; | 357   VLOG(2) << "Socket is created. Starting ARC instance..."; | 
| 357   state_ = State::STARTING_INSTANCE; | 358   state_ = State::STARTING_INSTANCE; | 
| 358   user_manager::UserManager* user_manager = user_manager::UserManager::Get(); | 359   user_manager::UserManager* user_manager = user_manager::UserManager::Get(); | 
| 359   DCHECK(user_manager->GetPrimaryUser()); | 360   DCHECK(user_manager->GetPrimaryUser()); | 
| 360   const cryptohome::Identification cryptohome_id( | 361   const cryptohome::Identification cryptohome_id( | 
| 361       user_manager->GetPrimaryUser()->GetAccountId()); | 362       user_manager->GetPrimaryUser()->GetAccountId()); | 
| 362 | 363 | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 383   } | 384   } | 
| 384 | 385 | 
| 385   DCHECK_EQ(state_, State::STARTING_INSTANCE); | 386   DCHECK_EQ(state_, State::STARTING_INSTANCE); | 
| 386 | 387 | 
| 387   if (stop_requested_) { | 388   if (stop_requested_) { | 
| 388     if (result == StartArcInstanceResult::SUCCESS) { | 389     if (result == StartArcInstanceResult::SUCCESS) { | 
| 389       // The ARC instance has started to run. Request to stop. | 390       // The ARC instance has started to run. Request to stop. | 
| 390       StopArcInstance(); | 391       StopArcInstance(); | 
| 391       return; | 392       return; | 
| 392     } | 393     } | 
| 393     OnStopped(ArcBridgeService::StopReason::SHUTDOWN); | 394     OnStopped(ArcSessionObserver::StopReason::SHUTDOWN); | 
| 394     return; | 395     return; | 
| 395   } | 396   } | 
| 396 | 397 | 
| 397   if (result != StartArcInstanceResult::SUCCESS) { | 398   if (result != StartArcInstanceResult::SUCCESS) { | 
| 398     LOG(ERROR) << "Failed to start ARC instance"; | 399     LOG(ERROR) << "Failed to start ARC instance"; | 
| 399     OnStopped(result == StartArcInstanceResult::LOW_FREE_DISK_SPACE | 400     OnStopped(result == StartArcInstanceResult::LOW_FREE_DISK_SPACE | 
| 400                   ? ArcBridgeService::StopReason::LOW_DISK_SPACE | 401                   ? ArcSessionObserver::StopReason::LOW_DISK_SPACE | 
| 401                   : ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); | 402                   : ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE); | 
| 402     return; | 403     return; | 
| 403   } | 404   } | 
| 404 | 405 | 
| 405   VLOG(2) << "ARC instance is successfully started. Connecting Mojo..."; | 406   VLOG(2) << "ARC instance is successfully started. Connecting Mojo..."; | 
| 406   state_ = State::CONNECTING_MOJO; | 407   state_ = State::CONNECTING_MOJO; | 
| 407 | 408 | 
| 408   // Prepare a pipe so that AcceptInstanceConnection can be interrupted on | 409   // Prepare a pipe so that AcceptInstanceConnection can be interrupted on | 
| 409   // Stop(). | 410   // Stop(). | 
| 410   base::ScopedFD cancel_fd; | 411   base::ScopedFD cancel_fd; | 
| 411   if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) { | 412   if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) { | 
| 412     OnStopped(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); | 413     OnStopped(ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE); | 
| 413     return; | 414     return; | 
| 414   } | 415   } | 
| 415 | 416 | 
| 416   base::PostTaskAndReplyWithResult( | 417   base::PostTaskAndReplyWithResult( | 
| 417       blocking_task_runner_.get(), FROM_HERE, | 418       blocking_task_runner_.get(), FROM_HERE, | 
| 418       base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd), | 419       base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd), | 
| 419                  base::Passed(&cancel_fd)), | 420                  base::Passed(&cancel_fd)), | 
| 420       base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr())); | 421       base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr())); | 
| 421 } | 422 } | 
| 422 | 423 | 
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 508 | 509 | 
| 509   // For second time or later, just do nothing. | 510   // For second time or later, just do nothing. | 
| 510   // It is already in the stopping phase. | 511   // It is already in the stopping phase. | 
| 511   if (stop_requested_) | 512   if (stop_requested_) | 
| 512     return; | 513     return; | 
| 513 | 514 | 
| 514   stop_requested_ = true; | 515   stop_requested_ = true; | 
| 515   arc_bridge_host_.reset(); | 516   arc_bridge_host_.reset(); | 
| 516   switch (state_) { | 517   switch (state_) { | 
| 517     case State::NOT_STARTED: | 518     case State::NOT_STARTED: | 
| 518       OnStopped(ArcBridgeService::StopReason::SHUTDOWN); | 519       OnStopped(ArcSessionObserver::StopReason::SHUTDOWN); | 
| 519       return; | 520       return; | 
| 520 | 521 | 
| 521     case State::CREATING_SOCKET: | 522     case State::CREATING_SOCKET: | 
| 522     case State::STARTING_INSTANCE: | 523     case State::STARTING_INSTANCE: | 
| 523       // Before starting the ARC instance, we do nothing here. | 524       // Before starting the ARC instance, we do nothing here. | 
| 524       // At some point, a callback will be invoked on UI thread, | 525       // At some point, a callback will be invoked on UI thread, | 
| 525       // and stopping procedure will be run there. | 526       // and stopping procedure will be run there. | 
| 526       // On Chrome shutdown, it is not the case because the message loop is | 527       // On Chrome shutdown, it is not the case because the message loop is | 
| 527       // already stopped here. Practically, it is not a problem because; | 528       // already stopped here. Practically, it is not a problem because; | 
| 528       // - On socket creating, it is ok to simply ignore such cases, | 529       // - On socket creating, it is ok to simply ignore such cases, | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 565 | 566 | 
| 566 void ArcSessionImpl::ArcInstanceStopped(bool clean) { | 567 void ArcSessionImpl::ArcInstanceStopped(bool clean) { | 
| 567   DCHECK(thread_checker_.CalledOnValidThread()); | 568   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 568   VLOG(1) << "Notified that ARC instance is stopped " | 569   VLOG(1) << "Notified that ARC instance is stopped " | 
| 569           << (clean ? "cleanly" : "uncleanly"); | 570           << (clean ? "cleanly" : "uncleanly"); | 
| 570 | 571 | 
| 571   // In case that crash happens during before the Mojo channel is connected, | 572   // In case that crash happens during before the Mojo channel is connected, | 
| 572   // unlock the BlockingPool thread. | 573   // unlock the BlockingPool thread. | 
| 573   accept_cancel_pipe_.reset(); | 574   accept_cancel_pipe_.reset(); | 
| 574 | 575 | 
| 575   ArcBridgeService::StopReason reason; | 576   ArcSessionObserver::StopReason reason; | 
| 576   if (stop_requested_) { | 577   if (stop_requested_) { | 
| 577     // If the ARC instance is stopped after its explicit request, | 578     // If the ARC instance is stopped after its explicit request, | 
| 578     // return SHUTDOWN. | 579     // return SHUTDOWN. | 
| 579     reason = ArcBridgeService::StopReason::SHUTDOWN; | 580     reason = ArcSessionObserver::StopReason::SHUTDOWN; | 
| 580   } else if (clean) { | 581   } else if (clean) { | 
| 581     // If the ARC instance is stopped, but it is not explicitly requested, | 582     // If the ARC instance is stopped, but it is not explicitly requested, | 
| 582     // then this is triggered by some failure during the starting procedure. | 583     // then this is triggered by some failure during the starting procedure. | 
| 583     // Return GENERIC_BOOT_FAILURE for the case. | 584     // Return GENERIC_BOOT_FAILURE for the case. | 
| 584     reason = ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE; | 585     reason = ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE; | 
| 585   } else { | 586   } else { | 
| 586     // Otherwise, this is caused by CRASH occured inside of the ARC instance. | 587     // Otherwise, this is caused by CRASH occured inside of the ARC instance. | 
| 587     reason = ArcBridgeService::StopReason::CRASH; | 588     reason = ArcSessionObserver::StopReason::CRASH; | 
| 588   } | 589   } | 
| 589   OnStopped(reason); | 590   OnStopped(reason); | 
| 590 } | 591 } | 
| 591 | 592 | 
| 592 void ArcSessionImpl::OnStopped(ArcBridgeService::StopReason reason) { | 593 void ArcSessionImpl::OnStopped(ArcSessionObserver::StopReason reason) { | 
| 593   DCHECK(thread_checker_.CalledOnValidThread()); | 594   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 594   // OnStopped() should be called once per instance. | 595   // OnStopped() should be called once per instance. | 
| 595   DCHECK_NE(state_, State::STOPPED); | 596   DCHECK_NE(state_, State::STOPPED); | 
| 596   VLOG(2) << "ARC session is stopped."; | 597   VLOG(2) << "ARC session is stopped."; | 
| 597   arc_bridge_host_.reset(); | 598   arc_bridge_host_.reset(); | 
| 598   state_ = State::STOPPED; | 599   state_ = State::STOPPED; | 
| 599   for (auto& observer : observer_list_) | 600   for (auto& observer : observer_list_) | 
| 600     observer.OnStopped(reason); | 601     observer.OnStopped(reason); | 
| 601 } | 602 } | 
| 602 | 603 | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 615   // Stops the ARC instance to let it graceful shutdown. | 616   // Stops the ARC instance to let it graceful shutdown. | 
| 616   // Note that this may fail if ARC container is not actually running, but | 617   // Note that this may fail if ARC container is not actually running, but | 
| 617   // ignore an error as described below. | 618   // ignore an error as described below. | 
| 618   if (state_ == State::STARTING_INSTANCE || | 619   if (state_ == State::STARTING_INSTANCE || | 
| 619       state_ == State::CONNECTING_MOJO || state_ == State::RUNNING) | 620       state_ == State::CONNECTING_MOJO || state_ == State::RUNNING) | 
| 620     StopArcInstance(); | 621     StopArcInstance(); | 
| 621 | 622 | 
| 622   // Directly set to the STOPPED stateby OnStopped(). Note that calling | 623   // Directly set to the STOPPED stateby OnStopped(). Note that calling | 
| 623   // StopArcInstance() may not work well. At least, because the UI thread is | 624   // StopArcInstance() may not work well. At least, because the UI thread is | 
| 624   // already stopped here, ArcInstanceStopped() callback cannot be invoked. | 625   // already stopped here, ArcInstanceStopped() callback cannot be invoked. | 
| 625   OnStopped(ArcBridgeService::StopReason::SHUTDOWN); | 626   OnStopped(ArcSessionObserver::StopReason::SHUTDOWN); | 
| 626 } | 627 } | 
| 627 | 628 | 
| 628 }  // namespace | 629 }  // namespace | 
| 629 | 630 | 
| 630 ArcSession::ArcSession() = default; | 631 ArcSession::ArcSession() = default; | 
| 631 ArcSession::~ArcSession() = default; | 632 ArcSession::~ArcSession() = default; | 
| 632 | 633 | 
| 633 void ArcSession::AddObserver(Observer* observer) { | 634 void ArcSession::AddObserver(ArcSessionObserver* observer) { | 
| 634   observer_list_.AddObserver(observer); | 635   observer_list_.AddObserver(observer); | 
| 635 } | 636 } | 
| 636 | 637 | 
| 637 void ArcSession::RemoveObserver(Observer* observer) { | 638 void ArcSession::RemoveObserver(ArcSessionObserver* observer) { | 
| 638   observer_list_.RemoveObserver(observer); | 639   observer_list_.RemoveObserver(observer); | 
| 639 } | 640 } | 
| 640 | 641 | 
| 641 // static | 642 // static | 
| 642 std::unique_ptr<ArcSession> ArcSession::Create( | 643 std::unique_ptr<ArcSession> ArcSession::Create( | 
| 643     ArcBridgeService* arc_bridge_service, | 644     ArcBridgeService* arc_bridge_service, | 
| 644     const scoped_refptr<base::TaskRunner>& blocking_task_runner) { | 645     const scoped_refptr<base::TaskRunner>& blocking_task_runner) { | 
| 645   return base::MakeUnique<ArcSessionImpl>(arc_bridge_service, | 646   return base::MakeUnique<ArcSessionImpl>(arc_bridge_service, | 
| 646                                           blocking_task_runner); | 647                                           blocking_task_runner); | 
| 647 } | 648 } | 
| 648 | 649 | 
| 649 }  // namespace arc | 650 }  // namespace arc | 
| OLD | NEW | 
|---|