Commit a3809f03 authored by Danila Kuzmin's avatar Danila Kuzmin Committed by Commit Bot

oobe: Add reboot progress dialog to UpdateScreen

Bug: 1108862
Change-Id: If36f057d4724f10f41558affe3900aee0d65a89d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2322827
Commit-Queue: Danila Kuzmin <dkuzmin@google.com>
Reviewed-by: default avatarRoman Aleksandrov <raleksandrov@google.com>
Reviewed-by: default avatarRoman Sorokin [CET] <rsorokin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797710}
parent 1bd8ee1d
...@@ -365,6 +365,9 @@ ...@@ -365,6 +365,9 @@
<message name="IDS_UPDATE_AVAILABLE" desc="Notification for available update"> <message name="IDS_UPDATE_AVAILABLE" desc="Notification for available update">
System update available. Preparing to download&#x2026; System update available. Preparing to download&#x2026;
</message> </message>
<message name="IDS_UPDATE_COMPLETED_REBOOTING" desc="Notification for update completed and reboot is in progress">
Restarting to apply updates
</message>
<message name="IDS_UPDATE_COMPLETED" desc="Notification for update completed"> <message name="IDS_UPDATE_COMPLETED" desc="Notification for update completed">
System update complete. Please restart the system. System update complete. Please restart the system.
</message> </message>
......
5b1d9d9d154116b2fbcd85c2fad7dba0f521f1fa
\ No newline at end of file
...@@ -41,6 +41,7 @@ class MockUpdateView : public UpdateView { ...@@ -41,6 +41,7 @@ class MockUpdateView : public UpdateView {
MOCK_METHOD(void, SetShowEstimatedTimeLeft, (bool value)); MOCK_METHOD(void, SetShowEstimatedTimeLeft, (bool value));
MOCK_METHOD(void, SetUpdateCompleted, (bool value)); MOCK_METHOD(void, SetUpdateCompleted, (bool value));
MOCK_METHOD(void, SetShowCurtain, (bool value)); MOCK_METHOD(void, SetShowCurtain, (bool value));
MOCK_METHOD(void, SetManualRebootNeeded, (bool value));
MOCK_METHOD(void, SetProgressMessage, (const base::string16& value)); MOCK_METHOD(void, SetProgressMessage, (const base::string16& value));
MOCK_METHOD(void, SetProgress, (int value)); MOCK_METHOD(void, SetProgress, (int value));
MOCK_METHOD(void, SetRequiresPermissionForCellular, (bool value)); MOCK_METHOD(void, SetRequiresPermissionForCellular, (bool value));
......
...@@ -36,6 +36,10 @@ constexpr const char kUserActionCancelUpdateShortcut[] = "cancel-update"; ...@@ -36,6 +36,10 @@ constexpr const char kUserActionCancelUpdateShortcut[] = "cancel-update";
const char kUpdateDeadlineFile[] = "/tmp/update-check-response-deadline"; const char kUpdateDeadlineFile[] = "/tmp/update-check-response-deadline";
// Time in seconds after which we initiate reboot.
constexpr const base::TimeDelta kWaitBeforeRebootTime =
base::TimeDelta::FromSeconds(2);
// Delay before showing error message if captive portal is detected. // Delay before showing error message if captive portal is detected.
// We wait for this delay to let captive portal to perform redirect and show // We wait for this delay to let captive portal to perform redirect and show
// its login page before error message appears. // its login page before error message appears.
...@@ -108,6 +112,7 @@ UpdateScreen::UpdateScreen(UpdateView* view, ...@@ -108,6 +112,7 @@ UpdateScreen::UpdateScreen(UpdateView* view,
histogram_helper_( histogram_helper_(
std::make_unique<ErrorScreensHistogramHelper>("Update")), std::make_unique<ErrorScreensHistogramHelper>("Update")),
version_updater_(std::make_unique<VersionUpdater>(this)), version_updater_(std::make_unique<VersionUpdater>(this)),
wait_before_reboot_time_(kWaitBeforeRebootTime),
tick_clock_(base::DefaultTickClock::GetInstance()) { tick_clock_(base::DefaultTickClock::GetInstance()) {
if (chromeos::features::IsBetterUpdateEnabled()) if (chromeos::features::IsBetterUpdateEnabled())
PowerManagerClient::Get()->AddObserver(this); PowerManagerClient::Get()->AddObserver(this);
...@@ -216,8 +221,13 @@ void UpdateScreen::ExitUpdate(Result result) { ...@@ -216,8 +221,13 @@ void UpdateScreen::ExitUpdate(Result result) {
void UpdateScreen::OnWaitForRebootTimeElapsed() { void UpdateScreen::OnWaitForRebootTimeElapsed() {
LOG(ERROR) << "Unable to reboot - asking user for a manual reboot."; LOG(ERROR) << "Unable to reboot - asking user for a manual reboot.";
MakeSureScreenIsShown(); MakeSureScreenIsShown();
if (view_) if (!view_)
return;
if (chromeos::features::IsBetterUpdateEnabled()) {
view_->SetManualRebootNeeded(true);
} else {
view_->SetUpdateCompleted(true); view_->SetUpdateCompleted(true);
}
} }
void UpdateScreen::PrepareForUpdateCheck() { void UpdateScreen::PrepareForUpdateCheck() {
...@@ -344,7 +354,14 @@ void UpdateScreen::UpdateInfoChanged( ...@@ -344,7 +354,14 @@ void UpdateScreen::UpdateInfoChanged(
finalize_time_); finalize_time_);
RecordDownloadingTime(tick_clock_->NowTicks() - RecordDownloadingTime(tick_clock_->NowTicks() -
start_update_downloading_); start_update_downloading_);
if (chromeos::features::IsBetterUpdateEnabled()) {
ShowRebootInProgress();
wait_reboot_timer_.Start(FROM_HERE, wait_before_reboot_time_,
version_updater_.get(),
&VersionUpdater::RebootAfterUpdate);
} else {
version_updater_->RebootAfterUpdate(); version_updater_->RebootAfterUpdate();
}
} else { } else {
hide_progress_on_exit_ = true; hide_progress_on_exit_ = true;
ExitUpdate(Result::UPDATE_NOT_REQUIRED); ExitUpdate(Result::UPDATE_NOT_REQUIRED);
...@@ -387,6 +404,12 @@ void UpdateScreen::PowerChanged( ...@@ -387,6 +404,12 @@ void UpdateScreen::PowerChanged(
UpdateBatteryWarningVisibility(); UpdateBatteryWarningVisibility();
} }
void UpdateScreen::ShowRebootInProgress() {
MakeSureScreenIsShown();
if (view_)
view_->SetUpdateCompleted(true);
}
void UpdateScreen::UpdateBatteryWarningVisibility() { void UpdateScreen::UpdateBatteryWarningVisibility() {
if (!view_) if (!view_)
return; return;
......
...@@ -107,6 +107,15 @@ class UpdateScreen : public BaseScreen, ...@@ -107,6 +107,15 @@ class UpdateScreen : public BaseScreen,
tick_clock_ = tick_clock; tick_clock_ = tick_clock;
} }
void set_wait_before_reboot_time_for_testing(
base::TimeDelta wait_before_reboot_time) {
wait_before_reboot_time_ = wait_before_reboot_time;
}
base::OneShotTimer* GetWaitRebootTimerForTesting() {
return &wait_reboot_timer_;
}
protected: protected:
// BaseScreen: // BaseScreen:
bool MaybeSkip(WizardContext* context) override; bool MaybeSkip(WizardContext* context) override;
...@@ -144,6 +153,9 @@ class UpdateScreen : public BaseScreen, ...@@ -144,6 +153,9 @@ class UpdateScreen : public BaseScreen,
// stages. Called when power or update status changes. // stages. Called when power or update status changes.
void UpdateBatteryWarningVisibility(); void UpdateBatteryWarningVisibility();
// Show reboot waiting screen.
void ShowRebootInProgress();
UpdateView* view_; UpdateView* view_;
ErrorScreen* error_screen_; ErrorScreen* error_screen_;
ScreenExitCallback exit_callback_; ScreenExitCallback exit_callback_;
...@@ -187,6 +199,13 @@ class UpdateScreen : public BaseScreen, ...@@ -187,6 +199,13 @@ class UpdateScreen : public BaseScreen,
// instead. // instead.
base::OneShotTimer error_message_timer_; base::OneShotTimer error_message_timer_;
// Timer for the interval to wait for the reboot progress screen to be shown
// for at least wait_before_reboot_time_ before reboot call.
base::OneShotTimer wait_reboot_timer_;
// Time in seconds after which we initiate reboot.
base::TimeDelta wait_before_reboot_time_;
const base::TickClock* tick_clock_; const base::TickClock* tick_clock_;
base::TimeTicks start_update_downloading_; base::TimeTicks start_update_downloading_;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/test/scoped_mock_time_message_loop_task_runner.h"
#include "base/test/simple_test_tick_clock.h" #include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/chromeos/login/login_wizard.h" #include "chrome/browser/chromeos/login/login_wizard.h"
...@@ -66,6 +67,11 @@ const test::UIPath kLowBatteryWarningMessage = {"oobe-update", ...@@ -66,6 +67,11 @@ const test::UIPath kLowBatteryWarningMessage = {"oobe-update",
"battery-warning"}; "battery-warning"};
const test::UIPath kErrorMessage = {"error-message"}; const test::UIPath kErrorMessage = {"error-message"};
// Paths for better update screen https://crbug.com/1101317
const test::UIPath kRestartingDialog = {"oobe-update", "restarting-dialog"};
const test::UIPath kBetterUpdateCompletedDialog = {
"oobe-update", "better-update-complete-dialog"};
// UMA names for better test reading. // UMA names for better test reading.
const char kTimeCheck[] = "OOBE.UpdateScreen.StageTime.Check"; const char kTimeCheck[] = "OOBE.UpdateScreen.StageTime.Check";
const char kTimeDownload[] = "OOBE.UpdateScreen.StageTime.Download"; const char kTimeDownload[] = "OOBE.UpdateScreen.StageTime.Download";
...@@ -86,6 +92,8 @@ constexpr base::TimeDelta kTimeAdvanceSeconds10 = ...@@ -86,6 +92,8 @@ constexpr base::TimeDelta kTimeAdvanceSeconds10 =
base::TimeDelta::FromSeconds(10); base::TimeDelta::FromSeconds(10);
constexpr base::TimeDelta kTimeAdvanceSeconds60 = constexpr base::TimeDelta kTimeAdvanceSeconds60 =
base::TimeDelta::FromSeconds(60); base::TimeDelta::FromSeconds(60);
constexpr base::TimeDelta kTimeDefaultWaiting =
base::TimeDelta::FromSeconds(10);
std::string GetDownloadingString(int status_resource_id) { std::string GetDownloadingString(int status_resource_id) {
return l10n_util::GetStringFUTF8( return l10n_util::GetStringFUTF8(
...@@ -181,6 +189,17 @@ class BetterUpdateScreenTest : public UpdateScreenTest { ...@@ -181,6 +189,17 @@ class BetterUpdateScreenTest : public UpdateScreenTest {
} }
~BetterUpdateScreenTest() override = default; ~BetterUpdateScreenTest() override = default;
void SetTickClockAndDefaultDelaysForTesting(
const base::TickClock* tick_clock) {
version_updater_->set_tick_clock_for_testing(tick_clock);
update_screen_->set_tick_clock_for_testing(tick_clock);
// Set time for waiting in the test to not update constants manually, if
// they change.
version_updater_->set_wait_for_reboot_time_for_testing(kTimeDefaultWaiting);
update_screen_->set_wait_before_reboot_time_for_testing(
kTimeDefaultWaiting);
}
protected: protected:
chromeos::FakePowerManagerClient* power_manager_client() { chromeos::FakePowerManagerClient* power_manager_client() {
return chromeos::FakePowerManagerClient::Get(); return chromeos::FakePowerManagerClient::Get();
...@@ -778,6 +797,9 @@ IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, TestInitialLowBatteryStatus) { ...@@ -778,6 +797,9 @@ IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, TestInitialLowBatteryStatus) {
IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest,
TestBatteryWarningDuringUpdateStages) { TestBatteryWarningDuringUpdateStages) {
base::ScopedMockTimeMessageLoopTaskRunner mocked_task_runner;
SetTickClockAndDefaultDelaysForTesting(
mocked_task_runner->GetMockTickClock());
update_screen_->set_ignore_update_deadlines_for_testing(true); update_screen_->set_ignore_update_deadlines_for_testing(true);
ShowUpdateScreen(); ShowUpdateScreen();
EXPECT_TRUE(power_manager_client()->HasObserver(update_screen_)); EXPECT_TRUE(power_manager_client()->HasObserver(update_screen_));
...@@ -832,6 +854,10 @@ IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, ...@@ -832,6 +854,10 @@ IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest,
update_engine_client()->set_default_status(status); update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status); update_engine_client()->NotifyObserversThatStatusChanged(status);
// Show waiting for reboot screen for several seconds.
ASSERT_TRUE(update_screen_->GetWaitRebootTimerForTesting()->IsRunning());
mocked_task_runner->FastForwardBy(kTimeDefaultWaiting);
// UpdateStatusChanged(status) calls RebootAfterUpdate(). // UpdateStatusChanged(status) calls RebootAfterUpdate().
EXPECT_EQ(update_engine_client()->reboot_after_update_call_count(), 1); EXPECT_EQ(update_engine_client()->reboot_after_update_call_count(), 1);
test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage); test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage);
...@@ -884,4 +910,42 @@ IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, ...@@ -884,4 +910,42 @@ IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest,
test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage); test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage);
} }
IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest,
TestUpdateCompletedRebootNeeded) {
base::ScopedMockTimeMessageLoopTaskRunner mocked_task_runner;
SetTickClockAndDefaultDelaysForTesting(
mocked_task_runner->GetMockTickClock());
update_screen_->set_ignore_update_deadlines_for_testing(true);
ShowUpdateScreen();
update_engine::StatusResult status;
status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
status.set_new_version("latest and greatest");
status.set_new_size(1'000'000'000);
update_engine_client()->set_default_status(status);
update_engine_client()->NotifyObserversThatStatusChanged(status);
test::OobeJS().CreateVisibilityWaiter(true, kRestartingDialog)->Wait();
test::OobeJS().ExpectHiddenPath(kCheckingForUpdatesDialog);
test::OobeJS().ExpectHiddenPath(kCellularPermissionDialog);
test::OobeJS().ExpectHiddenPath(kUpdatingDialog);
test::OobeJS().ExpectHiddenPath(kBetterUpdateCompletedDialog);
// Make sure that after the screen is shown waiting timer starts.
mocked_task_runner->RunUntilIdle();
// Show waiting for reboot screen for several seconds.
ASSERT_TRUE(update_screen_->GetWaitRebootTimerForTesting()->IsRunning());
mocked_task_runner->FastForwardBy(kTimeDefaultWaiting);
// UpdateStatusChanged(status) calls RebootAfterUpdate().
ASSERT_EQ(update_engine_client()->reboot_after_update_call_count(), 1);
// Simulate the situation where reboot does not happen in time.
ASSERT_TRUE(version_updater_->GetRebootTimerForTesting()->IsRunning());
mocked_task_runner->FastForwardBy(kTimeDefaultWaiting);
test::OobeJS().ExpectHiddenPath(kRestartingDialog);
test::OobeJS().ExpectVisiblePath(kBetterUpdateCompletedDialog);
}
} // namespace chromeos } // namespace chromeos
...@@ -50,7 +50,26 @@ ...@@ -50,7 +50,26 @@
</oobe-dialog> </oobe-dialog>
</div> </div>
<div hidden="[[!betterUpdateScreenFeatureEnabled_]]"> <div hidden="[[!betterUpdateScreenFeatureEnabled_]]">
<oobe-dialog> <oobe-dialog footer-shrinkable id="restarting-dialog"
hidden="[[!isRebootProgressBarShown_(manualRebootNeeded,
updateCompleted)]]"
title-key="updateCompeletedRebootingMsg"
aria-live="polite">
<hd-iron-icon slot="oobe-icon"
icon1x="oobe-32:googleg" icon2x="oobe-64:googleg">
</hd-iron-icon>
<paper-progress slot="progress" id="restarting-progress" indeterminate>
</paper-progress>
</oobe-dialog>
<oobe-dialog footer-shrinkable id="better-update-complete-dialog"
hidden="[[!manualRebootNeeded]]"
title-key="updateCompeletedMsg"
aria-live="polite">
<hd-iron-icon slot="oobe-icon"
icon1x="oobe-32:googleg" icon2x="oobe-64:googleg">
</hd-iron-icon>
</oobe-dialog>
<oobe-dialog hidden="[[!showLowBatteryWarning]]">
<div hidden="[[!showLowBatteryWarning]]" id="battery-warning" <div hidden="[[!showLowBatteryWarning]]" id="battery-warning"
slot="footer"> slot="footer">
</div> </div>
......
...@@ -23,6 +23,7 @@ Polymer({ ...@@ -23,6 +23,7 @@ Polymer({
'setEstimatedTimeLeft', 'setEstimatedTimeLeft',
'showEstimatedTimeLeft', 'showEstimatedTimeLeft',
'setUpdateCompleted', 'setUpdateCompleted',
'setManualRebootNeeded',
'showUpdateCurtain', 'showUpdateCurtain',
'setProgressMessage', 'setProgressMessage',
'setUpdateProgress', 'setUpdateProgress',
...@@ -100,6 +101,14 @@ Polymer({ ...@@ -100,6 +101,14 @@ Polymer({
value: false, value: false,
}, },
/**
* True if update is fully completed and manual action is required.
*/
manualRebootNeeded: {
type: Boolean,
value: false,
},
/** /**
* If update cancellation is allowed. * If update cancellation is allowed.
*/ */
...@@ -140,8 +149,10 @@ Polymer({ ...@@ -140,8 +149,10 @@ Polymer({
}, },
onBeforeShow() { onBeforeShow() {
if (!this.betterUpdateScreenFeatureEnabled_) {
cr.ui.login.invokePolymerMethod( cr.ui.login.invokePolymerMethod(
this.$['checking-downloading-update'], 'onBeforeShow'); this.$['checking-downloading-update'], 'onBeforeShow');
}
}, },
onBackClicked_() { onBackClicked_() {
...@@ -209,6 +220,13 @@ Polymer({ ...@@ -209,6 +220,13 @@ Polymer({
this.updateCompleted = is_completed; this.updateCompleted = is_completed;
}, },
/**
* @param {boolean} is_needed True if manual reboot after update is needed.
*/
setManualRebootNeeded(is_needed) {
this.manualRebootNeeded = is_needed;
},
/** /**
* Shows or hides update curtain. * Shows or hides update curtain.
* @param {boolean} visible Are curtains visible? * @param {boolean} visible Are curtains visible?
...@@ -225,5 +243,15 @@ Polymer({ ...@@ -225,5 +243,15 @@ Polymer({
this.showLowBatteryWarning = visible; this.showLowBatteryWarning = visible;
}, },
/**
* Calculates visibility of the reboot progress dialog.
* @param {Boolean} manualRebootNeeded If the automatic reboot timer has
* elapsed and manual reboot is needed.
* @param {Boolean} updateCompleted If update is completed and all
* intermediate status elements are hidden.
*/
isRebootProgressBarShown_(manualRebootNeeded, updateCompleted) {
return updateCompleted && !manualRebootNeeded;
},
}); });
})(); })();
...@@ -62,6 +62,10 @@ void UpdateScreenHandler::SetUpdateCompleted(bool value) { ...@@ -62,6 +62,10 @@ void UpdateScreenHandler::SetUpdateCompleted(bool value) {
CallJS("login.UpdateScreen.setUpdateCompleted", value); CallJS("login.UpdateScreen.setUpdateCompleted", value);
} }
void UpdateScreenHandler::SetManualRebootNeeded(bool value) {
CallJS("login.UpdateScreen.setManualRebootNeeded", value);
}
void UpdateScreenHandler::SetShowCurtain(bool value) { void UpdateScreenHandler::SetShowCurtain(bool value) {
CallJS("login.UpdateScreen.showUpdateCurtain", value); CallJS("login.UpdateScreen.showUpdateCurtain", value);
} }
...@@ -92,6 +96,7 @@ void UpdateScreenHandler::DeclareLocalizedValues( ...@@ -92,6 +96,7 @@ void UpdateScreenHandler::DeclareLocalizedValues(
builder->AddF("installingUpdateDesc", IDS_UPDATE_MSG, builder->AddF("installingUpdateDesc", IDS_UPDATE_MSG,
ui::GetChromeOSDeviceName()); ui::GetChromeOSDeviceName());
builder->Add("updateCompeletedMsg", IDS_UPDATE_COMPLETED); builder->Add("updateCompeletedMsg", IDS_UPDATE_COMPLETED);
builder->Add("updateCompeletedRebootingMsg", IDS_UPDATE_COMPLETED_REBOOTING);
builder->Add("updateScreenAccessibleTitle", builder->Add("updateScreenAccessibleTitle",
IDS_UPDATE_SCREEN_ACCESSIBLE_TITLE); IDS_UPDATE_SCREEN_ACCESSIBLE_TITLE);
builder->Add("checkingForUpdates", IDS_CHECKING_FOR_UPDATES); builder->Add("checkingForUpdates", IDS_CHECKING_FOR_UPDATES);
......
...@@ -39,6 +39,7 @@ class UpdateView { ...@@ -39,6 +39,7 @@ class UpdateView {
virtual void SetEstimatedTimeLeft(int value) = 0; virtual void SetEstimatedTimeLeft(int value) = 0;
virtual void SetShowEstimatedTimeLeft(bool value) = 0; virtual void SetShowEstimatedTimeLeft(bool value) = 0;
virtual void SetUpdateCompleted(bool value) = 0; virtual void SetUpdateCompleted(bool value) = 0;
virtual void SetManualRebootNeeded(bool value) = 0;
virtual void SetShowCurtain(bool value) = 0; virtual void SetShowCurtain(bool value) = 0;
virtual void SetProgressMessage(const base::string16& value) = 0; virtual void SetProgressMessage(const base::string16& value) = 0;
virtual void SetProgress(int value) = 0; virtual void SetProgress(int value) = 0;
...@@ -63,6 +64,7 @@ class UpdateScreenHandler : public UpdateView, public BaseScreenHandler { ...@@ -63,6 +64,7 @@ class UpdateScreenHandler : public UpdateView, public BaseScreenHandler {
void SetEstimatedTimeLeft(int value) override; void SetEstimatedTimeLeft(int value) override;
void SetShowEstimatedTimeLeft(bool value) override; void SetShowEstimatedTimeLeft(bool value) override;
void SetUpdateCompleted(bool value) override; void SetUpdateCompleted(bool value) override;
void SetManualRebootNeeded(bool value) override;
void SetShowCurtain(bool value) override; void SetShowCurtain(bool value) override;
void SetProgressMessage(const base::string16& value) override; void SetProgressMessage(const base::string16& value) override;
void SetProgress(int value) override; void SetProgress(int value) override;
......
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