blob: 6ad640826e096238286d2db7733b2ed9855231b1 [file] [log] [blame]
// Copyright 2019 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 "chromeos/login/session/session_termination_manager.h"
#include "base/bind.h"
#include "base/logging.h"
#include "chromeos/dbus/cryptohome/cryptohome_client.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/dbus/session_manager/session_manager_client.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
SessionTerminationManager* g_instance = nullptr;
} // namespace
SessionTerminationManager::SessionTerminationManager() {
DCHECK(!g_instance);
g_instance = this;
}
SessionTerminationManager::~SessionTerminationManager() {
g_instance = nullptr;
}
// static
SessionTerminationManager* SessionTerminationManager::Get() {
return g_instance;
}
void SessionTerminationManager::StopSession(
login_manager::SessionStopReason reason) {
// If the device is locked to single user, it must reboot on sign out.
if (is_locked_to_single_user_) {
Reboot();
} else {
SessionManagerClient::Get()->StopSession(reason);
}
}
void SessionTerminationManager::RebootIfNecessary() {
CryptohomeClient::Get()->WaitForServiceToBeAvailable(
base::BindOnce(&SessionTerminationManager::DidWaitForServiceToBeAvailable,
weak_factory_.GetWeakPtr()));
}
void SessionTerminationManager::SetDeviceLockedToSingleUser() {
is_locked_to_single_user_ = true;
}
bool SessionTerminationManager::IsLockedToSingleUser() {
return is_locked_to_single_user_;
}
void SessionTerminationManager::DidWaitForServiceToBeAvailable(
bool service_is_available) {
if (!service_is_available) {
LOG(ERROR) << "WaitForServiceToBeAvailable failed.";
return;
}
CryptohomeClient::Get()->GetTpmStatus(
cryptohome::GetTpmStatusRequest(),
base::BindOnce(&SessionTerminationManager::RebootIfNecessaryProcessReply,
weak_factory_.GetWeakPtr()));
}
void SessionTerminationManager::ProcessTpmStatusReply(
const base::Optional<cryptohome::BaseReply>& reply) {
if (!reply.has_value() || reply->has_error() ||
!reply->HasExtension(cryptohome::GetTpmStatusReply::reply)) {
LOG(ERROR) << "TPM status request failed, error: "
<< (reply.has_value() && reply->has_error() ? reply->error()
: 0);
return;
}
auto reply_proto = reply->GetExtension(cryptohome::GetTpmStatusReply::reply);
if (reply_proto.has_is_locked_to_single_user() &&
reply_proto.is_locked_to_single_user()) {
is_locked_to_single_user_ = true;
}
}
void SessionTerminationManager::Reboot() {
PowerManagerClient::Get()->RequestRestart(
power_manager::REQUEST_RESTART_OTHER, "Reboot forced by policy");
}
void SessionTerminationManager::RebootIfNecessaryProcessReply(
base::Optional<cryptohome::BaseReply> reply) {
ProcessTpmStatusReply(reply);
if (is_locked_to_single_user_)
Reboot();
}
} // namespace chromeos