// Copyright (c) 2012 The Chromium OS 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 "login_manager/session_manager_impl.h"

#include <errno.h>
#include <stdint.h>
#include <sys/socket.h>

#include <algorithm>
#include <iterator>
#include <locale>
#include <memory>
#include <set>
#include <string>
#include <utility>

#include <base/base64.h>
#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/files/file_util.h>
#include <base/message_loop/message_loop.h>
#include <base/rand_util.h>
#include <base/run_loop.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_tokenizer.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/default_tick_clock.h>
#include <base/time/time.h>
#include <brillo/cryptohome.h>
#include <brillo/dbus/dbus_object.h>
#include <chromeos/dbus/service_constants.h>
#include <crypto/scoped_nss_types.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
#include <install_attributes/libinstallattributes.h>
#include <libpasswordprovider/password.h>
#include <libpasswordprovider/password_provider.h>

#include "bindings/chrome_device_policy.pb.h"
#include "bindings/device_management_backend.pb.h"
#include "login_manager/arc_sideload_status_interface.h"
#include "login_manager/blob_util.h"
#include "login_manager/crossystem.h"
#include "login_manager/dbus_util.h"
#include "login_manager/device_local_account_manager.h"
#include "login_manager/device_policy_service.h"
#include "login_manager/init_daemon_controller.h"
#include "login_manager/key_generator.h"
#include "login_manager/login_metrics.h"
#include "login_manager/nss_util.h"
#include "login_manager/policy_key.h"
#include "login_manager/policy_service.h"
#include "login_manager/process_manager_service_interface.h"
#include "login_manager/proto_bindings/arc.pb.h"
#include "login_manager/proto_bindings/login_screen_storage.pb.h"
#include "login_manager/proto_bindings/policy_descriptor.pb.h"
#include "login_manager/regen_mitigator.h"
#include "login_manager/secret_util.h"
#include "login_manager/system_utils.h"
#include "login_manager/user_policy_service_factory.h"
#include "login_manager/validator_utils.h"
#include "login_manager/vpd_process.h"

using base::FilePath;
using brillo::cryptohome::home::GetHashedUserPath;
using brillo::cryptohome::home::GetUserPath;
using brillo::cryptohome::home::kGuestUserName;
using brillo::cryptohome::home::SanitizeUserName;

namespace login_manager {  // NOLINT

constexpr char SessionManagerImpl::kStarted[] = "started";
constexpr char SessionManagerImpl::kStopping[] = "stopping";
constexpr char SessionManagerImpl::kStopped[] = "stopped";

constexpr char SessionManagerImpl::kLoggedInFlag[] =
    "/run/session_manager/logged_in";
constexpr char SessionManagerImpl::kResetFile[] =
    "/mnt/stateful_partition/factory_install_reset";

constexpr char SessionManagerImpl::kTPMFirmwareUpdateLocationFile[] =
    "/run/tpm_firmware_update_location";
constexpr char SessionManagerImpl::kTPMFirmwareUpdateSRKVulnerableROCAFile[] =
    "/run/tpm_firmware_update_srk_vulnerable_roca";
constexpr char SessionManagerImpl::kTPMFirmwareUpdateRequestFlagFile[] =
    "/mnt/stateful_partition/unencrypted/preserve/tpm_firmware_update_request";
constexpr char SessionManagerImpl::kStatefulPreservationRequestFile[] =
    "/mnt/stateful_partition/preservation_request";

constexpr char SessionManagerImpl::kStartUserSessionImpulse[] =
    "start-user-session";

// ARC related impulse (systemd unit start or Upstart signal).
constexpr char SessionManagerImpl::kStartArcInstanceImpulse[] =
    "start-arc-instance";
constexpr char SessionManagerImpl::kStopArcInstanceImpulse[] =
    "stop-arc-instance";
constexpr char SessionManagerImpl::kContinueArcBootImpulse[] =
    "continue-arc-boot";
constexpr char SessionManagerImpl::kArcBootedImpulse[] = "arc-booted";

// Lock state related impulse (systemd unit start or Upstart signal).
constexpr char SessionManagerImpl::kScreenLockedImpulse[] = "screen-locked";
constexpr char SessionManagerImpl::kScreenUnlockedImpulse[] = "screen-unlocked";

// TODO(b:66919195): Optimize Android container shutdown time. It
// needs as long as 3s on kevin to perform graceful shutdown.
constexpr base::TimeDelta SessionManagerImpl::kContainerTimeout =
    base::TimeDelta::FromSeconds(3);

constexpr base::TimeDelta SessionManagerImpl::kCrashBeforeSuspendInterval =
    base::TimeDelta::FromSeconds(5);
constexpr base::TimeDelta SessionManagerImpl::kCrashAfterSuspendInterval =
    base::TimeDelta::FromSeconds(5);

namespace {

// The flag to pass to chrome to open a named socket for testing.
const char kTestingChannelFlag[] = "--testing-channel=NamedTestingInterface:";

// Device-local account state directory.
const char kDeviceLocalAccountStateDir[] = "/var/lib/device_local_accounts";

#if USE_CHEETS
// To launch ARC, certain amount of free disk space is needed.
// Path and the amount for the check.
constexpr char kArcDiskCheckPath[] = "/home";
constexpr int64_t kArcCriticalDiskFreeBytes = 64 << 20;  // 64MB

// To set the CPU limits of the Android container.
const char kCpuSharesFile[] =
    "/sys/fs/cgroup/cpu/session_manager_containers/cpu.shares";
const unsigned int kCpuSharesForeground = 1024;
const unsigned int kCpuSharesBackground = 64;
#endif

// The interval used to periodically check if time sync was done by tlsdated.
constexpr base::TimeDelta kSystemClockLastSyncInfoRetryDelay =
    base::TimeDelta::FromMilliseconds(1000);

// TPM firmware update modes.
constexpr char kTPMFirmwareUpdateModeFirstBoot[] = "first_boot";
constexpr char kTPMFirmwareUpdateModePreserveStateful[] = "preserve_stateful";
constexpr char kTPMFirmwareUpdateModeCleanup[] = "cleanup";

// Policy storage constants.
constexpr char kSigEncodeFailMessage[] = "Failed to retrieve policy data.";

// Default path of symlink to log file where stdout and stderr from
// session_manager and Chrome are redirected.
constexpr char kDefaultUiLogSymlinkPath[] = "/var/log/ui/ui.LATEST";

// A path of the directory that contains all the key-value pairs stored to the
// pesistent login screen storage.
const char kLoginScreenStoragePath[] = "/var/lib/login_screen_storage";

const char* ToSuccessSignal(bool success) {
  return success ? "success" : "failure";
}

#if USE_CHEETS
bool IsDevMode(SystemUtils* system) {
  // When GetDevModeState() returns UNKNOWN, return true.
  return system->GetDevModeState() != DevModeState::DEV_MODE_OFF;
}

bool IsInsideVm(SystemUtils* system) {
  // When GetVmState() returns UNKNOWN, return false.
  return system->GetVmState() == VmState::INSIDE_VM;
}
#endif

// Parses |descriptor_blob| into |descriptor| and validates it assuming the
// given |usage|. Returns true and sets |descriptor| on success. Returns false
// and sets |error| on failure.
bool ParseAndValidatePolicyDescriptor(
    const std::vector<uint8_t>& descriptor_blob,
    PolicyDescriptorUsage usage,
    PolicyDescriptor* descriptor,
    brillo::ErrorPtr* error) {
  DCHECK(descriptor);
  DCHECK(error);
  if (!descriptor->ParseFromArray(descriptor_blob.data(),
                                  descriptor_blob.size())) {
    *error = CreateError(DBUS_ERROR_INVALID_ARGS,
                         "PolicyDescriptor parsing failed.");
    return false;
  }

  if (!ValidatePolicyDescriptor(*descriptor, usage)) {
    *error = CreateError(DBUS_ERROR_INVALID_ARGS, "PolicyDescriptor invalid.");
    return false;
  }

  return true;
}

// Handles the result of an attempt to connect to a D-Bus signal, logging an
// error on failure.
void HandleDBusSignalConnected(const std::string& interface,
                               const std::string& signal,
                               bool success) {
  if (!success) {
    LOG(ERROR) << "Failed to connect to D-Bus signal " << interface << "."
               << signal;
  }
}

// Replaces the log file that |symlink_path| (typically /var/log/ui/ui.LATEST)
// points to with a new file containing the same contents. This is used to
// disconnect Chrome's stderr and stdout after a user logs in:
// https://crbug.com/904850
void DisconnectLogFile(const base::FilePath& symlink_path) {
  base::FilePath log_path;
  if (!base::ReadSymbolicLink(symlink_path, &log_path))
    return;

  if (!log_path.IsAbsolute())
    log_path = symlink_path.DirName().Append(log_path);

  // Perform a basic safety check.
  if (log_path.DirName() != symlink_path.DirName()) {
    LOG(WARNING) << "Log file " << log_path.value() << " isn't in same "
                 << "directory as symlink " << symlink_path.value()
                 << "; not disconnecting it";
    return;
  }

  // Copy the contents to a temp file and then move it over the original path.
  base::FilePath temp_path;
  if (!base::CreateTemporaryFileInDir(log_path.DirName(), &temp_path)) {
    PLOG(WARNING) << "Failed to create temp file in "
                  << log_path.DirName().value();
    return;
  }
  if (!base::CopyFile(log_path, temp_path)) {
    PLOG(WARNING) << "Failed to copy " << log_path.value() << " to "
                  << temp_path.value();
    return;
  }

  // Try to to copy permissions so the new file isn't 0600, which makes it hard
  // to investigate issues on non-dev devices.
  int mode = 0;
  if (!base::GetPosixFilePermissions(log_path, &mode) ||
      !base::SetPosixFilePermissions(temp_path, mode)) {
    PLOG(WARNING) << "Failed to copy permissions from " << log_path.value()
                  << " to " << temp_path.value();
  }

  if (!base::ReplaceFile(temp_path, log_path, nullptr /* error */)) {
    PLOG(WARNING) << "Failed to rename " << temp_path.value() << " to "
                  << log_path.value();
  }
}

}  // namespace

// Tracks D-Bus service running.
// Create*Callback functions return a callback adaptor from given
// DBusMethodResponse. These cancel in-progress operations when the instance is
// deleted.
class SessionManagerImpl::DBusService {
 public:
  explicit DBusService(org::chromium::SessionManagerInterfaceAdaptor* adaptor)
      : adaptor_(adaptor), weak_ptr_factory_(this) {}
  ~DBusService() = default;

  bool Start(const scoped_refptr<dbus::Bus>& bus) {
    DCHECK(!dbus_object_);

    // Registers the SessionManagerInterface D-Bus methods and signals.
    dbus_object_ = std::make_unique<brillo::dbus_utils::DBusObject>(
        nullptr, bus,
        org::chromium::SessionManagerInterfaceAdaptor::GetObjectPath());
    adaptor_->RegisterWithDBusObject(dbus_object_.get());
    dbus_object_->RegisterAndBlock();

    // Note that this needs to happen *after* all methods are exported
    // (http://crbug.com/331431).
    // This should pass dbus::Bus::REQUIRE_PRIMARY once on the new libchrome.
    return bus->RequestOwnershipAndBlock(kSessionManagerServiceName,
                                         dbus::Bus::REQUIRE_PRIMARY);
  }

  // Adaptor from DBusMethodResponse to PolicyService::Completion callback.
  PolicyService::Completion CreatePolicyServiceCompletionCallback(
      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response) {
    return base::Bind(&DBusService::HandlePolicyServiceCompletion,
                      weak_ptr_factory_.GetWeakPtr(), base::Passed(&response));
  }

  // Adaptor from DBusMethodResponse to
  // ServerBackedStateKeyGenerator::StateKeyCallback callback.
  ServerBackedStateKeyGenerator::StateKeyCallback CreateStateKeyCallback(
      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
          std::vector<std::vector<uint8_t>>>> response) {
    return base::Bind(&DBusService::HandleStateKeyCallback,
                      weak_ptr_factory_.GetWeakPtr(), base::Passed(&response));
  }

 private:
  void HandlePolicyServiceCompletion(
      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
      brillo::ErrorPtr error) {
    if (error) {
      response->ReplyWithError(error.get());
      return;
    }

    response->Return();
  }

  void HandleStateKeyCallback(
      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
          std::vector<std::vector<uint8_t>>>> response,
      const std::vector<std::vector<uint8_t>>& state_key) {
    response->Return(std::move(state_key));
  }

  org::chromium::SessionManagerInterfaceAdaptor* const adaptor_;
  std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;

  base::WeakPtrFactory<DBusService> weak_ptr_factory_;
  DISALLOW_COPY_AND_ASSIGN(DBusService);
};

struct SessionManagerImpl::UserSession {
 public:
  UserSession(const std::string& username,
              const std::string& userhash,
              bool is_incognito,
              crypto::ScopedPK11Slot slot,
              std::unique_ptr<PolicyService> policy_service)
      : username(username),
        userhash(userhash),
        is_incognito(is_incognito),
        slot(std::move(slot)),
        policy_service(std::move(policy_service)) {}
  ~UserSession() {}

  const std::string username;
  const std::string userhash;
  const bool is_incognito;
  crypto::ScopedPK11Slot slot;
  std::unique_ptr<PolicyService> policy_service;
};

SessionManagerImpl::SessionManagerImpl(
    Delegate* delegate,
    std::unique_ptr<InitDaemonController> init_controller,
    const scoped_refptr<dbus::Bus>& bus,
    KeyGenerator* key_gen,
    ServerBackedStateKeyGenerator* state_key_generator,
    ProcessManagerServiceInterface* manager,
    LoginMetrics* metrics,
    NssUtil* nss,
    SystemUtils* utils,
    Crossystem* crossystem,
    VpdProcess* vpd_process,
    PolicyKey* owner_key,
    ContainerManagerInterface* android_container,
    InstallAttributesReader* install_attributes_reader,
    dbus::ObjectProxy* powerd_proxy,
    dbus::ObjectProxy* system_clock_proxy,
    ArcSideloadStatusInterface* arc_sideload_status)
    : init_controller_(std::move(init_controller)),
      system_clock_last_sync_info_retry_delay_(
          kSystemClockLastSyncInfoRetryDelay),
      tick_clock_(std::make_unique<base::DefaultTickClock>()),
      bus_(bus),
      adaptor_(this),
      delegate_(delegate),
      key_gen_(key_gen),
      state_key_generator_(state_key_generator),
      manager_(manager),
      login_metrics_(metrics),
      nss_(nss),
      system_(utils),
      crossystem_(crossystem),
      vpd_process_(vpd_process),
      owner_key_(owner_key),
      android_container_(android_container),
      install_attributes_reader_(install_attributes_reader),
      powerd_proxy_(powerd_proxy),
      system_clock_proxy_(system_clock_proxy),
      arc_sideload_status_(arc_sideload_status),
      mitigator_(key_gen),
      ui_log_symlink_path_(kDefaultUiLogSymlinkPath),
      password_provider_(
          std::make_unique<password_provider::PasswordProvider>()),
      login_screen_storage_(std::make_unique<LoginScreenStorage>(
          base::FilePath(kLoginScreenStoragePath),
          std::make_unique<secret_util::SharedMemoryUtil>())),
      weak_ptr_factory_(this) {
  DCHECK(delegate_);
}

SessionManagerImpl::~SessionManagerImpl() {
  device_policy_->set_delegate(nullptr);  // Could use WeakPtr instead?
}

void SessionManagerImpl::SetPolicyServicesForTesting(
    std::unique_ptr<DevicePolicyService> device_policy,
    std::unique_ptr<UserPolicyServiceFactory> user_policy_factory,
    std::unique_ptr<DeviceLocalAccountManager> device_local_account_manager) {
  device_policy_ = std::move(device_policy);
  user_policy_factory_ = std::move(user_policy_factory);
  device_local_account_manager_ = std::move(device_local_account_manager);
}

void SessionManagerImpl::SetTickClockForTesting(
    std::unique_ptr<base::TickClock> clock) {
  tick_clock_ = std::move(clock);
}

void SessionManagerImpl::SetUiLogSymlinkPathForTesting(
    const base::FilePath& path) {
  ui_log_symlink_path_ = path;
}

void SessionManagerImpl::SetLoginScreenStorageForTesting(
    std::unique_ptr<LoginScreenStorage> login_screen_storage) {
  login_screen_storage_ = std::move(login_screen_storage);
}

void SessionManagerImpl::AnnounceSessionStoppingIfNeeded() {
  if (session_started_) {
    session_stopping_ = true;
    DLOG(INFO) << "Emitting D-Bus signal SessionStateChanged: " << kStopping;
    adaptor_.SendSessionStateChangedSignal(kStopping);
  }
}

void SessionManagerImpl::AnnounceSessionStopped() {
  session_stopping_ = session_started_ = false;
  DLOG(INFO) << "Emitting D-Bus signal SessionStateChanged: " << kStopped;
  adaptor_.SendSessionStateChangedSignal(kStopped);
}

bool SessionManagerImpl::ShouldEndSession(std::string* reason_out) {
  auto set_reason = [&](const std::string& reason) {
    if (reason_out)
      *reason_out = reason;
  };

  if (screen_locked_) {
    set_reason("screen is locked");
    return true;
  }

  if (supervised_user_creation_ongoing_) {
    set_reason("supervised user creation ongoing");
    return true;
  }

  if (suspend_ongoing_) {
    set_reason("suspend ongoing");
    return true;
  }

  if (!last_suspend_done_time_.is_null()) {
    const base::TimeDelta time_since_suspend =
        tick_clock_->NowTicks() - last_suspend_done_time_;
    if (time_since_suspend <= kCrashAfterSuspendInterval) {
      set_reason("suspend completed recently");
      return true;
    }
  }

  set_reason("");
  return false;
}

bool SessionManagerImpl::Initialize() {
  key_gen_->set_delegate(this);

  powerd_proxy_->ConnectToSignal(
      power_manager::kPowerManagerInterface,
      power_manager::kSuspendImminentSignal,
      base::Bind(&SessionManagerImpl::OnSuspendImminent,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&HandleDBusSignalConnected));
  powerd_proxy_->ConnectToSignal(power_manager::kPowerManagerInterface,
                                 power_manager::kSuspendDoneSignal,
                                 base::Bind(&SessionManagerImpl::OnSuspendDone,
                                            weak_ptr_factory_.GetWeakPtr()),
                                 base::Bind(&HandleDBusSignalConnected));

  system_clock_proxy_->WaitForServiceToBeAvailable(
      base::Bind(&SessionManagerImpl::OnSystemClockServiceAvailable,
                 weak_ptr_factory_.GetWeakPtr()));

  // Note: If SetPolicyServicesForTesting has been called, all services have
  // already been set and initialized.
  if (!device_policy_) {
    device_policy_ =
        DevicePolicyService::Create(owner_key_, login_metrics_, &mitigator_,
                                    nss_, crossystem_, vpd_process_);
    // Thinking about combining set_delegate() with the 'else' block below and
    // moving it down? Note that device_policy_->Initialize() might call
    // OnKeyPersisted() on the delegate, so be sure it's safe.
    device_policy_->set_delegate(this);
    if (!device_policy_->Initialize())
      return false;

    DCHECK(!user_policy_factory_);
    user_policy_factory_ =
        std::make_unique<UserPolicyServiceFactory>(nss_, system_);

    device_local_account_manager_ = std::make_unique<DeviceLocalAccountManager>(
        base::FilePath(kDeviceLocalAccountStateDir), owner_key_),
    device_local_account_manager_->UpdateDeviceSettings(
        device_policy_->GetSettings());
    if (device_policy_->MayUpdateSystemSettings())
      device_policy_->UpdateSystemSettings(PolicyService::Completion());
  } else {
    device_policy_->set_delegate(this);
  }

  arc_sideload_status_->Initialize();

  return true;
}

void SessionManagerImpl::Finalize() {
  // Reset the SessionManagerDBusAdaptor first to ensure that it'll permit
  // any outstanding DBusMethodCompletion objects to be abandoned without
  // having been run (http://crbug.com/638774, http://crbug.com/725734).
  dbus_service_.reset();

  device_policy_->PersistAllPolicy();
  for (const auto& kv : user_sessions_) {
    if (kv.second)
      kv.second->policy_service->PersistAllPolicy();
  }
  device_local_account_manager_->PersistAllPolicy();

  // We want to stop all running containers and VMs.  Containers and VMs are
  // per-session and cannot persist across sessions.
  android_container_->RequestJobExit(
      ArcContainerStopReason::SESSION_MANAGER_SHUTDOWN);
  android_container_->EnsureJobExit(kContainerTimeout);

  arc_sideload_status_.reset();
}

bool SessionManagerImpl::StartDBusService() {
  DCHECK(!dbus_service_);
  auto dbus_service = std::make_unique<DBusService>(&adaptor_);
  if (!dbus_service->Start(bus_))
    return false;

  dbus_service_ = std::move(dbus_service);
  return true;
}

void SessionManagerImpl::EmitLoginPromptVisible() {
  login_metrics_->RecordStats("login-prompt-visible");
  adaptor_.SendLoginPromptVisibleSignal();
  init_controller_->TriggerImpulse("login-prompt-visible", {},
                                   InitDaemonController::TriggerMode::ASYNC);
}

void SessionManagerImpl::EmitAshInitialized() {
  init_controller_->TriggerImpulse("ash-initialized", {},
                                   InitDaemonController::TriggerMode::ASYNC);
}

bool SessionManagerImpl::EnableChromeTesting(
    brillo::ErrorPtr* error,
    bool in_force_relaunch,
    const std::vector<std::string>& in_extra_arguments,
    const std::vector<std::string>& in_extra_environment_variables,
    std::string* out_filepath) {
  // Check to see if we already have Chrome testing enabled.
  bool already_enabled = !chrome_testing_path_.empty();

  if (!already_enabled) {
    base::FilePath temp_file_path;  // So we don't clobber chrome_testing_path_;
    if (!system_->GetUniqueFilenameInWriteOnlyTempDir(&temp_file_path)) {
      *error = CreateError(dbus_error::kTestingChannelError,
                           "Could not create testing channel filename.");
      return false;
    }
    chrome_testing_path_ = temp_file_path;
  }

  if (!already_enabled || in_force_relaunch) {
    // Delete testing channel file if it already exists.
    system_->RemoveFile(chrome_testing_path_);

    // Add testing channel argument to extra arguments.
    std::string testing_argument = kTestingChannelFlag;
    testing_argument.append(chrome_testing_path_.value());
    std::vector<std::string> extra_args = in_extra_arguments;
    extra_args.push_back(testing_argument);
    manager_->RestartBrowserWithArgs(extra_args, true /* args_are_extra */,
                                     in_extra_environment_variables);
  }
  *out_filepath = chrome_testing_path_.value();
  return true;
}

bool SessionManagerImpl::LoginScreenStorageListKeys(
    brillo::ErrorPtr* error, std::vector<std::string>* out_keys) {
  *out_keys = login_screen_storage_->ListKeys();
  return true;
}

void SessionManagerImpl::LoginScreenStorageDelete(const std::string& in_key) {
  login_screen_storage_->Delete(in_key);
}

bool SessionManagerImpl::StartSession(brillo::ErrorPtr* error,
                                      const std::string& in_account_id,
                                      const std::string& in_unique_identifier) {
  std::string actual_account_id;
  if (!NormalizeAccountId(in_account_id, &actual_account_id, error)) {
    DCHECK(*error);
    return false;
  }

  // Check if this user already started a session.
  if (user_sessions_.count(actual_account_id) > 0) {
    *error =
        CREATE_ERROR_AND_LOG(dbus_error::kSessionExists,
                             "Provided user id already started a session.");
    return false;
  }

  // Create a UserSession object for this user.
  const bool is_incognito = IsIncognitoAccountId(actual_account_id);
  auto user_session = CreateUserSession(actual_account_id, is_incognito, error);
  if (!user_session) {
    DCHECK(*error);
    return false;
  }

  // Check whether the current user is the owner, and if so make sure they are
  // whitelisted and have an owner key.
  bool user_is_owner = false;
  if (!device_policy_->CheckAndHandleOwnerLogin(user_session->username,
                                                user_session->slot.get(),
                                                &user_is_owner, error)) {
    DCHECK(*error);
    return false;
  }

  // If all previous sessions were incognito (or no previous sessions exist).
  bool is_first_real_user = AllSessionsAreIncognito() && !is_incognito;

  // Send each user login event to UMA (right before we start session
  // since the metrics library does not log events in guest mode).
  const DevModeState dev_mode_state = system_->GetDevModeState();
  if (dev_mode_state != DevModeState::DEV_MODE_UNKNOWN) {
    login_metrics_->SendLoginUserType(
        dev_mode_state != DevModeState::DEV_MODE_OFF, is_incognito,
        user_is_owner);
  }

  // Make sure that Chrome's stdout and stderr, which may contain log messages
  // with user-specific data, don't get saved after the first user logs in:
  // https://crbug.com/904850
  if (user_sessions_.empty())
    DisconnectLogFile(ui_log_symlink_path_);

  init_controller_->TriggerImpulse(kStartUserSessionImpulse,
                                   {"CHROMEOS_USER=" + actual_account_id},
                                   InitDaemonController::TriggerMode::ASYNC);
  LOG(INFO) << "Starting user session";
  manager_->SetBrowserSessionForUser(actual_account_id, user_session->userhash);
  session_started_ = true;
  user_sessions_[actual_account_id] = std::move(user_session);
  if (is_first_real_user) {
    DCHECK(primary_user_account_id_.empty());
    primary_user_account_id_ = actual_account_id;
  }
  DLOG(INFO) << "Emitting D-Bus signal SessionStateChanged: " << kStarted;
  adaptor_.SendSessionStateChangedSignal(kStarted);

  // Active Directory managed devices are not expected to have a policy key.
  // Don't create one for them.
  const bool is_active_directory =
      install_attributes_reader_->GetAttribute(
          InstallAttributesReader::kAttrMode) ==
      InstallAttributesReader::kDeviceModeEnterpriseAD;
  if (device_policy_->KeyMissing() && !is_active_directory &&
      !device_policy_->Mitigating() && is_first_real_user) {
    // This is the first sign-in on this unmanaged device.  Take ownership.
    key_gen_->Start(actual_account_id);
  }

  // Record that a login has successfully completed on this boot.
  system_->AtomicFileWrite(base::FilePath(kLoggedInFlag), "1");
  return true;
}

bool SessionManagerImpl::SaveLoginPassword(
    brillo::ErrorPtr* error, const base::ScopedFD& in_password_fd) {
  if (!secret_util::SaveSecretFromPipe(password_provider_.get(),
                                       in_password_fd)) {
    LOG(ERROR) << "Could not save password.";
    return false;
  }
  return true;
}

bool SessionManagerImpl::LoginScreenStorageStore(
    brillo::ErrorPtr* error,
    const std::string& in_key,
    const std::vector<uint8_t>& in_metadata,
    uint64_t in_value_size,
    const base::ScopedFD& in_value_fd) {
  if (!user_sessions_.empty()) {
    *error = CreateError(
        DBUS_ERROR_FAILED,
        "can't store login screen data while there are active user sessions.");
    return false;
  }

  LoginScreenStorageMetadata metadata;
  if (!metadata.ParseFromArray(in_metadata.data(), in_metadata.size())) {
    *error = CreateError(DBUS_ERROR_INVALID_ARGS, "metadata parsing failed.");
    return false;
  }

  return login_screen_storage_->Store(error, in_key, metadata, in_value_size,
                                      in_value_fd);
}

bool SessionManagerImpl::LoginScreenStorageRetrieve(
    brillo::ErrorPtr* error,
    const std::string& in_key,
    uint64_t* out_value_size,
    brillo::dbus_utils::FileDescriptor* out_value_fd) {
  base::ScopedFD value_fd;
  bool success =
      login_screen_storage_->Retrieve(error, in_key, out_value_size, &value_fd);
  *out_value_fd = std::move(value_fd);
  return success;
}

void SessionManagerImpl::StopSession(const std::string& in_unique_identifier) {
  StopSessionWithReason(
      static_cast<uint32_t>(SessionStopReason::REQUEST_FROM_SESSION_MANAGER));
}

void SessionManagerImpl::StopSessionWithReason(uint32_t reason) {
  LOG(INFO) << "Stopping all sessions reason = " << reason;
  // Most calls to StopSession() will log the reason for the call.
  // If you don't see a log message saying the reason for the call, it is
  // likely a D-Bus message.
  manager_->ScheduleShutdown();
  // TODO(cmasone): re-enable these when we try to enable logout without exiting
  //                the session manager
  // browser_.job->StopSession();
  // user_policy_.reset();
  // session_started_ = false;

  password_provider_->DiscardPassword();
}

void SessionManagerImpl::StorePolicyEx(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    const std::vector<uint8_t>& in_descriptor_blob,
    const std::vector<uint8_t>& in_policy_blob) {
  StorePolicyInternalEx(in_descriptor_blob, in_policy_blob,
                        SignatureCheck::kEnabled, std::move(response));
}

void SessionManagerImpl::StoreUnsignedPolicyEx(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    const std::vector<uint8_t>& in_descriptor_blob,
    const std::vector<uint8_t>& in_policy_blob) {
  brillo::ErrorPtr error = VerifyUnsignedPolicyStore();
  if (error) {
    response->ReplyWithError(error.get());
    return;
  }
  StorePolicyInternalEx(in_descriptor_blob, in_policy_blob,
                        SignatureCheck::kDisabled, std::move(response));
}

bool SessionManagerImpl::RetrievePolicyEx(
    brillo::ErrorPtr* error,
    const std::vector<uint8_t>& in_descriptor_blob,
    std::vector<uint8_t>* out_policy_blob) {
  PolicyDescriptor descriptor;
  if (!ParseAndValidatePolicyDescriptor(in_descriptor_blob,
                                        PolicyDescriptorUsage::kRetrieve,
                                        &descriptor, error)) {
    return false;
  }

  std::unique_ptr<PolicyService> storage;
  PolicyService* policy_service = GetPolicyService(descriptor, &storage, error);
  if (!policy_service)
    return false;

  PolicyNamespace ns(descriptor.domain(), descriptor.component_id());

  if (!policy_service->Retrieve(ns, out_policy_blob)) {
    LOG(ERROR) << kSigEncodeFailMessage;
    *error = CreateError(dbus_error::kSigEncodeFail, kSigEncodeFailMessage);
    return false;
  }
  return true;
}

bool SessionManagerImpl::ListStoredComponentPolicies(
    brillo::ErrorPtr* error,
    const std::vector<uint8_t>& in_descriptor_blob,
    std::vector<std::string>* out_component_ids) {
  PolicyDescriptor descriptor;
  if (!ParseAndValidatePolicyDescriptor(in_descriptor_blob,
                                        PolicyDescriptorUsage::kList,
                                        &descriptor, error)) {
    return false;
  }

  std::unique_ptr<PolicyService> storage;
  PolicyService* policy_service = GetPolicyService(descriptor, &storage, error);
  if (!policy_service)
    return false;

  *out_component_ids = policy_service->ListComponentIds(descriptor.domain());
  return true;
}

std::string SessionManagerImpl::RetrieveSessionState() {
  if (!session_started_)
    return kStopped;
  if (session_stopping_)
    return kStopping;
  return kStarted;
}

std::map<std::string, std::string>
SessionManagerImpl::RetrieveActiveSessions() {
  std::map<std::string, std::string> result;
  for (const auto& entry : user_sessions_) {
    if (!entry.second)
      continue;
    result[entry.second->username] = entry.second->userhash;
  }
  return result;
}

void SessionManagerImpl::RetrievePrimarySession(
    std::string* out_username, std::string* out_sanitized_username) {
  out_username->clear();
  out_sanitized_username->clear();
  if (user_sessions_.count(primary_user_account_id_) > 0) {
    out_username->assign(user_sessions_[primary_user_account_id_]->username);
    out_sanitized_username->assign(
        user_sessions_[primary_user_account_id_]->userhash);
  }
}

bool SessionManagerImpl::IsGuestSessionActive() {
  return !user_sessions_.empty() && AllSessionsAreIncognito();
}

void SessionManagerImpl::HandleSupervisedUserCreationStarting() {
  supervised_user_creation_ongoing_ = true;
}

void SessionManagerImpl::HandleSupervisedUserCreationFinished() {
  supervised_user_creation_ongoing_ = false;
}

bool SessionManagerImpl::LockScreen(brillo::ErrorPtr* error) {
  if (!session_started_) {
    *error = CREATE_WARNING_AND_LOG(
        dbus_error::kSessionDoesNotExist,
        "Attempt to lock screen outside of user session.");
    return false;
  }
  // If all sessions are incognito, then locking is not allowed.
  if (AllSessionsAreIncognito()) {
    *error =
        CREATE_WARNING_AND_LOG(dbus_error::kSessionExists,
                               "Attempt to lock screen during Guest session.");
    return false;
  }
  if (!screen_locked_) {
    screen_locked_ = true;
    init_controller_->TriggerImpulse(kScreenLockedImpulse, {},
                                     InitDaemonController::TriggerMode::ASYNC);
    delegate_->LockScreen();
  }
  LOG(INFO) << "LockScreen() method called.";
  return true;
}

void SessionManagerImpl::HandleLockScreenShown() {
  LOG(INFO) << "HandleLockScreenShown() method called.";
  adaptor_.SendScreenIsLockedSignal();
}

void SessionManagerImpl::HandleLockScreenDismissed() {
  screen_locked_ = false;
  init_controller_->TriggerImpulse(kScreenUnlockedImpulse, {},
                                   InitDaemonController::TriggerMode::ASYNC);
  LOG(INFO) << "HandleLockScreenDismissed() method called.";
  adaptor_.SendScreenIsUnlockedSignal();
}

bool SessionManagerImpl::IsScreenLocked() {
  return screen_locked_;
}

bool SessionManagerImpl::RestartJob(brillo::ErrorPtr* error,
                                    const base::ScopedFD& in_cred_fd,
                                    const std::vector<std::string>& in_argv) {
  struct ucred ucred = {0};
  socklen_t len = sizeof(struct ucred);
  if (!in_cred_fd.is_valid() || getsockopt(in_cred_fd.get(), SOL_SOCKET,
                                           SO_PEERCRED, &ucred, &len) == -1) {
    PLOG(ERROR) << "Can't get peer creds";
    *error = CreateError("GetPeerCredsFailed", strerror(errno));
    return false;
  }

  if (!manager_->IsBrowser(ucred.pid)) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kUnknownPid,
                                  "Provided pid is unknown.");
    return false;
  }

  // To set "logged-in" state for BWSI mode.
  if (!StartSession(error, kGuestUserName, "")) {
    DCHECK(*error);
    return false;
  }

  manager_->RestartBrowserWithArgs(in_argv, false /* args_are_extra */,
                                   {} /* env_vars */);
  return true;
}

bool SessionManagerImpl::StartDeviceWipe(brillo::ErrorPtr* error) {
  if (system_->Exists(base::FilePath(kLoggedInFlag))) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kSessionExists,
                                  "A user has already logged in this boot.");
    return false;
  }

  // Powerwash is not allowed for enterprise devices.
  if (device_policy_->InstallAttributesEnterpriseMode()) {
    constexpr char kMessage[] = "Powerwash not available on enterprise devices";
    LOG(ERROR) << kMessage;
    *error = CreateError(dbus_error::kNotAvailable, kMessage);
    return false;
  }

  InitiateDeviceWipe("session_manager_dbus_request");
  return true;
}

bool SessionManagerImpl::StartRemoteDeviceWipe(
    brillo::ErrorPtr* error, const std::vector<uint8_t>& in_signed_command) {
  if (!device_policy_->ValidateRemoteDeviceWipeCommand(in_signed_command)) {
    *error = CreateError(dbus_error::kInvalidParameter,
                         "Remote wipe command validation failed, aborting.");
    return false;
  }

  InitiateDeviceWipe("remote_wipe_request");
  return true;
}

void SessionManagerImpl::ClearForcedReEnrollmentVpd(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response) {
  device_policy_->ClearForcedReEnrollmentFlags(
      dbus_service_->CreatePolicyServiceCompletionCallback(
          std::move(response)));
}

bool SessionManagerImpl::StartTPMFirmwareUpdate(
    brillo::ErrorPtr* error, const std::string& update_mode) {
  // Make sure |update_mode| is supported.
  if (update_mode != kTPMFirmwareUpdateModeFirstBoot &&
      update_mode != kTPMFirmwareUpdateModePreserveStateful &&
      update_mode != kTPMFirmwareUpdateModeCleanup) {
    *error =
        CREATE_ERROR_AND_LOG(dbus_error::kInvalidParameter, "Bad update mode.");
    return false;
  }

  // Verify that we haven't seen a user log in since boot.
  if (system_->Exists(base::FilePath(kLoggedInFlag))) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kSessionExists,
                                  "A user has already logged in since boot.");
    return false;
  }

  // For remotely managed devices, make sure the requested update mode matches
  // the admin-configured one in device policy.
  if (device_policy_->InstallAttributesEnterpriseMode()) {
    const enterprise_management::TPMFirmwareUpdateSettingsProto& settings =
        device_policy_->GetSettings().tpm_firmware_update_settings();
    std::set<std::string> allowed_modes;
    if (settings.allow_user_initiated_powerwash()) {
      allowed_modes.insert(kTPMFirmwareUpdateModeFirstBoot);
    }
    if (settings.allow_user_initiated_preserve_device_state()) {
      allowed_modes.insert(kTPMFirmwareUpdateModePreserveStateful);
    }

    // See whether the requested mode is allowed. Cleanup is permitted when at
    // least one of the actual modes are allowed.
    bool allowed = (update_mode == kTPMFirmwareUpdateModeCleanup)
                       ? !allowed_modes.empty()
                       : allowed_modes.count(update_mode) > 0;
    if (!allowed) {
      *error = CreateError(dbus_error::kNotAvailable,
                           "Policy doesn't allow TPM firmware update.");
      return false;
    }
  }

  // Validate that a firmware update is actually available to make sure
  // enterprise users can't abuse TPM firmware update to trigger powerwash.
  bool available = false;
  if (update_mode == kTPMFirmwareUpdateModeFirstBoot ||
      update_mode == kTPMFirmwareUpdateModePreserveStateful) {
    std::string update_location;
    available =
        system_->ReadFileToString(
            base::FilePath(kTPMFirmwareUpdateLocationFile), &update_location) &&
        update_location.size();
  } else if (update_mode == kTPMFirmwareUpdateModeCleanup) {
    available = system_->Exists(
        base::FilePath(kTPMFirmwareUpdateSRKVulnerableROCAFile));
  }

  if (!available) {
    *error =
        CREATE_ERROR_AND_LOG(dbus_error::kNotAvailable, "No update available.");
    return false;
  }

  // Put the update request into place.
  if (!system_->AtomicFileWrite(
          base::FilePath(kTPMFirmwareUpdateRequestFlagFile), update_mode)) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kNotAvailable,
                                  "Failed to persist update request.");
    return false;
  }

  if (update_mode == kTPMFirmwareUpdateModeFirstBoot ||
      update_mode == kTPMFirmwareUpdateModeCleanup) {
    InitiateDeviceWipe("tpm_firmware_update_" + update_mode);
  } else if (update_mode == kTPMFirmwareUpdateModePreserveStateful) {
    // This flag file indicates that encrypted stateful should be preserved.
    if (!system_->AtomicFileWrite(
            base::FilePath(kStatefulPreservationRequestFile), update_mode)) {
      *error = CREATE_ERROR_AND_LOG(dbus_error::kNotAvailable,
                                    "Failed to request stateful preservation.");
      return false;
    }

    if (crossystem_->VbSetSystemPropertyInt(Crossystem::kClearTpmOwnerRequest,
                                            1) != 0) {
      *error = CREATE_ERROR_AND_LOG(dbus_error::kNotAvailable,
                                    "Failed to request TPM clear.");
      return false;
    }

    RestartDevice("tpm_firmware_update " + update_mode);
  } else {
    NOTREACHED();
    return false;
  }

  return true;
}

void SessionManagerImpl::SetFlagsForUser(
    const std::string& in_account_id,
    const std::vector<std::string>& in_flags) {
  manager_->SetFlagsForUser(in_account_id, in_flags);
}

void SessionManagerImpl::GetServerBackedStateKeys(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
        std::vector<std::vector<uint8_t>>>> response) {
  DCHECK(dbus_service_);
  ServerBackedStateKeyGenerator::StateKeyCallback callback =
      dbus_service_->CreateStateKeyCallback(std::move(response));
  if (system_clock_synchronized_) {
    state_key_generator_->RequestStateKeys(callback);
  } else {
    pending_state_key_callbacks_.push_back(callback);
  }
}

void SessionManagerImpl::OnSuspendImminent(dbus::Signal* signal) {
  suspend_ongoing_ = true;

  // If Chrome crashed recently, it might've missed this SuspendImminent signal
  // and failed to lock the screen. Stop the session as a precaution:
  // https://crbug.com/867970
  const base::TimeTicks start_time = manager_->GetLastBrowserRestartTime();
  if (!start_time.is_null() &&
      tick_clock_->NowTicks() - start_time <= kCrashBeforeSuspendInterval) {
    LOG(INFO) << "Stopping session for suspend after recent browser restart";
    StopSessionWithReason(
        static_cast<uint32_t>(SessionStopReason::SUSPEND_AFTER_RESTART));
  }
}

void SessionManagerImpl::OnSuspendDone(dbus::Signal* signal) {
  suspend_ongoing_ = false;
  last_suspend_done_time_ = tick_clock_->NowTicks();
}

void SessionManagerImpl::OnSystemClockServiceAvailable(bool service_available) {
  if (!service_available) {
    LOG(ERROR) << "Failed to listen for tlsdated service start";
    return;
  }

  GetSystemClockLastSyncInfo();
}

void SessionManagerImpl::GetSystemClockLastSyncInfo() {
  dbus::MethodCall method_call(system_clock::kSystemClockInterface,
                               system_clock::kSystemLastSyncInfo);
  system_clock_proxy_->CallMethod(
      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
      base::Bind(&SessionManagerImpl::OnGotSystemClockLastSyncInfo,
                 weak_ptr_factory_.GetWeakPtr()));
}

void SessionManagerImpl::OnGotSystemClockLastSyncInfo(
    dbus::Response* response) {
  if (!response) {
    LOG(ERROR) << system_clock::kSystemClockInterface << "."
               << system_clock::kSystemLastSyncInfo << " request failed.";
    base::MessageLoop::current()->task_runner()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&SessionManagerImpl::GetSystemClockLastSyncInfo,
                   weak_ptr_factory_.GetWeakPtr()),
        system_clock_last_sync_info_retry_delay_);
    return;
  }

  dbus::MessageReader reader(response);
  bool network_synchronized = false;
  if (!reader.PopBool(&network_synchronized)) {
    LOG(ERROR) << system_clock::kSystemClockInterface << "."
               << system_clock::kSystemLastSyncInfo
               << " response lacks network-synchronized argument";
    return;
  }

  if (network_synchronized) {
    system_clock_synchronized_ = true;
    for (const auto& callback : pending_state_key_callbacks_)
      state_key_generator_->RequestStateKeys(callback);
    pending_state_key_callbacks_.clear();
  } else {
    base::MessageLoop::current()->task_runner()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&SessionManagerImpl::GetSystemClockLastSyncInfo,
                   weak_ptr_factory_.GetWeakPtr()),
        system_clock_last_sync_info_retry_delay_);
  }
}

bool SessionManagerImpl::InitMachineInfo(brillo::ErrorPtr* error,
                                         const std::string& in_data) {
  std::map<std::string, std::string> params;
  if (!ServerBackedStateKeyGenerator::ParseMachineInfo(in_data, &params)) {
    *error = CreateError(dbus_error::kInitMachineInfoFail, "Parse failure.");
    return false;
  }

  if (!state_key_generator_->InitMachineInfo(params)) {
    *error =
        CreateError(dbus_error::kInitMachineInfoFail, "Missing parameters.");
    return false;
  }
  return true;
}

bool SessionManagerImpl::StartArcMiniContainer(
    brillo::ErrorPtr* error, const std::vector<uint8_t>& in_request) {
#if USE_CHEETS
  StartArcMiniContainerRequest request;
  if (!request.ParseFromArray(in_request.data(), in_request.size())) {
    *error = CreateError(DBUS_ERROR_INVALID_ARGS,
                         "StartArcMiniContainerRequest parsing failed.");
    return false;
  }
  std::vector<std::string> env_vars = {
      base::StringPrintf("CHROMEOS_DEV_MODE=%d", IsDevMode(system_)),
      base::StringPrintf("CHROMEOS_INSIDE_VM=%d", IsInsideVm(system_)),
      base::StringPrintf("NATIVE_BRIDGE_EXPERIMENT=%d",
                         request.native_bridge_experiment()),
      base::StringPrintf("ARC_FILE_PICKER_EXPERIMENT=%d",
                         request.arc_file_picker_experiment()),
      base::StringPrintf("ARC_CUSTOM_TABS_EXPERIMENT=%d",
                         request.arc_custom_tabs_experiment()),
      base::StringPrintf("ARC_PRINT_SPOOLER_EXPERIMENT=%d",
                         request.arc_print_spooler_experiment())};
  if (request.lcd_density() > 0) {
    env_vars.push_back(
        base::StringPrintf("ARC_LCD_DENSITY=%d", request.lcd_density()));
  }

  switch (request.play_store_auto_update()) {
    case StartArcMiniContainerRequest_PlayStoreAutoUpdate_AUTO_UPDATE_DEFAULT:
      break;
    case StartArcMiniContainerRequest_PlayStoreAutoUpdate_AUTO_UPDATE_ON:
      env_vars.emplace_back("PLAY_STORE_AUTO_UPDATE=1");
      break;
    case StartArcMiniContainerRequest_PlayStoreAutoUpdate_AUTO_UPDATE_OFF:
      env_vars.emplace_back("PLAY_STORE_AUTO_UPDATE=0");
      break;
    default:
      NOTREACHED() << "Unhandled play store auto-update mode: "
                   << request.play_store_auto_update() << ".";
  }

  if (!StartArcContainer(env_vars, error)) {
    DCHECK(*error);
    return false;
  }
  return true;
#else
  *error = CreateError(dbus_error::kNotAvailable, "ARC not supported.");
  return false;
#endif  // !USE_CHEETS
}

bool SessionManagerImpl::UpgradeArcContainer(
    brillo::ErrorPtr* error, const std::vector<uint8_t>& in_request) {
#if USE_CHEETS
  // Stop the existing instance if it fails to continue to boot an existing
  // container. Using Unretained() is okay because the closure will be called
  // before this function returns. If container was not running, this is no op.
  base::ScopedClosureRunner scoped_runner(base::Bind(
      &SessionManagerImpl::OnContinueArcBootFailed, base::Unretained(this)));

  UpgradeArcContainerRequest request;
  if (!request.ParseFromArray(in_request.data(), in_request.size())) {
    *error = CreateError(DBUS_ERROR_INVALID_ARGS,
                         "UpgradeArcContainerRequest parsing failed.");
    return false;
  }

  pid_t pid = 0;
  if (!android_container_->GetContainerPID(&pid)) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kArcContainerNotFound,
                                  "Failed to find mini-container for upgrade.");
    return false;
  }
  LOG(INFO) << "Android container is running with PID " << pid;

  // |arc_start_time_| is initialized when the container is upgraded (rather
  // than when the mini-container starts) since we are interested in measuring
  // time from when the user logs in until the system is ready to be interacted
  // with.
  arc_start_time_ = tick_clock_->NowTicks();

  // To upgrade the ARC mini-container, a certain amount of disk space is
  // needed under /home. We first check it.
  if (system_->AmountOfFreeDiskSpace(base::FilePath(kArcDiskCheckPath)) <
      kArcCriticalDiskFreeBytes) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kLowFreeDisk,
                                  "Low free disk under /home");
    StopArcInstanceInternal(ArcContainerStopReason::LOW_DISK_SPACE);
    ignore_result(scoped_runner.Release());
    return false;
  }

  std::string account_id;
  if (!NormalizeAccountId(request.account_id(), &account_id, error)) {
    DCHECK(*error);
    return false;
  }
  if (user_sessions_.count(account_id) == 0) {
    // This path can be taken if a forged D-Bus message for starting a full
    // (stateful) container is sent to session_manager before the actual
    // user's session has started. Do not remove the |account_id| check to
    // prevent such a container from starting on login screen.
    *error = CREATE_ERROR_AND_LOG(dbus_error::kSessionDoesNotExist,
                                  "Provided user ID does not have a session.");
    return false;
  }

  android_container_->SetStatefulMode(StatefulMode::STATEFUL);
  auto env_vars = CreateUpgradeArcEnvVars(request, account_id, pid);
  if (!init_controller_->TriggerImpulse(
          kContinueArcBootImpulse, env_vars,
          InitDaemonController::TriggerMode::SYNC)) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kEmitFailed,
                                  "Emitting continue-arc-boot impulse failed.");
    return false;
  }

  login_metrics_->StartTrackingArcUseTime();

  ignore_result(scoped_runner.Release());
  return true;
#else
  *error = CreateError(dbus_error::kNotAvailable, "ARC not supported.");
  return false;
#endif  // !USE_CHEETS
}

bool SessionManagerImpl::StopArcInstance(brillo::ErrorPtr* error) {
#if USE_CHEETS
  if (!StopArcInstanceInternal(ArcContainerStopReason::USER_REQUEST)) {
    *error = CREATE_ERROR_AND_LOG(dbus_error::kContainerShutdownFail,
                                  "Error getting Android container pid.");
    return false;
  }

  return true;
#else
  *error = CreateError(dbus_error::kNotAvailable, "ARC not supported.");
  return false;
#endif  // USE_CHEETS
}

bool SessionManagerImpl::SetArcCpuRestriction(brillo::ErrorPtr* error,
                                              uint32_t in_restriction_state) {
#if USE_CHEETS
  std::string shares_out;
  switch (static_cast<ContainerCpuRestrictionState>(in_restriction_state)) {
    case CONTAINER_CPU_RESTRICTION_FOREGROUND:
      shares_out = std::to_string(kCpuSharesForeground);
      break;
    case CONTAINER_CPU_RESTRICTION_BACKGROUND:
      shares_out = std::to_string(kCpuSharesBackground);
      break;
    default:
      *error = CREATE_ERROR_AND_LOG(dbus_error::kArcCpuCgroupFail,
                                    "Invalid CPU restriction state specified.");
      return false;
  }
  if (base::WriteFile(base::FilePath(kCpuSharesFile), shares_out.c_str(),
                      shares_out.length()) != shares_out.length()) {
    *error =
        CREATE_ERROR_AND_LOG(dbus_error::kArcCpuCgroupFail,
                             "Error updating Android container's cgroups.");
    return false;
  }
  return true;
#else
  *error = CreateError(dbus_error::kNotAvailable, "ARC not supported.");
  return false;
#endif
}

bool SessionManagerImpl::EmitArcBooted(brillo::ErrorPtr* error,
                                       const std::string& in_account_id) {
#if USE_CHEETS
  std::vector<std::string> env_vars;
  if (!in_account_id.empty()) {
    std::string actual_account_id;
    if (!NormalizeAccountId(in_account_id, &actual_account_id, error)) {
      DCHECK(*error);
      return false;
    }
    env_vars.emplace_back("CHROMEOS_USER=" + actual_account_id);
  }

  init_controller_->TriggerImpulse(kArcBootedImpulse, env_vars,
                                   InitDaemonController::TriggerMode::ASYNC);
  return true;
#else
  *error = CreateError(dbus_error::kNotAvailable, "ARC not supported.");
  return false;
#endif
}

bool SessionManagerImpl::GetArcStartTimeTicks(brillo::ErrorPtr* error,
                                              int64_t* out_start_time) {
#if USE_CHEETS
  if (arc_start_time_.is_null()) {
    *error = CreateError(dbus_error::kNotStarted, "ARC is not started yet.");
    return false;
  }
  *out_start_time = arc_start_time_.ToInternalValue();
  return true;
#else
  *error = CreateError(dbus_error::kNotAvailable, "ARC not supported.");
  return false;
#endif  // !USE_CHEETS
}

void SessionManagerImpl::EnableAdbSideloadCallbackAdaptor(
    brillo::dbus_utils::DBusMethodResponse<bool>* response,
    bool result,
    const char* error) {
  if (error != nullptr) {
    brillo::ErrorPtr dbus_error = CreateError(DBUS_ERROR_FAILED, error);
    response->ReplyWithError(dbus_error.get());
  } else {
    response->Return(result);
  }
}

void SessionManagerImpl::EnableAdbSideload(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  if (system_->Exists(base::FilePath(kLoggedInFlag))) {
    auto error = CREATE_ERROR_AND_LOG(
        dbus_error::kSessionExists,
        "EnableAdbSideload is not allowed once a user logged in this boot.");
    response->ReplyWithError(error.get());
    return;
  }

  arc_sideload_status_->EnableAdbSideload(base::Bind(
      &SessionManagerImpl::EnableAdbSideloadCallbackAdaptor,
      weak_ptr_factory_.GetWeakPtr(), base::Owned(response.release())));
}

void SessionManagerImpl::QueryAdbSideloadCallbackAdaptor(
    brillo::dbus_utils::DBusMethodResponse<bool>* response, bool result) {
  response->Return(result);
}

void SessionManagerImpl::QueryAdbSideload(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  arc_sideload_status_->QueryAdbSideload(base::Bind(
      &SessionManagerImpl::QueryAdbSideloadCallbackAdaptor,
      weak_ptr_factory_.GetWeakPtr(), base::Owned(response.release())));
}

void SessionManagerImpl::OnPolicyPersisted(bool success) {
  device_local_account_manager_->UpdateDeviceSettings(
      device_policy_->GetSettings());
  adaptor_.SendPropertyChangeCompleteSignal(ToSuccessSignal(success));
}

void SessionManagerImpl::OnKeyPersisted(bool success) {
  adaptor_.SendSetOwnerKeyCompleteSignal(ToSuccessSignal(success));
}

void SessionManagerImpl::OnKeyGenerated(const std::string& username,
                                        const base::FilePath& temp_key_file) {
  ImportValidateAndStoreGeneratedKey(username, temp_key_file);
}

void SessionManagerImpl::ImportValidateAndStoreGeneratedKey(
    const std::string& username, const base::FilePath& temp_key_file) {
  DLOG(INFO) << "Processing generated key at " << temp_key_file.value();
  std::string key;
  base::ReadFileToString(temp_key_file, &key);
  PLOG_IF(WARNING, !base::DeleteFile(temp_key_file, false))
      << "Can't delete " << temp_key_file.value();
  device_policy_->ValidateAndStoreOwnerKey(
      username, StringToBlob(key), user_sessions_[username]->slot.get());
}

void SessionManagerImpl::InitiateDeviceWipe(const std::string& reason) {
  // The log string must not be confused with other clobbers-state parameters.
  // Sanitize by replacing all non-alphanumeric characters with underscores and
  // clamping size to 50 characters.
  std::string sanitized_reason(reason.substr(0, 50));
  std::locale locale("C");
  std::replace_if(
      sanitized_reason.begin(), sanitized_reason.end(),
      [&locale](const std::string::value_type character) {
        return !std::isalnum(character, locale);
      },
      '_');
  const base::FilePath reset_path(kResetFile);
  system_->AtomicFileWrite(reset_path,
                           "fast safe keepimg reason=" + sanitized_reason);
  RestartDevice(sanitized_reason);
}

// static
bool SessionManagerImpl::NormalizeAccountId(const std::string& account_id,
                                            std::string* actual_account_id_out,
                                            brillo::ErrorPtr* error_out) {
  if (ValidateAccountId(account_id, actual_account_id_out)) {
    DCHECK(!actual_account_id_out->empty());
    return true;
  }

  // TODO(alemate): adjust this error message after ChromeOS will stop using
  // email as cryptohome identifier.
  *error_out =
      CREATE_ERROR_AND_LOG(dbus_error::kInvalidAccount,
                           "Provided email address is not valid.  ASCII only.");
  DCHECK(actual_account_id_out->empty());
  return false;
}

bool SessionManagerImpl::AllSessionsAreIncognito() {
  size_t incognito_count = 0;
  for (UserSessionMap::const_iterator it = user_sessions_.begin();
       it != user_sessions_.end(); ++it) {
    if (it->second)
      incognito_count += it->second->is_incognito;
  }
  return incognito_count == user_sessions_.size();
}

std::unique_ptr<SessionManagerImpl::UserSession>
SessionManagerImpl::CreateUserSession(const std::string& username,
                                      bool is_incognito,
                                      brillo::ErrorPtr* error) {
  std::unique_ptr<PolicyService> user_policy =
      user_policy_factory_->Create(username);
  if (!user_policy) {
    LOG(ERROR) << "User policy failed to initialize.";
    *error = CreateError(dbus_error::kPolicyInitFail, "Can't create session.");
    return nullptr;
  }

  crypto::ScopedPK11Slot slot(nss_->OpenUserDB(GetUserPath(username)));
  if (!slot) {
    LOG(ERROR) << "Could not open the current user's NSS database.";
    *error = CreateError(dbus_error::kNoUserNssDb, "Can't create session.");
    return nullptr;
  }

  return std::make_unique<UserSession>(username, SanitizeUserName(username),
                                       is_incognito, std::move(slot),
                                       std::move(user_policy));
}

brillo::ErrorPtr SessionManagerImpl::VerifyUnsignedPolicyStore() {
  // Unsigned policy store D-Bus call is allowed only in enterprise_ad mode.
  const std::string& mode = install_attributes_reader_->GetAttribute(
      InstallAttributesReader::kAttrMode);
  if (mode != InstallAttributesReader::kDeviceModeEnterpriseAD) {
    return CREATE_ERROR_AND_LOG(dbus_error::kPolicySignatureRequired,
                                "Device mode doesn't permit unsigned policy.");
  }

  return nullptr;
}

PolicyService* SessionManagerImpl::GetPolicyService(
    const PolicyDescriptor& descriptor,
    std::unique_ptr<PolicyService>* storage,
    brillo::ErrorPtr* error) {
  DCHECK(storage);
  DCHECK(error);
  PolicyService* policy_service = nullptr;
  switch (descriptor.account_type()) {
    case ACCOUNT_TYPE_DEVICE: {
      policy_service = device_policy_.get();
      break;
    }
    case ACCOUNT_TYPE_USER: {
      UserSessionMap::const_iterator it =
          user_sessions_.find(descriptor.account_id());
      policy_service = it != user_sessions_.end()
                           ? it->second->policy_service.get()
                           : nullptr;
      break;
    }
    case ACCOUNT_TYPE_SESSIONLESS_USER: {
      // Special case, different lifetime management than all other cases
      // (unique_ptr vs plain ptr). TODO(crbug.com/771638): Clean this up when
      // the bug is fixed and sessionless users are handled differently.
      *storage = user_policy_factory_->CreateForHiddenUserHome(
          descriptor.account_id());
      policy_service = storage->get();
      break;
    }
    case ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT: {
      policy_service = device_local_account_manager_->GetPolicyService(
          descriptor.account_id());
      break;
    }
  }
  if (policy_service)
    return policy_service;

  // Error case
  const std::string message =
      base::StringPrintf("Cannot get policy service for account type %i",
                         static_cast<int>(descriptor.account_type()));
  LOG(ERROR) << message;
  *error = CreateError(dbus_error::kGetServiceFail, message);
  return nullptr;
}

int SessionManagerImpl::GetKeyInstallFlags(const PolicyDescriptor& descriptor) {
  switch (descriptor.account_type()) {
    case ACCOUNT_TYPE_DEVICE: {
      int flags = PolicyService::KEY_ROTATE;
      if (!session_started_)
        flags |= PolicyService::KEY_INSTALL_NEW | PolicyService::KEY_CLOBBER;
      return flags;
    }
    case ACCOUNT_TYPE_USER:
      return PolicyService::KEY_INSTALL_NEW | PolicyService::KEY_ROTATE;
    case ACCOUNT_TYPE_SESSIONLESS_USER: {
      // Only supports retrieval, not storage.
      NOTREACHED();
      return PolicyService::KEY_NONE;
    }
    case ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT:
      return PolicyService::KEY_NONE;
  }
}

void SessionManagerImpl::StorePolicyInternalEx(
    const std::vector<uint8_t>& descriptor_blob,
    const std::vector<uint8_t>& policy_blob,
    SignatureCheck signature_check,
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response) {
  brillo::ErrorPtr error;
  PolicyDescriptor descriptor;
  if (!ParseAndValidatePolicyDescriptor(descriptor_blob,
                                        PolicyDescriptorUsage::kStore,
                                        &descriptor, &error)) {
    response->ReplyWithError(error.get());
    return;
  }

  std::unique_ptr<PolicyService> storage;
  PolicyService* policy_service =
      GetPolicyService(descriptor, &storage, &error);
  if (!policy_service) {
    response->ReplyWithError(error.get());
    return;
  }

  int key_flags = GetKeyInstallFlags(descriptor);
  PolicyNamespace ns(descriptor.domain(), descriptor.component_id());

  // If the blob is empty, delete the policy.
  DCHECK(dbus_service_);
  if (policy_blob.empty()) {
    if (!policy_service->Delete(ns, signature_check)) {
      auto error =
          CreateError(dbus_error::kDeleteFail, "Failed to delete policy");
      response->ReplyWithError(error.get());
      return;
    }
    response->Return();
  } else {
    policy_service->Store(ns, policy_blob, key_flags, signature_check,
                          dbus_service_->CreatePolicyServiceCompletionCallback(
                              std::move(response)));
  }
}

void SessionManagerImpl::RestartDevice(const std::string& reason) {
  delegate_->RestartDevice("session_manager (" + reason + ")");
}

#if USE_CHEETS
bool SessionManagerImpl::StartArcContainer(
    const std::vector<std::string>& env_vars, brillo::ErrorPtr* error_out) {
  init_controller_->TriggerImpulse(kStartArcInstanceImpulse, env_vars,
                                   InitDaemonController::TriggerMode::ASYNC);

  // Pass in the same environment variables that were passed to arc-setup
  // (through init, above) into the container invocation as environment values.
  // When the container is started with run_oci, this allows for it to correctly
  // propagate some information (such as the CHROMEOS_USER) to the hooks so it
  // can set itself up.
  if (!android_container_->StartContainer(
          env_vars, base::Bind(&SessionManagerImpl::OnAndroidContainerStopped,
                               weak_ptr_factory_.GetWeakPtr()))) {
    // Failed to start container. Thus, trigger stop-arc-instance impulse
    // manually for cleanup.
    init_controller_->TriggerImpulse(kStopArcInstanceImpulse, {},
                                     InitDaemonController::TriggerMode::SYNC);
    *error_out = CREATE_ERROR_AND_LOG(dbus_error::kContainerStartupFail,
                                      "Starting Android container failed.");
    return false;
  }

  pid_t pid = 0;
  android_container_->GetContainerPID(&pid);
  LOG(INFO) << "Started Android container with PID " << pid;
  return true;
}

std::vector<std::string> SessionManagerImpl::CreateUpgradeArcEnvVars(
    const UpgradeArcContainerRequest& request,
    const std::string& account_id,
    pid_t pid) {
  std::vector<std::string> env_vars = {
      base::StringPrintf("CHROMEOS_DEV_MODE=%d", IsDevMode(system_)),
      base::StringPrintf("CHROMEOS_INSIDE_VM=%d", IsInsideVm(system_)),
      "CHROMEOS_USER=" + account_id,
      base::StringPrintf("DISABLE_BOOT_COMPLETED_BROADCAST=%d",
                         request.skip_boot_completed_broadcast()),
      base::StringPrintf("CONTAINER_PID=%d", pid),
      "DEMO_SESSION_APPS_PATH=" + request.demo_session_apps_path(),
      base::StringPrintf("IS_DEMO_SESSION=%d", request.is_demo_session()),
      base::StringPrintf("SUPERVISION_TRANSITION=%d",
                         request.supervision_transition()),
      // Never allow for managed account until the policy is properly defined.
      base::StringPrintf("ENABLE_ADB_SIDELOAD=%d",
                         !request.is_account_managed() &&
                             arc_sideload_status_->IsAdbSideloadAllowed())};

  switch (request.packages_cache_mode()) {
    case UpgradeArcContainerRequest_PackageCacheMode_SKIP_SETUP_COPY_ON_INIT:
      env_vars.emplace_back("SKIP_PACKAGES_CACHE_SETUP=1");
      env_vars.emplace_back("COPY_PACKAGES_CACHE=1");
      break;
    case UpgradeArcContainerRequest_PackageCacheMode_COPY_ON_INIT:
      env_vars.emplace_back("SKIP_PACKAGES_CACHE_SETUP=0");
      env_vars.emplace_back("COPY_PACKAGES_CACHE=1");
      break;
    case UpgradeArcContainerRequest_PackageCacheMode_DEFAULT:
      env_vars.emplace_back("SKIP_PACKAGES_CACHE_SETUP=0");
      env_vars.emplace_back("COPY_PACKAGES_CACHE=0");
      break;
    default:
      NOTREACHED() << "Wrong packages cache mode: "
                   << request.packages_cache_mode() << ".";
  }

  if (request.skip_gms_core_cache()) {
    env_vars.emplace_back("SKIP_GMS_CORE_CACHE_SETUP=1");
  } else {
    env_vars.emplace_back("SKIP_GMS_CORE_CACHE_SETUP=0");
  }

  DCHECK(request.has_locale());
  env_vars.emplace_back("LOCALE=" + request.locale());

  std::string preferred_languages;
  for (int i = 0; i < request.preferred_languages_size(); ++i) {
    if (i != 0)
      preferred_languages += ",";
    preferred_languages += request.preferred_languages(i);
  }
  env_vars.emplace_back("PREFERRED_LANGUAGES=" + preferred_languages);

  return env_vars;
}

void SessionManagerImpl::OnContinueArcBootFailed() {
  LOG(ERROR) << "Failed to continue ARC boot. Stopping the container.";
  StopArcInstanceInternal(ArcContainerStopReason::UPGRADE_FAILURE);
}

bool SessionManagerImpl::StopArcInstanceInternal(
    ArcContainerStopReason reason) {
  pid_t pid;
  if (!android_container_->GetContainerPID(&pid))
    return false;

  android_container_->RequestJobExit(reason);
  android_container_->EnsureJobExit(kContainerTimeout);
  return true;
}

void SessionManagerImpl::OnAndroidContainerStopped(
    pid_t pid,
    ArcContainerStopReason reason) {
  if (reason == ArcContainerStopReason::CRASH) {
    LOG(ERROR) << "Android container with PID " << pid << " crashed";
  } else {
    LOG(INFO) << "Android container with PID " << pid << " stopped";
  }

  login_metrics_->StopTrackingArcUseTime();
  if (!init_controller_->TriggerImpulse(
          kStopArcInstanceImpulse, {},
          InitDaemonController::TriggerMode::SYNC)) {
    LOG(ERROR) << "Emitting stop-arc-instance impulse failed.";
  }

  adaptor_.SendArcInstanceStoppedSignal(static_cast<uint32_t>(reason));
}
#endif  // USE_CHEETS

}  // namespace login_manager
