blob: c87543e9b8770a6668b1ccaf75a5581b808cc54d [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERSISTENT_CACHE_BACKEND_PARAMS_MANAGER_H_
#define COMPONENTS_PERSISTENT_CACHE_BACKEND_PARAMS_MANAGER_H_
#include <type_traits>
#include <unordered_map>
#include "base/component_export.h"
#include "base/containers/lru_cache.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/hash/hash.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "components/persistent_cache/backend_params.h"
namespace persistent_cache {
struct FootprintReductionResult {
int64_t current_footprint = 0;
int64_t number_of_bytes_deleted = 0;
};
// Use to retrieve or create BackendParams to open a PersistentCache. Existing
// params are cached so that they can be retrieved synchronously when possible.
//
// Example:
// BackendParamsManager params_manager(GetPath());
// params_manager.GetParamsSyncOrCreateAsync(BackendType::kSqlite, "key",
// AccessRights::kReadOnly,
// std::move(callback));
// // `callback` called synchronously and result can be used right away.
// // ... or
// // `callback` will be invoked asynchronously to return result.
//
class COMPONENT_EXPORT(PERSISTENT_CACHE) BackendParamsManager {
public:
enum class AccessRights { kReadonly, kReadWrite };
// `top_directory` is the where BackendParamsManager will try to find existing
// files and create new ones.
explicit BackendParamsManager(base::FilePath top_directory);
~BackendParamsManager();
using CompletedCallback = base::OnceCallback<void(const BackendParams&)>;
// Use to get backend params matching parameters directly or through
// `callback`. An invalid BackendParams instance is returned if `key` does
// not respect restrictions. Keys used in this class should be as short as
// possible to minimize the risk of them being too long to be used in a file
// path. Not all characters are allowed. See
// `GetAllAllowedCharactersInKeysForTesting`.
void GetParamsSyncOrCreateAsync(BackendType backend_type,
const std::string& key,
AccessRights access_rights,
CompletedCallback callback);
BackendParams GetOrCreateParamsSync(BackendType backend_type,
const std::string& key,
AccessRights access_rights);
// Delete all managed files.
void DeleteAllFiles();
// Use to reduce the total size of files on disk until it's equal or smaller
// than `target_footprint`. Use when enforcing a quota or proactively saving
// space. If the goal is to get rid of all files use `DeleteAllFiles()`
// instead. Returns the number of bytes deleted.
FootprintReductionResult BringDownTotalFootprintOfFiles(
int64_t target_footprint);
// Use to get a string containing all characters supported in keys.
static std::string GetAllAllowedCharactersInKeysForTesting();
private:
FRIEND_TEST_ALL_PREFIXES(BackendParamsManager, InvalidCharactersHandled);
FRIEND_TEST_ALL_PREFIXES(BackendParamsManager, KeyToFileName);
FRIEND_TEST_ALL_PREFIXES(BackendParamsManager, KeyToFileNameIsReversible);
// Function that simplifies a key string into a form suitable to be used as a
// file name by this class. The function also takes care of lightly
// obfuscating the value. This is not a security measure but more a way to
// underline the fact that the files are not meant to be discovered and
// modified by third parties.
//
// On Windows some file names are reserved
// (https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#file-and-directory-names).
// As such the result of this function should always be used by appending a
// file extension as provided by this class to avoid using problems.
static std::string FileNameFromKey(const std::string& key);
// Inverse of `FileNameFromKey`. Will return an empty string on an invalid
// filename which needs to be handled.
static std::string KeyFromFileName(const std::string& key);
struct BackendParamsKey {
BackendType backend_type;
std::string key;
};
struct BackendParamsKeyHash {
BackendParamsKeyHash() = default;
~BackendParamsKeyHash() = default;
std::size_t operator()(const BackendParamsKey& k) const {
size_t hash = 0;
return base::HashCombine(hash, k.backend_type, k.key);
}
};
struct BackendParamsKeyEqual {
bool operator()(const BackendParamsKey& lhs,
const BackendParamsKey& rhs) const {
return lhs.backend_type == rhs.backend_type && lhs.key == rhs.key;
}
};
static BackendParams CreateParamsSync(base::FilePath directory,
BackendType backend_type,
const std::string& filename,
AccessRights access_rights);
// Saves params for later retrieval.
void SaveParams(const std::string& key,
CompletedCallback callback,
BackendParams backend_params);
base::HashingLRUCache<BackendParamsKey,
BackendParams,
BackendParamsKeyHash,
BackendParamsKeyEqual>
backend_params_map_ GUARDED_BY_CONTEXT(sequence_checker_);
const base::FilePath top_directory_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<BackendParamsManager> weak_factory_{this};
};
} // namespace persistent_cache
#endif // COMPONENTS_PERSISTENT_CACHE_BACKEND_PARAMS_MANAGER_H_