This source file includes following definitions.
- Base64Encode
- Base64Encode
- Base64Decode
- task_runner_
- Store
- Load
- LoadAllSubkeys
- Delete
- Clear
- FilterSubkeys
- PurgeOtherKeys
- PurgeOtherSubkeys
- VerifyKeyPath
- VerifyKeyPathAndGetSubkeyPath
#include "components/policy/core/common/cloud/resource_cache.h"
#include "base/base64.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
namespace policy {
namespace {
bool Base64Encode(const std::string& value, std::string* encoded) {
DCHECK(!value.empty());
if (value.empty())
return false;
base::Base64Encode(value, encoded);
base::ReplaceChars(*encoded, "+", "-", encoded);
base::ReplaceChars(*encoded, "/", "_", encoded);
return true;
}
bool Base64Encode(const std::set<std::string>& input,
std::set<std::string>* output) {
output->clear();
for (std::set<std::string>::const_iterator it = input.begin();
it != input.end(); ++it) {
std::string encoded;
if (!Base64Encode(*it, &encoded)) {
output->clear();
return false;
}
output->insert(encoded);
}
return true;
}
bool Base64Decode(const std::string& encoded, std::string* value) {
std::string buffer;
base::ReplaceChars(encoded, "-", "+", &buffer);
base::ReplaceChars(buffer, "_", "/", &buffer);
return base::Base64Decode(buffer, value) && !value->empty();
}
}
ResourceCache::ResourceCache(
const base::FilePath& cache_dir,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: cache_dir_(cache_dir),
task_runner_(task_runner) {
}
ResourceCache::~ResourceCache() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
}
bool ResourceCache::Store(const std::string& key,
const std::string& subkey,
const std::string& data) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
base::FilePath subkey_path;
int size = base::checked_cast<int>(data.size());
return VerifyKeyPathAndGetSubkeyPath(key, true, subkey, &subkey_path) &&
base::DeleteFile(subkey_path, false) &&
(base::WriteFile(subkey_path, data.data(), size) == size);
}
bool ResourceCache::Load(const std::string& key,
const std::string& subkey,
std::string* data) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
base::FilePath subkey_path;
if (!VerifyKeyPathAndGetSubkeyPath(key, false, subkey, &subkey_path) ||
base::IsLink(subkey_path)) {
return false;
}
data->clear();
return base::ReadFileToString(subkey_path, data);
}
void ResourceCache::LoadAllSubkeys(
const std::string& key,
std::map<std::string, std::string>* contents) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
contents->clear();
base::FilePath key_path;
if (!VerifyKeyPath(key, false, &key_path))
return;
base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES);
for (base::FilePath path = enumerator.Next(); !path.empty();
path = enumerator.Next()) {
const std::string encoded_subkey = path.BaseName().MaybeAsASCII();
std::string subkey;
std::string data;
if (!base::IsLink(path) &&
Base64Decode(encoded_subkey, &subkey) &&
base::ReadFileToString(path, &data)) {
(*contents)[subkey].swap(data);
}
}
}
void ResourceCache::Delete(const std::string& key, const std::string& subkey) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
base::FilePath subkey_path;
if (VerifyKeyPathAndGetSubkeyPath(key, false, subkey, &subkey_path))
base::DeleteFile(subkey_path, false);
base::DeleteFile(subkey_path.DirName(), false);
}
void ResourceCache::Clear(const std::string& key) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
base::FilePath key_path;
if (VerifyKeyPath(key, false, &key_path))
base::DeleteFile(key_path, true);
}
void ResourceCache::FilterSubkeys(const std::string& key,
const SubkeyFilter& test) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
base::FilePath key_path;
if (!VerifyKeyPath(key, false, &key_path))
return;
base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES);
for (base::FilePath subkey_path = enumerator.Next();
!subkey_path.empty(); subkey_path = enumerator.Next()) {
std::string subkey;
if (!Base64Decode(subkey_path.BaseName().MaybeAsASCII(), &subkey) ||
test.Run(subkey)) {
base::DeleteFile(subkey_path, true);
}
}
base::DeleteFile(key_path, false);
}
void ResourceCache::PurgeOtherKeys(const std::set<std::string>& keys_to_keep) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
std::set<std::string> encoded_keys_to_keep;
if (!Base64Encode(keys_to_keep, &encoded_keys_to_keep))
return;
base::FileEnumerator enumerator(
cache_dir_, false, base::FileEnumerator::DIRECTORIES);
for (base::FilePath path = enumerator.Next(); !path.empty();
path = enumerator.Next()) {
const std::string name(path.BaseName().MaybeAsASCII());
if (encoded_keys_to_keep.find(name) == encoded_keys_to_keep.end())
base::DeleteFile(path, true);
}
}
void ResourceCache::PurgeOtherSubkeys(
const std::string& key,
const std::set<std::string>& subkeys_to_keep) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
base::FilePath key_path;
if (!VerifyKeyPath(key, false, &key_path))
return;
std::set<std::string> encoded_subkeys_to_keep;
if (!Base64Encode(subkeys_to_keep, &encoded_subkeys_to_keep))
return;
base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES);
for (base::FilePath path = enumerator.Next(); !path.empty();
path = enumerator.Next()) {
const std::string name(path.BaseName().MaybeAsASCII());
if (encoded_subkeys_to_keep.find(name) == encoded_subkeys_to_keep.end())
base::DeleteFile(path, false);
}
base::DeleteFile(key_path, false);
}
bool ResourceCache::VerifyKeyPath(const std::string& key,
bool allow_create,
base::FilePath* path) {
std::string encoded;
if (!Base64Encode(key, &encoded))
return false;
*path = cache_dir_.AppendASCII(encoded);
return allow_create ? base::CreateDirectory(*path) :
base::DirectoryExists(*path);
}
bool ResourceCache::VerifyKeyPathAndGetSubkeyPath(const std::string& key,
bool allow_create_key,
const std::string& subkey,
base::FilePath* path) {
base::FilePath key_path;
std::string encoded;
if (!VerifyKeyPath(key, allow_create_key, &key_path) ||
!Base64Encode(subkey, &encoded)) {
return false;
}
*path = key_path.AppendASCII(encoded);
return true;
}
}