Commit 10c82a81 authored by Fergus Dall's avatar Fergus Dall Committed by Commit Bot

crostini: Add precondition checks for crostini upgrade

Currently we will check for an active network connection, a charging
battery, and at least 1 GiB of disk space.

Bug: 930901
Change-Id: Id742be21a985232ab8dc6f55e11e109151c13833
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1959242Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Reviewed-by: default avatarHector Carmona <hcarmona@chromium.org>
Reviewed-by: default avatarSam McNally <sammc@chromium.org>
Commit-Queue: Fergus Dall <sidereal@google.com>
Cr-Commit-Position: refs/heads/master@{#728777}
parent 3aae1a80
...@@ -3607,6 +3607,18 @@ ...@@ -3607,6 +3607,18 @@
<message name="IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_MESSAGE" desc="Text shown by the Crostini upgrader when the container backup completed successfully, prior to the main upgrade."> <message name="IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_MESSAGE" desc="Text shown by the Crostini upgrader when the container backup completed successfully, prior to the main upgrade.">
Linux apps and files have been successfully backed up. Upgrade will begin shortly. Linux apps and files have been successfully backed up. Upgrade will begin shortly.
</message> </message>
<message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_TITLE" desc="Title of the Crostini upgrader when the upgrade prechecks failed.">
Error starting upgrade
</message>
<message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_NETWORK" desc="Text shown by the Crostini upgrader when the upgrade did not start because there was no network connection.">
A network connection is required to upgrade Linux. Please connect to the internet and try again.
</message>
<message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_POWER" desc="Text shown by the Crostini upgrader when the upgrade did not start because there wasn't enough power.">
Upgrading Linux can drain your battery significantly. Please connect your device to a charger and try again.
</message>
<message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_SPACE" desc="Text shown by the Crostini upgrader when the upgrade did not start because there wasn't enough free disk space.">
At least <ph name="REQUIRED_SPACE">$1<ex>1GB</ex></ph> of free disk space is required to upgrade Linux. Please free some space on your device and try again.
</message>
<message name="IDS_CROSTINI_UPGRADER_UPGRADING_TITLE" desc="Title of the Crostini upgrader when the upgrade is in progress."> <message name="IDS_CROSTINI_UPGRADER_UPGRADING_TITLE" desc="Title of the Crostini upgrader when the upgrade is in progress.">
Upgrading Linux Upgrading Linux
</message> </message>
......
...@@ -76,6 +76,7 @@ source_set("chromeos") { ...@@ -76,6 +76,7 @@ source_set("chromeos") {
"//chrome/browser/resource_coordinator:tab_metrics_event_proto", "//chrome/browser/resource_coordinator:tab_metrics_event_proto",
"//chrome/browser/ssl:proto", "//chrome/browser/ssl:proto",
"//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings", "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings",
"//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings",
"//chrome/browser/web_applications", "//chrome/browser/web_applications",
"//chrome/browser/web_applications:web_applications_on_extensions", "//chrome/browser/web_applications:web_applications_on_extensions",
"//chrome/browser/web_applications/components", "//chrome/browser/web_applications/components",
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chrome/browser/chromeos/crostini/crostini_upgrader.h" #include "chrome/browser/chromeos/crostini/crostini_upgrader.h"
#include "base/barrier_closure.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_manager_factory.h" #include "chrome/browser/chromeos/crostini/crostini_manager_factory.h"
...@@ -17,6 +19,7 @@ ...@@ -17,6 +19,7 @@
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h" #include "content/public/browser/network_service_instance.h"
#include "services/network/public/cpp/network_connection_tracker.h"
namespace crostini { namespace crostini {
...@@ -58,7 +61,7 @@ CrostiniUpgrader* CrostiniUpgrader::GetForProfile(Profile* profile) { ...@@ -58,7 +61,7 @@ CrostiniUpgrader* CrostiniUpgrader::GetForProfile(Profile* profile) {
} }
CrostiniUpgrader::CrostiniUpgrader(Profile* profile) CrostiniUpgrader::CrostiniUpgrader(Profile* profile)
: profile_(profile), container_id_("", "") { : profile_(profile), container_id_("", ""), pmc_observer_(this) {
CrostiniManager::GetForProfile(profile_)->AddUpgradeContainerProgressObserver( CrostiniManager::GetForProfile(profile_)->AddUpgradeContainerProgressObserver(
this); this);
} }
...@@ -100,6 +103,72 @@ void CrostiniUpgrader::OnBackup(CrostiniResult result) { ...@@ -100,6 +103,72 @@ void CrostiniUpgrader::OnBackup(CrostiniResult result) {
} }
} }
void CrostiniUpgrader::StartPrechecks() {
auto* pmc = chromeos::PowerManagerClient::Get();
if (pmc_observer_.IsObserving(pmc)) {
// This could happen if two StartPrechecks were run at the same time. If it
// does, drop the second call.
return;
}
prechecks_callback_ =
base::BarrierClosure(2, /* Number of asynchronous prechecks to wait for */
base::BindOnce(&CrostiniUpgrader::DoPrechecks,
weak_ptr_factory_.GetWeakPtr()));
pmc_observer_.Add(pmc);
pmc->RequestStatusUpdate();
base::PostTaskAndReplyWithResult(
FROM_HERE, {base::ThreadPool(), base::MayBlock()},
base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
base::FilePath(crostini::kHomeDirectory)),
base::BindOnce(&CrostiniUpgrader::OnAvailableDiskSpace,
weak_ptr_factory_.GetWeakPtr()));
}
void CrostiniUpgrader::PowerChanged(
const power_manager::PowerSupplyProperties& proto) {
// A battery can be FULL, CHARGING, DISCHARGING, or NOT_PRESENT. If we're on a
// system with no battery, we can assume stable power from the fact that we
// are running at all. Otherwise we want the battery to be full or charging. A
// less conservative check is possible, but we can expect users to have access
// to a charger.
power_status_good_ = proto.battery_state() !=
power_manager::PowerSupplyProperties::DISCHARGING;
auto* pmc = chromeos::PowerManagerClient::Get();
pmc_observer_.Remove(pmc);
prechecks_callback_.Run();
}
void CrostiniUpgrader::OnAvailableDiskSpace(int64_t bytes) {
free_disk_space_ = bytes;
prechecks_callback_.Run();
}
void CrostiniUpgrader::DoPrechecks() {
chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus status;
if (free_disk_space_ < kDiskRequired) {
status = chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::
INSUFFICIENT_SPACE;
} else if (content::GetNetworkConnectionTracker()->IsOffline()) {
status = chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::
NETWORK_FAILURE;
} else if (!power_status_good_) {
status =
chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::LOW_POWER;
} else {
status = chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::OK;
}
for (auto& observer : upgrader_observers_) {
observer.PrecheckStatus(status);
}
}
void CrostiniUpgrader::Upgrade(const ContainerId& container_id) { void CrostiniUpgrader::Upgrade(const ContainerId& container_id) {
container_id_ = container_id; container_id_ = container_id;
CrostiniManager::GetForProfile(profile_)->UpgradeContainer( CrostiniManager::GetForProfile(profile_)->UpgradeContainer(
......
...@@ -6,8 +6,10 @@ ...@@ -6,8 +6,10 @@
#define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_UPGRADER_H_ #define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_UPGRADER_H_
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/scoped_observer.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_upgrader_ui_delegate.h" #include "chrome/browser/chromeos/crostini/crostini_upgrader_ui_delegate.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
class Profile; class Profile;
...@@ -16,6 +18,7 @@ namespace crostini { ...@@ -16,6 +18,7 @@ namespace crostini {
class CrostiniUpgrader : public KeyedService, class CrostiniUpgrader : public KeyedService,
public UpgradeContainerProgressObserver, public UpgradeContainerProgressObserver,
public chromeos::PowerManagerClient::Observer,
public CrostiniUpgraderUIDelegate { public CrostiniUpgraderUIDelegate {
public: public:
static CrostiniUpgrader* GetForProfile(Profile* profile); static CrostiniUpgrader* GetForProfile(Profile* profile);
...@@ -33,6 +36,7 @@ class CrostiniUpgrader : public KeyedService, ...@@ -33,6 +36,7 @@ class CrostiniUpgrader : public KeyedService,
void AddObserver(CrostiniUpgraderUIObserver* observer) override; void AddObserver(CrostiniUpgraderUIObserver* observer) override;
void RemoveObserver(CrostiniUpgraderUIObserver* observer) override; void RemoveObserver(CrostiniUpgraderUIObserver* observer) override;
void Backup() override; void Backup() override;
void StartPrechecks() override;
void Upgrade(const ContainerId& container_id) override; void Upgrade(const ContainerId& container_id) override;
void Cancel() override; void Cancel() override;
void CancelBeforeStart() override; void CancelBeforeStart() override;
...@@ -43,18 +47,36 @@ class CrostiniUpgrader : public KeyedService, ...@@ -43,18 +47,36 @@ class CrostiniUpgrader : public KeyedService,
UpgradeContainerProgressStatus status, UpgradeContainerProgressStatus status,
const std::vector<std::string>& messages) override; const std::vector<std::string>& messages) override;
// chromeos::PowerManagerClient::Observer:
void PowerChanged(const power_manager::PowerSupplyProperties& proto) override;
// Return true if internal state allows starting upgrade. // Return true if internal state allows starting upgrade.
bool CanUpgrade(); bool CanUpgrade();
// Require at least 1 GiB of free space. Experiments on an unmodified
// container suggest this is a bare minimum, anyone with a substantial amount
// of programs installed will likely require more.
static constexpr int64_t kDiskRequired = 1 << 30;
private: private:
void OnCancel(CrostiniResult result); void OnCancel(CrostiniResult result);
void OnBackup(CrostiniResult result); void OnBackup(CrostiniResult result);
void OnUpgrade(CrostiniResult result); void OnUpgrade(CrostiniResult result);
void OnAvailableDiskSpace(int64_t bytes);
void DoPrechecks();
Profile* profile_; Profile* profile_;
ContainerId container_id_; ContainerId container_id_;
base::ObserverList<CrostiniUpgraderUIObserver>::Unchecked upgrader_observers_; base::ObserverList<CrostiniUpgraderUIObserver>::Unchecked upgrader_observers_;
base::RepeatingClosure prechecks_callback_;
bool power_status_good_ = false;
int64_t free_disk_space_ = -1;
ScopedObserver<chromeos::PowerManagerClient,
chromeos::PowerManagerClient::Observer>
pmc_observer_;
base::WeakPtrFactory<CrostiniUpgrader> weak_ptr_factory_{this}; base::WeakPtrFactory<CrostiniUpgrader> weak_ptr_factory_{this};
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom.h"
namespace crostini { namespace crostini {
...@@ -17,6 +18,8 @@ class CrostiniUpgraderUIObserver { ...@@ -17,6 +18,8 @@ class CrostiniUpgraderUIObserver {
virtual void OnBackupProgress(int percent) = 0; virtual void OnBackupProgress(int percent) = 0;
virtual void OnBackupSucceeded() = 0; virtual void OnBackupSucceeded() = 0;
virtual void OnBackupFailed() = 0; virtual void OnBackupFailed() = 0;
virtual void PrecheckStatus(
chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus status) = 0;
virtual void OnUpgradeProgress(const std::vector<std::string>& messages) = 0; virtual void OnUpgradeProgress(const std::vector<std::string>& messages) = 0;
virtual void OnUpgradeSucceeded() = 0; virtual void OnUpgradeSucceeded() = 0;
virtual void OnUpgradeFailed() = 0; virtual void OnUpgradeFailed() = 0;
...@@ -33,6 +36,8 @@ class CrostiniUpgraderUIDelegate { ...@@ -33,6 +36,8 @@ class CrostiniUpgraderUIDelegate {
// Back up the current container before upgrading // Back up the current container before upgrading
virtual void Backup() = 0; virtual void Backup() = 0;
virtual void StartPrechecks() = 0;
// Start the upgrade. // Start the upgrade.
virtual void Upgrade(const ContainerId& container_id) = 0; virtual void Upgrade(const ContainerId& container_id) = 0;
......
...@@ -22,6 +22,7 @@ const State = { ...@@ -22,6 +22,7 @@ const State = {
PROMPT: 'prompt', PROMPT: 'prompt',
BACKUP: 'backup', BACKUP: 'backup',
BACKUP_SUCCEEDED: 'backupSucceeded', BACKUP_SUCCEEDED: 'backupSucceeded',
PRECHECKS_FAILED: 'prechecksFailed',
UPGRADING: 'upgrading', UPGRADING: 'upgrading',
ERROR: 'error', ERROR: 'error',
CANCELING: 'canceling', CANCELING: 'canceling',
...@@ -86,14 +87,31 @@ Polymer({ ...@@ -86,14 +87,31 @@ Polymer({
this.state_ = State.BACKUP_SUCCEEDED; this.state_ = State.BACKUP_SUCCEEDED;
// We do a short (2 second) interstitial display of the backup success // We do a short (2 second) interstitial display of the backup success
// message before continuing the upgrade. // message before continuing the upgrade.
setTimeout(() => { var timeout = new Promise((resolve, reject) => {
setTimeout(resolve, 2000);
});
// We also want to wait for the prechecks to finish.
var callback = new Promise((resolve, reject) => {
this.startPrechecks_(resolve, reject);
});
Promise.all([timeout, callback]).then(() => {
this.startUpgrade_(); this.startUpgrade_();
}, 2000); });
}), }),
callbackRouter.onBackupFailed.addListener(() => { callbackRouter.onBackupFailed.addListener(() => {
assert(this.state_ === State.BACKUP); assert(this.state_ === State.BACKUP);
this.state_ = State.ERROR; this.state_ = State.ERROR;
}), }),
callbackRouter.precheckStatus.addListener((status) => {
this.precheckStatus_ = status;
if (status ===
chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus.OK) {
this.precheckSuccessCallback_();
} else {
this.state_ = State.PRECHECKS_FAILED;
this.precheckFailureCallback_();
}
}),
callbackRouter.onUpgradeProgress.addListener((progressMessages) => { callbackRouter.onUpgradeProgress.addListener((progressMessages) => {
assert(this.state_ === State.UPGRADING); assert(this.state_ === State.UPGRADING);
this.progressMessages_.push(...progressMessages); this.progressMessages_.push(...progressMessages);
...@@ -134,11 +152,17 @@ Polymer({ ...@@ -134,11 +152,17 @@ Polymer({
BrowserProxy.getInstance().handler.launch(); BrowserProxy.getInstance().handler.launch();
this.closeDialog_(); this.closeDialog_();
break; break;
case State.PRECHECKS_FAILED:
this.startPrechecks_(() => {
this.startUpgrade_();
}, () => {});
case State.PROMPT: case State.PROMPT:
if (this.backupCheckboxChecked_) { if (this.backupCheckboxChecked_) {
this.startBackup_(); this.startBackup_();
} else { } else {
this.startUpgrade_(); this.startPrechecks_(() => {
this.startUpgrade_();
}, () => {});
} }
break; break;
} }
...@@ -154,6 +178,7 @@ Polymer({ ...@@ -154,6 +178,7 @@ Polymer({
this.state_ = State.CANCELING; this.state_ = State.CANCELING;
BrowserProxy.getInstance().handler.cancel(); BrowserProxy.getInstance().handler.cancel();
break; break;
case State.PRECHECKS_FAILED:
case State.ERROR: case State.ERROR:
case State.SUCCEEDED: case State.SUCCEEDED:
this.closeDialog_(); this.closeDialog_();
...@@ -174,6 +199,13 @@ Polymer({ ...@@ -174,6 +199,13 @@ Polymer({
BrowserProxy.getInstance().handler.backup(); BrowserProxy.getInstance().handler.backup();
}, },
/** @private */
startPrechecks_: function(success, failure) {
this.precheckSuccessCallback_ = success;
this.precheckFailureCallback_ = failure;
BrowserProxy.getInstance().handler.startPrechecks();
},
/** @private */ /** @private */
startUpgrade_: function() { startUpgrade_: function() {
this.state_ = State.UPGRADING; this.state_ = State.UPGRADING;
...@@ -203,6 +235,7 @@ Polymer({ ...@@ -203,6 +235,7 @@ Polymer({
canDoAction_: function(state) { canDoAction_: function(state) {
switch (state) { switch (state) {
case State.PROMPT: case State.PROMPT:
case State.PRECHECKS_FAILED:
case State.SUCCEEDED: case State.SUCCEEDED:
return true; return true;
} }
...@@ -240,6 +273,9 @@ Polymer({ ...@@ -240,6 +273,9 @@ Polymer({
case State.BACKUP_SUCCEEDED: case State.BACKUP_SUCCEEDED:
titleId = 'backupSucceededTitle'; titleId = 'backupSucceededTitle';
break; break;
case State.PRECHECKS_FAILED:
titleId = 'prechecksFailedTitle';
break;
case State.UPGRADING: case State.UPGRADING:
titleId = 'upgradingTitle'; titleId = 'upgradingTitle';
break; break;
...@@ -267,6 +303,8 @@ Polymer({ ...@@ -267,6 +303,8 @@ Polymer({
switch (state) { switch (state) {
case State.PROMPT: case State.PROMPT:
return loadTimeData.getString('upgrade'); return loadTimeData.getString('upgrade');
case State.PRECHECKS_FAILED:
return loadTimeData.getString('retry');
case State.ERROR: case State.ERROR:
return loadTimeData.getString('cancel'); return loadTimeData.getString('cancel');
case State.SUCCEEDED: case State.SUCCEEDED:
...@@ -306,6 +344,22 @@ Polymer({ ...@@ -306,6 +344,22 @@ Polymer({
case State.BACKUP_SUCCEEDED: case State.BACKUP_SUCCEEDED:
messageId = 'backupSucceededMessage'; messageId = 'backupSucceededMessage';
break; break;
case State.PRECHECKS_FAILED:
switch (this.precheckStatus_) {
case chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus
.NETWORK_FAILURE:
messageId = 'precheckNoNetwork';
break;
case chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus.LOW_POWER:
messageId = 'precheckNoPower';
break;
case chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus
.INSUFFICIENT_SPACE:
messageId = 'precheckNoSpace';
break;
default:
assertNotReached();
}
case State.UPGRADING: case State.UPGRADING:
messageId = 'upgradingMessage'; messageId = 'upgradingMessage';
break; break;
...@@ -334,6 +388,7 @@ Polymer({ ...@@ -334,6 +388,7 @@ Polymer({
getIllustrationStyle_: function(state) { getIllustrationStyle_: function(state) {
switch (state) { switch (state) {
case State.BACKUP_SUCCEEDED: case State.BACKUP_SUCCEEDED:
case State.PRECHECKS_FAILED:
case State.ERROR: case State.ERROR:
return 'img-square-illustration'; return 'img-square-illustration';
} }
...@@ -349,6 +404,7 @@ Polymer({ ...@@ -349,6 +404,7 @@ Polymer({
switch (state) { switch (state) {
case State.BACKUP_SUCCEEDED: case State.BACKUP_SUCCEEDED:
return 'images/success_illustration.png'; return 'images/success_illustration.png';
case State.PRECHECKS_FAILED:
case State.ERROR: case State.ERROR:
return 'images/error_illustration.png'; return 'images/error_illustration.png';
} }
......
...@@ -4,6 +4,18 @@ ...@@ -4,6 +4,18 @@
module chromeos.crostini_upgrader.mojom; module chromeos.crostini_upgrader.mojom;
enum UpgradePrecheckStatus {
// Good to continue
OK,
// No network connectivity
NETWORK_FAILURE,
// Battery is low and not charging
LOW_POWER,
// Not enough space to do the upgrade
INSUFFICIENT_SPACE
};
// Lives in the browser process. A renderer uses this to create a page handler // Lives in the browser process. A renderer uses this to create a page handler
// for controlling Crostini upgrade. // for controlling Crostini upgrade.
interface PageHandlerFactory { interface PageHandlerFactory {
...@@ -17,6 +29,9 @@ interface PageHandlerFactory { ...@@ -17,6 +29,9 @@ interface PageHandlerFactory {
interface PageHandler { interface PageHandler {
// Backup the existing container. // Backup the existing container.
Backup(); Backup();
// Start running upgrade prechecks. Result is asynchronously
// returned via Page::PrecheckStatus.
StartPrechecks();
// Start upgrade // Start upgrade
Upgrade(); Upgrade();
// Cancel an on-going upgrade // Cancel an on-going upgrade
...@@ -43,6 +58,8 @@ interface Page { ...@@ -43,6 +58,8 @@ interface Page {
OnBackupSucceeded(); OnBackupSucceeded();
// This is called when the backup failed. // This is called when the backup failed.
OnBackupFailed(); OnBackupFailed();
// Handle the result of the prechecks.
PrecheckStatus(UpgradePrecheckStatus status);
// Callback to receive the upgrade progress once the upgrade has started. // Callback to receive the upgrade progress once the upgrade has started.
OnUpgradeProgress(array<string> progress_messages); OnUpgradeProgress(array<string> progress_messages);
// This is called when the upgrade succeeded. // This is called when the upgrade succeeded.
......
...@@ -34,6 +34,10 @@ void CrostiniUpgraderPageHandler::Backup() { ...@@ -34,6 +34,10 @@ void CrostiniUpgraderPageHandler::Backup() {
upgrader_ui_delegate_->Backup(); upgrader_ui_delegate_->Backup();
} }
void CrostiniUpgraderPageHandler::StartPrechecks() {
upgrader_ui_delegate_->StartPrechecks();
}
void CrostiniUpgraderPageHandler::Upgrade() { void CrostiniUpgraderPageHandler::Upgrade() {
upgrader_ui_delegate_->Upgrade( upgrader_ui_delegate_->Upgrade(
crostini::ContainerId(crostini::kCrostiniDefaultVmName, crostini::ContainerId(crostini::kCrostiniDefaultVmName,
...@@ -81,6 +85,11 @@ void CrostiniUpgraderPageHandler::OnBackupFailed() { ...@@ -81,6 +85,11 @@ void CrostiniUpgraderPageHandler::OnBackupFailed() {
page_->OnBackupFailed(); page_->OnBackupFailed();
} }
void CrostiniUpgraderPageHandler::PrecheckStatus(
chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus status) {
page_->PrecheckStatus(status);
}
void CrostiniUpgraderPageHandler::OnCanceled() { void CrostiniUpgraderPageHandler::OnCanceled() {
page_->OnCanceled(); page_->OnCanceled();
} }
......
...@@ -33,6 +33,7 @@ class CrostiniUpgraderPageHandler ...@@ -33,6 +33,7 @@ class CrostiniUpgraderPageHandler
// chromeos::crostini_upgrader::mojom::PageHandler: // chromeos::crostini_upgrader::mojom::PageHandler:
void Backup() override; void Backup() override;
void StartPrechecks() override;
void Upgrade() override; void Upgrade() override;
void Cancel() override; void Cancel() override;
void CancelBeforeStart() override; void CancelBeforeStart() override;
...@@ -43,6 +44,8 @@ class CrostiniUpgraderPageHandler ...@@ -43,6 +44,8 @@ class CrostiniUpgraderPageHandler
void OnBackupProgress(int percent) override; void OnBackupProgress(int percent) override;
void OnBackupSucceeded() override; void OnBackupSucceeded() override;
void OnBackupFailed() override; void OnBackupFailed() override;
void PrecheckStatus(chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus
status) override;
void OnUpgradeProgress(const std::vector<std::string>& messages) override; void OnUpgradeProgress(const std::vector<std::string>& messages) override;
void OnUpgradeSucceeded() override; void OnUpgradeSucceeded() override;
void OnUpgradeFailed() override; void OnUpgradeFailed() override;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "components/strings/grit/components_strings.h" #include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_data_source.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h"
#include "ui/chromeos/devicetype_utils.h" #include "ui/chromeos/devicetype_utils.h"
#include "ui/resources/grit/webui_resources.h" #include "ui/resources/grit/webui_resources.h"
#include "ui/strings/grit/ui_strings.h" #include "ui/strings/grit/ui_strings.h"
...@@ -38,6 +39,7 @@ bool CrostiniUpgraderUI::IsEnabled() { ...@@ -38,6 +39,7 @@ bool CrostiniUpgraderUI::IsEnabled() {
void AddStringResources(content::WebUIDataSource* source) { void AddStringResources(content::WebUIDataSource* source) {
static constexpr webui::LocalizedString kStrings[] = { static constexpr webui::LocalizedString kStrings[] = {
{"upgrade", IDS_CROSTINI_UPGRADER_UPGRADE_BUTTON}, {"upgrade", IDS_CROSTINI_UPGRADER_UPGRADE_BUTTON},
{"retry", IDS_CROSTINI_INSTALLER_RETRY_BUTTON},
{"close", IDS_APP_CLOSE}, {"close", IDS_APP_CLOSE},
{"cancel", IDS_APP_CANCEL}, {"cancel", IDS_APP_CANCEL},
{"launch", IDS_CROSTINI_UPGRADER_LAUNCH_BUTTON}, {"launch", IDS_CROSTINI_UPGRADER_LAUNCH_BUTTON},
...@@ -46,11 +48,15 @@ void AddStringResources(content::WebUIDataSource* source) { ...@@ -46,11 +48,15 @@ void AddStringResources(content::WebUIDataSource* source) {
{"promptTitle", IDS_CROSTINI_UPGRADER_TITLE}, {"promptTitle", IDS_CROSTINI_UPGRADER_TITLE},
{"backingUpTitle", IDS_CROSTINI_UPGRADER_BACKING_UP_TITLE}, {"backingUpTitle", IDS_CROSTINI_UPGRADER_BACKING_UP_TITLE},
{"backupSucceededTitle", IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_TITLE}, {"backupSucceededTitle", IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_TITLE},
{"prechecksFailedTitle", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_TITLE},
{"upgradingTitle", IDS_CROSTINI_UPGRADER_UPGRADING_TITLE}, {"upgradingTitle", IDS_CROSTINI_UPGRADER_UPGRADING_TITLE},
{"succeededTitle", IDS_CROSTINI_UPGRADER_SUCCEEDED_TITLE}, {"succeededTitle", IDS_CROSTINI_UPGRADER_SUCCEEDED_TITLE},
{"cancelingTitle", IDS_CROSTINI_UPGRADER_CANCELING_TITLE}, {"cancelingTitle", IDS_CROSTINI_UPGRADER_CANCELING_TITLE},
{"errorTitle", IDS_CROSTINI_UPGRADER_ERROR_TITLE}, {"errorTitle", IDS_CROSTINI_UPGRADER_ERROR_TITLE},
{"precheckNoNetwork", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_NETWORK},
{"precheckNoPower", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_POWER},
{"promptMessage", IDS_CROSTINI_UPGRADER_BODY}, {"promptMessage", IDS_CROSTINI_UPGRADER_BODY},
{"backingUpMessage", IDS_CROSTINI_UPGRADER_BACKING_UP_MESSAGE}, {"backingUpMessage", IDS_CROSTINI_UPGRADER_BACKING_UP_MESSAGE},
{"backupSucceededMessage", {"backupSucceededMessage",
...@@ -71,6 +77,12 @@ void AddStringResources(content::WebUIDataSource* source) { ...@@ -71,6 +77,12 @@ void AddStringResources(content::WebUIDataSource* source) {
source->AddString("offlineError", source->AddString("offlineError",
l10n_util::GetStringFUTF8( l10n_util::GetStringFUTF8(
IDS_CROSTINI_INSTALLER_OFFLINE_ERROR, device_name)); IDS_CROSTINI_INSTALLER_OFFLINE_ERROR, device_name));
source->AddString("precheckNoSpace",
l10n_util::GetStringFUTF8(
IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_SPACE,
ui::FormatBytesWithUnits(
crostini::CrostiniUpgrader::kDiskRequired,
ui::DATA_UNITS_GIBIBYTE, /*show_units=*/true)));
} }
CrostiniUpgraderUI::CrostiniUpgraderUI(content::WebUI* web_ui) CrostiniUpgraderUI::CrostiniUpgraderUI(content::WebUI* web_ui)
......
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