blob: f209f8925c7984d8a6a09bc29a4b043bf5d4f777 [file] [log] [blame]
// Copyright 2019 The Chromium 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 "components/paint_preview/browser/file_manager.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/hash/hash.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "third_party/zlib/google/zip.h"
namespace paint_preview {
namespace {
constexpr char kZipExt[] = ".zip";
std::string HashToHex(const GURL& url) {
uint32_t hash = base::PersistentHash(url.spec());
return base::HexEncode(&hash, sizeof(uint32_t));
}
} // namespace
FileManager::FileManager(const base::FilePath& root_directory)
: root_directory_(root_directory) {}
FileManager::~FileManager() = default;
size_t FileManager::GetSizeOfArtifactsFor(const GURL& url) {
base::FilePath path;
StorageType storage_type = GetPathForUrl(url, &path);
switch (storage_type) {
case kDirectory: {
return base::ComputeDirectorySize(
root_directory_.AppendASCII(HashToHex(url)));
}
case kZip: {
int64_t file_size = 0;
if (!base::GetFileSize(path, &file_size) || file_size < 0)
return 0;
return file_size;
}
case kNone: // fallthrough
default:
return 0;
}
}
bool FileManager::GetCreatedTime(const GURL& url, base::Time* created_time) {
base::FilePath path;
StorageType storage_type = GetPathForUrl(url, &path);
if (storage_type == FileManager::StorageType::kNone)
return false;
base::File::Info info;
if (!base::GetFileInfo(path, &info))
return false;
*created_time = info.creation_time;
return true;
}
bool FileManager::GetLastModifiedTime(const GURL& url,
base::Time* last_modified_time) {
base::FilePath path;
StorageType storage_type = GetPathForUrl(url, &path);
if (storage_type == FileManager::StorageType::kNone)
return false;
base::File::Info info;
if (!base::GetFileInfo(path, &info))
return false;
*last_modified_time = info.last_modified;
return true;
}
bool FileManager::CreateOrGetDirectoryFor(const GURL& url,
base::FilePath* directory) {
base::FilePath path;
StorageType storage_type = GetPathForUrl(url, &path);
switch (storage_type) {
case kNone: {
base::FilePath new_path = root_directory_.AppendASCII(HashToHex(url));
base::File::Error error = base::File::FILE_OK;
if (base::CreateDirectoryAndGetError(new_path, &error)) {
*directory = new_path;
return true;
}
DVLOG(1) << "ERROR: failed to create directory: " << path
<< " with error code " << error;
return false;
}
case kDirectory: {
*directory = path;
return true;
}
case kZip: {
base::FilePath dst_path = root_directory_.AppendASCII(HashToHex(url));
base::File::Error error = base::File::FILE_OK;
if (!base::CreateDirectoryAndGetError(dst_path, &error)) {
DVLOG(1) << "ERROR: failed to create directory: " << path
<< " with error code " << error;
return false;
}
if (!zip::Unzip(path, dst_path)) {
DVLOG(1) << "ERROR: failed to unzip: " << path << " to " << dst_path;
return false;
}
base::DeleteFile(path, true);
*directory = dst_path;
return true;
}
default:
return false;
}
}
bool FileManager::CompressDirectoryFor(const GURL& url) {
base::FilePath path;
StorageType storage_type = GetPathForUrl(url, &path);
switch (storage_type) {
case kDirectory: {
// If there are no files in the directory, zip will succeed, but unzip
// will not. Thus don't compress since there is no point.
if (!base::ComputeDirectorySize(path))
return false;
base::FilePath dst_path = path.AddExtensionASCII(kZipExt);
if (!zip::Zip(path, dst_path, /* hidden files */ true))
return false;
base::DeleteFile(path, true);
return true;
}
case kZip:
return true;
case kNone: // fallthrough
default:
return false;
}
}
void FileManager::DeleteArtifactsFor(const std::vector<GURL>& urls) {
for (const auto& url : urls) {
base::FilePath path;
StorageType storage_type = GetPathForUrl(url, &path);
if (storage_type == FileManager::StorageType::kNone)
continue;
base::DeleteFile(path, true);
}
}
void FileManager::DeleteAll() {
base::DeleteFileRecursively(root_directory_);
}
FileManager::StorageType FileManager::GetPathForUrl(const GURL& url,
base::FilePath* path) {
base::FilePath directory_path = root_directory_.AppendASCII(HashToHex(url));
if (base::PathExists(directory_path)) {
*path = directory_path;
return kDirectory;
}
base::FilePath zip_path = directory_path.AddExtensionASCII(kZipExt);
if (base::PathExists(zip_path)) {
*path = zip_path;
return kZip;
}
return kNone;
}
} // namespace paint_preview