Commit 9a88453f authored by danielng's avatar danielng Committed by Commit Bot

borealis: Adding borealis installer

Implementing an installer for borealis, based on the install flow of
Plugin VM and Crostini. Currently there is no way of accessing the
installer (during testing I attached it to a dummy app entry I created).
Whilst the install process is quite lean right now, I left in some
structures, inspired by the other installers, that will be useful when
the installation flow gets more complex and/or when tests are added.
I haven't added any tests since things may be scrapped when proper UX
is decided, the installer is only being used internally and it exists
in a vacuum.

For more context into the installer, and Borealis, please see the
attached bug.

Tests: Tested manually on my machine.
Bug: b:161650651
Change-Id: I552c39f2ff4e0da86bc0f113bef6c4129e671a51
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2338275
Commit-Queue: Daniel Ng <danielng@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarNic Hollingum <hollingum@google.com>
Reviewed-by: default avatarDana Fried <dfried@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797571}
parent 1daff4ec
...@@ -5432,6 +5432,66 @@ ...@@ -5432,6 +5432,66 @@
Hide password Hide password
</message> </message>
<!-- Borealis strings -->
<!-- TODO(danielng): Add string descriptions and remove translateable tags
when strings are finalized. -->
<message name="IDS_BOREALIS_APP_NAME" desc="" translateable="false">
Borealis
</message>
<message name="IDS_BOREALIS_INSTALLER_CONFIRMATION_TITLE" desc="" translateable="false">
Set up <ph name="APP_NAME">$1<ex>BOREALIS</ex></ph>
</message>
<message name="IDS_BOREALIS_INSTALLER_CONFIRMATION_MESSAGE" desc="" translateable="false">
Set up Borealis on your device.
</message>
<message name="IDS_BOREALIS_INSTALLER_INSTALL_BUTTON" desc="" translateable="false">
Install
</message>
<message name="IDS_BOREALIS_INSTALLER_ENVIRONMENT_SETTING_TITLE" desc="" translateable="false">
Setting up <ph name="APP_NAME">$1<ex>BOREALIS</ex></ph>...
</message>
<message name="IDS_BOREALIS_INSTALLER_ERROR_TITLE" desc="" translateable="false">
Setup couldn't complete
</message>
<message name="IDS_BOREALIS_INSTALLER_FINISHED_TITLE" desc="" translateable="false">
Setup complete
</message>
<message name="IDS_BOREALIS_INSTALLER_IMPORTING_MESSAGE" desc="" translateable="false">
Configuring the virtual machine. This may take a few minutes.
</message>
<message name="IDS_BOREALIS_INSTALLER_IMPORTED_MESSAGE" desc="" translateable="false">
<ph name="APP_NAME">$1<ex>BOREALIS</ex></ph> is ready to use.
</message>
<message name="IDS_BOREALIS_INSTALLER_ERROR_MESSAGE" desc="" translateable="false">
Something went wrong.
</message>
<message name="IDS_BOREALIS_INSTALLER_RETRY_BUTTON" desc="" translateable="false">
Retry
</message>
<message name="IDS_BOREALIS_INSTALLER_LAUNCH_BUTTON" desc="" translateable="false">
Launch
</message>
<message name="IDS_BOREALIS_INSTALLER_NOT_ALLOWED_TITLE" desc="" translateable="false">
<ph name="APP_NAME">$1<ex>BOREALIS</ex></ph> needs permission to run
</message>
<message name="IDS_BOREALIS_INSTALLER_NOT_ALLOWED_MESSAGE" desc="" translateable="false">
<ph name="APP_NAME">$1<ex>BOREALIS</ex></ph> isn't allowed on this device. Contact your administrator. Error code: <ph name="ERROR_CODE">$2<ex>7</ex></ph>.
</message>
<message name="IDS_BOREALIS_DLC_INTERNAL_FAILED_MESSAGE" desc="" translateable="false">
Your device needs to be updated before you can use <ph name="APP_NAME">$1<ex>BOREALIS</ex></ph>.
</message>
<message name="IDS_BOREALIS_DLC_BUSY_FAILED_MESSAGE" desc="" translateable="false">
Something went wrong. Please wait a few minutes and run <ph name="APP_NAME">$1<ex>BOREALIS</ex></ph> again.
</message>
<message name="IDS_BOREALIS_DLC_NEED_REBOOT_FAILED_MESSAGE" desc="" translateable="false">
Please restart your device to use <ph name="APP_NAME">$1<ex>BOREALIS</ex></ph>.
</message>
<message name="IDS_BOREALIS_INSUFFICIENT_DISK_SPACE_MESSAGE" desc="" translateable="false">
Your device is low on storage. To increase free space, delete files from device.
</message>
<message name="IDS_BOREALIS_GENERIC_ERROR_MESSAGE" desc="" translateable="false">
Couldn't install <ph name="APP_NAME">$1<ex>BOREALIS</ex></ph>. Please try again later.
</message>
<!-- <!--
================================================================================== ==================================================================================
If you change any IDS_EDU_LOGIN_INFO_* string, update kConsentScreenTextVersion in If you change any IDS_EDU_LOGIN_INFO_* string, update kConsentScreenTextVersion in
......
...@@ -809,6 +809,14 @@ source_set("chromeos") { ...@@ -809,6 +809,14 @@ source_set("chromeos") {
"bluetooth/debug_logs_manager_factory.h", "bluetooth/debug_logs_manager_factory.h",
"boot_times_recorder.cc", "boot_times_recorder.cc",
"boot_times_recorder.h", "boot_times_recorder.h",
"borealis/borealis_installer.cc",
"borealis/borealis_installer.h",
"borealis/borealis_installer_factory.cc",
"borealis/borealis_installer_factory.h",
"borealis/borealis_installer_impl.cc",
"borealis/borealis_installer_impl.h",
"borealis/borealis_util.cc",
"borealis/borealis_util.h",
"browser_context_keyed_service_factories.cc", "browser_context_keyed_service_factories.cc",
"browser_context_keyed_service_factories.h", "browser_context_keyed_service_factories.h",
"camera_detector.cc", "camera_detector.cc",
...@@ -3054,6 +3062,8 @@ source_set("unit_tests") { ...@@ -3054,6 +3062,8 @@ source_set("unit_tests") {
"authpolicy/authpolicy_helper.unittest.cc", "authpolicy/authpolicy_helper.unittest.cc",
"base/file_flusher_unittest.cc", "base/file_flusher_unittest.cc",
"bluetooth/debug_logs_manager_unittest.cc", "bluetooth/debug_logs_manager_unittest.cc",
"borealis/borealis_installer_mock.cc",
"borealis/borealis_installer_mock.h",
"cert_provisioning/cert_provisioning_invalidator_unittest.cc", "cert_provisioning/cert_provisioning_invalidator_unittest.cc",
"cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc", "cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc",
"cert_provisioning/cert_provisioning_scheduler_unittest.cc", "cert_provisioning/cert_provisioning_scheduler_unittest.cc",
......
cpelling@google.com
danielng@google.com
hollingum@google.com
// Copyright 2020 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/borealis/borealis_installer.h"
namespace borealis {
BorealisInstaller::BorealisInstaller() = default;
BorealisInstaller::~BorealisInstaller() = default;
// static
std::string BorealisInstaller::GetInstallingStateName(InstallingState state) {
switch (state) {
case InstallingState::kInactive:
return "kInactive";
case InstallingState::kInstallingDlc:
return "kInstallingDlc";
}
}
void BorealisInstaller::AddObserver(Observer* observer) {
DCHECK(!observer);
observers_.AddObserver(observer);
}
void BorealisInstaller::RemoveObserver(Observer* observer) {
DCHECK(!observer);
observers_.RemoveObserver(observer);
}
} // namespace borealis
// Copyright 2020 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_BOREALIS_BOREALIS_INSTALLER_H_
#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "components/keyed_service/core/keyed_service.h"
namespace borealis {
class BorealisInstaller : public KeyedService {
public:
enum class InstallationResult {
kCompleted,
kCancelled,
kNotAllowed,
kOperationInProgress,
kDlcInternal,
kDlcUnsupported,
kDlcBusy,
kDlcNeedReboot,
kDlcNeedSpace,
kDlcUnknown,
};
enum class InstallingState {
kInactive,
kInstallingDlc,
};
// Observer class for the Borealis installation related events.
class Observer : public base::CheckedObserver {
public:
virtual void OnProgressUpdated(double fraction_complete) = 0;
virtual void OnStateUpdated(InstallingState new_state) = 0;
virtual void OnInstallationEnded(InstallationResult result) = 0;
virtual void OnCancelInitiated() = 0;
};
BorealisInstaller();
static std::string GetInstallingStateName(InstallingState state);
// Checks if an installation process is already running.
virtual bool IsProcessing() = 0;
// Start the installation process.
virtual void Start() = 0;
// Cancels the installation process.
virtual void Cancel() = 0;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
protected:
~BorealisInstaller() override;
base::ObserverList<Observer> observers_;
private:
base::WeakPtrFactory<BorealisInstaller> weak_ptr_factory_{this};
};
} // namespace borealis
#endif // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_H_
// Copyright 2020 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/borealis/borealis_installer_factory.h"
#include "chrome/browser/chromeos/borealis/borealis_installer_impl.h"
#include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
namespace borealis {
// static
BorealisInstaller* BorealisInstallerFactory::GetForProfile(Profile* profile) {
return static_cast<BorealisInstaller*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
// static
BorealisInstallerFactory* BorealisInstallerFactory::GetInstance() {
static base::NoDestructor<BorealisInstallerFactory> factory;
return factory.get();
}
BorealisInstallerFactory::BorealisInstallerFactory()
: BrowserContextKeyedServiceFactory(
"BorealisInstaller",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(DownloadServiceFactory::GetInstance());
}
BorealisInstallerFactory::~BorealisInstallerFactory() = default;
KeyedService* BorealisInstallerFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
return new BorealisInstallerImpl();
}
content::BrowserContext* BorealisInstallerFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextRedirectedInIncognito(context);
}
} // namespace borealis
// Copyright 2020 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_BOREALIS_BOREALIS_INSTALLER_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_FACTORY_H_
#include "base/macros.h"
#include "base/no_destructor.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace content {
class BrowserContext;
} // namespace content
class Profile;
namespace borealis {
class BorealisInstaller;
class BorealisInstallerFactory : public BrowserContextKeyedServiceFactory {
public:
static BorealisInstaller* GetForProfile(Profile* profile);
static BorealisInstallerFactory* GetInstance();
private:
friend base::NoDestructor<BorealisInstallerFactory>;
BorealisInstallerFactory();
~BorealisInstallerFactory() override;
// BrowserContextKeyedServiceFactory implementation.
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(BorealisInstallerFactory);
};
} // namespace borealis
#endif // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_FACTORY_H_
// Copyright 2020 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/borealis/borealis_installer_impl.h"
#include "base/bind.h"
#include "chrome/browser/chromeos/borealis/borealis_util.h"
#include "content/public/browser/browser_thread.h"
namespace borealis {
BorealisInstallerImpl::BorealisInstallerImpl() = default;
BorealisInstallerImpl::~BorealisInstallerImpl() = default;
bool BorealisInstallerImpl::IsProcessing() {
return state_ != State::kIdle;
}
void BorealisInstallerImpl::Start() {
if (!IsBorealisAllowed()) {
LOG(ERROR) << "Installation of Borealis cannot be started because "
<< "Borealis is not allowed.";
InstallationEnded(InstallationResult::kNotAllowed);
return;
}
if (IsProcessing()) {
LOG(ERROR) << "Installation of Borealis is already in progress.";
InstallationEnded(InstallationResult::kOperationInProgress);
return;
}
progress_ = 0;
StartDlcInstallation();
}
void BorealisInstallerImpl::Cancel() {
state_ = State::kCancelling;
for (auto& observer : observers_) {
observer.OnCancelInitiated();
}
}
void BorealisInstallerImpl::StartDlcInstallation() {
state_ = State::kInstalling;
UpdateInstallingState(InstallingState::kInstallingDlc);
chromeos::DlcserviceClient::Get()->Install(
"borealis-dlc",
base::BindOnce(&BorealisInstallerImpl::OnDlcInstallationCompleted,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(
&BorealisInstallerImpl::OnDlcInstallationProgressUpdated,
weak_ptr_factory_.GetWeakPtr()));
}
void BorealisInstallerImpl::InstallationEnded(InstallationResult result) {
state_ = State::kIdle;
installing_state_ = InstallingState::kInactive;
for (auto& observer : observers_) {
observer.OnInstallationEnded(result);
}
}
void BorealisInstallerImpl::UpdateProgress(double state_progress) {
DCHECK_EQ(state_, State::kInstalling);
if (state_progress < 0 || state_progress > 1) {
LOG(ERROR) << "Unexpected progress value " << state_progress
<< " in installing state "
<< GetInstallingStateName(installing_state_);
return;
}
double start_range = 0;
double end_range = 0;
switch (installing_state_) {
case InstallingState::kInstallingDlc:
start_range = 0;
end_range = 1;
break;
default:
NOTREACHED();
}
double new_progress =
start_range + (end_range - start_range) * state_progress;
if (new_progress < progress_) {
LOG(ERROR) << "Progress went backwards from " << progress_ << " to "
<< progress_;
return;
}
progress_ = new_progress;
for (auto& observer : observers_) {
observer.OnProgressUpdated(new_progress);
}
}
void BorealisInstallerImpl::UpdateInstallingState(
InstallingState installing_state) {
DCHECK_NE(installing_state, InstallingState::kInactive);
installing_state_ = installing_state;
for (auto& observer : observers_) {
observer.OnStateUpdated(installing_state_);
}
}
void BorealisInstallerImpl::OnDlcInstallationProgressUpdated(double progress) {
DCHECK_EQ(installing_state_, InstallingState::kInstallingDlc);
if (state_ == State::kCancelling)
return;
UpdateProgress(progress);
}
void BorealisInstallerImpl::OnDlcInstallationCompleted(
const chromeos::DlcserviceClient::InstallResult& install_result) {
DCHECK_EQ(installing_state_, InstallingState::kInstallingDlc);
if (state_ == State::kCancelling) {
// Since DLC installation is currently the only step of installation,
// Borealis has actually been installed by this stage. This is calling
// CancelFinished() instead of InstallFinished(), to help provide clarity
// and also make it easier to add new installation steps in the future.
InstallationEnded(InstallationResult::kCancelled);
return;
}
// If success, continue to the next state.
if (install_result.error == dlcservice::kErrorNone) {
InstallationEnded(InstallationResult::kCompleted);
return;
}
// At this point, the Borealis DLC installation has failed.
InstallationResult result = InstallationResult::kDlcUnknown;
if (install_result.error == dlcservice::kErrorInternal) {
LOG(ERROR) << "Something went wrong internally with DlcService.";
result = InstallationResult::kDlcInternal;
} else if (install_result.error == dlcservice::kErrorInvalidDlc) {
LOG(ERROR) << "Borealis DLC is not supported, need to enable Borealis DLC.";
result = InstallationResult::kDlcUnsupported;
} else if (install_result.error == dlcservice::kErrorBusy) {
LOG(ERROR)
<< "Borealis DLC is not able to be installed as dlcservice is busy.";
result = InstallationResult::kDlcBusy;
} else if (install_result.error == dlcservice::kErrorNeedReboot) {
LOG(ERROR)
<< "Device has pending update and needs a reboot to use Borealis DLC.";
result = InstallationResult::kDlcBusy;
} else if (install_result.error == dlcservice::kErrorAllocation) {
LOG(ERROR) << "Device needs to free space to use Borealis DLC.";
result = InstallationResult::kDlcNeedSpace;
} else {
LOG(ERROR) << "Failed to install Borealis DLC: " << install_result.error;
}
InstallationEnded(result);
}
} // namespace borealis
// Copyright 2020 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_BOREALIS_BOREALIS_INSTALLER_IMPL_H_
#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_IMPL_H_
#include "chrome/browser/chromeos/borealis/borealis_installer.h"
#include "chromeos/dbus/dlcservice/dlcservice_client.h"
namespace borealis {
// This class is responsible for installing the Borealis VM. Currently
// the only installation requirements for Borealis is to install the
// relevant DLC component. The installer works with closesly with
// chrome/browser/ui/views/borealis/borealis_installer_view.h.
class BorealisInstallerImpl : public BorealisInstaller {
public:
BorealisInstallerImpl();
// Disallow copy and assign.
BorealisInstallerImpl(const BorealisInstallerImpl&) = delete;
BorealisInstallerImpl& operator=(const BorealisInstallerImpl&) = delete;
// Checks if an installation process is already running.
bool IsProcessing() override;
// Start the installation process.
void Start() override;
// Cancels the installation process.
void Cancel() override;
private:
enum class State {
kIdle,
kInstalling,
kCancelling,
};
~BorealisInstallerImpl() override;
void StartDlcInstallation();
void InstallationEnded(InstallationResult result);
void UpdateProgress(double state_progress);
void UpdateInstallingState(InstallingState installing_state);
void OnDlcInstallationProgressUpdated(double progress);
void OnDlcInstallationCompleted(
const chromeos::DlcserviceClient::InstallResult& install_result);
State state_ = State::kIdle;
InstallingState installing_state_ = InstallingState::kInactive;
double progress_ = 0;
base::WeakPtrFactory<BorealisInstallerImpl> weak_ptr_factory_{this};
};
} // namespace borealis
#endif // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_IMPL_H_
// Copyright 2020 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/borealis/borealis_installer_mock.h"
namespace borealis {
namespace test {
BorealisInstallerMock::BorealisInstallerMock() = default;
BorealisInstallerMock::~BorealisInstallerMock() = default;
} // namespace test
} // namespace borealis
// Copyright 2020 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_BOREALIS_BOREALIS_INSTALLER_MOCK_H_
#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_MOCK_H_
#include "chrome/browser/chromeos/borealis/borealis_installer.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace borealis {
namespace test {
class BorealisInstallerMock : public BorealisInstaller {
public:
BorealisInstallerMock();
~BorealisInstallerMock();
BorealisInstallerMock(const BorealisInstallerMock&) = delete;
BorealisInstallerMock& operator=(const BorealisInstallerMock&) = delete;
MOCK_METHOD(bool, IsProcessing, (), ());
MOCK_METHOD(void, Start, (), ());
MOCK_METHOD(void, Cancel, (), ());
};
} // namespace test
} // namespace borealis
#endif // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_INSTALLER_MOCK_H_
// Copyright 2020 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/borealis/borealis_util.h"
#include "chrome/common/chrome_features.h"
namespace borealis {
bool IsBorealisAllowed() {
// Check that the Borealis feature is enabled.
return base::FeatureList::IsEnabled(features::kBorealis);
}
} // namespace borealis
// Copyright 2020 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_BOREALIS_BOREALIS_UTIL_H_
#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_UTIL_H_
class Profile;
namespace borealis {
// Checks if Borealis is allowed to run in the current environment.
bool IsBorealisAllowed();
// Shows the Borealis installer (borealis_installer_view).
void ShowBorealisInstallerView(Profile* profile);
} // namespace borealis
#endif // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_UTIL_H_
...@@ -2000,6 +2000,8 @@ static_library("ui") { ...@@ -2000,6 +2000,8 @@ static_library("ui") {
"views/apps/chrome_native_app_window_views_aura_ash.h", "views/apps/chrome_native_app_window_views_aura_ash.h",
"views/arc_app_dialog_view.cc", "views/arc_app_dialog_view.cc",
"views/arc_data_removal_dialog_view.cc", "views/arc_data_removal_dialog_view.cc",
"views/borealis/borealis_installer_view.cc",
"views/borealis/borealis_installer_view.h",
"views/chrome_views_delegate_chromeos.cc", "views/chrome_views_delegate_chromeos.cc",
"views/crostini/crostini_ansible_software_config_view.cc", "views/crostini/crostini_ansible_software_config_view.cc",
"views/crostini/crostini_ansible_software_config_view.h", "views/crostini/crostini_ansible_software_config_view.h",
......
file://chrome/browser/chromeos/borealis/OWNERS
# Please also consider adding an owner from chrome/browser/ui/views/OWNERS.
This diff is collapsed.
// Copyright 2020 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_UI_VIEWS_BOREALIS_BOREALIS_INSTALLER_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_BOREALIS_BOREALIS_INSTALLER_VIEW_H_
#include "base/callback.h"
#include "base/macros.h"
#include "chrome/browser/chromeos/borealis/borealis_installer_impl.h"
#include "ui/views/window/dialog_delegate.h"
namespace views {
class BoxLayout;
class ImageView;
class Label;
class ProgressBar;
} // namespace views
class Profile;
// The front end for the Borealis installation process, works closely with
// "chrome/browser/chromeos/borealis/borealis_installer.h".
class BorealisInstallerView : public views::DialogDelegateView,
public borealis::BorealisInstaller::Observer {
public:
explicit BorealisInstallerView(Profile* profile);
// Disallow copy and assign.
BorealisInstallerView(const BorealisInstallerView&) = delete;
BorealisInstallerView& operator=(const BorealisInstallerView&) = delete;
static BorealisInstallerView* GetActiveViewForTesting();
// views::DialogDelegateView implementation.
bool ShouldShowCloseButton() const override;
bool ShouldShowWindowTitle() const override;
bool Accept() override;
bool Cancel() override;
gfx::Size CalculatePreferredSize() const override;
// borealis::BorealisInstaller::Observer implementation.
void OnStateUpdated(
borealis::BorealisInstaller::InstallingState new_state) override;
void OnProgressUpdated(double fraction_complete) override;
void OnInstallationEnded(
borealis::BorealisInstaller::InstallationResult result) override;
void OnCancelInitiated() override {}
// Public for testing purposes.
base::string16 GetPrimaryMessage() const;
base::string16 GetSecondaryMessage() const;
private:
class TitleLabel;
enum class State {
kConfirmInstall, // Waiting for user to start installation.
kInstalling, // Installation in progress.
kCompleted, // Installation process completed.
kError, // Something unexpected happened.
};
using InstallingState = borealis::BorealisInstaller::InstallingState;
~BorealisInstallerView() override;
// Returns the dialog buttons that should be displayed, based on the current
// |state_| and error |reason_| (if relevant).
int GetCurrentDialogButtons() const;
// Returns the label for a dialog |button|, based on the current |state_|
// and error |reason_| (if relevant).
base::string16 GetCurrentDialogButtonLabel(ui::DialogButton button) const;
void OnStateUpdated();
// views::DialogDelegateView implementation.
void AddedToWidget() override;
void SetPrimaryMessageLabel();
void SetSecondaryMessageLabel();
void SetImage();
void StartInstallation();
base::string16 app_name_;
views::Label* primary_message_label_ = nullptr;
views::Label* secondary_message_label_ = nullptr;
views::ProgressBar* progress_bar_ = nullptr;
views::Label* installation_progress_message_label_ = nullptr;
views::BoxLayout* lower_container_layout_ = nullptr;
views::ImageView* big_image_ = nullptr;
borealis::BorealisInstaller* borealis_installer_ = nullptr;
State state_ = State::kConfirmInstall;
InstallingState installing_state_ = InstallingState::kInactive;
base::Optional<borealis::BorealisInstaller::InstallationResult> result_;
};
#endif // CHROME_BROWSER_UI_VIEWS_BOREALIS_BOREALIS_INSTALLER_VIEW_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