blob: 7575e754ffef44daff30db948e65090c1b80682a [file] [log] [blame]
// Copyright 2020 The Chromium OS 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 <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <base/files/file_path.h>
#include <brillo/errors/error.h>
#include <dbus/dlcservice/dbus-constants.h>
#include <dlcservice/proto_bindings/dlcservice.pb.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include <libimageloader/manifest.h>
#include <chromeos/dbus/service_constants.h>
#include "dlcservice/boot/boot_slot.h"
#include "dlcservice/ref_count.h"
namespace dlcservice {
// |DlcId| is the ID of the DLC.
using DlcId = std::string;
class DlcBase {
explicit DlcBase(DlcId id) : id_(std::move(id)) {}
virtual ~DlcBase() = default;
// Returns the list of directories related to a DLC for deletion.
static std::vector<base::FilePath> GetPathsToDelete(const DlcId& id);
// Initializes the DLC. This should be called right after creating the DLC
// object.
bool Initialize();
// Returns the ID of the DLC.
const DlcId& GetId() const;
// Returns the human readable name of the DLC.
const std::string& GetName() const;
// Returns the description of the DLC.
const std::string& GetDescription() const;
// Returns the current state of the DLC.
DlcState GetState() const;
// Returns the root directory inside a mounted DLC module.
base::FilePath GetRoot() const;
// Returns true if the DLC is currently being installed.
bool IsInstalling() const;
// Returns true if the DLC is already installed and mounted.
bool IsInstalled() const;
// Returns true if the DLC is marked verified.
bool IsVerified() const;
// Returns true if the DLC has any content on disk that is taking space. This
// means mainly if it has images on disk.
bool HasContent() const;
// Returns the amount of disk space this DLC is using right now.
uint64_t GetUsedBytesOnDisk() const;
// Returns true if the DLC has a boolean true for 'preload-allowed'
// attribute in the manifest for the given |id| and |package|.
bool IsPreloadAllowed() const;
// Creates the DLC image based on the fields from the manifest if the DLC is
// not installed. If the DLC image exists or is installed already, some
// verifications are passed to validate that the DLC is mounted.
// Initializes the installation like creating the necessary files, etc.
bool Install(brillo::ErrorPtr* err);
// This is called after the update_engine finishes the installation of a
// DLC. This marks the DLC as installed and mounts the DLC image.
bool FinishInstall(bool installed_by_ue, brillo::ErrorPtr* err);
// Cancels the ongoing installation of this DLC. The state will be set to
// uninstalled after this call if successful.
// The |err_in| argument is the error that causes the install to be cancelled.
bool CancelInstall(const brillo::ErrorPtr& err_in, brillo::ErrorPtr* err);
// Uninstalls the DLC.
bool Uninstall(brillo::ErrorPtr* err);
// Deletes all files associated with the DLC.
bool Purge(brillo::ErrorPtr* err);
// Returns true if the DLC has to be removed/purged.
bool ShouldPurge();
// Is called when the DLC image is finally installed on the disk and is
// verified.
bool InstallCompleted(brillo::ErrorPtr* err);
// Is called when the inactive DLC image is updated and verified.
bool UpdateCompleted(brillo::ErrorPtr* err);
// Makes the DLC ready to be updated (creates and resizes the inactive
// image). Returns false if anything goes wrong.
bool MakeReadyForUpdate() const;
// Changes the install progress on this DLC. Only changes if the |progress| is
// greater than the current progress value.
void ChangeProgress(double progress);
friend class DBusServiceTest;
FRIEND_TEST(DBusServiceTest, GetInstalled);
FRIEND_TEST(DlcBaseTest, GetUsedBytesOnDisk);
FRIEND_TEST(DlcBaseTest, DefaultState);
FRIEND_TEST(DlcBaseTest, ChangeStateNotInstalled);
FRIEND_TEST(DlcBaseTest, ChangeStateInstalling);
FRIEND_TEST(DlcBaseTest, ChangeStateInstalled);
FRIEND_TEST(DlcBaseTest, ChangeProgress);
FRIEND_TEST(DlcBaseTest, MakeReadyForUpdate);
FRIEND_TEST(DlcBaseTest, MarkUnverified);
FRIEND_TEST(DlcBaseTest, MarkVerified);
FRIEND_TEST(DlcBaseTest, PreloadCopyShouldMarkUnverified);
FRIEND_TEST(DlcBaseTest, PreloadCopyFailOnInvalidFileSize);
FRIEND_TEST(DlcBaseTest, InstallingCorruptPreloadedImageCleansUp);
FRIEND_TEST(DlcBaseTest, PreloadingSkippedOnAlreadyVerifiedDlc);
FRIEND_TEST(DlcBaseTest, UnmountClearsMountPoint);
// Returns the path to the DLC image given the slot number.
base::FilePath GetImagePath(BootSlot::Slot slot) const;
// Creates the DLC directories and files if they don't exist. This function
// should be used as fall-through. We should call this even if we presumably
// know the files are already there. This allows us to create any new DLC
// files that didn't exist on a previous version of the DLC.
bool CreateDlc(brillo::ErrorPtr* err);
// Mark the current active DLC image as verified.
bool MarkVerified();
// Mark the current active DLC image as unverified.
bool MarkUnverified();
// Returns true if the DLC image in the current active slot matches the hash
// of that in the rootfs manifest for the DLC.
bool Verify();
// Helper used to load in (copy + cleanup) preloadable files for the DLC.
bool PreloadedCopier(brillo::ErrorPtr* err);
// Mounts the DLC image.
bool Mount(brillo::ErrorPtr* err);
// Unmounts the DLC image.
bool Unmount(brillo::ErrorPtr* err);
// Returns true if the active DLC image is present.
bool IsActiveImagePresent() const;
// Deletes all directories related to this DLC.
bool DeleteInternal(brillo::ErrorPtr* err);
// Changes the state of the current DLC. It also notifies the state change
// reporter that a state change has been made.
void ChangeState(DlcState::State state);
// Sets the DLC as being active or not based on |active| value.
void SetActiveValue(bool active);
DlcId id_;
std::string package_;
// The verification value which validates the current verification stamps is
// valid.
std::string verification_value_;
DlcState state_;
base::FilePath mount_point_;
std::shared_ptr<imageloader::Manifest> manifest_;
// The directories on the stateful partition where the DLC image will reside.
base::FilePath content_id_path_;
base::FilePath content_package_path_;
base::FilePath prefs_path_;
base::FilePath prefs_package_path_;
base::FilePath preloaded_image_path_;
// The object that keeps track of ref counts. NOTE: Do NOT access this object
// directly. Use |GetRefCount()| instead.
std::unique_ptr<RefCountInterface> ref_count_;
DlcBase(const DlcBase&) = delete;
DlcBase& operator=(const DlcBase&) = delete;
using DlcMap = std::map<DlcId, DlcBase>;
using DlcIdList = std::vector<DlcId>;
} // namespace dlcservice