| // 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 |