blob: 2d9a2ff8187bca05f142c23b64f34c5a29b6cf23 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/power/idle_action_warning_observer.h"
#include <memory>
#include "ash/constants/ash_pref_names.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chrome/browser/ash/power/idle_action_warning_dialog_view.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chromeos/ash/components/dbus/dbus_thread_manager.h"
#include "chromeos/ash/components/demo_mode/utils/demo_session_utils.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/dbus/power/power_policy_controller.h"
#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
#include "components/prefs/pref_service.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace ash {
namespace {
// DO NOT REORDER - used to report metrics.
enum class IdleLogoutWarningEvent {
kShown = 0,
kCanceled = 1,
kMaxValue = kCanceled
};
void ReportMetricsForDemoMode(IdleLogoutWarningEvent event) {
if (ash::demo_mode::IsDeviceInDemoMode()) {
UMA_HISTOGRAM_ENUMERATION("DemoMode.IdleLogoutWarningEvent", event);
}
}
chromeos::PowerPolicyController::Action GetIdleAction(bool on_battery_power) {
PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs();
int action;
if (on_battery_power) {
action = prefs->GetInteger(ash::prefs::kPowerBatteryIdleAction);
} else {
action = prefs->GetInteger(ash::prefs::kPowerAcIdleAction);
}
return static_cast<chromeos::PowerPolicyController::Action>(action);
}
} // namespace
class IdleActionWarningObserver::PowerManagerObserver
: public chromeos::PowerManagerClient::Observer {
public:
PowerManagerObserver(IdleActionWarningObserver* idle_action_warning_observer,
chromeos::PowerManagerClient* client)
: idle_action_warning_observer_(idle_action_warning_observer) {
observation_.Observe(client);
}
void IdleActionImminent(base::TimeDelta time_until_idle_action) override {
idle_action_warning_observer_->IdleActionImminent(time_until_idle_action);
}
void IdleActionDeferred() override {
idle_action_warning_observer_->IdleActionDeferred();
}
void PowerChanged(
const power_manager::PowerSupplyProperties& proto) override {
idle_action_warning_observer_->PowerChanged(proto);
}
private:
base::ScopedObservation<chromeos::PowerManagerClient, PowerManagerObserver>
observation_{this};
raw_ptr<IdleActionWarningObserver> idle_action_warning_observer_;
};
class IdleActionWarningObserver::WidgetObserver : public views::WidgetObserver {
public:
WidgetObserver(IdleActionWarningObserver* idle_action_warning_observer,
views::Widget* widget)
: idle_action_warning_observer_(idle_action_warning_observer) {
observation_.Observe(widget);
}
void OnWidgetDestroying(views::Widget* widget) override {
idle_action_warning_observer_->OnWidgetDestroying(widget);
}
private:
base::ScopedObservation<views::Widget, WidgetObserver> observation_{this};
raw_ptr<IdleActionWarningObserver> idle_action_warning_observer_;
};
IdleActionWarningObserver::IdleActionWarningObserver() {
power_manager_observer_ = std::make_unique<PowerManagerObserver>(
this, chromeos::PowerManagerClient::Get());
}
IdleActionWarningObserver::~IdleActionWarningObserver() {
power_manager_observer_.reset();
widged_observer_.reset();
if (warning_dialog_) {
warning_dialog_->CloseDialog();
}
}
void IdleActionWarningObserver::IdleActionImminent(
base::TimeDelta time_until_idle_action) {
// Only display warning if idle action is to shut down or logout.
chromeos::PowerPolicyController::Action idle_action =
GetIdleAction(on_battery_power_);
if (idle_action != chromeos::PowerPolicyController::ACTION_STOP_SESSION &&
idle_action != chromeos::PowerPolicyController::ACTION_SHUT_DOWN) {
HideDialogIfPresent();
return;
}
const base::TimeTicks idle_action_time =
base::TimeTicks::Now() + time_until_idle_action;
if (warning_dialog_) {
warning_dialog_->Update(idle_action_time);
} else {
warning_dialog_ = new IdleActionWarningDialogView(idle_action_time);
widged_observer_ =
std::make_unique<WidgetObserver>(this, warning_dialog_->GetWidget());
ReportMetricsForDemoMode(IdleLogoutWarningEvent::kShown);
}
}
void IdleActionWarningObserver::IdleActionDeferred() {
HideDialogIfPresent();
}
void IdleActionWarningObserver::PowerChanged(
const power_manager::PowerSupplyProperties& proto) {
on_battery_power_ =
proto.battery_state() ==
power_manager::PowerSupplyProperties_BatteryState_DISCHARGING;
}
void IdleActionWarningObserver::OnWidgetDestroying(views::Widget* widget) {
DCHECK(warning_dialog_);
DCHECK_EQ(widget, warning_dialog_->GetWidget());
widged_observer_.reset();
warning_dialog_ = nullptr;
}
void IdleActionWarningObserver::HideDialogIfPresent() {
if (warning_dialog_) {
warning_dialog_->CloseDialog();
ReportMetricsForDemoMode(IdleLogoutWarningEvent::kCanceled);
}
}
} // namespace ash