Commit 7a1d56b0 authored by Nicholas Verne's avatar Nicholas Verne Committed by Commit Bot

Refactor Crostini Export/Import business logic.

This is to allow different UI treatments.

Currently, Export/Import progress is surfaced in ChromeOS notifications.
The current design for the container upgrade needs to show export progress in
main dialog rather than a notification. This refactor enables both UI options.

Bug: 1024693
Change-Id: Icb39ae531dab34b673ad0e5f86ee4de804665c8b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1930271
Auto-Submit: Nicholas Verne <nverne@chromium.org>
Commit-Queue: Nicholas Verne <nverne@chromium.org>
Reviewed-by: default avatarJulian Watson <juwa@google.com>
Cr-Commit-Position: refs/heads/master@{#720366}
parent ca55861f
...@@ -820,6 +820,8 @@ source_set("chromeos") { ...@@ -820,6 +820,8 @@ source_set("chromeos") {
"crostini/crostini_export_import.h", "crostini/crostini_export_import.h",
"crostini/crostini_export_import_notification.cc", "crostini/crostini_export_import_notification.cc",
"crostini/crostini_export_import_notification.h", "crostini/crostini_export_import_notification.h",
"crostini/crostini_export_import_status_tracker.cc",
"crostini/crostini_export_import_status_tracker.h",
"crostini/crostini_features.cc", "crostini/crostini_features.cc",
"crostini/crostini_features.h", "crostini/crostini_features.h",
"crostini/crostini_force_close_watcher.cc", "crostini/crostini_force_close_watcher.cc",
......
...@@ -68,6 +68,21 @@ class CrostiniExportImport : public KeyedService, ...@@ -68,6 +68,21 @@ class CrostiniExportImport : public KeyedService,
bool in_progress) = 0; bool in_progress) = 0;
}; };
using TrackerFactory =
base::OnceCallback<CrostiniExportImportStatusTracker*(ExportImportType,
base::FilePath)>;
struct OperationData {
OperationData(ExportImportType type,
ContainerId id,
TrackerFactory factory);
~OperationData();
ExportImportType type;
ContainerId container_id;
TrackerFactory tracker_factory;
};
static CrostiniExportImport* GetForProfile(Profile* profile); static CrostiniExportImport* GetForProfile(Profile* profile);
explicit CrostiniExportImport(Profile* profile); explicit CrostiniExportImport(Profile* profile);
...@@ -122,13 +137,19 @@ class CrostiniExportImport : public KeyedService, ...@@ -122,13 +137,19 @@ class CrostiniExportImport : public KeyedService,
TestImportFailArchitecture); TestImportFailArchitecture);
FRIEND_TEST_ALL_PREFIXES(CrostiniExportImportTest, TestImportFailSpace); FRIEND_TEST_ALL_PREFIXES(CrostiniExportImportTest, TestImportFailSpace);
OperationData* NewOperationData(ExportImportType type,
ContainerId id,
TrackerFactory cb);
OperationData* NewOperationData(ExportImportType type, ContainerId id);
OperationData* NewOperationData(ExportImportType type);
// ui::SelectFileDialog::Listener implementation. // ui::SelectFileDialog::Listener implementation.
void FileSelected(const base::FilePath& path, void FileSelected(const base::FilePath& path,
int index, int index,
void* params) override; void* params) override;
void FileSelectionCanceled(void* params) override;
void Start(ExportImportType type, void Start(OperationData* params,
ContainerId container_id,
base::FilePath path, base::FilePath path,
CrostiniManager::CrostiniResultCallback callback); CrostiniManager::CrostiniResultCallback callback);
...@@ -175,20 +196,24 @@ class CrostiniExportImport : public KeyedService, ...@@ -175,20 +196,24 @@ class CrostiniExportImport : public KeyedService,
CrostiniManager::CrostiniResultCallback callback, CrostiniManager::CrostiniResultCallback callback,
CrostiniResult result); CrostiniResult result);
void OpenFileDialog(ExportImportType type, void OpenFileDialog(OperationData* params,
content::WebContents* web_contents); content::WebContents* web_contents);
std::string GetUniqueNotificationId(); std::string GetUniqueNotificationId();
CrostiniExportImportNotification& RemoveNotification( CrostiniExportImportStatusTracker& RemoveTracker(
std::map<ContainerId, CrostiniExportImportNotification*>::iterator it); std::map<ContainerId, CrostiniExportImportStatusTracker*>::iterator it);
Profile* profile_; Profile* profile_;
scoped_refptr<ui::SelectFileDialog> select_folder_dialog_; scoped_refptr<ui::SelectFileDialog> select_folder_dialog_;
std::map<ContainerId, CrostiniExportImportNotification*> notifications_; std::map<ContainerId, CrostiniExportImportStatusTracker*> status_trackers_;
// Notifications must have unique-per-profile identifiers. // |operation_data_storage_| persists the data required to complete an
// operation while the file selection dialog is open/operation is in progress.
std::unordered_map<OperationData*, std::unique_ptr<OperationData>>
operation_data_storage_;
// Trackers must have unique-per-profile identifiers.
// A non-static member on a profile-keyed-service will suffice. // A non-static member on a profile-keyed-service will suffice.
int next_notification_id_; int next_status_tracker_id_;
base::ObserverList<Observer> observers_; base::ObserverList<Observer> observers_;
// weak_ptr_factory_ should always be last member. // weak_ptr_factory_ should always be last member.
base::WeakPtrFactory<CrostiniExportImport> weak_ptr_factory_{this}; base::WeakPtrFactory<CrostiniExportImport> weak_ptr_factory_{this};
......
...@@ -38,12 +38,9 @@ CrostiniExportImportNotification::CrostiniExportImportNotification( ...@@ -38,12 +38,9 @@ CrostiniExportImportNotification::CrostiniExportImportNotification(
const std::string& notification_id, const std::string& notification_id,
base::FilePath path, base::FilePath path,
ContainerId container_id) ContainerId container_id)
: profile_(profile), : CrostiniExportImportStatusTracker(type, std::move(path)),
type_(type), profile_(profile),
path_(std::move(path)),
container_id_(std::move(container_id)) { container_id_(std::move(container_id)) {
DCHECK(type == ExportImportType::EXPORT || type == ExportImportType::IMPORT);
message_center::RichNotificationData rich_notification_data; message_center::RichNotificationData rich_notification_data;
rich_notification_data.vector_small_image = &kNotificationLinuxIcon; rich_notification_data.vector_small_image = &kNotificationLinuxIcon;
rich_notification_data.accent_color = ash::kSystemNotificationColorNormal; rich_notification_data.accent_color = ash::kSystemNotificationColorNormal;
...@@ -60,7 +57,6 @@ CrostiniExportImportNotification::CrostiniExportImportNotification( ...@@ -60,7 +57,6 @@ CrostiniExportImportNotification::CrostiniExportImportNotification(
rich_notification_data, rich_notification_data,
base::MakeRefCounted<message_center::ThunkNotificationDelegate>( base::MakeRefCounted<message_center::ThunkNotificationDelegate>(
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
SetStatusRunning(0); SetStatusRunning(0);
} }
...@@ -74,17 +70,8 @@ void CrostiniExportImportNotification::ForceRedisplay() { ...@@ -74,17 +70,8 @@ void CrostiniExportImportNotification::ForceRedisplay() {
/*metadata=*/nullptr); /*metadata=*/nullptr);
} }
void CrostiniExportImportNotification::SetStatusRunning(int progress_percent) { void CrostiniExportImportNotification::SetStatusRunningUI(
DCHECK(status_ == Status::RUNNING || status_ == Status::CANCELLING); int progress_percent) {
// Progress updates can still be received while the notification is being
// cancelled. These should not be displayed, as the operation will eventually
// cancel (or fail to cancel).
if (status_ == Status::CANCELLING) {
return;
}
status_ = Status::RUNNING;
if (hidden_) { if (hidden_) {
return; return;
} }
...@@ -92,7 +79,7 @@ void CrostiniExportImportNotification::SetStatusRunning(int progress_percent) { ...@@ -92,7 +79,7 @@ void CrostiniExportImportNotification::SetStatusRunning(int progress_percent) {
notification_->set_type(message_center::NOTIFICATION_TYPE_PROGRESS); notification_->set_type(message_center::NOTIFICATION_TYPE_PROGRESS);
notification_->set_accent_color(ash::kSystemNotificationColorNormal); notification_->set_accent_color(ash::kSystemNotificationColorNormal);
notification_->set_title(l10n_util::GetStringUTF16( notification_->set_title(l10n_util::GetStringUTF16(
type_ == ExportImportType::EXPORT type() == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_RUNNING ? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_RUNNING
: IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_RUNNING)); : IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_RUNNING));
notification_->set_message( notification_->set_message(
...@@ -106,11 +93,7 @@ void CrostiniExportImportNotification::SetStatusRunning(int progress_percent) { ...@@ -106,11 +93,7 @@ void CrostiniExportImportNotification::SetStatusRunning(int progress_percent) {
ForceRedisplay(); ForceRedisplay();
} }
void CrostiniExportImportNotification::SetStatusCancelling() { void CrostiniExportImportNotification::SetStatusCancellingUI() {
DCHECK(status_ == Status::RUNNING);
status_ = Status::CANCELLING;
if (hidden_) { if (hidden_) {
return; return;
} }
...@@ -118,7 +101,7 @@ void CrostiniExportImportNotification::SetStatusCancelling() { ...@@ -118,7 +101,7 @@ void CrostiniExportImportNotification::SetStatusCancelling() {
notification_->set_type(message_center::NOTIFICATION_TYPE_PROGRESS); notification_->set_type(message_center::NOTIFICATION_TYPE_PROGRESS);
notification_->set_accent_color(ash::kSystemNotificationColorNormal); notification_->set_accent_color(ash::kSystemNotificationColorNormal);
notification_->set_title(l10n_util::GetStringUTF16( notification_->set_title(l10n_util::GetStringUTF16(
type_ == ExportImportType::EXPORT type() == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_CANCELLING ? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_CANCELLING
: IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_CANCELLING)); : IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_CANCELLING));
notification_->set_message({}); notification_->set_message({});
...@@ -130,20 +113,15 @@ void CrostiniExportImportNotification::SetStatusCancelling() { ...@@ -130,20 +113,15 @@ void CrostiniExportImportNotification::SetStatusCancelling() {
ForceRedisplay(); ForceRedisplay();
} }
void CrostiniExportImportNotification::SetStatusDone() { void CrostiniExportImportNotification::SetStatusDoneUI() {
DCHECK(status_ == Status::RUNNING ||
(type_ == ExportImportType::IMPORT && status_ == Status::CANCELLING));
status_ = Status::DONE;
notification_->set_type(message_center::NOTIFICATION_TYPE_SIMPLE); notification_->set_type(message_center::NOTIFICATION_TYPE_SIMPLE);
notification_->set_accent_color(ash::kSystemNotificationColorNormal); notification_->set_accent_color(ash::kSystemNotificationColorNormal);
notification_->set_title(l10n_util::GetStringUTF16( notification_->set_title(l10n_util::GetStringUTF16(
type_ == ExportImportType::EXPORT type() == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_DONE ? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_DONE
: IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_DONE)); : IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_DONE));
notification_->set_message(l10n_util::GetStringUTF16( notification_->set_message(l10n_util::GetStringUTF16(
type_ == ExportImportType::EXPORT type() == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_MESSAGE_DONE ? IDS_CROSTINI_EXPORT_NOTIFICATION_MESSAGE_DONE
: IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_DONE)); : IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_DONE));
notification_->set_buttons({}); notification_->set_buttons({});
...@@ -153,64 +131,18 @@ void CrostiniExportImportNotification::SetStatusDone() { ...@@ -153,64 +131,18 @@ void CrostiniExportImportNotification::SetStatusDone() {
ForceRedisplay(); ForceRedisplay();
} }
void CrostiniExportImportNotification::SetStatusCancelled() { void CrostiniExportImportNotification::SetStatusCancelledUI() {
DCHECK(status_ == Status::CANCELLING);
status_ = Status::CANCELLED;
NotificationDisplayService::GetForProfile(profile_)->Close( NotificationDisplayService::GetForProfile(profile_)->Close(
NotificationHandler::Type::TRANSIENT, notification_->id()); NotificationHandler::Type::TRANSIENT, notification_->id());
} }
void CrostiniExportImportNotification::SetStatusFailed() { void CrostiniExportImportNotification::SetStatusFailedWithMessageUI(
SetStatusFailed(Status::FAILED_UNKNOWN_REASON,
l10n_util::GetStringUTF16(
type_ == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_MESSAGE_FAILED
: IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED));
}
void CrostiniExportImportNotification::SetStatusFailedArchitectureMismatch(
const std::string& architecture_container,
const std::string& architecture_device) {
DCHECK(type_ == ExportImportType::IMPORT);
SetStatusFailed(
Status::FAILED_ARCHITECTURE_MISMATCH,
l10n_util::GetStringFUTF16(
IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED_ARCHITECTURE,
base::ASCIIToUTF16(architecture_container),
base::ASCIIToUTF16(architecture_device)));
}
void CrostiniExportImportNotification::SetStatusFailedInsufficientSpace(
uint64_t additional_required_space) {
DCHECK(type_ == ExportImportType::IMPORT);
SetStatusFailed(Status::FAILED_INSUFFICIENT_SPACE,
l10n_util::GetStringFUTF16(
IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED_SPACE,
ui::FormatBytes(additional_required_space)));
}
void CrostiniExportImportNotification::SetStatusFailedConcurrentOperation(
ExportImportType in_progress_operation_type) {
SetStatusFailed(
Status::FAILED_CONCURRENT_OPERATION,
l10n_util::GetStringUTF16(
in_progress_operation_type == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_MESSAGE_FAILED_IN_PROGRESS
: IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED_IN_PROGRESS));
}
void CrostiniExportImportNotification::SetStatusFailed(
Status status, Status status,
const base::string16& message) { const base::string16& message) {
DCHECK(status_ == Status::RUNNING || status_ == Status::CANCELLING);
status_ = status;
notification_->set_type(message_center::NOTIFICATION_TYPE_SIMPLE); notification_->set_type(message_center::NOTIFICATION_TYPE_SIMPLE);
notification_->set_accent_color(ash::kSystemNotificationColorCriticalWarning); notification_->set_accent_color(ash::kSystemNotificationColorCriticalWarning);
notification_->set_title(l10n_util::GetStringUTF16( notification_->set_title(l10n_util::GetStringUTF16(
type_ == ExportImportType::EXPORT type() == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_FAILED ? IDS_CROSTINI_EXPORT_NOTIFICATION_TITLE_FAILED
: IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_FAILED)); : IDS_CROSTINI_IMPORT_NOTIFICATION_TITLE_FAILED));
notification_->set_message(message); notification_->set_message(message);
...@@ -222,7 +154,7 @@ void CrostiniExportImportNotification::SetStatusFailed( ...@@ -222,7 +154,7 @@ void CrostiniExportImportNotification::SetStatusFailed(
} }
void CrostiniExportImportNotification::Close(bool by_user) { void CrostiniExportImportNotification::Close(bool by_user) {
switch (status_) { switch (status()) {
case Status::RUNNING: case Status::RUNNING:
case Status::CANCELLING: case Status::CANCELLING:
hidden_ = true; hidden_ = true;
...@@ -243,18 +175,18 @@ void CrostiniExportImportNotification::Close(bool by_user) { ...@@ -243,18 +175,18 @@ void CrostiniExportImportNotification::Close(bool by_user) {
void CrostiniExportImportNotification::Click( void CrostiniExportImportNotification::Click(
const base::Optional<int>& button_index, const base::Optional<int>& button_index,
const base::Optional<base::string16>&) { const base::Optional<base::string16>&) {
switch (status_) { switch (status()) {
case Status::RUNNING: case Status::RUNNING:
if (button_index) { if (button_index) {
DCHECK(*button_index == 1); DCHECK(*button_index == 1);
CrostiniExportImport::GetForProfile(profile_)->CancelOperation( CrostiniExportImport::GetForProfile(profile_)->CancelOperation(
type_, container_id_); type(), container_id_);
} }
return; return;
case Status::DONE: case Status::DONE:
DCHECK(!button_index); DCHECK(!button_index);
if (type_ == ExportImportType::EXPORT) { if (type() == ExportImportType::EXPORT) {
platform_util::ShowItemInFolder(profile_, path_); platform_util::ShowItemInFolder(profile_, path());
} }
return; return;
case Status::FAILED_UNKNOWN_REASON: case Status::FAILED_UNKNOWN_REASON:
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/chromeos/crostini/crostini_export_import_status_tracker.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "ui/message_center/public/cpp/notification_delegate.h" #include "ui/message_center/public/cpp/notification_delegate.h"
...@@ -25,53 +26,24 @@ enum class ExportImportType; ...@@ -25,53 +26,24 @@ enum class ExportImportType;
// Notification for Crostini export and import. // Notification for Crostini export and import.
class CrostiniExportImportNotification class CrostiniExportImportNotification
: public message_center::NotificationObserver { : public CrostiniExportImportStatusTracker,
public message_center::NotificationObserver {
public: public:
enum class Status {
RUNNING,
CANCELLING,
DONE,
CANCELLED,
FAILED_UNKNOWN_REASON,
FAILED_ARCHITECTURE_MISMATCH,
FAILED_INSUFFICIENT_SPACE,
FAILED_CONCURRENT_OPERATION,
};
// Used to construct CrostiniExportImportNotification to ensure it controls // Used to construct CrostiniExportImportNotification to ensure it controls
// its lifetime. // its lifetime.
static CrostiniExportImportNotification* Create( static CrostiniExportImportStatusTracker* Create(
Profile* profile, Profile* profile,
ExportImportType type, ContainerId container_id,
const std::string& notification_id, const std::string& notification_id,
base::FilePath path, ExportImportType type,
ContainerId container_id) { base::FilePath path) {
return new CrostiniExportImportNotification(profile, type, notification_id, return new CrostiniExportImportNotification(profile, type, notification_id,
std::move(path), std::move(path),
std::move(container_id)); std::move(container_id));
} }
virtual ~CrostiniExportImportNotification(); ~CrostiniExportImportNotification() override;
// Can be used to draw attention to the notification without changing its
// status, even if it has been hidden.
void ForceRedisplay();
void SetStatusRunning(int progress_percent);
void SetStatusCancelling();
void SetStatusDone();
void SetStatusCancelled();
void SetStatusFailed();
void SetStatusFailedArchitectureMismatch(
const std::string& architecture_container,
const std::string& architecture_device);
void SetStatusFailedInsufficientSpace(uint64_t additional_required_space);
void SetStatusFailedConcurrentOperation(
ExportImportType in_progress_operation_type);
Status status() const { return status_; }
ExportImportType type() const { return type_; }
const base::FilePath& path() const { return path_; }
// Getters for testing. // Getters for testing.
message_center::Notification* get_notification() { message_center::Notification* get_notification() {
return notification_.get(); return notification_.get();
...@@ -89,13 +61,18 @@ class CrostiniExportImportNotification ...@@ -89,13 +61,18 @@ class CrostiniExportImportNotification
base::FilePath path, base::FilePath path,
ContainerId container_id); ContainerId container_id);
void SetStatusFailed(Status status, const base::string16& message); // CrostiniExportImportStatusTracker:
void ForceRedisplay() override;
void SetStatusRunningUI(int progress_percent) override;
void SetStatusCancellingUI() override;
void SetStatusDoneUI() override;
void SetStatusCancelledUI() override;
void SetStatusFailedWithMessageUI(Status status,
const base::string16& message) override;
Profile* profile_; Profile* profile_; // Not owned.
ExportImportType type_;
base::FilePath path_;
ContainerId container_id_; ContainerId container_id_;
Status status_ = Status::RUNNING;
// Time when the operation started. Used for estimating time remaining. // Time when the operation started. Used for estimating time remaining.
base::TimeTicks started_ = base::TimeTicks::Now(); base::TimeTicks started_ = base::TimeTicks::Now();
std::unique_ptr<message_center::Notification> notification_; std::unique_ptr<message_center::Notification> notification_;
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/crostini/crostini_export_import_status_tracker.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/crostini/crostini_export_import.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h"
namespace crostini {
CrostiniExportImportStatusTracker::CrostiniExportImportStatusTracker(
ExportImportType type,
base::FilePath path)
: type_(type), path_(path) {
DCHECK(type == ExportImportType::EXPORT || type == ExportImportType::IMPORT);
}
CrostiniExportImportStatusTracker::~CrostiniExportImportStatusTracker() =
default;
void CrostiniExportImportStatusTracker::SetStatusRunning(int progress_percent) {
DCHECK(status_ == Status::RUNNING || status_ == Status::CANCELLING);
// Progress updates can still be received while the notification is being
// cancelled. These should not be displayed, as the operation will eventually
// cancel (or fail to cancel).
if (status_ == Status::CANCELLING) {
return;
}
status_ = Status::RUNNING;
SetStatusRunningUI(progress_percent);
}
void CrostiniExportImportStatusTracker::SetStatusCancelling() {
DCHECK(status_ == Status::RUNNING);
status_ = Status::CANCELLING;
SetStatusCancellingUI();
}
void CrostiniExportImportStatusTracker::SetStatusDone() {
DCHECK(status_ == Status::RUNNING ||
(type() == ExportImportType::IMPORT && status_ == Status::CANCELLING));
status_ = Status::DONE;
SetStatusDoneUI();
}
void CrostiniExportImportStatusTracker::SetStatusCancelled() {
DCHECK(status_ == Status::CANCELLING);
status_ = Status::CANCELLED;
SetStatusCancelledUI();
}
void CrostiniExportImportStatusTracker::SetStatusFailed() {
SetStatusFailedWithMessage(
Status::FAILED_UNKNOWN_REASON,
l10n_util::GetStringUTF16(
type() == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_MESSAGE_FAILED
: IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED));
}
void CrostiniExportImportStatusTracker::SetStatusFailedArchitectureMismatch(
const std::string& architecture_container,
const std::string& architecture_device) {
DCHECK(type() == ExportImportType::IMPORT);
SetStatusFailedWithMessage(
Status::FAILED_ARCHITECTURE_MISMATCH,
l10n_util::GetStringFUTF16(
IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED_ARCHITECTURE,
base::ASCIIToUTF16(architecture_container),
base::ASCIIToUTF16(architecture_device)));
}
void CrostiniExportImportStatusTracker::SetStatusFailedInsufficientSpace(
uint64_t additional_required_space) {
DCHECK(type() == ExportImportType::IMPORT);
SetStatusFailedWithMessage(
Status::FAILED_INSUFFICIENT_SPACE,
l10n_util::GetStringFUTF16(
IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED_SPACE,
ui::FormatBytes(additional_required_space)));
}
void CrostiniExportImportStatusTracker::SetStatusFailedConcurrentOperation(
ExportImportType in_progress_operation_type) {
SetStatusFailedWithMessage(
Status::FAILED_CONCURRENT_OPERATION,
l10n_util::GetStringUTF16(
in_progress_operation_type == ExportImportType::EXPORT
? IDS_CROSTINI_EXPORT_NOTIFICATION_MESSAGE_FAILED_IN_PROGRESS
: IDS_CROSTINI_IMPORT_NOTIFICATION_MESSAGE_FAILED_IN_PROGRESS));
}
void CrostiniExportImportStatusTracker::SetStatusFailedWithMessage(
Status status,
const base::string16& message) {
DCHECK(status_ == Status::RUNNING || status_ == Status::CANCELLING);
status_ = status;
SetStatusFailedWithMessageUI(status, message);
}
} // namespace crostini
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_EXPORT_IMPORT_STATUS_TRACKER_H_
#define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_EXPORT_IMPORT_STATUS_TRACKER_H_
#include <memory>
#include <string>
#include "base/files/file_path.h"
#include "base/strings/string16.h"
namespace crostini {
enum class ExportImportType;
class CrostiniExportImportStatusTracker {
public:
enum class Status {
RUNNING,
CANCELLING,
DONE,
CANCELLED,
FAILED_UNKNOWN_REASON,
FAILED_ARCHITECTURE_MISMATCH,
FAILED_INSUFFICIENT_SPACE,
FAILED_CONCURRENT_OPERATION,
};
CrostiniExportImportStatusTracker(ExportImportType type, base::FilePath path);
virtual ~CrostiniExportImportStatusTracker();
Status status() const { return status_; }
ExportImportType type() const { return type_; }
const base::FilePath& path() const { return path_; }
// Can be used to draw attention to the UI without changing its
// status, even if it has been hidden.
virtual void ForceRedisplay() {}
virtual void SetStatusRunningUI(int progress_percent) = 0;
virtual void SetStatusCancellingUI() = 0;
virtual void SetStatusDoneUI() = 0;
virtual void SetStatusCancelledUI() = 0;
virtual void SetStatusFailedWithMessageUI(Status status,
const base::string16& message) = 0;
void SetStatusRunning(int progress_percent);
void SetStatusCancelling();
void SetStatusDone();
void SetStatusCancelled();
void SetStatusFailed();
void SetStatusFailedArchitectureMismatch(
const std::string& architecture_container,
const std::string& architecture_device);
void SetStatusFailedInsufficientSpace(uint64_t additional_required_space);
void SetStatusFailedConcurrentOperation(
ExportImportType in_progress_operation_type);
private:
void SetStatusFailedWithMessage(Status status, const base::string16& message);
ExportImportType type_;
base::FilePath path_;
Status status_ = Status::RUNNING;
};
} // namespace crostini
#endif // CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_EXPORT_IMPORT_STATUS_TRACKER_H_
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