chromium/chrome/browser/ash/borealis/borealis_task.h

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_BOREALIS_BOREALIS_TASK_H_
#define CHROME_BROWSER_ASH_BOREALIS_BOREALIS_TASK_H_

#include <memory>
#include "base/callback_list.h"
#include "base/files/file.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/ash/borealis/borealis_context_manager.h"
#include "chrome/browser/ash/borealis/borealis_features.h"
#include "chrome/browser/ash/borealis/borealis_launch_options.h"
#include "chrome/browser/ash/borealis/borealis_metrics.h"
#include "chrome/browser/ash/guest_os/guest_os_dlc_helper.h"
#include "chrome/browser/ash/guest_os/guest_os_session_tracker.h"
#include "chrome/browser/ash/guest_os/public/guest_os_wayland_server.h"
#include "chromeos/ash/components/dbus/concierge/concierge_client.h"

namespace borealis {

class BorealisContext;

// BorealisTasks are collections of operations that are run by the
// Borealis Context Manager.
class BorealisTask {
 public:
  // Callback to be run when the task completes. The |result| should reflect
  // if the task succeeded with kSuccess and an empty string. If it fails, a
  // different result should be used, and an error string provided.
  using CompletionResultCallback =
      base::OnceCallback<void(BorealisStartupResult, std::string)>;
  explicit BorealisTask(std::string name);
  BorealisTask(const BorealisTask&) = delete;
  BorealisTask& operator=(const BorealisTask&) = delete;
  virtual ~BorealisTask();

  void Run(BorealisContext* context, CompletionResultCallback callback);

 protected:
  virtual void RunInternal(BorealisContext* context) = 0;

  void Complete(BorealisStartupResult result, std::string message);

 private:
  std::string name_;
  base::Time start_time_;
  CompletionResultCallback callback_;
};

// Double-checks that borealis is allowed.
class CheckAllowed : public BorealisTask {
 public:
  CheckAllowed();
  ~CheckAllowed() override;
  void RunInternal(BorealisContext* context) override;

 private:
  void OnAllowednessChecked(BorealisContext* context,
                            BorealisFeatures::AllowStatus allow_status);
  base::WeakPtrFactory<CheckAllowed> weak_factory_{this};
};

// Finds the options used for the current borealis launch.
class GetLaunchOptions : public BorealisTask {
 public:
  GetLaunchOptions();
  ~GetLaunchOptions() override;
  void RunInternal(BorealisContext* context) override;

 private:
  void HandleOptions(BorealisContext* context,
                     BorealisLaunchOptions::Options options);

  base::WeakPtrFactory<GetLaunchOptions> weak_factory_{this};
};

// Mounts the Borealis DLC.
class MountDlc : public BorealisTask {
 public:
  MountDlc();
  ~MountDlc() override;
  void RunInternal(BorealisContext* context) override;

 private:
  void OnMountDlc(BorealisContext* context,
                  guest_os::GuestOsDlcInstallation::Result install_result);

  std::unique_ptr<guest_os::GuestOsDlcInstallation> installation_;
  base::WeakPtrFactory<MountDlc> weak_factory_{this};
};

// Creates a disk image for the Borealis VM.
class CreateDiskImage : public BorealisTask {
 public:
  CreateDiskImage();
  ~CreateDiskImage() override;
  void RunInternal(BorealisContext* context) override;

 private:
  void OnConciergeAvailable(BorealisContext* context, bool is_available);
  void OnCreateDiskImage(
      BorealisContext* context,
      std::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 RunInternal(BorealisContext* context) override;

 private:
  void OnConciergeAvailable(BorealisContext* context,
                            bool service_is_available);
  void StartBorealisWithExternalDisk(BorealisContext* context,
                                     std::optional<base::File> external_disk);
  void OnStartBorealisVm(
      BorealisContext* context,
      std::optional<vm_tools::concierge::StartVmResponse> response);
  base::WeakPtrFactory<StartBorealisVm> weak_factory_{this};
};

// Waits for the startup daemon to signal completion.
class AwaitBorealisStartup : public BorealisTask {
 public:
  AwaitBorealisStartup();
  ~AwaitBorealisStartup() override;
  void RunInternal(BorealisContext* context) override;

 private:
  void OnContainerStarted(BorealisContext* context, guest_os::GuestInfo info);
  void OnTimeout();

  base::CallbackListSubscription subscription_;
  base::WeakPtrFactory<AwaitBorealisStartup> weak_factory_{this};
};

// Updates the value of some chrome://flags in the VM.
class UpdateChromeFlags : public BorealisTask {
 public:
  explicit UpdateChromeFlags(Profile* profile);
  ~UpdateChromeFlags() override;
  void RunInternal(BorealisContext* context) override;

 private:
  void OnFlagsUpdated(BorealisContext* context, std::string error);

  const raw_ptr<Profile> profile_;
  base::WeakPtrFactory<UpdateChromeFlags> weak_factory_{this};
};

}  // namespace borealis

#endif  // CHROME_BROWSER_ASH_BOREALIS_BOREALIS_TASK_H_