blob: 6f8464f44abdf44074407ce8c1af83065ddba861 [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 <memory>
#include <set>
#include <string>
#include <base/files/file_path.h>
#include <base/time/time.h>
#include <brillo/errors/error.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "dlcservice/ref_count.pb.h"
namespace dlcservice {
// The file name for the ref count proto file.
extern const char kRefCountFileName[];
// TODO(ahassani): Move this to login_manager's dbus-constant.h.
extern const char kSessionStarted[];
// Is passed when the ref count should count against the device users.
extern const char kUsedByUser[];
// Is passed when the DLC belongs to system and ref count should count toward
// it.
extern const char kUsedBySystem[];
// The default expiration delay in days.
extern const int kDefaultExpirationDelayDays;
// The default user name used in system based ref counts.
extern const char kSystemUsername[];
// The interface for different types of ref counts. Ref counts are used to keep
// track of the users of a DLC. If multiple users using the same DLC on a
// device, one user should not be able to easily remove the DLC because
// otherwise other users' experience will suffer. Ref counts also can be based
// on things other than users depending on the need. They can also include an
// expiration delay so the DLC is removed once the expiration is timed out.
class RefCountInterface {
virtual ~RefCountInterface() = default;
static std::unique_ptr<RefCountInterface> Create(
const std::string& used_by, const base::FilePath& prefs_path);
// Should be called when a DLC is successfully installed.
virtual bool InstalledDlc() = 0;
// Should be called when a DLC is successfully uninstalled.
virtual bool UninstalledDlc() = 0;
// Returns true if the DLC should be removed based on the ref count and
// expiration delays.
virtual bool ShouldPurgeDlc() const = 0;
RefCountInterface() = default;
RefCountInterface(const RefCountInterface&) = delete;
RefCountInterface& operator=(const RefCountInterface&) = delete;
// The base class for ref counts based on ref count proto file.
class RefCountBase : public RefCountInterface {
~RefCountBase() = default;
bool InstalledDlc() override;
bool UninstalledDlc() override;
bool ShouldPurgeDlc() const override;
explicit RefCountBase(const base::FilePath& prefs_path);
// Returns the current user name that should be used in the ref count.
virtual std::string GetCurrentUserName() const = 0;
// Returns the expiration delay for which a DLC should be removed after if
// there was no users of it.
virtual base::TimeDelta GetExpirationDelay() const {
return base::TimeDelta::FromDays(kDefaultExpirationDelayDays);
std::set<std::string> users_;
int64_t last_access_time_us_;
friend class RefCountTest;
FRIEND_TEST(RefCountTest, Ctor);
// Persists the ref count proto file to disk.
bool Persist();
// Utility for reading the ref count info.
static bool ReadRefCountInfo(const base::FilePath& path, RefCountInfo* info);
base::FilePath ref_count_path_;
RefCountBase(const RefCountBase&) = delete;
RefCountBase& operator=(const RefCountBase&) = delete;
class UserRefCount : public RefCountBase {
explicit UserRefCount(const base::FilePath& prefs_path);
~UserRefCount() = default;
// Refreshes the internal cache of the user names we keep.
static void SessionChanged(const std::string& state);
static void OnSuccessRetrievePrimarySessionAsyncForTest(
const std::string& username, const std::string& sanitized_username);
std::string GetCurrentUserName() const override {
return primary_session_username_ ? *primary_session_username_ : "";
static void OnSuccessRetrievePrimarySessionAsync(
const std::string& username, const std::string& sanitized_username);
static void OnErrorRetrievePrimarySessionAsync(brillo::Error* err);
static std::set<std::string> device_users_;
static std::unique_ptr<std::string> primary_session_username_;
UserRefCount(const UserRefCount&) = delete;
UserRefCount& operator=(const UserRefCount&) = delete;
class SystemRefCount : public RefCountBase {
explicit SystemRefCount(const base::FilePath& prefs_path)
: RefCountBase(prefs_path) {}
~SystemRefCount() = default;
std::string GetCurrentUserName() const override { return kSystemUsername; }
SystemRefCount(const SystemRefCount&) = delete;
SystemRefCount& operator=(const SystemRefCount&) = delete;
} // namespace dlcservice