Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(477)

Unified Diff: content/browser/cache_storage/cache_storage.cc

Issue 1422363004: [CacheStorage] Give cache directories unique names (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2526
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | content/browser/cache_storage/cache_storage.proto » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/cache_storage/cache_storage.cc
diff --git a/content/browser/cache_storage/cache_storage.cc b/content/browser/cache_storage/cache_storage.cc
index 42f0215b8477c7a4afac97353e844b331c97e3f4..e385480624a3944127e91e5f43b47dedb87d86d4 100644
--- a/content/browser/cache_storage/cache_storage.cc
+++ b/content/browser/cache_storage/cache_storage.cc
@@ -9,6 +9,7 @@
#include "base/barrier_closure.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
+#include "base/guid.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_macros.h"
@@ -33,6 +34,13 @@ namespace content {
namespace {
+std::string HexedHash(const std::string& value) {
+ std::string value_hash = base::SHA1HashString(value);
+ std::string valued_hexed_hash = base::ToLowerASCII(
+ base::HexEncode(value_hash.c_str(), value_hash.length()));
+ return valued_hexed_hash;
+}
+
void CloseAllCachesDidCloseCache(const scoped_refptr<CacheStorageCache>& cache,
const base::Closure& barrier_closure) {
barrier_closure.Run();
@@ -42,8 +50,7 @@ void CloseAllCachesDidCloseCache(const scoped_refptr<CacheStorageCache>& cache,
const char CacheStorage::kIndexFileName[] = "index.txt";
-// Handles the loading and clean up of CacheStorageCache objects. The
-// callback of every public method is guaranteed to be called.
+// Handles the loading and clean up of CacheStorageCache objects.
class CacheStorage::CacheLoader {
public:
typedef base::Callback<void(const scoped_refptr<CacheStorageCache>&)>
@@ -74,8 +81,8 @@ class CacheStorage::CacheLoader {
const std::string& cache_name) = 0;
// Deletes any pre-existing cache of the same name and then loads it.
- virtual void CreateCache(const std::string& cache_name,
- const CacheCallback& callback) = 0;
+ virtual void PrepareNewCacheDestination(const std::string& cache_name,
+ const CacheCallback& callback) = 0;
// After the backend has been deleted, do any extra house keeping such as
// removing the cache's directory.
@@ -122,8 +129,8 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
origin_, request_context_getter_, quota_manager_proxy_, blob_context_);
}
- void CreateCache(const std::string& cache_name,
- const CacheCallback& callback) override {
+ void PrepareNewCacheDestination(const std::string& cache_name,
+ const CacheCallback& callback) override {
scoped_refptr<CacheStorageCache> cache = CreateCache(cache_name);
cache_refs_.insert(std::make_pair(cache_name, cache));
callback.Run(cache);
@@ -177,56 +184,61 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
scoped_refptr<CacheStorageCache> CreateCache(
const std::string& cache_name) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(ContainsKey(cache_name_to_cache_dir_, cache_name));
+ std::string cache_dir = cache_name_to_cache_dir_[cache_name];
+ base::FilePath cache_path = origin_path_.AppendASCII(cache_dir);
return CacheStorageCache::CreatePersistentCache(
- origin_, CreatePersistentCachePath(origin_path_, cache_name),
- request_context_getter_, quota_manager_proxy_, blob_context_);
+ origin_, cache_path, request_context_getter_, quota_manager_proxy_,
+ blob_context_);
}
- void CreateCache(const std::string& cache_name,
- const CacheCallback& callback) override {
+ void PrepareNewCacheDestination(const std::string& cache_name,
+ const CacheCallback& callback) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // 1. Delete the cache's directory if it exists.
- // (CreateCacheDeleteFilesInPool)
- // 2. Load the cache. (LoadCreateDirectoryInPool)
-
- base::FilePath cache_path =
- CreatePersistentCachePath(origin_path_, cache_name);
-
PostTaskAndReplyWithResult(
cache_task_runner_.get(), FROM_HERE,
- base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
- base::Bind(&SimpleCacheLoader::CreateCachePreppedDir, cache_name,
- callback, weak_ptr_factory_.GetWeakPtr()));
+ base::Bind(&SimpleCacheLoader::PrepareNewCacheDirectoryInPool,
+ origin_path_),
+ base::Bind(&SimpleCacheLoader::PrepareNewCacheCreateCache,
+ weak_ptr_factory_.GetWeakPtr(), cache_name, callback));
}
- static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
- if (base::PathExists(cache_path))
- base::DeleteFile(cache_path, /* recursive */ true);
- return base::CreateDirectory(cache_path);
+ // Runs on the cache_task_runner_.
+ static std::string PrepareNewCacheDirectoryInPool(
+ const base::FilePath& origin_path) {
+ std::string cache_dir;
+ base::FilePath cache_path;
+ do {
+ cache_dir = base::GenerateGUID();
+ cache_path = origin_path.AppendASCII(cache_dir);
+ } while (base::PathExists(cache_path));
+
+ return base::CreateDirectory(cache_path) ? cache_dir : "";
}
- static void CreateCachePreppedDir(const std::string& cache_name,
- const CacheCallback& callback,
- base::WeakPtr<SimpleCacheLoader> loader,
- bool success) {
- if (!success || !loader) {
+ void PrepareNewCacheCreateCache(const std::string& cache_name,
+ const CacheCallback& callback,
+ const std::string& cache_dir) {
+ if (cache_dir.empty()) {
callback.Run(scoped_refptr<CacheStorageCache>());
return;
}
- callback.Run(loader->CreateCache(cache_name));
+ cache_name_to_cache_dir_[cache_name] = cache_dir;
+ callback.Run(CreateCache(cache_name));
}
void CleanUpDeletedCache(const std::string& cache_name,
const BoolCallback& callback) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
+ DCHECK(ContainsKey(cache_name_to_cache_dir_, cache_name));
base::FilePath cache_path =
- CreatePersistentCachePath(origin_path_, cache_name);
+ origin_path_.AppendASCII(cache_name_to_cache_dir_[cache_name]);
+ cache_name_to_cache_dir_.erase(cache_name);
+
cache_task_runner_->PostTask(
FROM_HERE,
base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool, cache_path,
@@ -252,8 +264,11 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
index.set_origin(origin_.spec());
for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
+ DCHECK(ContainsKey(cache_name_to_cache_dir_, cache_names[i]));
+
CacheStorageIndex::Cache* index_cache = index.add_cache();
index_cache->set_name(cache_names[i]);
+ index_cache->set_cache_dir(cache_name_to_cache_dir_[cache_names[i]]);
}
std::string serialized;
@@ -297,35 +312,26 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
base::FilePath index_path =
origin_path_.AppendASCII(CacheStorage::kIndexFileName);
- cache_task_runner_->PostTask(
- FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
- index_path, base::Passed(names.Pass()), callback,
- base::ThreadTaskRunnerHandle::Get()));
- }
-
- static void LoadIndexReadFileInPool(
- const base::FilePath& index_path,
- scoped_ptr<std::vector<std::string>> names,
- const StringVectorCallback& callback,
- const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
- std::string body;
- base::ReadFileToString(index_path, &body);
-
- original_task_runner->PostTask(
- FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
- base::Passed(names.Pass()), callback, body));
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(), FROM_HERE,
+ base::Bind(&SimpleCacheLoader::ReadAndMigrateIndexInPool, index_path),
+ base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
+ weak_ptr_factory_.GetWeakPtr(), base::Passed(&names),
+ callback));
}
- static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string>> names,
- const StringVectorCallback& callback,
- const std::string& serialized) {
+ void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string>> names,
+ const StringVectorCallback& callback,
+ const std::string& serialized) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
CacheStorageIndex index;
if (index.ParseFromString(serialized)) {
for (int i = 0, max = index.cache_size(); i < max; ++i) {
const CacheStorageIndex::Cache& cache = index.cache(i);
+ DCHECK(cache.has_cache_dir());
names->push_back(cache.name());
+ cache_name_to_cache_dir_[cache.name()] = cache.cache_dir();
}
}
@@ -335,22 +341,72 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
}
private:
+ friend class MigratedLegacyCacheDirectoryNameTest;
~SimpleCacheLoader() override {}
- static std::string HexedHash(const std::string& value) {
- std::string value_hash = base::SHA1HashString(value);
- std::string valued_hexed_hash = base::ToLowerASCII(
- base::HexEncode(value_hash.c_str(), value_hash.length()));
- return valued_hexed_hash;
+ // Runs on cache_task_runner_
+ static std::string MigrateCachesIfNecessaryInPool(
+ const std::string& body,
+ const base::FilePath& index_path) {
+ CacheStorageIndex index;
+ if (!index.ParseFromString(body))
+ return body;
+
+ base::FilePath origin_path = index_path.DirName();
+ bool index_is_dirty = false;
+ const std::string kBadIndexState("");
+
+ // Look for caches that have no cache_dir. Give any such caches a directory
+ // with a random name and move them there. Then, rewrite the index file.
+ for (int i = 0, max = index.cache_size(); i < max; ++i) {
+ const CacheStorageIndex::Cache& cache = index.cache(i);
+ if (!cache.has_cache_dir()) {
+ // Find a new home for the cache.
+ base::FilePath legacy_cache_path =
+ origin_path.AppendASCII(HexedHash(cache.name()));
+ std::string cache_dir;
+ base::FilePath cache_path;
+ do {
+ cache_dir = base::GenerateGUID();
+ cache_path = origin_path.AppendASCII(cache_dir);
+ } while (base::PathExists(cache_path));
+
+ if (!base::Move(legacy_cache_path, cache_path)) {
+ // If the move fails then the cache is in a bad state. Return an empty
+ // index so that the CacheStorage can start fresh. The unreferenced
+ // caches will be discarded later in initialization.
+ return kBadIndexState;
+ }
+
+ index.mutable_cache(i)->set_cache_dir(cache_dir);
+ index_is_dirty = true;
+ }
+ }
+
+ if (index_is_dirty) {
+ std::string new_body;
+ if (!index.SerializeToString(&new_body))
+ return kBadIndexState;
+ if (base::WriteFile(index_path, new_body.c_str(), new_body.size()) !=
+ base::checked_cast<int>(new_body.size()))
+ return kBadIndexState;
+ return new_body;
+ }
+
+ return body;
}
- static base::FilePath CreatePersistentCachePath(
- const base::FilePath& origin_path,
- const std::string& cache_name) {
- return origin_path.AppendASCII(HexedHash(cache_name));
+ // Runs on cache_task_runner_
+ static std::string ReadAndMigrateIndexInPool(
+ const base::FilePath& index_path) {
+ std::string body;
+ base::ReadFileToString(index_path, &body);
+
+ return MigrateCachesIfNecessaryInPool(body, index_path);
}
const base::FilePath origin_path_;
+ std::map<std::string, std::string> cache_name_to_cache_dir_;
base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
};
@@ -569,7 +625,7 @@ void CacheStorage::OpenCacheImpl(const std::string& cache_name,
return;
}
- cache_loader_->CreateCache(
+ cache_loader_->PrepareNewCacheDestination(
cache_name, base::Bind(&CacheStorage::CreateCacheDidCreateCache,
weak_factory_.GetWeakPtr(), cache_name, callback));
}
@@ -612,8 +668,7 @@ void CacheStorage::CreateCacheDidWriteIndex(
void CacheStorage::HasCacheImpl(const std::string& cache_name,
const BoolAndErrorCallback& callback) {
- bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
-
+ bool has_cache = ContainsKey(cache_map_, cache_name);
callback.Run(has_cache, CACHE_STORAGE_OK);
}
« no previous file with comments | « no previous file | content/browser/cache_storage/cache_storage.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698