Commit 10d6a55d authored by Danila Kuzmin's avatar Danila Kuzmin Committed by Commit Bot

oobe: Show battery warning on the update screen

Battery warning message is shown after UPDATE_AVAILABLE stage on update
screen iff the battery is DISCHARGING and is lower 50%. In this CL only
placeholder for html part is provided.

Bug: 1101783
Change-Id: I70376a668c1a905e5dbab6cda986f13029e8e71c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2285009
Commit-Queue: Danila Kuzmin <dkuzmin@google.com>
Reviewed-by: default avatarRoman Sorokin [CET] <rsorokin@chromium.org>
Reviewed-by: default avatarRoman Aleksandrov <raleksandrov@google.com>
Cr-Commit-Position: refs/heads/master@{#791222}
parent 86818c5c
......@@ -45,6 +45,7 @@ class MockUpdateView : public UpdateView {
MOCK_METHOD(void, SetProgress, (int value));
MOCK_METHOD(void, SetRequiresPermissionForCellular, (bool value));
MOCK_METHOD(void, SetCancelUpdateShortcutEnabled, (bool value));
MOCK_METHOD(void, ShowLowBatteryWarningMessage, (bool value));
private:
UpdateScreen* screen_ = nullptr;
......
......@@ -20,6 +20,7 @@
#include "chrome/browser/chromeos/login/wizard_context.h"
#include "chrome/browser/chromeos/policy/enrollment_requisition_manager.h"
#include "chrome/browser/ui/webui/chromeos/login/update_screen_handler.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/network/network_state.h"
namespace chromeos {
......@@ -44,6 +45,9 @@ constexpr const base::TimeDelta kDelayErrorMessage =
constexpr const base::TimeDelta kShowDelay =
base::TimeDelta::FromMicroseconds(400);
// When battery percent is lower and DISCHARGING warn user about it.
const double kInsufficientBatteryPercent = 50;
void RecordDownloadingTime(base::TimeDelta duration) {
base::UmaHistogramLongTimes("OOBE.UpdateScreen.UpdateDownloadingTime",
duration);
......@@ -105,11 +109,15 @@ UpdateScreen::UpdateScreen(UpdateView* view,
std::make_unique<ErrorScreensHistogramHelper>("Update")),
version_updater_(std::make_unique<VersionUpdater>(this)),
tick_clock_(base::DefaultTickClock::GetInstance()) {
if (chromeos::features::IsBetterUpdateEnabled())
PowerManagerClient::Get()->AddObserver(this);
if (view_)
view_->Bind(this);
}
UpdateScreen::~UpdateScreen() {
if (chromeos::features::IsBetterUpdateEnabled())
PowerManagerClient::Get()->RemoveObserver(this);
if (view_)
view_->Unbind();
}
......@@ -145,6 +153,8 @@ bool UpdateScreen::MaybeSkip(WizardContext* context) {
}
void UpdateScreen::ShowImpl() {
if (chromeos::features::IsBetterUpdateEnabled())
PowerManagerClient::Get()->RequestStatusUpdate();
#if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
if (view_) {
view_->SetCancelUpdateShortcutEnabled(true);
......@@ -355,6 +365,8 @@ void UpdateScreen::UpdateInfoChanged(
default:
NOTREACHED();
}
if (chromeos::features::IsBetterUpdateEnabled())
UpdateBatteryWarningVisibility();
if (need_refresh_view)
RefreshView(update_info);
}
......@@ -370,6 +382,25 @@ void UpdateScreen::FinishExitUpdate(Result result) {
exit_callback_.Run(result);
}
void UpdateScreen::PowerChanged(
const power_manager::PowerSupplyProperties& proto) {
UpdateBatteryWarningVisibility();
}
void UpdateScreen::UpdateBatteryWarningVisibility() {
if (!view_)
return;
const base::Optional<power_manager::PowerSupplyProperties>& proto =
PowerManagerClient::Get()->GetLastStatus();
if (!proto.has_value())
return;
view_->ShowLowBatteryWarningMessage(
is_critical_checked_ && HasCriticalUpdate() &&
proto->battery_state() ==
power_manager::PowerSupplyProperties_BatteryState_DISCHARGING &&
proto->battery_percent() < kInsufficientBatteryPercent);
}
void UpdateScreen::RefreshView(const VersionUpdater::UpdateInfo& update_info) {
if (view_) {
view_->SetProgress(update_info.progress);
......@@ -386,6 +417,9 @@ void UpdateScreen::RefreshView(const VersionUpdater::UpdateInfo& update_info) {
bool UpdateScreen::HasCriticalUpdate() {
if (ignore_update_deadlines_)
return true;
if (has_critical_update_.has_value())
return has_critical_update_.value();
has_critical_update_ = true;
std::string deadline;
// Checking for update flag file causes us to do blocking IO on UI thread.
......@@ -394,6 +428,7 @@ bool UpdateScreen::HasCriticalUpdate() {
base::FilePath update_deadline_file_path(kUpdateDeadlineFile);
if (!base::ReadFileToString(update_deadline_file_path, &deadline) ||
deadline.empty()) {
has_critical_update_ = false;
return false;
}
......
......@@ -16,6 +16,7 @@
#include "chrome/browser/chromeos/login/screens/base_screen.h"
#include "chrome/browser/chromeos/login/screens/error_screen.h"
#include "chrome/browser/chromeos/login/version_updater/version_updater.h"
#include "chromeos/dbus/power/power_manager_client.h"
namespace base {
class TickClock;
......@@ -54,7 +55,9 @@ class WizardContext;
// has network connectivity - if the current network is not online (e.g. behind
// a protal), it will request an ErrorScreen to be shown. Update check will be
// delayed until the Internet connectivity is established.
class UpdateScreen : public BaseScreen, public VersionUpdater::Delegate {
class UpdateScreen : public BaseScreen,
public VersionUpdater::Delegate,
public PowerManagerClient::Observer {
public:
using Result = VersionUpdater::Result;
......@@ -93,6 +96,9 @@ class UpdateScreen : public BaseScreen, public VersionUpdater::Delegate {
const VersionUpdater::UpdateInfo& update_info) override;
void FinishExitUpdate(VersionUpdater::Result result) override;
// PowerManagerClient::Observer:
void PowerChanged(const power_manager::PowerSupplyProperties& proto) override;
void set_exit_callback_for_testing(ScreenExitCallback exit_callback) {
exit_callback_ = exit_callback;
}
......@@ -134,6 +140,10 @@ class UpdateScreen : public BaseScreen, public VersionUpdater::Delegate {
// screen gets hidden.
void OnErrorScreenHidden();
// Updates visibility of the low battery warning message during the update
// stages. Called when power or update status changes.
void UpdateBatteryWarningVisibility();
UpdateView* view_;
ErrorScreen* error_screen_;
ScreenExitCallback exit_callback_;
......@@ -151,6 +161,9 @@ class UpdateScreen : public BaseScreen, public VersionUpdater::Delegate {
// True if already checked that update is critical.
bool is_critical_checked_ = false;
// Caches the result of HasCriticalUpdate function.
base::Optional<bool> has_critical_update_;
// True if the update progress should be hidden even if update_info suggests
// the opposite.
bool hide_progress_on_exit_ = false;
......
......@@ -11,6 +11,7 @@
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
......@@ -28,8 +29,10 @@
#include "chrome/browser/ui/webui/chromeos/login/update_screen_handler.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_update_engine_client.h"
#include "chromeos/dbus/power/fake_power_manager_client.h"
#include "chromeos/network/network_connection_handler.h"
#include "chromeos/network/network_handler.h"
#include "content/public/test/browser_test.h"
......@@ -59,6 +62,8 @@ const test::UIPath kCellularPermissionNext = {"oobe-update",
"cellular-permission-next"};
const test::UIPath kCellularPermissionBack = {"oobe-update",
"cellular-permission-back"};
const test::UIPath kLowBatteryWarningMessage = {"oobe-update",
"battery-warning"};
const test::UIPath kErrorMessage = {"error-message"};
// UMA names for better test reading.
......@@ -168,6 +173,23 @@ class UpdateScreenTest : public OobeBaseTest {
DISALLOW_COPY_AND_ASSIGN(UpdateScreenTest);
};
class BetterUpdateScreenTest : public UpdateScreenTest {
public:
BetterUpdateScreenTest() {
feature_list_.InitWithFeatures({chromeos::features::kBetterUpdateScreen},
{});
}
~BetterUpdateScreenTest() override = default;
protected:
chromeos::FakePowerManagerClient* power_manager_client() {
return chromeos::FakePowerManagerClient::Get();
}
private:
base::test::ScopedFeatureList feature_list_;
};
void UpdateScreenTest::CheckPathVisiblity(
std::initializer_list<base::StringPiece> element_ids,
bool visibility) {
......@@ -729,4 +751,137 @@ IN_PROC_BROWSER_TEST_F(UpdateScreenTest, UpdateOverCellularRejected) {
histogram_tester_.ExpectTotalCount(kTimeFinalize, 0);
}
IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, TestInitialLowBatteryStatus) {
update_screen_->set_ignore_update_deadlines_for_testing(true);
// Set low battery and discharging status before oobe-update screen is shown.
power_manager::PowerSupplyProperties props;
props.set_battery_percent(49);
props.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
power_manager_client()->UpdatePowerProperties(props);
ShowUpdateScreen();
EXPECT_TRUE(power_manager_client()->HasObserver(update_screen_));
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
update_engine::StatusResult status;
status.set_current_operation(update_engine::Operation::DOWNLOADING);
status.set_new_version("latest and greatest");
status.set_new_size(1'000'000'000);
status.set_progress(0.0);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
// Warning message is shown while not charging and battery is low.
test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage);
}
IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest,
TestBatteryWarningDuringUpdateStages) {
update_screen_->set_ignore_update_deadlines_for_testing(true);
ShowUpdateScreen();
EXPECT_TRUE(power_manager_client()->HasObserver(update_screen_));
power_manager::PowerSupplyProperties props;
props.set_battery_percent(49);
props.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
power_manager_client()->UpdatePowerProperties(props);
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
update_engine::StatusResult status;
// Warning message is hidden before DOWNLOADING stage.
status.set_current_operation(update_engine::Operation::CHECKING_FOR_UPDATE);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
status.set_current_operation(update_engine::Operation::UPDATE_AVAILABLE);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
status.set_current_operation(update_engine::Operation::DOWNLOADING);
status.set_new_version("latest and greatest");
status.set_new_size(1'000'000'000);
status.set_progress(0.0);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage);
// Warning message remains on the screen during next update stages, iff the
// battery is low and discharging.
status.set_current_operation(update_engine::Operation::VERIFYING);
status.set_progress(1.0);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage);
status.set_current_operation(update_engine::Operation::FINALIZING);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage);
status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
// UpdateStatusChanged(status) calls RebootAfterUpdate().
EXPECT_EQ(update_engine_client()->reboot_after_update_call_count(), 1);
test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage);
}
IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest,
TestBatteryWarningOnDifferentBatteryStatus) {
update_screen_->set_ignore_update_deadlines_for_testing(true);
ShowUpdateScreen();
EXPECT_TRUE(power_manager_client()->HasObserver(update_screen_));
update_engine::StatusResult status;
status.set_current_operation(update_engine::Operation::DOWNLOADING);
status.set_new_version("latest and greatest");
status.set_new_size(1'000'000'000);
status.set_progress(0.0);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
power_manager::PowerSupplyProperties props;
// Warning message is hidden while not charging, but enough battery.
props.set_battery_percent(100);
props.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_FULL);
power_manager_client()->UpdatePowerProperties(props);
test::OobeJS().ExpectVisible("oobe-update");
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
props.set_battery_percent(85);
props.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
power_manager_client()->UpdatePowerProperties(props);
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
// Warning message is shown while not charging and battery is low.
props.set_battery_percent(48);
power_manager_client()->UpdatePowerProperties(props);
test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage);
// Warning message is hidden while charging.
props.set_battery_percent(49);
props.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_CHARGING);
power_manager_client()->UpdatePowerProperties(props);
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
}
} // namespace chromeos
......@@ -10,6 +10,7 @@
<template>
<style include="oobe-dialog-host"></style>
<link rel="stylesheet" href="oobe_update.css">
<div hidden="[[betterUpdateScreenFeatureEnabled_]]">
<checking-downloading-update id="checking-downloading-update"
aria-label$="[[i18nDynamic(locale, 'updateScreenAccessibleTitle')]]"
hidden="[[requiresPermissionForCellular]]"
......@@ -47,5 +48,13 @@
on-tap="onNextClicked_"></oobe-next-button>
</div>
</oobe-dialog>
</div>
<div hidden="[[!betterUpdateScreenFeatureEnabled_]]">
<oobe-dialog>
<div hidden="[[!showLowBatteryWarning]]" id="battery-warning"
slot="footer">
</div>
</oobe-dialog>
</div>
</template>
</dom-module>
......@@ -28,9 +28,22 @@ Polymer({
'setUpdateProgress',
'setRequiresPermissionForCellular',
'setCancelUpdateShortcutEnabled',
'showLowBatteryWarningMessage',
],
properties: {
/**
* Shows better update screen instead of the old one. True when
* kBetterUpdateScreen feature flag is enabled.
*/
betterUpdateScreenFeatureEnabled_: {
type: Boolean,
value() {
return loadTimeData.getBoolean('betterUpdateScreenFeatureEnabled');
},
readOnly: true,
},
/**
* Shows "Checking for update ..." section and hides "Updating..." section.
*/
......@@ -102,6 +115,14 @@ Polymer({
type: String,
value: 'cancelUpdateHint',
},
/**
* Shows battery warning message during Downloading stage.
*/
showLowBatteryWarning: {
type: Boolean,
value: false,
},
},
ready() {
......@@ -196,5 +217,13 @@ Polymer({
this.checkingForUpdate = visible;
},
/**
* Shows or hides battery warning message.
* @param {boolean} visible Is message visible?
*/
showLowBatteryWarningMessage(visible) {
this.showLowBatteryWarning = visible;
},
});
})();
......@@ -12,6 +12,7 @@
#include "chrome/browser/chromeos/login/screens/update_screen.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/constants/chromeos_features.h"
#include "components/login/localized_values_builder.h"
#include "ui/chromeos/devicetype_utils.h"
......@@ -81,6 +82,10 @@ void UpdateScreenHandler::SetCancelUpdateShortcutEnabled(bool value) {
CallJS("login.UpdateScreen.setCancelUpdateShortcutEnabled", value);
}
void UpdateScreenHandler::ShowLowBatteryWarningMessage(bool value) {
CallJS("login.UpdateScreen.showLowBatteryWarningMessage", value);
}
void UpdateScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
builder->Add("checkingForUpdatesMsg", IDS_CHECKING_FOR_UPDATE_MSG);
......@@ -115,6 +120,12 @@ void UpdateScreenHandler::DeclareLocalizedValues(
builder->Add("updatingScreenTitle", IDS_UPDATING_SCREEN_TITLE);
}
void UpdateScreenHandler::GetAdditionalParameters(base::DictionaryValue* dict) {
dict->SetBoolKey("betterUpdateScreenFeatureEnabled",
chromeos::features::IsBetterUpdateEnabled());
BaseScreenHandler::GetAdditionalParameters(dict);
}
void UpdateScreenHandler::Initialize() {
if (show_on_init_) {
Show();
......
......@@ -44,6 +44,7 @@ class UpdateView {
virtual void SetProgress(int value) = 0;
virtual void SetRequiresPermissionForCellular(bool value) = 0;
virtual void SetCancelUpdateShortcutEnabled(bool value) = 0;
virtual void ShowLowBatteryWarningMessage(bool value) = 0;
};
class UpdateScreenHandler : public UpdateView, public BaseScreenHandler {
......@@ -67,10 +68,12 @@ class UpdateScreenHandler : public UpdateView, public BaseScreenHandler {
void SetProgress(int value) override;
void SetRequiresPermissionForCellular(bool value) override;
void SetCancelUpdateShortcutEnabled(bool value) override;
void ShowLowBatteryWarningMessage(bool value) override;
// BaseScreenHandler:
void DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) override;
void GetAdditionalParameters(base::DictionaryValue* dict) override;
void Initialize() override;
UpdateScreen* screen_ = nullptr;
......
......@@ -56,6 +56,13 @@ const base::Feature kAssistPersonalInfo{"AssistPersonalInfo",
extern const base::Feature kAvatarToolbarButton{
"AvatarToolbarButton", base::FEATURE_DISABLED_BY_DEFAULT};
// Enables better version of the UpdateScreen in OOBE. Displays low battery
// warnings during the update downloading and further stages. Provides time
// estimates of the update stages.
// https://crbug.com/1101317
const base::Feature kBetterUpdateScreen{"BetterUpdateScreen",
base::FEATURE_DISABLED_BY_DEFAULT};
// Enables or disables more aggressive filtering out of Bluetooth devices with
// "appearances" that are less likely to be pairable or useful.
const base::Feature kBluetoothAggressiveAppearanceFilter{
......@@ -504,6 +511,10 @@ bool IsAmbientModeEnabled() {
return base::FeatureList::IsEnabled(kAmbientModeFeature);
}
bool IsBetterUpdateEnabled() {
return base::FeatureList::IsEnabled(kBetterUpdateScreen);
}
bool IsDeepLinkingEnabled() {
return base::FeatureList::IsEnabled(kOsSettingsDeepLinking);
}
......
......@@ -34,6 +34,8 @@ extern const base::Feature kAssistPersonalInfo;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kAvatarToolbarButton;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kBetterUpdateScreen;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kBluetoothAggressiveAppearanceFilter;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kBluetoothFixA2dpPacketSize;
......@@ -220,6 +222,7 @@ extern const base::Feature kImeMozcProto;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsAmbientModeEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsAssistantEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsBetterUpdateEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsDeepLinkingEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsEduCoexistenceEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsImeSandboxEnabled();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment