| Index: content/browser/cache_storage/cache_storage_manager_unittest.cc
|
| diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc
|
| index 2a5541fc2314e4cb342d1d9f369f77c74e44cd56..af0da92c81cfd33a11361822491ad8524f6ac72d 100644
|
| --- a/content/browser/cache_storage/cache_storage_manager_unittest.cc
|
| +++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
|
| @@ -7,9 +7,13 @@
|
| #include "base/files/file_path.h"
|
| #include "base/files/file_util.h"
|
| #include "base/files/scoped_temp_dir.h"
|
| +#include "base/guid.h"
|
| #include "base/run_loop.h"
|
| +#include "base/sha1.h"
|
| #include "base/stl_util.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| #include "base/thread_task_runner_handle.h"
|
| +#include "content/browser/cache_storage/cache_storage.pb.h"
|
| #include "content/browser/cache_storage/cache_storage_quota_client.h"
|
| #include "content/browser/fileapi/chrome_blob_storage_context.h"
|
| #include "content/browser/quota/mock_quota_manager_proxy.h"
|
| @@ -17,17 +21,33 @@
|
| #include "content/public/browser/cache_storage_usage_info.h"
|
| #include "content/public/test/test_browser_context.h"
|
| #include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "net/url_request/url_request_context.h"
|
| #include "net/url_request/url_request_context_getter.h"
|
| +#include "net/url_request/url_request_job_factory_impl.h"
|
| +#include "storage/browser/blob/blob_data_builder.h"
|
| +#include "storage/browser/blob/blob_data_handle.h"
|
| #include "storage/browser/blob/blob_storage_context.h"
|
| +#include "storage/browser/blob/blob_url_request_job_factory.h"
|
| #include "storage/browser/quota/quota_manager_proxy.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| namespace content {
|
|
|
| +// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
|
| +// the memory.
|
| +scoped_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
|
| + storage::BlobStorageContext* blob_storage_context) {
|
| + // The FileSystemContext and thread task runner are not actually used but a
|
| + // task runner is needed to avoid a DCHECK in BlobURLRequestJob ctor.
|
| + return make_scoped_ptr(new storage::BlobProtocolHandler(
|
| + blob_storage_context, NULL, base::ThreadTaskRunnerHandle::Get().get()));
|
| +}
|
| +
|
| class CacheStorageManagerTest : public testing::Test {
|
| public:
|
| CacheStorageManagerTest()
|
| : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
|
| + blob_storage_context_(nullptr),
|
| callback_bool_(false),
|
| callback_error_(CACHE_STORAGE_OK),
|
| origin1_("http://example1.com"),
|
| @@ -39,6 +59,17 @@ class CacheStorageManagerTest : public testing::Test {
|
| // Wait for ChromeBlobStorageContext to finish initializing.
|
| base::RunLoop().RunUntilIdle();
|
|
|
| + blob_storage_context_ = blob_storage_context->context();
|
| +
|
| + url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
|
| + url_request_job_factory_->SetProtocolHandler(
|
| + "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
|
| +
|
| + net::URLRequestContext* url_request_context =
|
| + browser_context_.GetRequestContext()->GetURLRequestContext();
|
| +
|
| + url_request_context->set_job_factory(url_request_job_factory_.get());
|
| +
|
| quota_manager_proxy_ = new MockQuotaManagerProxy(
|
| nullptr, base::ThreadTaskRunnerHandle::Get().get());
|
|
|
| @@ -101,7 +132,7 @@ class CacheStorageManagerTest : public testing::Test {
|
| scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
|
| callback_error_ = error;
|
| callback_cache_response_ = response.Pass();
|
| - // Deliberately drop the data handle as only the url is being tested.
|
| + callback_data_handle_ = blob_data_handle.Pass();
|
| run_loop->Quit();
|
| }
|
|
|
| @@ -186,9 +217,18 @@ class CacheStorageManagerTest : public testing::Test {
|
| bool CachePut(const scoped_refptr<CacheStorageCache>& cache,
|
| const GURL& url) {
|
| ServiceWorkerFetchRequest request;
|
| - ServiceWorkerResponse response;
|
| request.url = url;
|
| - response.url = url;
|
| +
|
| + scoped_ptr<storage::BlobDataBuilder> blob_data(
|
| + new storage::BlobDataBuilder(base::GenerateGUID()));
|
| + blob_data->AppendData(url.spec());
|
| +
|
| + scoped_ptr<storage::BlobDataHandle> blob_handle =
|
| + blob_storage_context_->AddFinishedBlob(blob_data.get());
|
| + ServiceWorkerResponse response(
|
| + url, 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
|
| + ServiceWorkerHeaderMap(), blob_handle->uuid(), url.spec().size(),
|
| + GURL(), blink::WebServiceWorkerResponseErrorUnknown);
|
|
|
| CacheStorageBatchOperation operation;
|
| operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
|
| @@ -256,6 +296,8 @@ class CacheStorageManagerTest : public testing::Test {
|
| protected:
|
| TestBrowserContext browser_context_;
|
| TestBrowserThreadBundle browser_thread_bundle_;
|
| + scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
|
| + storage::BlobStorageContext* blob_storage_context_;
|
|
|
| base::ScopedTempDir temp_dir_;
|
| scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
|
| @@ -265,6 +307,7 @@ class CacheStorageManagerTest : public testing::Test {
|
| int callback_bool_;
|
| CacheStorageError callback_error_;
|
| scoped_ptr<ServiceWorkerResponse> callback_cache_response_;
|
| + scoped_ptr<storage::BlobDataHandle> callback_data_handle_;
|
| std::vector<std::string> callback_strings_;
|
|
|
| const GURL origin1_;
|
| @@ -413,6 +456,21 @@ TEST_P(CacheStorageManagerTestP, StorageMatchAllNoCaches) {
|
| EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
|
| }
|
|
|
| +TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
|
| + // Deleting a cache and creating one with the same name and adding an entry
|
| + // with the same URL should work. (see crbug.com/542668)
|
| + const GURL kTestURL = GURL("http://example.com/foo");
|
| + EXPECT_TRUE(Open(origin1_, "foo"));
|
| + EXPECT_TRUE(CachePut(callback_cache_, kTestURL));
|
| + EXPECT_TRUE(CacheMatch(callback_cache_, kTestURL));
|
| + scoped_ptr<storage::BlobDataHandle> data_handle =
|
| + callback_data_handle_.Pass();
|
| +
|
| + EXPECT_TRUE(Delete(origin1_, "foo"));
|
| + EXPECT_TRUE(Open(origin1_, "foo"));
|
| + EXPECT_TRUE(CachePut(callback_cache_, kTestURL));
|
| +}
|
| +
|
| TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExistsTwice) {
|
| EXPECT_TRUE(Open(origin1_, "foo"));
|
| EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
|
| @@ -685,6 +743,100 @@ TEST_F(CacheStorageMigrationTest, MoveFailure) {
|
| EXPECT_EQ(expected_keys, callback_strings_);
|
| }
|
|
|
| +// Tests that legacy caches created via a hash of the cache name instead of a
|
| +// random name are migrated and continue to function in a new world of random
|
| +// cache names.
|
| +class MigratedLegacyCacheDirectoryNameTest : public CacheStorageManagerTest {
|
| + protected:
|
| + MigratedLegacyCacheDirectoryNameTest()
|
| + : legacy_cache_name_("foo"), stored_url_("http://example.com/foo") {}
|
| +
|
| + void SetUp() override {
|
| + CacheStorageManagerTest::SetUp();
|
| +
|
| + // Create a cache that is stored on disk with the legacy naming scheme (hash
|
| + // of the name) and without a directory name in the index.
|
| + base::FilePath origin_path = CacheStorageManager::ConstructOriginPath(
|
| + cache_manager_->root_path(), origin1_);
|
| +
|
| + // Populate a legacy cache.
|
| + ASSERT_TRUE(Open(origin1_, legacy_cache_name_));
|
| + EXPECT_TRUE(CachePut(callback_cache_, stored_url_));
|
| + base::FilePath new_path = callback_cache_->path();
|
| +
|
| + // Close the cache.
|
| + callback_cache_ = nullptr;
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Legacy index files didn't have the cache directory, so remove it from the
|
| + // index.
|
| + base::FilePath index_path = origin_path.AppendASCII("index.txt");
|
| + std::string index_contents;
|
| + base::ReadFileToString(index_path, &index_contents);
|
| + CacheStorageIndex index;
|
| + ASSERT_TRUE(index.ParseFromString(index_contents));
|
| + ASSERT_EQ(1, index.cache_size());
|
| + index.mutable_cache(0)->release_cache_dir();
|
| + ASSERT_TRUE(index.SerializeToString(&index_contents));
|
| + index.ParseFromString(index_contents);
|
| + ASSERT_EQ(index_contents.size(),
|
| + (uint32_t)base::WriteFile(index_path, index_contents.c_str(),
|
| + index_contents.size()));
|
| +
|
| + // Move the cache to the legacy location.
|
| + legacy_path_ = origin_path.AppendASCII(HexedHash(legacy_cache_name_));
|
| + ASSERT_FALSE(base::DirectoryExists(legacy_path_));
|
| + ASSERT_TRUE(base::Move(new_path, legacy_path_));
|
| +
|
| + // Create a new manager to reread the index file and force migration.
|
| + quota_manager_proxy_->SimulateQuotaManagerDestroyed();
|
| + cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
|
| + }
|
| +
|
| + 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;
|
| + }
|
| +
|
| + base::FilePath legacy_path_;
|
| + const std::string legacy_cache_name_;
|
| + const GURL stored_url_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MigratedLegacyCacheDirectoryNameTest);
|
| +};
|
| +
|
| +TEST_F(MigratedLegacyCacheDirectoryNameTest, LegacyCacheMigrated) {
|
| + EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
|
| +
|
| + // Verify that the cache migrated away from the legacy_path_ directory.
|
| + ASSERT_FALSE(base::DirectoryExists(legacy_path_));
|
| +
|
| + // Verify that the existing entry still works.
|
| + EXPECT_TRUE(CacheMatch(callback_cache_, stored_url_));
|
| +
|
| + // Verify that adding new entries works.
|
| + EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo2")));
|
| + EXPECT_TRUE(CacheMatch(callback_cache_, GURL("http://example.com/foo2")));
|
| +}
|
| +
|
| +TEST_F(MigratedLegacyCacheDirectoryNameTest,
|
| + RandomDirectoryCacheSideBySideWithLegacy) {
|
| + EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
|
| + EXPECT_TRUE(Open(origin1_, "bar"));
|
| + EXPECT_TRUE(CachePut(callback_cache_, stored_url_));
|
| + EXPECT_TRUE(CacheMatch(callback_cache_, stored_url_));
|
| +}
|
| +
|
| +TEST_F(MigratedLegacyCacheDirectoryNameTest, DeleteLegacyCacheAndRecreateNew) {
|
| + EXPECT_TRUE(Delete(origin1_, legacy_cache_name_));
|
| + EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
|
| + EXPECT_FALSE(CacheMatch(callback_cache_, stored_url_));
|
| + EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo2")));
|
| + EXPECT_TRUE(CacheMatch(callback_cache_, GURL("http://example.com/foo2")));
|
| +}
|
| +
|
| class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
|
| protected:
|
| CacheStorageQuotaClientTest() {}
|
|
|