// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/arc/arc_session.h"

#include <fcntl.h>
#include <grp.h>
#include <poll.h>
#include <unistd.h>

#include <string>
#include <utility>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sys_info.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/arc/arc_bridge_host_impl.h"
#include "components/arc/arc_features.h"
#include "components/arc/arc_session_observer.h"
#include "components/user_manager/user_manager.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/named_platform_handle_utils.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/public/cpp/bindings/binding.h"

namespace arc {

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.
void DoNothingInstanceStopped(bool) {}

chromeos::SessionManagerClient* GetSessionManagerClient() {
  // If the DBusThreadManager or the SessionManagerClient aren't available,
  // there isn't much we can do. This should only happen when running tests.
  if (!chromeos::DBusThreadManager::IsInitialized() ||
      !chromeos::DBusThreadManager::Get() ||
      !chromeos::DBusThreadManager::Get()->GetSessionManagerClient())
    return nullptr;
  return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
}

// Creates a pipe. Returns true on success, otherwise false.
// On success, |read_fd| will be set to the fd of the read side, and
// |write_fd| will be set to the one of write side.
bool CreatePipe(base::ScopedFD* read_fd, base::ScopedFD* write_fd) {
  int fds[2];
  if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0) {
    PLOG(ERROR) << "pipe2()";
    return false;
  }

  read_fd->reset(fds[0]);
  write_fd->reset(fds[1]);
  return true;
}

// Waits until |raw_socket_fd| is readable.
// The operation may be cancelled originally triggered by user interaction to
// disable ARC, or ARC instance is unexpectedly stopped (e.g. crash).
// To notify such a situation, |raw_cancel_fd| is also passed to here, and the
// write side will be closed in such a case.
bool WaitForSocketReadable(int raw_socket_fd, int raw_cancel_fd) {
  struct pollfd fds[2] = {
      {raw_socket_fd, POLLIN, 0}, {raw_cancel_fd, POLLIN, 0},
  };

  if (HANDLE_EINTR(poll(fds, arraysize(fds), -1)) <= 0) {
    PLOG(ERROR) << "poll()";
    return false;
  }

  if (fds[1].revents) {
    // Notified that Stop() is invoked. Cancel the Mojo connecting.
    VLOG(1) << "Stop() was called during ConnectMojo()";
    return false;
  }

  DCHECK(fds[0].revents);
  return true;
}

// TODO(hidehiko): Refactor more to make this class unittest-able, for at least
// state-machine part.
class ArcSessionImpl : public ArcSession,
                       public chromeos::SessionManagerClient::Observer {
 public:
  // The possible states of the session.  In the normal flow, the state changes
  // in the following sequence:
  //
  // NOT_STARTED
  //   Start() ->
  // CREATING_SOCKET
  //   CreateSocket() -> OnSocketCreated() ->
  // STARTING_INSTANCE
  //   -> OnInstanceStarted() ->
  // CONNECTING_MOJO
  //   ConnectMojo() -> OnMojoConnected() ->
  // RUNNING
  //
  // At any state, Stop() can be called. It does not immediately stop the
  // instance, but will eventually stop it.
  // The actual stop will be notified via ArcSessionObserver::OnStopped().
  //
  // When Stop() is called, it makes various behavior based on the current
  // phase.
  //
  // 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
  //   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.
  //   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
  //   SessionManager, and ArcInstanceStopped handles remaining procedure.
  // RUNNING:
  //   There is no more callback which runs on normal flow, so Stop() requests
  //   to stop the ARC instance via SessionManager.
  //
  // Another trigger to change the state coming from outside of this class
  // is an event ArcInstanceStopped() sent from SessionManager, when ARC
  // instace unexpectedly terminates. ArcInstanceStopped() turns the state into
  // STOPPED immediately.
  // This happens only when STARTING_INSTANCE, CONNECTING_MOJO or RUNNING
  // state.
  //
  // STARTING_INSTANCE:
  //   In OnInstanceStarted(), |state_| is checked at the beginning. If it is
  //   STOPPED, then ArcInstanceStopped() is called. Do nothing in that case.
  // CONNECTING_MOJO:
  //   Similar to Stop() case above, ArcInstanceStopped() also notifies to
  //   BlockingPool thread to cancel it to unblock the thread. In
  //   OnMojoConnected(), similar to OnInstanceStarted(), check if |state_| is
  //   STOPPED, then do nothing.
  // RUNNING:
  //   It is not necessary to do anything special here.
  //
  // In NOT_STARTED or STOPPED state, the instance can be safely destructed.
  // Specifically, in STOPPED state, there may be inflight operations or
  // pending callbacks. Though, what they do is just do-nothing conceptually
  // and they can be safely ignored.
  //
  // Note: Order of constants below matters. Please make sure to sort them
  // in chronological order.
  enum class State {
    // ARC is not yet started.
    NOT_STARTED,

    // An UNIX socket is being created.
    CREATING_SOCKET,

    // The request to start the instance has been sent.
    STARTING_INSTANCE,

    // The instance has started. Waiting for it to connect to the IPC bridge.
    CONNECTING_MOJO,

    // The instance is fully set up.
    RUNNING,

    // ARC is terminated.
    STOPPED,
  };

  ArcSessionImpl(ArcBridgeService* arc_bridge_service,
                 const scoped_refptr<base::TaskRunner>& blocking_task_runner);
  ~ArcSessionImpl() override;

  // ArcSession overrides:
  void Start() override;
  void Stop() override;
  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(mojo::edk::ScopedPlatformHandle fd);

  // DBus callback for StartArcInstance().
  void OnInstanceStarted(mojo::edk::ScopedPlatformHandle socket_fd,
                         StartArcInstanceResult result);

  // Synchronously accepts a connection on |socket_fd| and then processes the
  // connected socket's file descriptor.
  static mojo::ScopedMessagePipeHandle ConnectMojo(
      mojo::edk::ScopedPlatformHandle socket_fd,
      base::ScopedFD cancel_fd);
  void OnMojoConnected(mojo::ScopedMessagePipeHandle server_pipe);

  // Request to stop ARC instance via DBus.
  void StopArcInstance();

  // chromeos::SessionManagerClient::Observer:
  void ArcInstanceStopped(bool clean) override;

  // Completes the termination procedure.
  void OnStopped(ArcSessionObserver::StopReason reason);

  // Checks whether a function runs on the thread where the instance is
  // created.
  base::ThreadChecker thread_checker_;

  // Owned by ArcServiceManager.
  ArcBridgeService* const arc_bridge_service_;

  // Task runner to run a blocking tasks.
  scoped_refptr<base::TaskRunner> blocking_task_runner_;

  // The state of the session.
  State state_ = State::NOT_STARTED;

  // When Stop() is called, this flag is set.
  bool stop_requested_ = false;

  // In CONNECTING_MOJO state, this is set to the write side of the pipe
  // to notify cancelling of the procedure.
  base::ScopedFD accept_cancel_pipe_;

  // Mojo endpoint.
  std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_;

  // WeakPtrFactory to use callbacks.
  base::WeakPtrFactory<ArcSessionImpl> weak_factory_;

 private:
  DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl);
};

ArcSessionImpl::ArcSessionImpl(
    ArcBridgeService* arc_bridge_service,
    const scoped_refptr<base::TaskRunner>& blocking_task_runner)
    : arc_bridge_service_(arc_bridge_service),
      blocking_task_runner_(blocking_task_runner),
      weak_factory_(this) {
  chromeos::SessionManagerClient* client = GetSessionManagerClient();
  if (client == nullptr)
    return;
  client->AddObserver(this);
}

ArcSessionImpl::~ArcSessionImpl() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(state_ == State::NOT_STARTED || state_ == State::STOPPED);
  chromeos::SessionManagerClient* client = GetSessionManagerClient();
  if (client == nullptr)
    return;
  client->RemoveObserver(this);
}

void ArcSessionImpl::Start() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(state_, State::NOT_STARTED);
  VLOG(2) << "Starting ARC session.";
  VLOG(2) << "Creating socket...";

  state_ = State::CREATING_SOCKET;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::Bind(&ArcSessionImpl::CreateSocket),
      base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr()));
}

// 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(
    mojo::edk::ScopedPlatformHandle socket_fd) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(state_, State::CREATING_SOCKET);

  if (stop_requested_) {
    VLOG(1) << "Stop() called while connecting";
    OnStopped(ArcSessionObserver::StopReason::SHUTDOWN);
    return;
  }

  if (!socket_fd.is_valid()) {
    LOG(ERROR) << "ARC: Error creating socket";
    OnStopped(ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE);
    return;
  }

  VLOG(2) << "Socket is created. Starting ARC instance...";
  state_ = State::STARTING_INSTANCE;
  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
  DCHECK(user_manager->GetPrimaryUser());
  const cryptohome::Identification cryptohome_id(
      user_manager->GetPrimaryUser()->GetAccountId());

  bool disable_boot_completed_broadcast =
      !base::FeatureList::IsEnabled(arc::kBootCompletedBroadcastFeature);

  chromeos::SessionManagerClient* session_manager_client =
      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
  session_manager_client->StartArcInstance(
      cryptohome_id, disable_boot_completed_broadcast,
      base::Bind(&ArcSessionImpl::OnInstanceStarted, weak_factory_.GetWeakPtr(),
                 base::Passed(&socket_fd)));
}

void ArcSessionImpl::OnInstanceStarted(
    mojo::edk::ScopedPlatformHandle socket_fd,
    StartArcInstanceResult result) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (state_ == State::STOPPED) {
    // This is the case that error is notified via DBus before the
    // OnInstanceStarted() callback is invoked. The stopping procedure has
    // been run, so do nothing.
    return;
  }

  DCHECK_EQ(state_, State::STARTING_INSTANCE);

  if (stop_requested_) {
    if (result == StartArcInstanceResult::SUCCESS) {
      // The ARC instance has started to run. Request to stop.
      StopArcInstance();
      return;
    }
    OnStopped(ArcSessionObserver::StopReason::SHUTDOWN);
    return;
  }

  if (result != StartArcInstanceResult::SUCCESS) {
    LOG(ERROR) << "Failed to start ARC instance";
    OnStopped(result == StartArcInstanceResult::LOW_FREE_DISK_SPACE
                  ? ArcSessionObserver::StopReason::LOW_DISK_SPACE
                  : ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE);
    return;
  }

  VLOG(2) << "ARC instance is successfully started. Connecting Mojo...";
  state_ = State::CONNECTING_MOJO;

  // Prepare a pipe so that AcceptInstanceConnection can be interrupted on
  // Stop().
  base::ScopedFD cancel_fd;
  if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) {
    OnStopped(ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE);
    return;
  }

  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd),
                 base::Passed(&cancel_fd)),
      base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr()));
}

// static
mojo::ScopedMessagePipeHandle ArcSessionImpl::ConnectMojo(
    mojo::edk::ScopedPlatformHandle socket_fd,
    base::ScopedFD cancel_fd) {
  if (!WaitForSocketReadable(socket_fd.get().handle, cancel_fd.get())) {
    VLOG(1) << "Mojo connection was cancelled.";
    return mojo::ScopedMessagePipeHandle();
  }

  mojo::edk::ScopedPlatformHandle scoped_fd;
  if (!mojo::edk::ServerAcceptConnection(socket_fd.get(), &scoped_fd,
                                         /* check_peer_user = */ false) ||
      !scoped_fd.is_valid()) {
    return mojo::ScopedMessagePipeHandle();
  }

  // Hardcode pid 0 since it is unused in mojo.
  const base::ProcessHandle kUnusedChildProcessHandle = 0;
  mojo::edk::PlatformChannelPair channel_pair;
  std::string child_token = mojo::edk::GenerateRandomToken();
  mojo::edk::ChildProcessLaunched(kUnusedChildProcessHandle,
                                  channel_pair.PassServerHandle(), child_token);

  mojo::edk::ScopedPlatformHandleVectorPtr handles(
      new mojo::edk::PlatformHandleVector{
          channel_pair.PassClientHandle().release()});

  std::string token = mojo::edk::GenerateRandomToken();
  // We need to send the length of the message as a single byte, so make sure it
  // fits.
  DCHECK_LT(token.size(), 256u);
  uint8_t message_length = static_cast<uint8_t>(token.size());
  struct iovec iov[] = {{&message_length, sizeof(message_length)},
                        {const_cast<char*>(token.c_str()), token.size()}};
  ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles(
      scoped_fd.get(), iov, sizeof(iov) / sizeof(iov[0]), handles->data(),
      handles->size());
  if (result == -1) {
    PLOG(ERROR) << "sendmsg";
    return mojo::ScopedMessagePipeHandle();
  }

  return mojo::edk::CreateParentMessagePipe(token, child_token);
}

void ArcSessionImpl::OnMojoConnected(
    mojo::ScopedMessagePipeHandle server_pipe) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (state_ == State::STOPPED) {
    // This is the case that error is notified via DBus before the
    // OnMojoConnected() callback is invoked. The stopping procedure has
    // been run, so do nothing.
    return;
  }

  DCHECK_EQ(state_, State::CONNECTING_MOJO);
  accept_cancel_pipe_.reset();

  if (stop_requested_) {
    StopArcInstance();
    return;
  }

  if (!server_pipe.is_valid()) {
    LOG(ERROR) << "Invalid pipe";
    StopArcInstance();
    return;
  }

  mojom::ArcBridgeInstancePtr instance;
  instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>(
      std::move(server_pipe), 0u));
  arc_bridge_host_ = base::MakeUnique<ArcBridgeHostImpl>(arc_bridge_service_,
                                                         std::move(instance));

  VLOG(2) << "Mojo is connected. ARC is running.";
  state_ = State::RUNNING;
  for (auto& observer : observer_list_)
    observer.OnSessionReady();
}

void ArcSessionImpl::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  VLOG(2) << "Stopping ARC session is requested.";

  // For second time or later, just do nothing.
  // It is already in the stopping phase.
  if (stop_requested_)
    return;

  stop_requested_ = true;
  arc_bridge_host_.reset();
  switch (state_) {
    case State::NOT_STARTED:
      OnStopped(ArcSessionObserver::StopReason::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.
      return;

    case State::CONNECTING_MOJO:
      // Mojo connection is being waited on a BlockingPool thread.
      // Request to cancel it. Following stopping procedure will run
      // in its callback.
      accept_cancel_pipe_.reset();
      return;

    case State::RUNNING:
      // Now ARC instance is running. Request to stop it.
      StopArcInstance();
      return;

    case State::STOPPED:
      // The instance is already stopped. Do nothing.
      return;
  }
}

void ArcSessionImpl::StopArcInstance() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(state_ == State::STARTING_INSTANCE ||
         state_ == State::CONNECTING_MOJO || state_ == State::RUNNING);

  // Notification will arrive through ArcInstanceStopped().
  VLOG(2) << "Requesting to stop ARC instance";
  chromeos::SessionManagerClient* session_manager_client =
      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
  session_manager_client->StopArcInstance(
      base::Bind(&DoNothingInstanceStopped));
}

void ArcSessionImpl::ArcInstanceStopped(bool clean) {
  DCHECK(thread_checker_.CalledOnValidThread());
  VLOG(1) << "Notified that ARC instance is stopped "
          << (clean ? "cleanly" : "uncleanly");

  // In case that crash happens during before the Mojo channel is connected,
  // unlock the BlockingPool thread.
  accept_cancel_pipe_.reset();

  ArcSessionObserver::StopReason reason;
  if (stop_requested_) {
    // If the ARC instance is stopped after its explicit request,
    // return SHUTDOWN.
    reason = ArcSessionObserver::StopReason::SHUTDOWN;
  } else if (clean) {
    // If the ARC instance is stopped, but it is not explicitly requested,
    // then this is triggered by some failure during the starting procedure.
    // Return GENERIC_BOOT_FAILURE for the case.
    reason = ArcSessionObserver::StopReason::GENERIC_BOOT_FAILURE;
  } else {
    // Otherwise, this is caused by CRASH occured inside of the ARC instance.
    reason = ArcSessionObserver::StopReason::CRASH;
  }
  OnStopped(reason);
}

void ArcSessionImpl::OnStopped(ArcSessionObserver::StopReason reason) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // OnStopped() should be called once per instance.
  DCHECK_NE(state_, State::STOPPED);
  VLOG(2) << "ARC session is stopped.";
  arc_bridge_host_.reset();
  state_ = State::STOPPED;
  for (auto& observer : observer_list_)
    observer.OnSessionStopped(reason);
}

void ArcSessionImpl::OnShutdown() {
  DCHECK(thread_checker_.CalledOnValidThread());
  stop_requested_ = true;
  if (state_ == State::STOPPED)
    return;

  // 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.
  accept_cancel_pipe_.reset();

  // Stops the ARC instance to let it graceful shutdown.
  // Note that this may fail if ARC container is not actually running, but
  // ignore an error as described below.
  if (state_ == State::STARTING_INSTANCE ||
      state_ == State::CONNECTING_MOJO || state_ == State::RUNNING)
    StopArcInstance();

  // Directly set to the STOPPED stateby OnStopped(). Note that calling
  // StopArcInstance() may not work well. At least, because the UI thread is
  // already stopped here, ArcInstanceStopped() callback cannot be invoked.
  OnStopped(ArcSessionObserver::StopReason::SHUTDOWN);
}

}  // namespace

ArcSession::ArcSession() = default;
ArcSession::~ArcSession() = default;

void ArcSession::AddObserver(ArcSessionObserver* observer) {
  observer_list_.AddObserver(observer);
}

void ArcSession::RemoveObserver(ArcSessionObserver* observer) {
  observer_list_.RemoveObserver(observer);
}

// static
std::unique_ptr<ArcSession> ArcSession::Create(
    ArcBridgeService* arc_bridge_service,
    const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
  return base::MakeUnique<ArcSessionImpl>(arc_bridge_service,
                                          blocking_task_runner);
}

}  // namespace arc
