summaryrefslogtreecommitdiff
path: root/chromium/components/arc/arc_session.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 10:33:36 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:45:12 +0000
commitbe59a35641616a4cf23c4a13fa0632624b021c1b (patch)
tree9da183258bdf9cc413f7562079d25ace6955467f /chromium/components/arc/arc_session.cc
parentd702e4b6a64574e97fc7df8fe3238cde70242080 (diff)
downloadqtwebengine-chromium-be59a35641616a4cf23c4a13fa0632624b021c1b.tar.gz
BASELINE: Update Chromium to 62.0.3202.101
Change-Id: I2d5eca8117600df6d331f6166ab24d943d9814ac Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/arc/arc_session.cc')
-rw-r--r--chromium/components/arc/arc_session.cc193
1 files changed, 51 insertions, 142 deletions
diff --git a/chromium/components/arc/arc_session.cc b/chromium/components/arc/arc_session.cc
index bfe9c8a4b91..64b543e2454 100644
--- a/chromium/components/arc/arc_session.cc
+++ b/chromium/components/arc/arc_session.cc
@@ -12,7 +12,6 @@
#include <string>
#include <utility>
-#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
@@ -48,11 +47,6 @@ namespace {
using StartArcInstanceResult =
chromeos::SessionManagerClient::StartArcInstanceResult;
-const base::FilePath::CharType kArcBridgeSocketPath[] =
- FILE_PATH_LITERAL("/var/run/chrome/arc_bridge.sock");
-
-const char kArcBridgeSocketGroup[] = "arc-bridge";
-
// This is called when StopArcInstance D-Bus method completes. Since we have the
// ArcInstanceStopped() callback and are notified if StartArcInstance fails, we
// don't need to do anything when StopArcInstance completes.
@@ -118,8 +112,6 @@ class ArcSessionImpl : public ArcSession,
//
// NOT_STARTED
// Start() ->
- // CREATING_SOCKET
- // CreateSocket() -> OnSocketCreated() ->
// STARTING_INSTANCE
// -> OnInstanceStarted() ->
// CONNECTING_MOJO
@@ -132,14 +124,12 @@ class ArcSessionImpl : public ArcSession,
//
// NOT_STARTED
// StartForLoginScreen() ->
- // CREATING_SOCKET
- // CreateSocket() -> OnSocketCreated() ->
// STARTING_INSTANCE
// -> OnInstanceStarted() ->
// RUNNING_FOR_LOGIN_SCREEN
//
- // Start() can also be used at any of these 3 state (from CREATING_SOCKET to
- // RUNNING_FOR_LOGIN_SCREEN) to turn the instance for login screen into a
+ // Start() can also be used at both STARTING_INSTANCE and
+ // RUNNING_FOR_LOGIN_SCREEN to turn the instance for login screen into a
// fully functional one.
//
// Regardless of whether the instance is for login screen or not, at any
@@ -152,21 +142,17 @@ class ArcSessionImpl : public ArcSession,
//
// NOT_STARTED:
// Do nothing. Immediately transition to the STOPPED state.
- // CREATING_SOCKET:
- // The main task of the phase runs on BlockingPool thread. So, Stop() just
- // sets the flag and return. On the main task completion, a callback
- // will run on the main (practically UI) thread, and the flag is checked
- // at the beginning of them. This should work under the assumption that
- // the main tasks do not block indefinitely.
// STARTING_INSTANCE:
- // The ARC instance is starting via SessionManager. So, similar to
- // CREATING_SOCKET case, Stop() just sets the flag and return. In its
- // callback, it checks if ARC instance is successfully started or not.
- // In case of success, a request to stop the ARC instance is sent to
+ // The ARC instance is starting via SessionManager. Stop() just sets the
+ // flag and return. On the main task completion, a callback will run on the
+ // thread, and the flag is checked at the beginning of them. This should
+ // work under the assumption that the main tasks do not block indefinitely.
+ // In its callback, it checks if ARC instance is successfully started or
+ // not. In case of success, a request to stop the ARC instance is sent to
// SessionManager. Its completion will be notified via ArcInstanceStopped.
// Otherwise, it just turns into STOPPED state.
// CONNECTING_MOJO:
- // The main task runs on BlockingPool thread, but it is blocking call.
+ // The main task runs on TaskScheduler's thread, but it is a blocking call.
// So, Stop() sends a request to cancel the blocking by closing the pipe
// whose read side is also polled. Then, in its callback, similar to
// STARTING_INSTANCE, a request to stop the ARC instance is sent to
@@ -192,9 +178,6 @@ class ArcSessionImpl : public ArcSession,
// ARC is not yet started.
NOT_STARTED,
- // An UNIX socket is being created.
- CREATING_SOCKET,
-
// The request to start or resume the instance has been sent.
STARTING_INSTANCE,
@@ -223,17 +206,11 @@ class ArcSessionImpl : public ArcSession,
void OnShutdown() override;
private:
- // Creates the UNIX socket on a worker pool and then processes its file
- // descriptor.
- static mojo::edk::ScopedPlatformHandle CreateSocket();
- void OnSocketCreated(bool instance_is_for_login_screen,
- mojo::edk::ScopedPlatformHandle fd);
-
// DBus callback for StartArcInstance().
void OnInstanceStarted(bool instance_is_for_login_screen,
- mojo::edk::ScopedPlatformHandle socket_fd,
StartArcInstanceResult result,
- const std::string& container_instance_id);
+ const std::string& container_instance_id,
+ base::ScopedFD socket_fd);
// Synchronously accepts a connection on |socket_fd| and then processes the
// connected socket's file descriptor.
@@ -275,10 +252,6 @@ class ArcSessionImpl : public ArcSession,
// that, when Start() is called to resume the boot, the flag is unset.
bool login_screen_instance_requested_ = false;
- // The handle StartForLoginScreen() has created. The variable has a
- // valid handle only when |state_| is RUNNING_FOR_LOGIN_SCREEN.
- mojo::edk::ScopedPlatformHandle socket_fd_;
-
// Container instance id passed from session_manager.
// Should be available only after OnInstanceStarted().
std::string container_instance_id_;
@@ -322,7 +295,7 @@ void ArcSessionImpl::Start() {
// RUNNING_FOR_LOGIN_SCREEN.
DCHECK_GE(State::RUNNING_FOR_LOGIN_SCREEN, state_);
- // Flip the flag now so that callback functions like OnSocketCreated()
+ // Flip the flag now so that callback functions like OnInstanceStarted()
// can do the right thing.
login_screen_instance_requested_ = false;
@@ -330,16 +303,13 @@ void ArcSessionImpl::Start() {
// An instance for login screen does not exist. Start a new one from
// scratch.
VLOG(2) << "Starting ARC session";
- VLOG(2) << "Creating socket...";
- state_ = State::CREATING_SOCKET;
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()},
- base::Bind(&ArcSessionImpl::CreateSocket),
- base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr(),
- false /* not for login screen */));
- } else if (state_ == State::CREATING_SOCKET) {
- VLOG(2) << "Requested to start ARC instance with an existing socket";
- // OnSocketCreated() will start a fully featured instance.
+ state_ = State::STARTING_INSTANCE;
+ SendStartArcInstanceDBusMessage(
+ false /* instance_is_for_login_screen */,
+ base::Bind(&ArcSessionImpl::OnInstanceStarted,
+ weak_factory_.GetWeakPtr(),
+ false /* instance_is_for_login_screen */));
+
} else if (state_ == State::STARTING_INSTANCE) {
VLOG(2) << "Requested to resume an existing ARC instance";
// OnInstanceStarted() will start a fully featured instance.
@@ -347,76 +317,11 @@ void ArcSessionImpl::Start() {
VLOG(2) << "Resuming an existing ARC instance";
state_ = State::STARTING_INSTANCE;
SendStartArcInstanceDBusMessage(
- false /* not for login screen */,
+ false /* instance_is_for_login_screen */,
base::Bind(&ArcSessionImpl::OnInstanceStarted,
- weak_factory_.GetWeakPtr(), false /* the same */,
- base::Passed(&socket_fd_)));
- }
-}
-
-// static
-mojo::edk::ScopedPlatformHandle ArcSessionImpl::CreateSocket() {
- base::FilePath socket_path(kArcBridgeSocketPath);
-
- mojo::edk::ScopedPlatformHandle socket_fd = mojo::edk::CreateServerHandle(
- mojo::edk::NamedPlatformHandle(socket_path.value()));
- if (!socket_fd.is_valid())
- return socket_fd;
-
- // Change permissions on the socket.
- struct group arc_bridge_group;
- struct group* arc_bridge_group_res = nullptr;
- char buf[10000];
- if (HANDLE_EINTR(getgrnam_r(kArcBridgeSocketGroup, &arc_bridge_group, buf,
- sizeof(buf), &arc_bridge_group_res)) < 0) {
- PLOG(ERROR) << "getgrnam_r";
- return mojo::edk::ScopedPlatformHandle();
- }
-
- if (!arc_bridge_group_res) {
- LOG(ERROR) << "Group '" << kArcBridgeSocketGroup << "' not found";
- return mojo::edk::ScopedPlatformHandle();
- }
-
- if (HANDLE_EINTR(chown(kArcBridgeSocketPath, -1, arc_bridge_group.gr_gid)) <
- 0) {
- PLOG(ERROR) << "chown";
- return mojo::edk::ScopedPlatformHandle();
- }
-
- if (!base::SetPosixFilePermissions(socket_path, 0660)) {
- PLOG(ERROR) << "Could not set permissions: " << socket_path.value();
- return mojo::edk::ScopedPlatformHandle();
- }
-
- return socket_fd;
-}
-
-void ArcSessionImpl::OnSocketCreated(
- bool instance_is_for_login_screen,
- mojo::edk::ScopedPlatformHandle socket_fd) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(state_, State::CREATING_SOCKET);
-
- if (stop_requested_) {
- VLOG(1) << "Stop() called while connecting";
- OnStopped(ArcStopReason::SHUTDOWN);
- return;
+ weak_factory_.GetWeakPtr(),
+ false /* instance_is_for_login_screen */));
}
-
- if (!socket_fd.is_valid()) {
- LOG(ERROR) << "ARC: Error creating socket";
- OnStopped(ArcStopReason::GENERIC_BOOT_FAILURE);
- return;
- }
-
- VLOG(2) << "Socket is created. Starting ARC instance"
- << (instance_is_for_login_screen ? " for login screen" : "");
- state_ = State::STARTING_INSTANCE;
- SendStartArcInstanceDBusMessage(
- instance_is_for_login_screen,
- base::Bind(&ArcSessionImpl::OnInstanceStarted, weak_factory_.GetWeakPtr(),
- instance_is_for_login_screen, base::Passed(&socket_fd)));
}
// static
@@ -425,11 +330,14 @@ void ArcSessionImpl::SendStartArcInstanceDBusMessage(
const chromeos::SessionManagerClient::StartArcInstanceCallback& cb) {
chromeos::SessionManagerClient* session_manager_client =
chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
+ const bool native_bridge_experiment =
+ base::FeatureList::IsEnabled(arc::kNativeBridgeExperimentFeature);
if (instance_is_for_login_screen) {
session_manager_client->StartArcInstance(
chromeos::SessionManagerClient::ArcStartupMode::LOGIN_SCREEN,
// All variables below except |cb| will be ignored.
- cryptohome::Identification(), false, false, cb);
+ cryptohome::Identification(), false, false,
+ native_bridge_experiment, cb);
return;
}
@@ -448,14 +356,14 @@ void ArcSessionImpl::SendStartArcInstanceDBusMessage(
session_manager_client->StartArcInstance(
chromeos::SessionManagerClient::ArcStartupMode::FULL, cryptohome_id,
- skip_boot_completed_broadcast, scan_vendor_priv_app, cb);
+ skip_boot_completed_broadcast, scan_vendor_priv_app,
+ native_bridge_experiment, cb);
}
-void ArcSessionImpl::OnInstanceStarted(
- bool instance_is_for_login_screen,
- mojo::edk::ScopedPlatformHandle socket_fd,
- StartArcInstanceResult result,
- const std::string& container_instance_id) {
+void ArcSessionImpl::OnInstanceStarted(bool instance_is_for_login_screen,
+ StartArcInstanceResult result,
+ const std::string& container_instance_id,
+ base::ScopedFD socket_fd) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_EQ(state_, State::STARTING_INSTANCE);
@@ -492,16 +400,15 @@ void ArcSessionImpl::OnInstanceStarted(
VLOG(2) << "ARC instance for login screen is successfully started.";
if (login_screen_instance_requested_) {
state_ = State::RUNNING_FOR_LOGIN_SCREEN;
- socket_fd_ = std::move(socket_fd);
} else {
// Start() has been called.
VLOG(2) << "Resuming an existing ARC instance";
state_ = State::STARTING_INSTANCE;
SendStartArcInstanceDBusMessage(
- false /* not for login screen */,
+ false /* instance_is_for_login_screen */,
base::Bind(&ArcSessionImpl::OnInstanceStarted,
- weak_factory_.GetWeakPtr(), false /* the same */,
- base::Passed(&socket_fd_)));
+ weak_factory_.GetWeakPtr(),
+ false /* instance_is_for_login_screen */));
}
return;
}
@@ -518,9 +425,16 @@ void ArcSessionImpl::OnInstanceStarted(
return;
}
+ // For production, |socket_fd| passed from session_manager is either a valid
+ // socket or a valid file descriptor (/dev/null). For testing, |socket_fd|
+ // might be invalid.
+ mojo::edk::PlatformHandle raw_handle(socket_fd.release());
+ raw_handle.needs_connection = true;
+
+ mojo::edk::ScopedPlatformHandle mojo_socket_fd(raw_handle);
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {base::MayBlock()},
- base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd),
+ base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&mojo_socket_fd),
base::Passed(&cancel_fd)),
base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr()));
}
@@ -620,15 +534,12 @@ void ArcSessionImpl::Stop() {
OnStopped(ArcStopReason::SHUTDOWN);
return;
- case State::CREATING_SOCKET:
case State::STARTING_INSTANCE:
// Before starting the ARC instance, we do nothing here.
// At some point, a callback will be invoked on UI thread,
// and stopping procedure will be run there.
// On Chrome shutdown, it is not the case because the message loop is
// already stopped here. Practically, it is not a problem because;
- // - On socket creating, it is ok to simply ignore such cases,
- // because we no-longer continue the bootstrap procedure.
// - On starting instance, the container instance can be leaked.
// Practically it is not problematic because the session manager will
// clean it up.
@@ -640,7 +551,7 @@ void ArcSessionImpl::Stop() {
return;
case State::CONNECTING_MOJO:
- // Mojo connection is being waited on a BlockingPool thread.
+ // Mojo connection is being waited on TaskScheduler's thread.
// Request to cancel it. Following stopping procedure will run
// in its callback.
accept_cancel_pipe_.reset();
@@ -690,7 +601,7 @@ void ArcSessionImpl::ArcInstanceStopped(
container_instance_id_.clear();
// In case that crash happens during before the Mojo channel is connected,
- // unlock the BlockingPool thread.
+ // unlock the TaskScheduler's thread.
accept_cancel_pipe_.reset();
ArcStopReason reason;
@@ -714,13 +625,12 @@ void ArcSessionImpl::StartForLoginScreen() {
DCHECK_EQ(State::NOT_STARTED, state_);
VLOG(2) << "Starting ARC session for login screen";
- VLOG(2) << "Creating socket...";
login_screen_instance_requested_ = true;
- state_ = State::CREATING_SOCKET;
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()}, base::Bind(&ArcSessionImpl::CreateSocket),
- base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr(),
- true /* for login screen */));
+ state_ = State::STARTING_INSTANCE;
+ SendStartArcInstanceDBusMessage(
+ true /* instance_is_for_login_screen */,
+ base::Bind(&ArcSessionImpl::OnInstanceStarted, weak_factory_.GetWeakPtr(),
+ true /* instance_is_for_login_screen */));
}
bool ArcSessionImpl::IsForLoginScreen() {
@@ -746,8 +656,7 @@ void ArcSessionImpl::OnShutdown() {
// Here, the message loop is already stopped, and the Chrome will be soon
// shutdown. Thus, it is not necessary to take care about restarting case.
- // If ArcSession is waiting for mojo connection, cancels it. The BlockingPool
- // will be joined later.
+ // If ArcSession is waiting for mojo connection, cancels it.
accept_cancel_pipe_.reset();
// Stops the ARC instance to let it graceful shutdown.