Commit 088f78ee authored by Daniel Ng's avatar Daniel Ng Committed by Commit Bot

borealis: Added borealis launch functionality

Added the basic borealis starter flow functionality and enabled the
borealis installer to launch the VM when it has finished installing.

Cq-Depend: 2434020
Tests: Wrote and ran tests. Tested on DUT.
Bug: b:168425531
Change-Id: I79e0c736fff318177d82909fc687d61061395f06
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2435028
Commit-Queue: Daniel Ng <danielng@google.com>
Reviewed-by: default avatarNic Hollingum <hollingum@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815403}
parent fe6d7ffa
......@@ -831,6 +831,7 @@ source_set("chromeos") {
"bluetooth/debug_logs_manager_factory.h",
"boot_times_recorder.cc",
"boot_times_recorder.h",
"borealis/borealis_context.cc",
"borealis/borealis_context.h",
"borealis/borealis_context_manager.h",
"borealis/borealis_context_manager_factory.cc",
......@@ -849,6 +850,7 @@ source_set("chromeos") {
"borealis/borealis_installer_impl.h",
"borealis/borealis_prefs.cc",
"borealis/borealis_prefs.h",
"borealis/borealis_task.cc",
"borealis/borealis_task.h",
"borealis/borealis_util.cc",
"borealis/borealis_util.h",
......@@ -3226,6 +3228,7 @@ source_set("unit_tests") {
"borealis/borealis_context_manager_unittest.cc",
"borealis/borealis_features_unittest.cc",
"borealis/borealis_installer_unittest.cc",
"borealis/borealis_task_unittest.cc",
"camera_mic/vm_camera_mic_manager_unittest.cc",
"cert_provisioning/cert_provisioning_invalidator_unittest.cc",
"cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc",
......
// 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_context.h"
namespace borealis {
BorealisContext::BorealisContext() = default;
BorealisContext::BorealisContext(Profile* profile) : profile_(profile) {}
} // namespace borealis
......@@ -5,6 +5,9 @@
#ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_CONTEXT_H_
#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_CONTEXT_H_
#include <string>
#include "base/files/file_path.h"
#include "chrome/browser/profiles/profile.h"
namespace borealis {
......@@ -28,14 +31,25 @@ class BorealisContext {
bool borealis_running() const { return borealis_running_; }
void set_borealis_running(bool success) { borealis_running_ = success; }
const std::string& container_name() { return container_name_; }
const std::string& root_path() const { return root_path_; }
void set_root_path(const std::string& path) { root_path_ = path; }
const base::FilePath& disk_path() const { return disk_path_; }
void set_disk_path(const base::FilePath& path) { disk_path_ = path; }
private:
friend class BorealisContextManagerImpl;
BorealisContext() = default;
explicit BorealisContext(Profile* profile) : profile_(profile) {}
BorealisContext();
explicit BorealisContext(Profile* profile);
Profile* profile_ = nullptr;
bool borealis_running_ = false;
std::string container_name_ = "borealis";
std::string root_path_;
base::FilePath disk_path_;
};
} // namespace borealis
......
......@@ -11,7 +11,6 @@
namespace borealis {
class BorealisContext;
class BorealisTask;
using BorealisContextCallback =
base::OnceCallback<void(const BorealisContext&)>;
......@@ -25,8 +24,6 @@ class BorealisContextManager : public KeyedService {
// Starts the Borealis VM and/or runs the callback when it is running.
virtual void StartBorealis(BorealisContextCallback callback) = 0;
virtual void AddTaskForTesting(std::unique_ptr<BorealisTask> task) = 0;
};
} // namespace borealis
......
......@@ -22,18 +22,18 @@ void BorealisContextManagerImpl::StartBorealis(
AddCallback(std::move(callback));
if (!is_borealis_starting_) {
is_borealis_starting_ = true;
// TODO(b/168425531): add actual startup tasks here.
task_queue_ = GetTasks();
NextTask(/*should_continue=*/true);
}
}
void BorealisContextManagerImpl::AddTaskForTesting(
std::unique_ptr<BorealisTask> task) {
AddTask(std::move(task));
}
void BorealisContextManagerImpl::AddTask(std::unique_ptr<BorealisTask> task) {
task_queue_.push(std::move(task));
base::queue<std::unique_ptr<BorealisTask>>
BorealisContextManagerImpl::GetTasks() {
base::queue<std::unique_ptr<BorealisTask>> task_queue;
task_queue.push(std::make_unique<MountDlc>());
task_queue.push(std::make_unique<CreateDiskImage>());
task_queue.push(std::make_unique<StartBorealisVm>());
return task_queue;
}
void BorealisContextManagerImpl::AddCallback(BorealisContextCallback callback) {
......@@ -55,11 +55,11 @@ void BorealisContextManagerImpl::NextTask(bool should_continue) {
OnQueueComplete();
return;
}
std::unique_ptr<BorealisTask> next_task = std::move(task_queue_.front());
current_task_ = std::move(task_queue_.front());
task_queue_.pop();
next_task->Run(&context_,
base::BindOnce(&BorealisContextManagerImpl::NextTask,
weak_factory_.GetWeakPtr()));
current_task_->Run(&context_,
base::BindOnce(&BorealisContextManagerImpl::NextTask,
weak_factory_.GetWeakPtr()));
}
void BorealisContextManagerImpl::OnQueueComplete() {
......
......@@ -29,10 +29,11 @@ class BorealisContextManagerImpl : public BorealisContextManager {
// BorealisContextManager:
void StartBorealis(BorealisContextCallback callback) override;
void AddTaskForTesting(std::unique_ptr<BorealisTask> task) override;
// Public due to testing.
virtual base::queue<std::unique_ptr<BorealisTask>> GetTasks();
private:
void AddTask(std::unique_ptr<BorealisTask> task);
void AddCallback(BorealisContextCallback callback);
void NextTask(bool should_continue);
void OnQueueComplete();
......@@ -44,6 +45,7 @@ class BorealisContextManagerImpl : public BorealisContextManager {
BorealisContext context_;
base::queue<BorealisContextCallback> callback_queue_;
base::queue<std::unique_ptr<BorealisTask>> task_queue_;
std::unique_ptr<BorealisTask> current_task_;
base::WeakPtrFactory<BorealisContextManagerImpl> weak_factory_{this};
};
......
// 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_task.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/borealis/borealis_context.h"
#include "chrome/browser/chromeos/borealis/borealis_util.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/dbus/dbus_thread_manager.h"
namespace borealis {
MountDlc::MountDlc() = default;
MountDlc::~MountDlc() = default;
void MountDlc::Run(BorealisContext* context,
CompletionStatusCallback callback) {
chromeos::DlcserviceClient::Get()->Install(
kBorealisDlcName,
base::BindOnce(&MountDlc::OnMountDlc, weak_factory_.GetWeakPtr(), context,
std::move(callback)),
base::DoNothing());
}
void MountDlc::OnMountDlc(
BorealisContext* context,
CompletionStatusCallback callback,
const chromeos::DlcserviceClient::InstallResult& install_result) {
if (install_result.error != dlcservice::kErrorNone) {
LOG(ERROR) << "Mounting the DLC for Borealis failed: "
<< install_result.error;
std::move(callback).Run(false);
} else {
context->set_root_path(install_result.root_path);
std::move(callback).Run(true);
}
}
CreateDiskImage::CreateDiskImage() = default;
CreateDiskImage::~CreateDiskImage() = default;
void CreateDiskImage::Run(BorealisContext* context,
CompletionStatusCallback callback) {
vm_tools::concierge::CreateDiskImageRequest request;
request.set_disk_path(
base::FilePath(context->container_name()).AsUTF8Unsafe());
request.set_cryptohome_id(
chromeos::ProfileHelper::GetUserIdHashFromProfile(context->profile()));
request.set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
request.set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT);
request.set_disk_size(0);
chromeos::DBusThreadManager::Get()->GetConciergeClient()->CreateDiskImage(
std::move(request),
base::BindOnce(&CreateDiskImage::OnCreateDiskImage,
weak_factory_.GetWeakPtr(), context, std::move(callback)));
}
void CreateDiskImage::OnCreateDiskImage(
BorealisContext* context,
CompletionStatusCallback callback,
base::Optional<vm_tools::concierge::CreateDiskImageResponse> response) {
if (!response) {
LOG(ERROR) << "Failed to create disk image for Borealis. Empty response.";
context->set_disk_path(base::FilePath());
std::move(callback).Run(false);
return;
}
if (response->status() != vm_tools::concierge::DISK_STATUS_EXISTS &&
response->status() != vm_tools::concierge::DISK_STATUS_CREATED) {
LOG(ERROR) << "Failed to create disk image for Borealis: "
<< response->failure_reason();
context->set_disk_path(base::FilePath());
std::move(callback).Run(false);
return;
}
context->set_disk_path(base::FilePath(response->disk_path()));
std::move(callback).Run(true);
}
StartBorealisVm::StartBorealisVm() = default;
StartBorealisVm::~StartBorealisVm() = default;
void StartBorealisVm::Run(BorealisContext* context,
CompletionStatusCallback callback) {
vm_tools::concierge::StartVmRequest request;
vm_tools::concierge::VirtualMachineSpec* vm = request.mutable_vm();
vm->set_kernel(context->root_path() + "/vm_kernel");
vm->set_rootfs(context->root_path() + "/vm_rootfs.img");
request.set_start_termina(false);
request.set_owner_id(
chromeos::ProfileHelper::GetUserIdHashFromProfile(context->profile()));
request.set_enable_gpu(true);
request.set_software_tpm(false);
request.set_enable_audio_capture(false);
request.set_name(context->container_name());
vm_tools::concierge::DiskImage* disk_image = request.add_disks();
disk_image->set_path(context->disk_path().AsUTF8Unsafe());
disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
disk_image->set_writable(true);
disk_image->set_do_mount(false);
chromeos::DBusThreadManager::Get()->GetConciergeClient()->StartTerminaVm(
std::move(request),
base::BindOnce(&StartBorealisVm::OnStartBorealisVm,
weak_factory_.GetWeakPtr(), context, std::move(callback)));
}
void StartBorealisVm::OnStartBorealisVm(
BorealisContext* context,
CompletionStatusCallback callback,
base::Optional<vm_tools::concierge::StartVmResponse> response) {
if (!response) {
LOG(ERROR) << "Failed to start Borealis VM. Empty response.";
std::move(callback).Run(false);
return;
}
if (response->status() == vm_tools::concierge::VM_STATUS_RUNNING) {
std::move(callback).Run(true);
return;
}
if (response->status() == vm_tools::concierge::VM_STATUS_FAILURE ||
response->status() == vm_tools::concierge::VM_STATUS_UNKNOWN) {
LOG(ERROR) << "Failed to start Borealis VM: " << response->failure_reason();
std::move(callback).Run(false);
return;
}
DCHECK_EQ(response->status(), vm_tools::concierge::VM_STATUS_STARTING);
std::move(callback).Run(true);
}
} // namespace borealis
......@@ -5,6 +5,10 @@
#ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_TASK_H_
#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_TASK_H_
#include "base/memory/weak_ptr.h"
#include "chromeos/dbus/concierge_client.h"
#include "chromeos/dbus/dlcservice/dlcservice_client.h"
namespace borealis {
class BorealisContext;
......@@ -16,10 +20,62 @@ class BorealisTask {
// Callback to be run when the task completes. The |bool| should reflect
// if the task succeeded (true) or failed (false).
using CompletionStatusCallback = base::OnceCallback<void(bool)>;
BorealisTask() = default;
BorealisTask(const BorealisTask&) = delete;
BorealisTask& operator=(const BorealisTask&) = delete;
virtual void Run(BorealisContext* context,
CompletionStatusCallback callback) = 0;
virtual ~BorealisTask() = default;
};
// Mounts the Borealis DLC.
class MountDlc : public BorealisTask {
public:
MountDlc();
~MountDlc() override;
void Run(BorealisContext* context,
CompletionStatusCallback callback) override;
private:
void OnMountDlc(
BorealisContext* context,
CompletionStatusCallback callback,
const chromeos::DlcserviceClient::InstallResult& install_result);
base::WeakPtrFactory<MountDlc> weak_factory_{this};
};
// Creates a disk image for the Borealis VM.
class CreateDiskImage : public BorealisTask {
public:
CreateDiskImage();
~CreateDiskImage() override;
void Run(BorealisContext* context,
CompletionStatusCallback callback) override;
private:
void OnCreateDiskImage(
BorealisContext* context,
CompletionStatusCallback callback,
base::Optional<vm_tools::concierge::CreateDiskImageResponse> response);
base::WeakPtrFactory<CreateDiskImage> weak_factory_{this};
};
// Instructs Concierge to start the Borealis VM.
class StartBorealisVm : public BorealisTask {
public:
StartBorealisVm();
~StartBorealisVm() override;
void Run(BorealisContext* context,
CompletionStatusCallback callback) override;
private:
void OnStartBorealisVm(
BorealisContext* context,
CompletionStatusCallback callback,
base::Optional<vm_tools::concierge::StartVmResponse> response);
base::WeakPtrFactory<StartBorealisVm> weak_factory_{this};
};
} // namespace borealis
#endif // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_TASK_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_task.h"
#include <memory>
#include "chrome/browser/chromeos/borealis/borealis_context.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
#include "chromeos/dbus/fake_concierge_client.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace borealis {
namespace {
class CallbackForTesting {
public:
base::OnceCallback<void(bool)> GetCallback() {
return base::BindOnce(&CallbackForTesting::Callback,
base::Unretained(this));
}
MOCK_METHOD(void, Callback, (bool), ());
};
class BorealisTasksTest : public testing::Test {
public:
BorealisTasksTest() = default;
~BorealisTasksTest() override = default;
protected:
void SetUp() override {
chromeos::DBusThreadManager::Initialize();
fake_concierge_client_ = static_cast<chromeos::FakeConciergeClient*>(
chromeos::DBusThreadManager::Get()->GetConciergeClient());
CreateProfile();
context_ = BorealisContext::CreateBorealisContextForTesting();
context_->set_profile(profile_.get());
chromeos::DlcserviceClient::InitializeFake();
fake_dlcservice_client_ = static_cast<chromeos::FakeDlcserviceClient*>(
chromeos::DlcserviceClient::Get());
}
void TearDown() override {
profile_.reset();
chromeos::DlcserviceClient::Shutdown();
chromeos::DBusThreadManager::Shutdown();
}
std::unique_ptr<TestingProfile> profile_;
BorealisContext* context_;
content::BrowserTaskEnvironment task_environment_;
// Owned by chromeos::DBusThreadManager
chromeos::FakeConciergeClient* fake_concierge_client_;
chromeos::FakeDlcserviceClient* fake_dlcservice_client_;
private:
void CreateProfile() {
TestingProfile::Builder profile_builder;
profile_builder.SetProfileName("defaultprofile");
profile_ = profile_builder.Build();
}
// Disallow copy and assign.
BorealisTasksTest(const BorealisTasksTest&) = delete;
BorealisTasksTest& operator=(const BorealisTasksTest&) = delete;
};
TEST_F(BorealisTasksTest, MountDlcSucceedsAndCallbackRanWithResults) {
fake_dlcservice_client_->set_install_error(dlcservice::kErrorNone);
fake_dlcservice_client_->set_install_root_path("test/path");
EXPECT_EQ(context_->root_path(), "");
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(true));
MountDlc task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
EXPECT_EQ(context_->root_path(), "test/path");
}
TEST_F(BorealisTasksTest, CreateDiskSucceedsAndCallbackRanWithResults) {
vm_tools::concierge::CreateDiskImageResponse response;
base::FilePath path = base::FilePath("test/path");
response.set_status(vm_tools::concierge::DISK_STATUS_CREATED);
response.set_disk_path(path.AsUTF8Unsafe());
fake_concierge_client_->set_create_disk_image_response(std::move(response));
EXPECT_EQ(context_->disk_path(), base::FilePath());
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(true));
CreateDiskImage task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
EXPECT_EQ(context_->disk_path(), path);
}
TEST_F(BorealisTasksTest,
CreateDiskImageAlreadyExistsAndCallbackRanWithResults) {
vm_tools::concierge::CreateDiskImageResponse response;
base::FilePath path = base::FilePath("test/path");
response.set_status(vm_tools::concierge::DISK_STATUS_EXISTS);
response.set_disk_path(path.AsUTF8Unsafe());
fake_concierge_client_->set_create_disk_image_response(std::move(response));
EXPECT_EQ(context_->disk_path(), base::FilePath());
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(true));
CreateDiskImage task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
EXPECT_EQ(context_->disk_path(), path);
}
TEST_F(BorealisTasksTest, StartBorealisVmSucceedsAndCallbackRanWithResults) {
vm_tools::concierge::StartVmResponse response;
response.set_status(vm_tools::concierge::VM_STATUS_STARTING);
fake_concierge_client_->set_start_vm_response(std::move(response));
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(true));
StartBorealisVm task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
}
TEST_F(BorealisTasksTest,
StartBorealisVmVmAlreadyRunningAndCallbackRanWithResults) {
vm_tools::concierge::StartVmResponse response;
response.set_status(vm_tools::concierge::VM_STATUS_RUNNING);
fake_concierge_client_->set_start_vm_response(std::move(response));
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(true));
StartBorealisVm task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
}
class BorealisTasksTestDlc : public BorealisTasksTest,
public testing::WithParamInterface<std::string> {};
TEST_P(BorealisTasksTestDlc, MountDlcFailsAndCallbackRanWithResults) {
fake_dlcservice_client_->set_install_error(GetParam());
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(false));
MountDlc task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
}
INSTANTIATE_TEST_SUITE_P(BorealisTasksTestDlcErrors,
BorealisTasksTestDlc,
testing::Values(dlcservice::kErrorInternal,
dlcservice::kErrorInvalidDlc,
dlcservice::kErrorBusy,
dlcservice::kErrorNeedReboot,
dlcservice::kErrorAllocation,
"unknown"));
class BorealisTasksTestDiskImage
: public BorealisTasksTest,
public testing::WithParamInterface<vm_tools::concierge::DiskImageStatus> {
};
TEST_P(BorealisTasksTestDiskImage, CreateDiskFailsAndCallbackRanWithResults) {
vm_tools::concierge::CreateDiskImageResponse response;
response.set_status(GetParam());
fake_concierge_client_->set_create_disk_image_response(std::move(response));
EXPECT_EQ(context_->disk_path(), base::FilePath());
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(false));
CreateDiskImage task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
EXPECT_EQ(context_->disk_path(), base::FilePath());
}
INSTANTIATE_TEST_SUITE_P(
BorealisTasksTestCreateDiskImageErrors,
BorealisTasksTestDiskImage,
testing::Values(vm_tools::concierge::DISK_STATUS_UNKNOWN,
vm_tools::concierge::DISK_STATUS_FAILED,
vm_tools::concierge::DISK_STATUS_DOES_NOT_EXIST,
vm_tools::concierge::DISK_STATUS_DESTROYED,
vm_tools::concierge::DISK_STATUS_IN_PROGRESS,
vm_tools::concierge::DISK_STATUS_RESIZED));
class BorealisTasksTestsStartBorealisVm
: public BorealisTasksTest,
public testing::WithParamInterface<vm_tools::concierge::VmStatus> {};
TEST_P(BorealisTasksTestsStartBorealisVm,
StartBorealisVmErrorsAndCallbackRanWithResults) {
vm_tools::concierge::StartVmResponse response;
response.set_status(GetParam());
fake_concierge_client_->set_start_vm_response(std::move(response));
testing::StrictMock<CallbackForTesting> callback;
EXPECT_CALL(callback, Callback(false));
StartBorealisVm task;
task.Run(context_, callback.GetCallback());
task_environment_.RunUntilIdle();
EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
}
INSTANTIATE_TEST_SUITE_P(
BorealisTasksTestStartBorealisVmErrors,
BorealisTasksTestsStartBorealisVm,
testing::Values(vm_tools::concierge::VM_STATUS_UNKNOWN,
vm_tools::concierge::VM_STATUS_FAILURE));
} // namespace
} // namespace borealis
......@@ -12,6 +12,8 @@
#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/borealis/borealis_context_manager_factory.h"
#include "chrome/browser/chromeos/borealis/borealis_context_manager_impl.h"
#include "chrome/browser/chromeos/borealis/borealis_installer_factory.h"
#include "chrome/browser/chromeos/borealis/borealis_util.h"
#include "chrome/browser/ui/browser_navigator.h"
......@@ -77,8 +79,9 @@ class BorealisInstallerView::TitleLabel : public views::Label {
// Currently using the UI specs that the Plugin VM installer use.
BorealisInstallerView::BorealisInstallerView(Profile* profile)
: app_name_(l10n_util::GetStringUTF16(IDS_BOREALIS_APP_NAME)),
profile_(profile),
borealis_installer_(
borealis::BorealisInstallerFactory::GetForProfile(profile)) {
borealis::BorealisInstallerFactory::GetForProfile(profile_)) {
// Layout constants from the spec used for the plugin vm installer.
gfx::Insets kDialogInsets(60, 64, 0, 64);
const int kPrimaryMessageHeight = views::style::GetLineHeight(
......@@ -187,7 +190,8 @@ bool BorealisInstallerView::Accept() {
if (state_ == State::kCompleted) {
// Launch button has been clicked.
// TODO(danielng): Link to launch VM command, once implemented.
borealis::BorealisContextManagerFactory::GetForProfile(profile_)
->StartBorealis(base::DoNothing());
return true;
}
......
......@@ -85,6 +85,7 @@ class BorealisInstallerView : public views::DialogDelegateView,
void StartInstallation();
base::string16 app_name_;
Profile* profile_ = nullptr;
views::Label* primary_message_label_ = nullptr;
views::Label* secondary_message_label_ = nullptr;
views::ProgressBar* progress_bar_ = nullptr;
......
......@@ -5,7 +5,11 @@
#include "chrome/browser/ui/views/borealis/borealis_installer_view.h"
#include "base/bind.h"
#include "chrome/browser/chromeos/borealis/borealis_context.h"
#include "chrome/browser/chromeos/borealis/borealis_context_manager.h"
#include "chrome/browser/chromeos/borealis/borealis_context_manager_factory.h"
#include "chrome/browser/chromeos/borealis/borealis_installer_factory.h"
#include "chrome/browser/chromeos/borealis/borealis_task.h"
#include "chrome/browser/chromeos/borealis/borealis_util.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
......@@ -23,6 +27,9 @@
using ::testing::_;
using InstallationResult = borealis::BorealisInstaller::InstallationResult;
namespace borealis {
namespace {
class BorealisInstallerMock : public borealis::BorealisInstaller {
public:
BorealisInstallerMock() = default;
......@@ -37,6 +44,17 @@ class BorealisInstallerMock : public borealis::BorealisInstaller {
MOCK_METHOD1(RemoveObserver, void(Observer*));
};
class BorealisContextManagerMock : public borealis::BorealisContextManager {
public:
BorealisContextManagerMock() = default;
~BorealisContextManagerMock() = default;
BorealisContextManagerMock(const BorealisContextManagerMock&) = delete;
BorealisContextManagerMock& operator=(const BorealisContextManagerMock&) =
delete;
MOCK_METHOD1(StartBorealis, void(borealis::BorealisContextCallback));
};
class BorealisInstallerViewBrowserTest : public DialogBrowserTest {
public:
BorealisInstallerViewBrowserTest() = default;
......@@ -53,6 +71,15 @@ class BorealisInstallerViewBrowserTest : public DialogBrowserTest {
-> std::unique_ptr<KeyedService> {
return std::make_unique<BorealisInstallerMock>();
})));
mock_context_manager_ =
static_cast<::testing::StrictMock<BorealisContextManagerMock>*>(
borealis::BorealisContextManagerFactory::GetInstance()
->SetTestingFactoryAndUse(
browser()->profile(),
base::BindRepeating([](content::BrowserContext* context)
-> std::unique_ptr<KeyedService> {
return std::make_unique<BorealisContextManagerMock>();
})));
}
void ShowUi(const std::string& name) override {
......@@ -128,6 +155,7 @@ class BorealisInstallerViewBrowserTest : public DialogBrowserTest {
}
::testing::StrictMock<BorealisInstallerMock>* mock_installer_;
::testing::StrictMock<BorealisContextManagerMock>* mock_context_manager_;
BorealisInstallerView* view_;
base::string16 app_name_;
......@@ -152,6 +180,7 @@ IN_PROC_BROWSER_TEST_F(BorealisInstallerViewBrowserTest, SucessfulInstall) {
view_->OnInstallationEnded(InstallationResult::kCompleted);
ExpectInstallationCompletedSucessfully();
EXPECT_CALL(*mock_context_manager_, StartBorealis(_));
EXPECT_CALL(*mock_installer_, RemoveObserver(_));
view_->AcceptDialog();
......@@ -193,6 +222,7 @@ IN_PROC_BROWSER_TEST_F(BorealisInstallerViewBrowserTest,
view_->OnInstallationEnded(InstallationResult::kCompleted);
ExpectInstallationCompletedSucessfully();
EXPECT_CALL(*mock_context_manager_, StartBorealis(_));
EXPECT_CALL(*mock_installer_, RemoveObserver(_));
view_->AcceptDialog();
......@@ -305,3 +335,5 @@ IN_PROC_BROWSER_TEST_F(BorealisInstallerViewBrowserTest, DlcUnknownError) {
ClickCancel();
}
} // namespace
} // namespace borealis
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