diff options
author | Andras Becsi <andras.becsi@digia.com> | 2013-12-11 21:33:03 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@digia.com> | 2013-12-13 12:34:07 +0100 |
commit | f2a33ff9cbc6d19943f1c7fbddd1f23d23975577 (patch) | |
tree | 0586a32aa390ade8557dfd6b4897f43a07449578 /chromium/webkit/browser | |
parent | 5362912cdb5eea702b68ebe23702468d17c3017a (diff) | |
download | qtwebengine-chromium-f2a33ff9cbc6d19943f1c7fbddd1f23d23975577.tar.gz |
Update Chromium to branch 1650 (31.0.1650.63)
Change-Id: I57d8c832eaec1eb2364e0a8e7352a6dd354db99f
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'chromium/webkit/browser')
120 files changed, 3777 insertions, 2593 deletions
diff --git a/chromium/webkit/browser/appcache/appcache_database.cc b/chromium/webkit/browser/appcache/appcache_database.cc index de7308425d0..68738d1dbee 100644 --- a/chromium/webkit/browser/appcache/appcache_database.cc +++ b/chromium/webkit/browser/appcache/appcache_database.cc @@ -21,8 +21,13 @@ namespace appcache { // Schema ------------------------------------------------------------------- namespace { +#if defined(APPCACHE_USE_SIMPLE_CACHE) +const int kCurrentVersion = 6; +const int kCompatibleVersion = 6; +#else const int kCurrentVersion = 5; const int kCompatibleVersion = 5; +#endif // A mechanism to run experiments that may affect in data being persisted // in different ways such that when the experiment is toggled on/off via @@ -1094,6 +1099,9 @@ bool AppCacheDatabase::CreateSchema() { } bool AppCacheDatabase::UpgradeSchema() { +#if defined(APPCACHE_USE_SIMPLE_CACHE) + return DeleteExistingAndCreateNewDatabase(); +#else if (meta_table_->GetVersionNumber() == 3) { // version 3 was pre 12/17/2011 DCHECK_EQ(strcmp(kNamespacesTable, kTables[3].table_name), 0); @@ -1170,6 +1178,7 @@ bool AppCacheDatabase::UpgradeSchema() { // If there is no upgrade path for the version on disk to the current // version, nuke everything and start over. return DeleteExistingAndCreateNewDatabase(); +#endif } void AppCacheDatabase::ResetConnectionAndTables() { diff --git a/chromium/webkit/browser/appcache/appcache_database_unittest.cc b/chromium/webkit/browser/appcache/appcache_database_unittest.cc index e67a68dafdb..9dc90808fec 100644 --- a/chromium/webkit/browser/appcache/appcache_database_unittest.cc +++ b/chromium/webkit/browser/appcache/appcache_database_unittest.cc @@ -668,6 +668,9 @@ TEST(AppCacheDatabaseTest, OriginUsage) { EXPECT_EQ(5000, usage_map[kOtherOrigin]); } +#if defined(APPCACHE_USE_SIMPLE_CACHE) +// There is no such upgrade path in this case. +#else TEST(AppCacheDatabaseTest, UpgradeSchema3to5) { // Real file on disk for this test. base::ScopedTempDir temp_dir; @@ -886,7 +889,11 @@ TEST(AppCacheDatabaseTest, UpgradeSchema3to5) { EXPECT_FALSE(fallbacks[i].namespace_.is_pattern); } } +#endif // !APPCACHE_USE_SIMPLE_CACHE +#if defined(APPCACHE_USE_SIMPLE_CACHE) +// There is no such upgrade path in this case. +#else TEST(AppCacheDatabaseTest, UpgradeSchema4to5) { // Real file on disk for this test. base::ScopedTempDir temp_dir; @@ -1124,5 +1131,6 @@ TEST(AppCacheDatabaseTest, UpgradeSchema4to5) { EXPECT_FALSE(whitelists[i].is_pattern); } } +#endif // !APPCACHE_USE_SIMPLE_CACHE } // namespace appcache diff --git a/chromium/webkit/browser/appcache/appcache_disk_cache.cc b/chromium/webkit/browser/appcache/appcache_disk_cache.cc index e486f1d7d6f..4aa3e8ef182 100644 --- a/chromium/webkit/browser/appcache/appcache_disk_cache.cc +++ b/chromium/webkit/browser/appcache/appcache_disk_cache.cc @@ -270,8 +270,13 @@ int AppCacheDiskCache::Init(net::CacheType cache_type, is_disabled_ = false; create_backend_callback_ = new CreateBackendCallbackShim(this); +#if defined(APPCACHE_USE_SIMPLE_CACHE) + const net::BackendType backend_type = net::CACHE_BACKEND_SIMPLE; +#else + const net::BackendType backend_type = net::CACHE_BACKEND_DEFAULT; +#endif int rv = disk_cache::CreateCacheBackend( - cache_type, net::CACHE_BACKEND_DEFAULT, cache_directory, cache_size, + cache_type, backend_type, cache_directory, cache_size, force, cache_thread, NULL, &(create_backend_callback_->backend_ptr_), base::Bind(&CreateBackendCallbackShim::Callback, create_backend_callback_)); diff --git a/chromium/webkit/browser/appcache/appcache_quota_client.cc b/chromium/webkit/browser/appcache/appcache_quota_client.cc index 7f2d647021c..fc8db6d5815 100644 --- a/chromium/webkit/browser/appcache/appcache_quota_client.cc +++ b/chromium/webkit/browser/appcache/appcache_quota_client.cc @@ -139,6 +139,10 @@ void AppCacheQuotaClient::DeleteOriginData(const GURL& origin, origin, GetServiceDeleteCallback()->callback()); } +bool AppCacheQuotaClient::DoesSupport(quota::StorageType type) const { + return type == quota::kStorageTypeTemporary; +} + void AppCacheQuotaClient::DidDeleteAppCachesForOrigin(int rv) { DCHECK(service_); if (quota_manager_is_destroyed_) diff --git a/chromium/webkit/browser/appcache/appcache_quota_client.h b/chromium/webkit/browser/appcache/appcache_quota_client.h index d2efb12ee67..c4901831e38 100644 --- a/chromium/webkit/browser/appcache/appcache_quota_client.h +++ b/chromium/webkit/browser/appcache/appcache_quota_client.h @@ -50,6 +50,7 @@ class AppCacheQuotaClient : public quota::QuotaClient { virtual void DeleteOriginData(const GURL& origin, quota::StorageType type, const DeletionCallback& callback) OVERRIDE; + virtual bool DoesSupport(quota::StorageType type) const OVERRIDE; private: friend class AppCacheService; // for NotifyAppCacheIsDestroyed diff --git a/chromium/webkit/browser/appcache/appcache_quota_client_unittest.cc b/chromium/webkit/browser/appcache/appcache_quota_client_unittest.cc index 9c7476a1697..5b7adeda009 100644 --- a/chromium/webkit/browser/appcache/appcache_quota_client_unittest.cc +++ b/chromium/webkit/browser/appcache/appcache_quota_client_unittest.cc @@ -6,8 +6,8 @@ #include <set> #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/appcache/appcache_quota_client.h" @@ -44,7 +44,7 @@ class AppCacheQuotaClientTest : public testing::Test { quota::StorageType type) { usage_ = -1; AsyncGetOriginUsage(client, origin, type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return usage_; } @@ -53,7 +53,7 @@ class AppCacheQuotaClientTest : public testing::Test { quota::StorageType type) { origins_.clear(); AsyncGetOriginsForType(client, type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return origins_; } @@ -63,7 +63,7 @@ class AppCacheQuotaClientTest : public testing::Test { const std::string& host) { origins_.clear(); AsyncGetOriginsForHost(client, type, host); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return origins_; } @@ -73,7 +73,7 @@ class AppCacheQuotaClientTest : public testing::Test { const GURL& origin) { delete_status_ = quota::kQuotaStatusUnknown; AsyncDeleteOriginData(client, type, origin); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return delete_status_; } @@ -315,7 +315,7 @@ TEST_F(AppCacheQuotaClientTest, PendingRequests) { EXPECT_EQ(0, num_get_origin_usage_completions_); EXPECT_EQ(0, num_get_origins_completions_); EXPECT_EQ(0, num_delete_origins_completions_); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, num_get_origin_usage_completions_); EXPECT_EQ(0, num_get_origins_completions_); EXPECT_EQ(0, num_delete_origins_completions_); @@ -325,7 +325,7 @@ TEST_F(AppCacheQuotaClientTest, PendingRequests) { EXPECT_EQ(2, num_get_origin_usage_completions_); EXPECT_EQ(4, num_get_origins_completions_); EXPECT_EQ(0, num_delete_origins_completions_); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(3, num_delete_origins_completions_); // deletes are really async // They should be serviced in order requested. @@ -354,7 +354,7 @@ TEST_F(AppCacheQuotaClientTest, DestroyServiceWithPending) { AsyncDeleteOriginData(client, kTemp, kOriginA); AsyncDeleteOriginData(client, kPerm, kOriginA); AsyncDeleteOriginData(client, kTemp, kOriginB); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, num_get_origin_usage_completions_); EXPECT_EQ(0, num_get_origins_completions_); EXPECT_EQ(0, num_delete_origins_completions_); @@ -390,7 +390,7 @@ TEST_F(AppCacheQuotaClientTest, DestroyQuotaManagerWithPending) { AsyncDeleteOriginData(client, kTemp, kOriginA); AsyncDeleteOriginData(client, kPerm, kOriginA); AsyncDeleteOriginData(client, kTemp, kOriginB); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, num_get_origin_usage_completions_); EXPECT_EQ(0, num_get_origins_completions_); EXPECT_EQ(0, num_delete_origins_completions_); @@ -400,7 +400,7 @@ TEST_F(AppCacheQuotaClientTest, DestroyQuotaManagerWithPending) { Call_NotifyAppCacheReady(client); // Callbacks should be deleted and not called. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, num_get_origin_usage_completions_); EXPECT_EQ(0, num_get_origins_completions_); EXPECT_EQ(0, num_delete_origins_completions_); @@ -425,7 +425,7 @@ TEST_F(AppCacheQuotaClientTest, DestroyWithDeleteInProgress) { // A real completion callback from the service should // be dropped if it comes in after NotifyAppCacheDestroyed. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, num_delete_origins_completions_); EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_); diff --git a/chromium/webkit/browser/appcache/appcache_service_unittest.cc b/chromium/webkit/browser/appcache/appcache_service_unittest.cc index 41b6bc2c583..75817930630 100644 --- a/chromium/webkit/browser/appcache/appcache_service_unittest.cc +++ b/chromium/webkit/browser/appcache/appcache_service_unittest.cc @@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/message_loop/message_loop.h" #include "base/pickle.h" +#include "base/run_loop.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/http/http_response_headers.h" @@ -184,7 +184,7 @@ TEST_F(AppCacheServiceTest, DeleteAppCachesForOrigin) { // Without giving mock storage simiulated info, should fail. service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); EXPECT_EQ(0, delete_completion_count_); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, delete_completion_count_); EXPECT_EQ(net::ERR_FAILED, delete_result_); delete_completion_count_ = 0; @@ -193,7 +193,7 @@ TEST_F(AppCacheServiceTest, DeleteAppCachesForOrigin) { mock_storage()->SimulateGetAllInfo(new AppCacheInfoCollection); service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); EXPECT_EQ(0, delete_completion_count_); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, delete_completion_count_); EXPECT_EQ(net::OK, delete_result_); delete_completion_count_ = 0; @@ -215,7 +215,7 @@ TEST_F(AppCacheServiceTest, DeleteAppCachesForOrigin) { mock_storage()->SimulateGetAllInfo(info.get()); service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); EXPECT_EQ(0, delete_completion_count_); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, delete_completion_count_); EXPECT_EQ(net::OK, delete_result_); delete_completion_count_ = 0; @@ -226,7 +226,7 @@ TEST_F(AppCacheServiceTest, DeleteAppCachesForOrigin) { mock_storage()->SimulateMakeGroupObsoleteFailure(); service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); EXPECT_EQ(0, delete_completion_count_); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, delete_completion_count_); EXPECT_EQ(net::ERR_FAILED, delete_result_); delete_completion_count_ = 0; @@ -242,7 +242,7 @@ TEST_F(AppCacheServiceTest, DeleteAppCachesForOrigin) { // Let any tasks lingering from the sudden deletion run and verify // no other completion calls occur. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, delete_completion_count_); } @@ -250,7 +250,7 @@ TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { // Check a non-existing manifest. EXPECT_FALSE(IsGroupStored(kManifestUrl)); service_->CheckAppCacheResponse(kManifestUrl, 1, 1); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, CountPendingHelpers()); EXPECT_FALSE(IsGroupStored(kManifestUrl)); ResetStorage(); @@ -261,7 +261,7 @@ TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { EXPECT_TRUE(IsGroupStored(kManifestUrl)); SetupMockReader(true, true, true); service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, CountPendingHelpers()); EXPECT_TRUE(IsGroupStored(kManifestUrl)); ResetStorage(); @@ -271,7 +271,7 @@ TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { SetupMockGroup(); service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMissingResponseId); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, CountPendingHelpers()); EXPECT_FALSE(IsGroupStored(kManifestUrl)); ResetStorage(); @@ -281,7 +281,7 @@ TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { SetupMockGroup(); service_->CheckAppCacheResponse(kManifestUrl, kMissingCacheId, kMissingResponseId); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, CountPendingHelpers()); EXPECT_TRUE(IsGroupStored(kManifestUrl)); ResetStorage(); @@ -290,7 +290,7 @@ TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { SetupMockGroup(); service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); SetupMockReader(false, true, true); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, CountPendingHelpers()); EXPECT_FALSE(IsGroupStored(kManifestUrl)); ResetStorage(); @@ -299,7 +299,7 @@ TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { SetupMockGroup(); service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); SetupMockReader(true, false, true); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, CountPendingHelpers()); EXPECT_FALSE(IsGroupStored(kManifestUrl)); ResetStorage(); @@ -308,13 +308,13 @@ TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { SetupMockGroup(); service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); SetupMockReader(true, true, false); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, CountPendingHelpers()); EXPECT_FALSE(IsGroupStored(kManifestUrl)); ResetStorage(); service_.reset(); // Clean up. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } } // namespace appcache diff --git a/chromium/webkit/browser/appcache/mock_appcache_storage_unittest.cc b/chromium/webkit/browser/appcache/mock_appcache_storage_unittest.cc index 0ed9cd556bc..0e187bd2b3c 100644 --- a/chromium/webkit/browser/appcache/mock_appcache_storage_unittest.cc +++ b/chromium/webkit/browser/appcache/mock_appcache_storage_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/appcache/appcache.h" #include "webkit/browser/appcache/appcache_group.h" @@ -87,7 +87,7 @@ TEST_F(MockAppCacheStorageTest, LoadCache_Miss) { MockStorageDelegate delegate; service.storage()->LoadCache(111, &delegate); EXPECT_NE(111, delegate.loaded_cache_id_); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(111, delegate.loaded_cache_id_); EXPECT_FALSE(delegate.loaded_cache_.get()); } @@ -121,7 +121,7 @@ TEST_F(MockAppCacheStorageTest, CreateGroup) { service.storage()->LoadOrCreateGroup(manifest_url, &delegate); EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); EXPECT_FALSE(delegate.loaded_group_.get()); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); EXPECT_TRUE(delegate.loaded_group_.get()); EXPECT_TRUE(delegate.loaded_group_->HasOneRef()); @@ -140,7 +140,7 @@ TEST_F(MockAppCacheStorageTest, LoadGroup_NearHit) { // to be "unstored" and "currently in use". GURL manifest_url("http://blah/"); service.storage()->LoadOrCreateGroup(manifest_url, &delegate); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); EXPECT_TRUE(delegate.loaded_group_.get()); @@ -192,7 +192,7 @@ TEST_F(MockAppCacheStorageTest, LoadGroupAndCache_FarHit) { storage->LoadCache(cache_id, &delegate); EXPECT_NE(cache_id, delegate.loaded_cache_id_); EXPECT_NE(cache_ptr, delegate.loaded_cache_.get()); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(cache_id, delegate.loaded_cache_id_); EXPECT_EQ(cache_ptr, delegate.loaded_cache_.get()); delegate.loaded_cache_ = NULL; @@ -203,7 +203,7 @@ TEST_F(MockAppCacheStorageTest, LoadGroupAndCache_FarHit) { storage->LoadOrCreateGroup(manifest_url, &delegate); EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); EXPECT_FALSE(delegate.loaded_group_.get()); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); EXPECT_EQ(group_ptr, delegate.loaded_group_.get()); } @@ -232,7 +232,7 @@ TEST_F(MockAppCacheStorageTest, StoreNewGroup) { EXPECT_FALSE(delegate.stored_group_success_); EXPECT_TRUE(storage->stored_caches_.empty()); EXPECT_TRUE(storage->stored_groups_.empty()); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_TRUE(delegate.stored_group_success_); EXPECT_FALSE(storage->stored_caches_.empty()); EXPECT_FALSE(storage->stored_groups_.empty()); @@ -275,7 +275,7 @@ TEST_F(MockAppCacheStorageTest, StoreExistingGroup) { EXPECT_EQ(size_t(1), storage->stored_groups_.size()); EXPECT_TRUE(storage->IsCacheStored(old_cache.get())); EXPECT_FALSE(storage->IsCacheStored(new_cache.get())); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_TRUE(delegate.stored_group_success_); EXPECT_EQ(size_t(1), storage->stored_caches_.size()); EXPECT_EQ(size_t(1), storage->stored_groups_.size()); @@ -318,7 +318,7 @@ TEST_F(MockAppCacheStorageTest, StoreExistingGroupExistingCache) { EXPECT_FALSE(delegate.stored_group_success_); EXPECT_EQ(size_t(1), storage->stored_caches_.size()); EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_TRUE(delegate.stored_group_success_); EXPECT_EQ(size_t(1), storage->stored_caches_.size()); EXPECT_EQ(size_t(1), storage->stored_groups_.size()); @@ -359,7 +359,7 @@ TEST_F(MockAppCacheStorageTest, MakeGroupObsolete) { EXPECT_EQ(size_t(1), storage->stored_groups_.size()); EXPECT_FALSE(cache->HasOneRef()); EXPECT_FALSE(group->HasOneRef()); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_TRUE(delegate.obsoleted_success_); EXPECT_EQ(group.get(), delegate.obsoleted_group_.get()); EXPECT_TRUE(group->is_obsolete()); @@ -404,7 +404,7 @@ TEST_F(MockAppCacheStorageTest, FindNoMainResponse) { EXPECT_NE(url, delegate.found_url_); storage->FindResponseForMainRequest(url, GURL(), &delegate); EXPECT_NE(url, delegate.found_url_); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(url, delegate.found_url_); EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); @@ -441,7 +441,7 @@ TEST_F(MockAppCacheStorageTest, BasicFindMainResponse) { EXPECT_NE(kEntryUrl, delegate.found_url_); storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); EXPECT_NE(kEntryUrl, delegate.found_url_); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(kEntryUrl, delegate.found_url_); EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_); EXPECT_EQ(kCacheId, delegate.found_cache_id_); @@ -498,7 +498,7 @@ TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) { EXPECT_NE(kTestUrl, delegate.found_url_); storage->FindResponseForMainRequest(kTestUrl, GURL(), &delegate); EXPECT_NE(kTestUrl, delegate.found_url_); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(kTestUrl, delegate.found_url_); EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_); EXPECT_EQ(kCacheId, delegate.found_cache_id_); @@ -555,7 +555,7 @@ TEST_F(MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates) { EXPECT_NE(kEntryUrl, delegate.found_url_); storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); EXPECT_NE(kEntryUrl, delegate.found_url_); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(kEntryUrl, delegate.found_url_); EXPECT_EQ(kManifestUrl2, delegate.found_manifest_url_); EXPECT_EQ(kCacheId2, delegate.found_cache_id_); @@ -602,7 +602,7 @@ TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) { EXPECT_NE(kEntryUrl, delegate.found_url_); storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); EXPECT_NE(kEntryUrl, delegate.found_url_); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(kEntryUrl, delegate.found_url_); EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); @@ -616,7 +616,7 @@ TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) { EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_); storage->FindResponseForMainRequest(kOnlineNamespaceUrl, GURL(), &delegate); EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_); - base::MessageLoop::current()->RunUntilIdle(); // Do async task execution. + base::RunLoop().RunUntilIdle(); // Do async task execution. EXPECT_EQ(kOnlineNamespaceUrl, delegate.found_url_); EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); diff --git a/chromium/webkit/browser/blob/blob_data_handle.h b/chromium/webkit/browser/blob/blob_data_handle.h index 25eeefe259f..5f870f2731a 100644 --- a/chromium/webkit/browser/blob/blob_data_handle.h +++ b/chromium/webkit/browser/blob/blob_data_handle.h @@ -43,6 +43,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobDataHandle BlobData* blob_data_; // Intentionally a raw ptr to a non-thread-safe ref. base::WeakPtr<BlobStorageContext> context_; scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(BlobDataHandle); }; } // namespace webkit_blob diff --git a/chromium/webkit/browser/blob/blob_storage_context.cc b/chromium/webkit/browser/blob/blob_storage_context.cc index 4a0260736a0..34a1bee59df 100644 --- a/chromium/webkit/browser/blob/blob_storage_context.cc +++ b/chromium/webkit/browser/blob/blob_storage_context.cc @@ -94,6 +94,14 @@ scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob( return handle.Pass(); } +std::string BlobStorageContext::LookupUuidFromDeprecatedURL( + const GURL& url) { + BlobURLMap::const_iterator found = deprecated_blob_urls_.find(url); + if (found == deprecated_blob_urls_.end()) + return std::string(); + return found->second; +} + void BlobStorageContext::StartBuildingBlob(const std::string& uuid) { DCHECK(!IsInUse(uuid) && !uuid.empty()); blob_map_[uuid] = BlobMapEntry(1, BEING_BUILT, new BlobData(uuid)); @@ -146,7 +154,10 @@ void BlobStorageContext::AppendBlobDataItem( item.expected_modification_time()); break; case BlobData::Item::TYPE_BLOB: { - scoped_ptr<BlobDataHandle> src = GetBlobDataFromUUID(item.blob_uuid()); + scoped_ptr<BlobDataHandle> src = GetBlobDataFromUUID( + item.blob_uuid().empty() + ? LookupUuidFromDeprecatedURL(item.blob_url()) + : item.blob_uuid()); if (src) exceeded_memory = !ExpandStorageItems(target_blob_data, src->data(), @@ -222,6 +233,21 @@ void BlobStorageContext::RevokePublicBlobURL(const GURL& blob_url) { public_blob_urls_.erase(blob_url); } +void BlobStorageContext::DeprecatedRegisterPrivateBlobURL( + const GURL& url, const std::string& uuid) { + if (!IsInUse(uuid)) + return; + IncrementBlobRefCount(uuid); + deprecated_blob_urls_[url] = uuid; +} + +void BlobStorageContext::DeprecatedRevokePrivateBlobURL(const GURL& url) { + if (deprecated_blob_urls_.find(url) == deprecated_blob_urls_.end()) + return; + DecrementBlobRefCount(deprecated_blob_urls_[url]); + deprecated_blob_urls_.erase(url); +} + bool BlobStorageContext::ExpandStorageItems( BlobData* target_blob_data, BlobData* src_blob_data, uint64 offset, uint64 length) { diff --git a/chromium/webkit/browser/blob/blob_storage_context.h b/chromium/webkit/browser/blob/blob_storage_context.h index c9747aea3ed..eec1fee8c23 100644 --- a/chromium/webkit/browser/blob/blob_storage_context.h +++ b/chromium/webkit/browser/blob/blob_storage_context.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/webkit_storage_browser_export.h" #include "webkit/common/blob/blob_data.h" @@ -42,9 +43,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext // blob cannot be added due to memory consumption, returns NULL. scoped_ptr<BlobDataHandle> AddFinishedBlob(const BlobData* blob_data); + // Temporary support for mapping oldstyle blobUrls to new style uuids. + std::string LookupUuidFromDeprecatedURL(const GURL& url); + private: friend class BlobDataHandle; friend class BlobStorageHost; + friend class ViewBlobInternalsJob; enum EntryFlags { BEING_BUILT = 1 << 0, @@ -75,6 +80,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext void RegisterPublicBlobURL(const GURL& url, const std::string& uuid); void RevokePublicBlobURL(const GURL& url); + // Temporary support for mapping old style blobUrls to new style uuids. + void DeprecatedRegisterPrivateBlobURL(const GURL& url, + const std::string& uuid); + void DeprecatedRevokePrivateBlobURL(const GURL& url); + bool ExpandStorageItems(BlobData* target_blob_data, BlobData* src_blob_data, uint64 offset, @@ -96,6 +106,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext BlobMap blob_map_; BlobURLMap public_blob_urls_; + BlobURLMap deprecated_blob_urls_; // Used to keep track of how much memory is being utitlized for blob data, // we count only the items of TYPE_DATA which are held in memory and not diff --git a/chromium/webkit/browser/blob/blob_storage_context_unittest.cc b/chromium/webkit/browser/blob/blob_storage_context_unittest.cc index 5ce15455ed7..e2c115c21a1 100644 --- a/chromium/webkit/browser/blob/blob_storage_context_unittest.cc +++ b/chromium/webkit/browser/blob/blob_storage_context_unittest.cc @@ -203,4 +203,6 @@ TEST(BlobStorageContextTest, EarlyContextDeletion) { EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); } +// TODO(michaeln): tests for the depcrecated url stuff + } // namespace webkit_blob diff --git a/chromium/webkit/browser/blob/blob_storage_controller.cc b/chromium/webkit/browser/blob/blob_storage_controller.cc deleted file mode 100644 index f5dd60ec99e..00000000000 --- a/chromium/webkit/browser/blob/blob_storage_controller.cc +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2012 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 "webkit/browser/blob/blob_storage_controller.h" - -#include "base/logging.h" -#include "url/gurl.h" -#include "webkit/common/blob/blob_data.h" - -namespace webkit_blob { - -namespace { - -// We can't use GURL directly for these hash fragment manipulations -// since it doesn't have specific knowlege of the BlobURL format. GURL -// treats BlobURLs as if they were PathURLs which don't support hash -// fragments. - -bool BlobUrlHasRef(const GURL& url) { - return url.spec().find('#') != std::string::npos; -} - -GURL ClearBlobUrlRef(const GURL& url) { - size_t hash_pos = url.spec().find('#'); - if (hash_pos == std::string::npos) - return url; - return GURL(url.spec().substr(0, hash_pos)); -} - -static const int64 kMaxMemoryUsage = 1024 * 1024 * 1024; // 1G - -} // namespace - -BlobStorageController::BlobStorageController() - : memory_usage_(0) { -} - -BlobStorageController::~BlobStorageController() { -} - -void BlobStorageController::StartBuildingBlob(const GURL& url) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - BlobData* blob_data = new BlobData; - unfinalized_blob_map_[url.spec()] = blob_data; - IncrementBlobDataUsage(blob_data); -} - -void BlobStorageController::AppendBlobDataItem( - const GURL& url, const BlobData::Item& item) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - BlobMap::iterator found = unfinalized_blob_map_.find(url.spec()); - if (found == unfinalized_blob_map_.end()) - return; - BlobData* target_blob_data = found->second.get(); - DCHECK(target_blob_data); - - memory_usage_ -= target_blob_data->GetMemoryUsage(); - - // The blob data is stored in the "canonical" way. That is, it only contains a - // list of Data and File items. - // 1) The Data item is denoted by the raw data and the range. - // 2) The File item is denoted by the file path, the range and the expected - // modification time. - // 3) The FileSystem File item is denoted by the FileSystem URL, the range - // and the expected modification time. - // All the Blob items in the passing blob data are resolved and expanded into - // a set of Data and File items. - - DCHECK(item.length() > 0); - switch (item.type()) { - case BlobData::Item::TYPE_BYTES: - DCHECK(!item.offset()); - target_blob_data->AppendData(item.bytes(), item.length()); - break; - case BlobData::Item::TYPE_FILE: - AppendFileItem(target_blob_data, - item.path(), - item.offset(), - item.length(), - item.expected_modification_time()); - break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: - AppendFileSystemFileItem(target_blob_data, - item.url(), - item.offset(), - item.length(), - item.expected_modification_time()); - break; - case BlobData::Item::TYPE_BLOB: { - BlobData* src_blob_data = GetBlobDataFromUrl(item.url()); - DCHECK(src_blob_data); - if (src_blob_data) - AppendStorageItems(target_blob_data, - src_blob_data, - item.offset(), - item.length()); - break; - } - default: - NOTREACHED(); - break; - } - - memory_usage_ += target_blob_data->GetMemoryUsage(); - - // If we're using too much memory, drop this blob. - // TODO(michaeln): Blob memory storage does not yet spill over to disk, - // until it does, we'll prevent memory usage over a max amount. - if (memory_usage_ > kMaxMemoryUsage) - RemoveBlob(url); -} - -void BlobStorageController::FinishBuildingBlob( - const GURL& url, const std::string& content_type) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - BlobMap::iterator found = unfinalized_blob_map_.find(url.spec()); - if (found == unfinalized_blob_map_.end()) - return; - found->second->set_content_type(content_type); - blob_map_[url.spec()] = found->second; - unfinalized_blob_map_.erase(found); -} - -void BlobStorageController::AddFinishedBlob(const GURL& url, - const BlobData* data) { - StartBuildingBlob(url); - for (std::vector<BlobData::Item>::const_iterator iter = - data->items().begin(); - iter != data->items().end(); ++iter) { - AppendBlobDataItem(url, *iter); - } - FinishBuildingBlob(url, data->content_type()); -} - -void BlobStorageController::CloneBlob( - const GURL& url, const GURL& src_url) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - - BlobData* blob_data = GetBlobDataFromUrl(src_url); - DCHECK(blob_data); - if (!blob_data) - return; - - blob_map_[url.spec()] = blob_data; - IncrementBlobDataUsage(blob_data); -} - -void BlobStorageController::RemoveBlob(const GURL& url) { - DCHECK(url.SchemeIs("blob")); - DCHECK(!BlobUrlHasRef(url)); - - if (!RemoveFromMapHelper(&unfinalized_blob_map_, url)) - RemoveFromMapHelper(&blob_map_, url); -} - -bool BlobStorageController::RemoveFromMapHelper( - BlobMap* map, const GURL& url) { - BlobMap::iterator found = map->find(url.spec()); - if (found == map->end()) - return false; - if (DecrementBlobDataUsage(found->second.get())) - memory_usage_ -= found->second->GetMemoryUsage(); - map->erase(found); - return true; -} - - -BlobData* BlobStorageController::GetBlobDataFromUrl(const GURL& url) { - BlobMap::iterator found = blob_map_.find( - BlobUrlHasRef(url) ? ClearBlobUrlRef(url).spec() : url.spec()); - return (found != blob_map_.end()) ? found->second.get() : NULL; -} - -void BlobStorageController::AppendStorageItems( - BlobData* target_blob_data, BlobData* src_blob_data, - uint64 offset, uint64 length) { - DCHECK(target_blob_data && src_blob_data && - length != static_cast<uint64>(-1)); - - std::vector<BlobData::Item>::const_iterator iter = - src_blob_data->items().begin(); - if (offset) { - for (; iter != src_blob_data->items().end(); ++iter) { - if (offset >= iter->length()) - offset -= iter->length(); - else - break; - } - } - - for (; iter != src_blob_data->items().end() && length > 0; ++iter) { - uint64 current_length = iter->length() - offset; - uint64 new_length = current_length > length ? length : current_length; - if (iter->type() == BlobData::Item::TYPE_BYTES) { - target_blob_data->AppendData( - iter->bytes() + static_cast<size_t>(iter->offset() + offset), - static_cast<uint32>(new_length)); - } else if (iter->type() == BlobData::Item::TYPE_FILE) { - AppendFileItem(target_blob_data, - iter->path(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); - } else { - DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM); - AppendFileSystemFileItem(target_blob_data, - iter->url(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); - } - length -= new_length; - offset = 0; - } -} - -void BlobStorageController::AppendFileItem( - BlobData* target_blob_data, - const base::FilePath& file_path, uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - target_blob_data->AppendFile(file_path, offset, length, - expected_modification_time); - - // It may be a temporary file that should be deleted when no longer needed. - scoped_refptr<ShareableFileReference> shareable_file = - ShareableFileReference::Get(file_path); - if (shareable_file.get()) - target_blob_data->AttachShareableFileReference(shareable_file.get()); -} - -void BlobStorageController::AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& url, uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - target_blob_data->AppendFileSystemFile(url, offset, length, - expected_modification_time); -} - -void BlobStorageController::IncrementBlobDataUsage(BlobData* blob_data) { - blob_data_usage_count_[blob_data] += 1; -} - -bool BlobStorageController::DecrementBlobDataUsage(BlobData* blob_data) { - BlobDataUsageMap::iterator found = blob_data_usage_count_.find(blob_data); - DCHECK(found != blob_data_usage_count_.end()); - if (--(found->second)) - return false; // Still in use - blob_data_usage_count_.erase(found); - return true; -} - -} // namespace webkit_blob diff --git a/chromium/webkit/browser/blob/blob_storage_controller.h b/chromium/webkit/browser/blob/blob_storage_controller.h deleted file mode 100644 index 03dfb08045b..00000000000 --- a/chromium/webkit/browser/blob/blob_storage_controller.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef WEBKIT_BROWSER_BLOB_BLOB_STORAGE_CONTROLLER_H_ -#define WEBKIT_BROWSER_BLOB_BLOB_STORAGE_CONTROLLER_H_ - -#include <map> -#include <string> - -#include "base/containers/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "base/process/process.h" -#include "webkit/browser/webkit_storage_browser_export.h" -#include "webkit/common/blob/blob_data.h" - -class GURL; - -namespace base { -class FilePath; -class Time; -} - -namespace webkit_blob { - -// This class handles the logistics of blob Storage within the browser process. -class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageController { - public: - BlobStorageController(); - ~BlobStorageController(); - - void StartBuildingBlob(const GURL& url); - void AppendBlobDataItem(const GURL& url, const BlobData::Item& data_item); - void FinishBuildingBlob(const GURL& url, const std::string& content_type); - void AddFinishedBlob(const GURL& url, const BlobData* blob_data); - void CloneBlob(const GURL& url, const GURL& src_url); - void RemoveBlob(const GURL& url); - BlobData* GetBlobDataFromUrl(const GURL& url); - - private: - friend class ViewBlobInternalsJob; - - typedef base::hash_map<std::string, scoped_refptr<BlobData> > BlobMap; - typedef std::map<BlobData*, int> BlobDataUsageMap; - - void AppendStorageItems(BlobData* target_blob_data, - BlobData* src_blob_data, - uint64 offset, - uint64 length); - void AppendFileItem(BlobData* target_blob_data, - const base::FilePath& file_path, uint64 offset, - uint64 length, - const base::Time& expected_modification_time); - void AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& url, uint64 offset, uint64 length, - const base::Time& expected_modification_time); - - bool RemoveFromMapHelper(BlobMap* map, const GURL& url); - - void IncrementBlobDataUsage(BlobData* blob_data); - // Returns true if no longer in use. - bool DecrementBlobDataUsage(BlobData* blob_data); - - BlobMap blob_map_; - BlobMap unfinalized_blob_map_; - - // Used to keep track of how much memory is being utitlized for blob data, - // we count only the items of TYPE_DATA which are held in memory and not - // items of TYPE_FILE. - int64 memory_usage_; - - // Multiple urls can refer to the same blob data, this map keeps track of - // how many urls refer to a BlobData. - BlobDataUsageMap blob_data_usage_count_; - - DISALLOW_COPY_AND_ASSIGN(BlobStorageController); -}; - -} // namespace webkit_blob - -#endif // WEBKIT_BROWSER_BLOB_BLOB_STORAGE_CONTROLLER_H_ diff --git a/chromium/webkit/browser/blob/blob_storage_controller_unittest.cc b/chromium/webkit/browser/blob/blob_storage_controller_unittest.cc deleted file mode 100644 index fbef876a57c..00000000000 --- a/chromium/webkit/browser/blob/blob_storage_controller_unittest.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2011 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 "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/blob/blob_storage_controller.h" -#include "webkit/common/blob/blob_data.h" - -namespace webkit_blob { - -TEST(BlobStorageControllerTest, RegisterBlobUrl) { - // Setup a set of blob data for testing. - base::Time time1, time2; - base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); - base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2); - - scoped_refptr<BlobData> blob_data1(new BlobData()); - blob_data1->AppendData("Data1"); - blob_data1->AppendData("Data2"); - blob_data1->AppendFile(base::FilePath(FILE_PATH_LITERAL("File1.txt")), - 10, 1024, time1); - - scoped_refptr<BlobData> blob_data2(new BlobData()); - blob_data2->AppendData("Data3"); - blob_data2->AppendBlob(GURL("blob://url_1"), 8, 100); - blob_data2->AppendFile(base::FilePath(FILE_PATH_LITERAL("File2.txt")), - 0, 20, time2); - - scoped_refptr<BlobData> canonicalized_blob_data2(new BlobData()); - canonicalized_blob_data2->AppendData("Data3"); - canonicalized_blob_data2->AppendData("a2___", 2); - canonicalized_blob_data2->AppendFile( - base::FilePath(FILE_PATH_LITERAL("File1.txt")), - 10, 98, time1); - canonicalized_blob_data2->AppendFile( - base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); - - BlobStorageController blob_storage_controller; - - // Test registering a blob URL referring to the blob data containing only - // data and file. - GURL blob_url1("blob://url_1"); - blob_storage_controller.AddFinishedBlob(blob_url1, blob_data1.get()); - - BlobData* blob_data_found = - blob_storage_controller.GetBlobDataFromUrl(blob_url1); - ASSERT_TRUE(blob_data_found != NULL); - EXPECT_TRUE(*blob_data_found == *blob_data1.get()); - - // Test registering a blob URL referring to the blob data containing data, - // file and blob. - GURL blob_url2("blob://url_2"); - blob_storage_controller.AddFinishedBlob(blob_url2, blob_data2.get()); - - blob_data_found = blob_storage_controller.GetBlobDataFromUrl(blob_url2); - ASSERT_TRUE(blob_data_found != NULL); - EXPECT_TRUE(*blob_data_found == *canonicalized_blob_data2.get()); - - // Test registering a blob URL referring to existent blob URL. - GURL blob_url3("blob://url_3"); - blob_storage_controller.CloneBlob(blob_url3, blob_url1); - - blob_data_found = blob_storage_controller.GetBlobDataFromUrl(blob_url3); - ASSERT_TRUE(blob_data_found != NULL); - EXPECT_TRUE(*blob_data_found == *blob_data1.get()); - - // Test unregistering a blob URL. - blob_storage_controller.RemoveBlob(blob_url3); - blob_data_found = blob_storage_controller.GetBlobDataFromUrl(blob_url3); - EXPECT_TRUE(!blob_data_found); -} - -} // namespace webkit_blob diff --git a/chromium/webkit/browser/blob/blob_storage_host.cc b/chromium/webkit/browser/blob/blob_storage_host.cc index eebf3fbace7..9d3ddb959f6 100644 --- a/chromium/webkit/browser/blob/blob_storage_host.cc +++ b/chromium/webkit/browser/blob/blob_storage_host.cc @@ -5,6 +5,7 @@ #include "webkit/browser/blob/blob_storage_host.h" #include "base/sequenced_task_runner.h" +#include "base/strings/string_util.h" #include "url/gurl.h" #include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/blob/blob_storage_context.h" @@ -27,6 +28,10 @@ BlobStorageHost::~BlobStorageHost() { for (int i = 0; i < iter->second; ++i) context_->DecrementBlobRefCount(iter->first); } + for (std::set<GURL>::iterator iter = private_blob_urls_.begin(); + iter != private_blob_urls_.end(); ++iter) { + context_->DeprecatedRevokePrivateBlobURL(*iter); + } } bool BlobStorageHost::StartBuildingBlob(const std::string& uuid) { @@ -98,6 +103,56 @@ bool BlobStorageHost::RevokePublicBlobURL(const GURL& blob_url) { return true; } +namespace { +bool IsPrivateBlobURL(const GURL& url) { + return StartsWithASCII(url.spec(), "blob:blobinternal", true); +} +} + +void BlobStorageHost::DeprecatedRegisterBlobURL( + const GURL& private_url, const std::string& uuid) { + DCHECK(IsPrivateBlobURL(private_url)); + if (!context_.get()) + return; + context_->DeprecatedRegisterPrivateBlobURL(private_url, uuid); + private_blob_urls_.insert(private_url); +} + +void BlobStorageHost::DeprecatedCloneBlobURL( + const GURL& url, const GURL& src_private_url) { + // This method is used in two ways. + // 1. During serialization/deserialization to 'clone' an existing blob. + // In this case the src and dest urls are 'private' blob urls. + // 2. To register public blob urls. In this case the dest url is a + // 'public' blob url. + DCHECK(IsPrivateBlobURL(src_private_url)); + if (!context_.get()) + return; + std::string uuid = context_->LookupUuidFromDeprecatedURL(src_private_url); + if (uuid.empty()) + return; + if (IsPrivateBlobURL(url)) { + DeprecatedRegisterBlobURL(url, uuid); + } else { + // Temporarily bump the refcount so the uuid passes the InUse + // check inside the RegisterPublicBlobURL method. + ignore_result(IncrementBlobRefCount(uuid)); + ignore_result(RegisterPublicBlobURL(url, uuid)); + ignore_result(DecrementBlobRefCount(uuid)); + } +} + +void BlobStorageHost::DeprecatedRevokeBlobURL(const GURL& url) { + if (!context_.get()) + return; + if (IsPrivateBlobURL(url)) { + context_->DeprecatedRevokePrivateBlobURL(url); + private_blob_urls_.erase(url); + } else { + ignore_result(RevokePublicBlobURL(url)); + } +} + bool BlobStorageHost::IsInUseInHost(const std::string& uuid) { return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end(); } diff --git a/chromium/webkit/browser/blob/blob_storage_host.h b/chromium/webkit/browser/blob/blob_storage_host.h index 954c32ce400..890db3a7448 100644 --- a/chromium/webkit/browser/blob/blob_storage_host.h +++ b/chromium/webkit/browser/blob/blob_storage_host.h @@ -47,6 +47,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageHost { const std::string& uuid) WARN_UNUSED_RESULT; bool RevokePublicBlobURL(const GURL& blob_url) WARN_UNUSED_RESULT; + // Temporary support for mapping old style private blob urls to uuids. + void DeprecatedRegisterBlobURL(const GURL& private_url, + const std::string& uuid); + void DeprecatedCloneBlobURL(const GURL& url, + const GURL& src_private_url); + void DeprecatedRevokeBlobURL(const GURL& url); + private: typedef std::map<std::string, int> BlobReferenceMap; @@ -61,7 +68,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageHost { // The set of public blob urls coined by this consumer. std::set<GURL> public_blob_urls_; + // And private deprecated blob urls. + std::set<GURL> private_blob_urls_; + base::WeakPtr<BlobStorageContext> context_; + + DISALLOW_COPY_AND_ASSIGN(BlobStorageHost); }; } // namespace webkit_blob diff --git a/chromium/webkit/browser/blob/blob_url_request_job.cc b/chromium/webkit/browser/blob/blob_url_request_job.cc index a845fc94a4a..8f27edee6a8 100644 --- a/chromium/webkit/browser/blob/blob_url_request_job.cc +++ b/chromium/webkit/browser/blob/blob_url_request_job.cc @@ -24,7 +24,7 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_error_job.h" #include "net/url_request/url_request_status.h" -#include "webkit/browser/blob/local_file_stream_reader.h" +#include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_url.h" @@ -551,14 +551,16 @@ void BlobURLRequestJob::CreateFileStreamReader(size_t index, FileStreamReader* reader = NULL; switch (item.type()) { case BlobData::Item::TYPE_FILE: - reader = new LocalFileStreamReader(file_thread_proxy_.get(), - item.path(), - item.offset() + additional_offset, - item.expected_modification_time()); + reader = FileStreamReader::CreateForLocalFile( + file_thread_proxy_.get(), + item.path(), + item.offset() + additional_offset, + item.expected_modification_time()); break; case BlobData::Item::TYPE_FILE_FILESYSTEM: reader = file_system_context_->CreateFileStreamReader( - fileapi::FileSystemURL(file_system_context_->CrackURL(item.url())), + fileapi::FileSystemURL( + file_system_context_->CrackURL(item.filesystem_url())), item.offset() + additional_offset, item.expected_modification_time()).release(); break; diff --git a/chromium/webkit/browser/blob/blob_url_request_job_factory.cc b/chromium/webkit/browser/blob/blob_url_request_job_factory.cc index cc600d1c228..71fad4926fe 100644 --- a/chromium/webkit/browser/blob/blob_url_request_job_factory.cc +++ b/chromium/webkit/browser/blob/blob_url_request_job_factory.cc @@ -7,45 +7,77 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/message_loop/message_loop_proxy.h" -#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_data_handle.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/blob/blob_url_request_job.h" #include "webkit/browser/fileapi/file_system_context.h" namespace webkit_blob { +namespace { + +int kUserDataKey; // The value is not important, the addr is a key. + +BlobDataHandle* GetRequestedBlobDataHandle(net::URLRequest* request) { + return static_cast<BlobDataHandle*>(request->GetUserData(&kUserDataKey)); +} + +} // namespace + +// static +net::URLRequest* BlobProtocolHandler::CreateBlobRequest( + scoped_ptr<BlobDataHandle> blob_data_handle, + const net::URLRequestContext* request_context, + net::URLRequest::Delegate* request_delegate) { + const GURL kBlobUrl("blob://see_user_data/"); + net::URLRequest* request = request_context->CreateRequest( + kBlobUrl, request_delegate); + SetRequestedBlobDataHandle(request, blob_data_handle.Pass()); + return request; +} + +// static +void BlobProtocolHandler::SetRequestedBlobDataHandle( + net::URLRequest* request, + scoped_ptr<BlobDataHandle> blob_data_handle) { + request->SetUserData(&kUserDataKey, blob_data_handle.release()); +} + BlobProtocolHandler::BlobProtocolHandler( - webkit_blob::BlobStorageController* blob_storage_controller, + BlobStorageContext* context, fileapi::FileSystemContext* file_system_context, base::MessageLoopProxy* loop_proxy) - : blob_storage_controller_(blob_storage_controller), - file_system_context_(file_system_context), + : file_system_context_(file_system_context), file_loop_proxy_(loop_proxy) { - DCHECK(blob_storage_controller_); - DCHECK(file_system_context_.get()); - DCHECK(file_loop_proxy_.get()); + if (context) + context_ = context->AsWeakPtr(); } -BlobProtocolHandler::~BlobProtocolHandler() {} +BlobProtocolHandler::~BlobProtocolHandler() { +} net::URLRequestJob* BlobProtocolHandler::MaybeCreateJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) const { - scoped_refptr<webkit_blob::BlobData> data = LookupBlobData(request); - if (!data.get()) { - // This request is not coming through resource dispatcher host. - data = blob_storage_controller_->GetBlobDataFromUrl(request->url()); - } - return new webkit_blob::BlobURLRequestJob(request, - network_delegate, - data.get(), - file_system_context_.get(), - file_loop_proxy_.get()); + return new webkit_blob::BlobURLRequestJob( + request, network_delegate, LookupBlobData(request), + file_system_context_, file_loop_proxy_); } scoped_refptr<webkit_blob::BlobData> BlobProtocolHandler::LookupBlobData(net::URLRequest* request) const { - return NULL; + BlobDataHandle* blob_data_handle = GetRequestedBlobDataHandle(request); + if (blob_data_handle) + return blob_data_handle->data(); + if (!context_.get()) + return NULL; + + // Retain support for looking up based on deprecated blob urls for now. + // The FeedbackExtensionAPI relies on this. + scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID( + context_->LookupUuidFromDeprecatedURL(request->url())); + return handle.get() ? handle->data() : NULL; } } // namespace webkit_blob diff --git a/chromium/webkit/browser/blob/blob_url_request_job_factory.h b/chromium/webkit/browser/blob/blob_url_request_job_factory.h index 2a78c95d1a6..88ccc64dd6c 100644 --- a/chromium/webkit/browser/blob/blob_url_request_job_factory.h +++ b/chromium/webkit/browser/blob/blob_url_request_job_factory.h @@ -7,6 +7,8 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/url_request/url_request.h" #include "net/url_request/url_request_job_factory.h" #include "webkit/browser/webkit_storage_browser_export.h" @@ -19,19 +21,31 @@ class FileSystemContext; } // namespace fileapi namespace net { -class URLRequest; +class URLRequestContext; } // namespace net namespace webkit_blob { class BlobData; -class BlobStorageController; +class BlobDataHandle; +class BlobStorageContext; class WEBKIT_STORAGE_BROWSER_EXPORT BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: - // |controller|'s lifetime should exceed the lifetime of the ProtocolHandler. - BlobProtocolHandler(BlobStorageController* blob_storage_controller, + // A helper to manufacture an URLRequest to retrieve the given blob. + static net::URLRequest* CreateBlobRequest( + scoped_ptr<BlobDataHandle> blob_data_handle, + const net::URLRequestContext* request_context, + net::URLRequest::Delegate* request_delegate); + + // This class ignores the request's URL and uses the value given + // to SetRequestedBlobDataHandle instead. + static void SetRequestedBlobDataHandle( + net::URLRequest* request, + scoped_ptr<BlobDataHandle> blob_data_handle); + + BlobProtocolHandler(BlobStorageContext* context, fileapi::FileSystemContext* file_system_context, base::MessageLoopProxy* file_loop_proxy); virtual ~BlobProtocolHandler(); @@ -41,12 +55,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobProtocolHandler net::NetworkDelegate* network_delegate) const OVERRIDE; private: - virtual scoped_refptr<BlobData> LookupBlobData( + scoped_refptr<BlobData> LookupBlobData( net::URLRequest* request) const; - // No scoped_refptr because |blob_storage_controller_| is owned by the - // ProfileIOData, which also owns this ProtocolHandler. - BlobStorageController* const blob_storage_controller_; + base::WeakPtr<BlobStorageContext> context_; const scoped_refptr<fileapi::FileSystemContext> file_system_context_; const scoped_refptr<base::MessageLoopProxy> file_loop_proxy_; diff --git a/chromium/webkit/browser/blob/blob_url_request_job_unittest.cc b/chromium/webkit/browser/blob/blob_url_request_job_unittest.cc index 4b0749ee35b..8a814f5422f 100644 --- a/chromium/webkit/browser/blob/blob_url_request_job_unittest.cc +++ b/chromium/webkit/browser/blob/blob_url_request_job_unittest.cc @@ -8,7 +8,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "base/time/time.h" #include "net/base/io_buffer.h" #include "net/http/http_request_headers.h" @@ -18,8 +18,8 @@ #include "net/url_request/url_request_job_factory_impl.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/blob/blob_url_request_job.h" +#include "webkit/browser/fileapi/async_file_test_helper.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_file_util.h" #include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/mock_file_system_context.h" @@ -175,7 +175,7 @@ class BlobURLRequestJobTest : public testing::Test { fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&BlobURLRequestJobTest::OnValidateFileSystem, base::Unretained(this))); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); ASSERT_TRUE(file_system_root_url_.is_valid()); // Prepare files on file system. @@ -204,31 +204,14 @@ class BlobURLRequestJobTest : public testing::Test { kFileSystemType, base::FilePath().AppendASCII(filename)); - fileapi::FileSystemFileUtil* file_util = - file_system_context_->GetFileUtil(kFileSystemType); - - fileapi::FileSystemOperationContext context(file_system_context_.get()); - context.set_allowed_bytes_growth(1024); - - base::PlatformFile handle = base::kInvalidPlatformFileValue; - bool created = false; - ASSERT_EQ(base::PLATFORM_FILE_OK, file_util->CreateOrOpen( - &context, - url, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, - &handle, - &created)); - EXPECT_TRUE(created); - ASSERT_NE(base::kInvalidPlatformFileValue, handle); - ASSERT_EQ(buf_size, - base::WritePlatformFile(handle, 0 /* offset */, buf, buf_size)); - base::ClosePlatformFile(handle); + ASSERT_EQ(base::PLATFORM_FILE_OK, + fileapi::AsyncFileTestHelper::CreateFileWithData( + file_system_context_, url, buf, buf_size)); base::PlatformFileInfo file_info; - base::FilePath platform_path; ASSERT_EQ(base::PLATFORM_FILE_OK, - file_util->GetFileInfo(&context, url, &file_info, - &platform_path)); + fileapi::AsyncFileTestHelper::GetMetadata( + file_system_context_, url, &file_info)); if (modification_time) *modification_time = file_info.last_modified; } diff --git a/chromium/webkit/browser/blob/file_stream_reader.h b/chromium/webkit/browser/blob/file_stream_reader.h index dd49a52c2bc..d60dfdbd91c 100644 --- a/chromium/webkit/browser/blob/file_stream_reader.h +++ b/chromium/webkit/browser/blob/file_stream_reader.h @@ -10,15 +10,52 @@ #include "net/base/completion_callback.h" #include "webkit/browser/webkit_storage_browser_export.h" +namespace base { +class FilePath; +class TaskRunner; +class Time; +} + namespace net { class IOBuffer; } +namespace fileapi { +class FileSystemContext; +class FileSystemURL; +} + namespace webkit_blob { // A generic interface for reading a file-like object. -class WEBKIT_STORAGE_BROWSER_EXPORT FileStreamReader { +class FileStreamReader { public: + // Creates a new FileReader for a local file |file_path|. + // |initial_offset| specifies the offset in the file where the first read + // should start. If the given offset is out of the file range any + // read operation may error out with net::ERR_REQUEST_RANGE_NOT_SATISFIABLE. + // |expected_modification_time| specifies the expected last modification + // If the value is non-null, the reader will check the underlying file's + // actual modification time to see if the file has been modified, and if + // it does any succeeding read operations should fail with + // ERR_UPLOAD_FILE_CHANGED error. + WEBKIT_STORAGE_BROWSER_EXPORT static FileStreamReader* + CreateForLocalFile(base::TaskRunner* task_runner, + const base::FilePath& file_path, + int64 initial_offset, + const base::Time& expected_modification_time); + + // Creates a new reader for a filesystem URL |url| form |initial_offset|. + // |expected_modification_time| specifies the expected last modification if + // the value is non-null, the reader will check the underlying file's actual + // modification time to see if the file has been modified, and if it does any + // succeeding read operations should fail with ERR_UPLOAD_FILE_CHANGED error. + WEBKIT_STORAGE_BROWSER_EXPORT static FileStreamReader* + CreateForFileSystemFile(fileapi::FileSystemContext* context, + const fileapi::FileSystemURL& url, + int64 initial_offset, + const base::Time& expected_modification_time); + // It is valid to delete the reader at any time. If the stream is deleted // while it has a pending read, its callback will not be called. virtual ~FileStreamReader() {} diff --git a/chromium/webkit/browser/blob/local_file_stream_reader.cc b/chromium/webkit/browser/blob/local_file_stream_reader.cc index a72709cb800..0686821ac24 100644 --- a/chromium/webkit/browser/blob/local_file_stream_reader.cc +++ b/chromium/webkit/browser/blob/local_file_stream_reader.cc @@ -32,17 +32,14 @@ bool VerifySnapshotTime(const base::Time& expected_modification_time, } // namespace -LocalFileStreamReader::LocalFileStreamReader( +FileStreamReader* FileStreamReader::CreateForLocalFile( base::TaskRunner* task_runner, const base::FilePath& file_path, int64 initial_offset, - const base::Time& expected_modification_time) - : task_runner_(task_runner), - file_path_(file_path), - initial_offset_(initial_offset), - expected_modification_time_(expected_modification_time), - has_pending_open_(false), - weak_factory_(this) {} + const base::Time& expected_modification_time) { + return new LocalFileStreamReader(task_runner, file_path, initial_offset, + expected_modification_time); +} LocalFileStreamReader::~LocalFileStreamReader() { } @@ -69,6 +66,18 @@ int64 LocalFileStreamReader::GetLength( return net::ERR_IO_PENDING; } +LocalFileStreamReader::LocalFileStreamReader( + base::TaskRunner* task_runner, + const base::FilePath& file_path, + int64 initial_offset, + const base::Time& expected_modification_time) + : task_runner_(task_runner), + file_path_(file_path), + initial_offset_(initial_offset), + expected_modification_time_(expected_modification_time), + has_pending_open_(false), + weak_factory_(this) {} + int LocalFileStreamReader::Open(const net::CompletionCallback& callback) { DCHECK(!has_pending_open_); DCHECK(!stream_impl_.get()); diff --git a/chromium/webkit/browser/blob/local_file_stream_reader.h b/chromium/webkit/browser/blob/local_file_stream_reader.h index 143a43bf87e..18a5424514a 100644 --- a/chromium/webkit/browser/blob/local_file_stream_reader.h +++ b/chromium/webkit/browser/blob/local_file_stream_reader.h @@ -27,22 +27,8 @@ namespace webkit_blob { // A thin wrapper of net::FileStream with range support for sliced file // handling. class WEBKIT_STORAGE_BROWSER_EXPORT LocalFileStreamReader - : public FileStreamReader { + : public NON_EXPORTED_BASE(FileStreamReader) { public: - // Creates a new FileReader for a local file |file_path|. - // |initial_offset| specifies the offset in the file where the first read - // should start. If the given offset is out of the file range any - // read operation may error out with net::ERR_REQUEST_RANGE_NOT_SATISFIABLE. - // - // |expected_modification_time| specifies the expected last modification - // If the value is non-null, the reader will check the underlying file's - // actual modification time to see if the file has been modified, and if - // it does any succeeding read operations should fail with - // ERR_UPLOAD_FILE_CHANGED error. - LocalFileStreamReader(base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - const base::Time& expected_modification_time); virtual ~LocalFileStreamReader(); // FileStreamReader overrides. @@ -52,6 +38,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT LocalFileStreamReader const net::Int64CompletionCallback& callback) OVERRIDE; private: + friend class FileStreamReader; + friend class LocalFileStreamReaderTest; + + LocalFileStreamReader(base::TaskRunner* task_runner, + const base::FilePath& file_path, + int64 initial_offset, + const base::Time& expected_modification_time); int Open(const net::CompletionCallback& callback); // Callbacks that are chained from Open for Read. diff --git a/chromium/webkit/browser/blob/local_file_stream_reader_unittest.cc b/chromium/webkit/browser/blob/local_file_stream_reader_unittest.cc index f1ec01dbe3a..86a3c3d7a89 100644 --- a/chromium/webkit/browser/blob/local_file_stream_reader_unittest.cc +++ b/chromium/webkit/browser/blob/local_file_stream_reader_unittest.cc @@ -10,8 +10,8 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/platform_file.h" +#include "base/run_loop.h" #include "base/threading/thread.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -75,9 +75,9 @@ class LocalFileStreamReaderTest : public testing::Test { virtual void TearDown() OVERRIDE { // Give another chance for deleted streams to perform Close. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); file_thread_.Stop(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } protected: diff --git a/chromium/webkit/browser/blob/mock_blob_url_request_context.cc b/chromium/webkit/browser/blob/mock_blob_url_request_context.cc index 45c61340bfb..1794a58eb62 100644 --- a/chromium/webkit/browser/blob/mock_blob_url_request_context.cc +++ b/chromium/webkit/browser/blob/mock_blob_url_request_context.cc @@ -4,71 +4,46 @@ #include "webkit/browser/blob/mock_blob_url_request_context.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/blob/blob_url_request_job.h" +#include "webkit/browser/blob/blob_url_request_job_factory.h" #include "webkit/common/blob/blob_data.h" -namespace webkit_blob { - -namespace { - -class MockBlobProtocolHandler - : public net::URLRequestJobFactory::ProtocolHandler { - public: - explicit MockBlobProtocolHandler( - BlobStorageController* blob_storage_controller, - fileapi::FileSystemContext* file_system_context) - : blob_storage_controller_(blob_storage_controller), - file_system_context_(file_system_context) {} - - virtual ~MockBlobProtocolHandler() {} - - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE { - return new BlobURLRequestJob( - request, - network_delegate, - blob_storage_controller_->GetBlobDataFromUrl(request->url()), - file_system_context_, - base::MessageLoopProxy::current().get()); - } - - private: - webkit_blob::BlobStorageController* const blob_storage_controller_; - fileapi::FileSystemContext* const file_system_context_; - DISALLOW_COPY_AND_ASSIGN(MockBlobProtocolHandler); -}; - -} // namespace +namespace webkit_blob { MockBlobURLRequestContext::MockBlobURLRequestContext( fileapi::FileSystemContext* file_system_context) - : blob_storage_controller_(new BlobStorageController) { + : blob_storage_context_(new BlobStorageContext) { // Job factory owns the protocol handler. job_factory_.SetProtocolHandler( - "blob", new MockBlobProtocolHandler(blob_storage_controller_.get(), - file_system_context)); + "blob", new BlobProtocolHandler(blob_storage_context_.get(), + file_system_context, + base::MessageLoopProxy::current())); set_job_factory(&job_factory_); } -MockBlobURLRequestContext::~MockBlobURLRequestContext() {} +MockBlobURLRequestContext::~MockBlobURLRequestContext() { +} ScopedTextBlob::ScopedTextBlob( const MockBlobURLRequestContext& request_context, - const GURL& blob_url, + const std::string& blob_id, const std::string& data) - : blob_url_(blob_url), - blob_storage_controller_(request_context.blob_storage_controller()) { - DCHECK(blob_storage_controller_); - scoped_refptr<BlobData> blob_data(new BlobData()); - blob_data->AppendData(data); - blob_storage_controller_->AddFinishedBlob(blob_url_, blob_data.get()); + : blob_id_(blob_id), + context_(request_context.blob_storage_context()) { + DCHECK(context_); + scoped_refptr<BlobData> blob_data(new BlobData(blob_id_)); + if (!data.empty()) + blob_data->AppendData(data); + handle_ = context_->AddFinishedBlob(blob_data); } ScopedTextBlob::~ScopedTextBlob() { - blob_storage_controller_->RemoveBlob(blob_url_); +} + +scoped_ptr<BlobDataHandle> ScopedTextBlob::GetBlobDataHandle() { + return context_->GetBlobDataFromUUID(blob_id_); } } // namespace webkit_blob diff --git a/chromium/webkit/browser/blob/mock_blob_url_request_context.h b/chromium/webkit/browser/blob/mock_blob_url_request_context.h index b89027c95e7..a5d1acc8a4c 100644 --- a/chromium/webkit/browser/blob/mock_blob_url_request_context.h +++ b/chromium/webkit/browser/blob/mock_blob_url_request_context.h @@ -15,34 +15,40 @@ class FileSystemContext; namespace webkit_blob { -class BlobStorageController; +class BlobDataHandle; +class BlobStorageContext; class MockBlobURLRequestContext : public net::URLRequestContext { public: MockBlobURLRequestContext(fileapi::FileSystemContext* file_system_context); virtual ~MockBlobURLRequestContext(); - BlobStorageController* blob_storage_controller() const { - return blob_storage_controller_.get(); + BlobStorageContext* blob_storage_context() const { + return blob_storage_context_.get(); } private: net::URLRequestJobFactoryImpl job_factory_; - scoped_ptr<BlobStorageController> blob_storage_controller_; + scoped_ptr<BlobStorageContext> blob_storage_context_; DISALLOW_COPY_AND_ASSIGN(MockBlobURLRequestContext); }; class ScopedTextBlob { public: + // Registers a blob with the given |id| that contains |data|. ScopedTextBlob(const MockBlobURLRequestContext& request_context, - const GURL& blob_url, + const std::string& blob_id, const std::string& data); ~ScopedTextBlob(); + // Returns a BlobDataHandle referring to the scoped blob. + scoped_ptr<BlobDataHandle> GetBlobDataHandle(); + private: - const GURL blob_url_; - BlobStorageController* blob_storage_controller_; + const std::string blob_id_; + BlobStorageContext* context_; + scoped_ptr<BlobDataHandle> handle_; DISALLOW_COPY_AND_ASSIGN(ScopedTextBlob); }; diff --git a/chromium/webkit/browser/blob/view_blob_internals_job.cc b/chromium/webkit/browser/blob/view_blob_internals_job.cc index 41ef7883de5..e0523a4277b 100644 --- a/chromium/webkit/browser/blob/view_blob_internals_job.cc +++ b/chromium/webkit/browser/blob/view_blob_internals_job.cc @@ -11,13 +11,14 @@ #include "base/i18n/time_formatting.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "net/base/escape.h" #include "net/base/net_errors.h" #include "net/url_request/url_request.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/common/blob/blob_data.h" namespace { @@ -34,6 +35,8 @@ const char kURL[] = "URL: "; const char kModificationTime[] = "Modification Time: "; const char kOffset[] = "Offset: "; const char kLength[] = "Length: "; +const char kUUID[] = "Uuid: "; +const char kRefcount[] = "Refcount: "; void StartHTML(std::string* out) { out->append( @@ -48,11 +51,11 @@ void StartHTML(std::string* out) { ".subsection_body { margin: 10px 0 10px 2em; }\n" ".subsection_title { font-weight: bold; }\n" "</style>\n" - "</head><body>\n"); + "</head><body>\n\n"); } void EndHTML(std::string* out) { - out->append("</body></html>"); + out->append("\n</body></html>"); } void AddHTMLBoldText(const std::string& text, std::string* out) { @@ -62,11 +65,11 @@ void AddHTMLBoldText(const std::string& text, std::string* out) { } void StartHTMLList(std::string* out) { - out->append("<ul>"); + out->append("\n<ul>"); } void EndHTMLList(std::string* out) { - out->append("</ul>"); + out->append("</ul>\n"); } void AddHTMLListItem(const std::string& element_title, @@ -76,21 +79,11 @@ void AddHTMLListItem(const std::string& element_title, // No need to escape element_title since constant string is passed. out->append(element_title); out->append(net::EscapeForHTML(element_data)); - out->append("</li>"); + out->append("</li>\n"); } -void AddHTMLButton(const std::string& title, - const std::string& command, - std::string* out) { - // No need to escape title since constant string is passed. - std::string escaped_command = net::EscapeForHTML(command.c_str()); - base::StringAppendF(out, - "<form action=\"\" method=\"GET\">\n" - "<input type=\"hidden\" name=\"remove\" value=\"%s\">\n" - "<input type=\"submit\" value=\"%s\">\n" - "</form><br/>\n", - escaped_command.c_str(), - title.c_str()); +void AddHorizontalRule(std::string* out) { + out->append("\n<hr>\n"); } } // namespace @@ -100,9 +93,9 @@ namespace webkit_blob { ViewBlobInternalsJob::ViewBlobInternalsJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, - BlobStorageController* blob_storage_controller) + BlobStorageContext* blob_storage_context) : net::URLRequestSimpleJob(request, network_delegate), - blob_storage_controller_(blob_storage_controller), + blob_storage_context_(blob_storage_context), weak_factory_(this) { } @@ -112,7 +105,7 @@ ViewBlobInternalsJob::~ViewBlobInternalsJob() { void ViewBlobInternalsJob::Start() { base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&ViewBlobInternalsJob::DoWorkAsync, + base::Bind(&ViewBlobInternalsJob::StartAsync, weak_factory_.GetWeakPtr())); } @@ -134,18 +127,6 @@ void ViewBlobInternalsJob::Kill() { weak_factory_.InvalidateWeakPtrs(); } -void ViewBlobInternalsJob::DoWorkAsync() { - if (request_->url().has_query() && - StartsWithASCII(request_->url().query(), "remove=", true)) { - std::string blob_url = request_->url().query().substr(strlen("remove=")); - blob_url = net::UnescapeURLComponent(blob_url, - net::UnescapeRule::NORMAL | net::UnescapeRule::URL_SPECIAL_CHARS); - blob_storage_controller_->RemoveBlob(GURL(blob_url)); - } - - StartAsync(); -} - int ViewBlobInternalsJob::GetData( std::string* mime_type, std::string* charset, @@ -156,7 +137,7 @@ int ViewBlobInternalsJob::GetData( data->clear(); StartHTML(data); - if (blob_storage_controller_->blob_map_.empty()) + if (blob_storage_context_->blob_map_.empty()) data->append(kEmptyBlobStorageMessage); else GenerateHTML(data); @@ -165,20 +146,47 @@ int ViewBlobInternalsJob::GetData( } void ViewBlobInternalsJob::GenerateHTML(std::string* out) const { - for (BlobStorageController::BlobMap::const_iterator iter = - blob_storage_controller_->blob_map_.begin(); - iter != blob_storage_controller_->blob_map_.end(); + for (BlobStorageContext::BlobMap::const_iterator iter = + blob_storage_context_->blob_map_.begin(); + iter != blob_storage_context_->blob_map_.end(); ++iter) { AddHTMLBoldText(iter->first, out); - AddHTMLButton(kRemove, iter->first, out); - GenerateHTMLForBlobData(*iter->second.get(), out); + GenerateHTMLForBlobData(*(iter->second.data.get()), + iter->second.refcount, + out); + } + if (!blob_storage_context_->public_blob_urls_.empty()) { + AddHorizontalRule(out); + for (BlobStorageContext::BlobURLMap::const_iterator iter = + blob_storage_context_->public_blob_urls_.begin(); + iter != blob_storage_context_->public_blob_urls_.end(); + ++iter) { + AddHTMLBoldText(iter->first.spec(), out); + StartHTMLList(out); + AddHTMLListItem(kUUID, iter->second, out); + EndHTMLList(out); + } + } + if (!blob_storage_context_->deprecated_blob_urls_.empty()) { + AddHorizontalRule(out); + for (BlobStorageContext::BlobURLMap::const_iterator iter = + blob_storage_context_->deprecated_blob_urls_.begin(); + iter != blob_storage_context_->deprecated_blob_urls_.end(); + ++iter) { + AddHTMLBoldText(iter->first.spec(), out); + StartHTMLList(out); + AddHTMLListItem(kUUID, iter->second, out); + EndHTMLList(out); + } } } void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data, + int refcount, std::string* out) { StartHTMLList(out); + AddHTMLListItem(kRefcount, base::IntToString(refcount), out); if (!blob_data.content_type().empty()) AddHTMLListItem(kContentType, blob_data.content_type(), out); if (!blob_data.content_disposition().empty()) @@ -213,12 +221,11 @@ void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data, } break; case BlobData::Item::TYPE_BLOB: - AddHTMLListItem(kType, "blob", out); - AddHTMLListItem(kURL, item.url().spec(), out); + NOTREACHED(); // Should be flattened in the storage context. break; case BlobData::Item::TYPE_FILE_FILESYSTEM: AddHTMLListItem(kType, "filesystem", out); - AddHTMLListItem(kURL, item.url().spec(), out); + AddHTMLListItem(kURL, item.filesystem_url().spec(), out); if (!item.expected_modification_time().is_null()) { AddHTMLListItem(kModificationTime, UTF16ToUTF8( TimeFormatFriendlyDateAndTime(item.expected_modification_time())), diff --git a/chromium/webkit/browser/blob/view_blob_internals_job.h b/chromium/webkit/browser/blob/view_blob_internals_job.h index 41687d9c3b4..ed9d657f70d 100644 --- a/chromium/webkit/browser/blob/view_blob_internals_job.h +++ b/chromium/webkit/browser/blob/view_blob_internals_job.h @@ -18,7 +18,7 @@ class URLRequest; namespace webkit_blob { class BlobData; -class BlobStorageController; +class BlobStorageContext; // A job subclass that implements a protocol to inspect the internal // state of blob registry. @@ -27,7 +27,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ViewBlobInternalsJob public: ViewBlobInternalsJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - BlobStorageController* blob_storage_controller); + BlobStorageContext* blob_storage_context); virtual void Start() OVERRIDE; virtual int GetData(std::string* mime_type, @@ -41,12 +41,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ViewBlobInternalsJob private: virtual ~ViewBlobInternalsJob(); - void DoWorkAsync(); void GenerateHTML(std::string* out) const; static void GenerateHTMLForBlobData(const BlobData& blob_data, + int refcount, std::string* out); - BlobStorageController* blob_storage_controller_; + BlobStorageContext* blob_storage_context_; base::WeakPtrFactory<ViewBlobInternalsJob> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ViewBlobInternalsJob); diff --git a/chromium/webkit/browser/database/database_quota_client.cc b/chromium/webkit/browser/database/database_quota_client.cc index 650edfe4c18..08e86660375 100644 --- a/chromium/webkit/browser/database/database_quota_client.cc +++ b/chromium/webkit/browser/database/database_quota_client.cc @@ -215,4 +215,8 @@ void DatabaseQuotaClient::DeleteOriginData( delete_callback); } +bool DatabaseQuotaClient::DoesSupport(quota::StorageType type) const { + return type == quota::kStorageTypeTemporary; +} + } // namespace webkit_database diff --git a/chromium/webkit/browser/database/database_quota_client.h b/chromium/webkit/browser/database/database_quota_client.h index bc070213182..2c6d0aeda71 100644 --- a/chromium/webkit/browser/database/database_quota_client.h +++ b/chromium/webkit/browser/database/database_quota_client.h @@ -39,10 +39,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE DatabaseQuotaClient const GetOriginsCallback& callback) OVERRIDE; virtual void GetOriginsForHost(quota::StorageType type, const std::string& host, - const GetOriginsCallback& callback) OVERRIDE; + const GetOriginsCallback& callback) OVERRIDE; virtual void DeleteOriginData(const GURL& origin, quota::StorageType type, const DeletionCallback& callback) OVERRIDE; + virtual bool DoesSupport(quota::StorageType type) const OVERRIDE; private: scoped_refptr<base::MessageLoopProxy> db_tracker_thread_; scoped_refptr<DatabaseTracker> db_tracker_; // only used on its thread diff --git a/chromium/webkit/browser/database/database_quota_client_unittest.cc b/chromium/webkit/browser/database/database_quota_client_unittest.cc index 93ca2d0893d..3d4f71aef53 100644 --- a/chromium/webkit/browser/database/database_quota_client_unittest.cc +++ b/chromium/webkit/browser/database/database_quota_client_unittest.cc @@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/files/file_path.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "net/base/completion_callback.h" #include "net/base/net_errors.h" @@ -142,7 +142,7 @@ class DatabaseQuotaClientTest : public testing::Test { origin, type, base::Bind(&DatabaseQuotaClientTest::OnGetOriginUsageComplete, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return usage_; } @@ -154,7 +154,7 @@ class DatabaseQuotaClientTest : public testing::Test { type, base::Bind(&DatabaseQuotaClientTest::OnGetOriginsComplete, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return origins_; } @@ -167,7 +167,7 @@ class DatabaseQuotaClientTest : public testing::Test { type, host, base::Bind(&DatabaseQuotaClientTest::OnGetOriginsComplete, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return origins_; } @@ -180,7 +180,7 @@ class DatabaseQuotaClientTest : public testing::Test { origin, type, base::Bind(&DatabaseQuotaClientTest::OnDeleteOriginDataComplete, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return delete_status_ == quota::kQuotaStatusOk; } diff --git a/chromium/webkit/browser/database/database_tracker.cc b/chromium/webkit/browser/database/database_tracker.cc index e3b3c6abe83..f9adb3bed43 100644 --- a/chromium/webkit/browser/database/database_tracker.cc +++ b/chromium/webkit/browser/database/database_tracker.cc @@ -289,15 +289,13 @@ base::FilePath DatabaseTracker::GetFullDBFilePath( if (!LazyInit()) return base::FilePath(); - int64 id = databases_table_->GetDatabaseID( - origin_identifier, database_name); + int64 id = databases_table_->GetDatabaseID(origin_identifier, database_name); if (id < 0) return base::FilePath(); - base::FilePath file_name = base::FilePath::FromWStringHack( - UTF8ToWide(base::Int64ToString(id))); - return db_dir_.Append(base::FilePath::FromWStringHack( - UTF16ToWide(GetOriginDirectory(origin_identifier)))).Append(file_name); + return db_dir_.Append(base::FilePath::FromUTF16Unsafe( + GetOriginDirectory(origin_identifier))).AppendASCII( + base::Int64ToString(id)); } bool DatabaseTracker::GetOriginInfo(const std::string& origin_identifier, diff --git a/chromium/webkit/browser/database/database_tracker_unittest.cc b/chromium/webkit/browser/database/database_tracker_unittest.cc index 25f0a6949d2..860faa0cd2c 100644 --- a/chromium/webkit/browser/database/database_tracker_unittest.cc +++ b/chromium/webkit/browser/database/database_tracker_unittest.cc @@ -220,12 +220,12 @@ class DatabaseTracker_TestHelper_Test { tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0, &database_size); - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - base::FilePath::FromWStringHack(UTF16ToWide( - tracker->GetOriginDirectory(kOrigin1)))))); - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - base::FilePath::FromWStringHack(UTF16ToWide( - tracker->GetOriginDirectory(kOrigin2)))))); + EXPECT_TRUE(file_util::CreateDirectory( + tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe( + tracker->GetOriginDirectory(kOrigin1))))); + EXPECT_TRUE(file_util::CreateDirectory( + tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe( + tracker->GetOriginDirectory(kOrigin2))))); EXPECT_EQ(1, file_util::WriteFile( tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); EXPECT_EQ(2, file_util::WriteFile( @@ -255,9 +255,9 @@ class DatabaseTracker_TestHelper_Test { // Recreate db1. tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size); - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - base::FilePath::FromWStringHack(UTF16ToWide( - tracker->GetOriginDirectory(kOrigin1)))))); + EXPECT_TRUE(file_util::CreateDirectory( + tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe( + tracker->GetOriginDirectory(kOrigin1))))); EXPECT_EQ(1, file_util::WriteFile( tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); tracker->DatabaseModified(kOrigin1, kDB1); @@ -348,12 +348,12 @@ class DatabaseTracker_TestHelper_Test { // Write some data to each file and check that the listeners are // called with the appropriate values. - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - base::FilePath::FromWStringHack(UTF16ToWide( - tracker->GetOriginDirectory(kOrigin1)))))); - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - base::FilePath::FromWStringHack(UTF16ToWide( - tracker->GetOriginDirectory(kOrigin2)))))); + EXPECT_TRUE(file_util::CreateDirectory( + tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe( + tracker->GetOriginDirectory(kOrigin1))))); + EXPECT_TRUE(file_util::CreateDirectory( + tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe( + tracker->GetOriginDirectory(kOrigin2))))); EXPECT_EQ(1, file_util::WriteFile( tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); EXPECT_EQ(2, file_util::WriteFile( diff --git a/chromium/webkit/browser/fileapi/async_file_test_helper.cc b/chromium/webkit/browser/fileapi/async_file_test_helper.cc index 8a01fd2a474..e3343d51935 100644 --- a/chromium/webkit/browser/fileapi/async_file_test_helper.cc +++ b/chromium/webkit/browser/fileapi/async_file_test_helper.cc @@ -3,6 +3,8 @@ // found in the LICENSE file. #include "base/bind.h" +#include "base/file_util.h" +#include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/fileapi/async_file_test_helper.h" @@ -92,10 +94,19 @@ base::PlatformFileError AsyncFileTestHelper::Copy( FileSystemContext* context, const FileSystemURL& src, const FileSystemURL& dest) { + return CopyWithProgress(context, src, dest, CopyProgressCallback()); +} + +base::PlatformFileError AsyncFileTestHelper::CopyWithProgress( + FileSystemContext* context, + const FileSystemURL& src, + const FileSystemURL& dest, + const CopyProgressCallback& progress_callback) { base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED; base::RunLoop run_loop; context->operation_runner()->Copy( - src, dest, AssignAndQuitCallback(&run_loop, &result)); + src, dest, progress_callback, + AssignAndQuitCallback(&run_loop, &result)); run_loop.Run(); return result; } @@ -164,6 +175,25 @@ base::PlatformFileError AsyncFileTestHelper::CreateFile( return result; } +base::PlatformFileError AsyncFileTestHelper::CreateFileWithData( + FileSystemContext* context, + const FileSystemURL& url, + const char* buf, + int buf_size) { + base::ScopedTempDir dir; + if (!dir.CreateUniqueTempDir()) + return base::PLATFORM_FILE_ERROR_FAILED; + base::FilePath local_path = dir.path().AppendASCII("tmp"); + if (buf_size != file_util::WriteFile(local_path, buf, buf_size)) + return base::PLATFORM_FILE_ERROR_FAILED; + base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED; + base::RunLoop run_loop; + context->operation_runner()->CopyInForeignFile( + local_path, url, AssignAndQuitCallback(&run_loop, &result)); + run_loop.Run(); + return result; +} + base::PlatformFileError AsyncFileTestHelper::TruncateFile( FileSystemContext* context, const FileSystemURL& url, @@ -232,7 +262,7 @@ quota::QuotaStatusCode AsyncFileTestHelper::GetUsageAndQuota( origin, FileSystemTypeToQuotaStorageType(type), base::Bind(&DidGetUsageAndQuota, &status, usage, quota)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return status; } diff --git a/chromium/webkit/browser/fileapi/async_file_test_helper.h b/chromium/webkit/browser/fileapi/async_file_test_helper.h index cfa7981e03e..168400fd0ef 100644 --- a/chromium/webkit/browser/fileapi/async_file_test_helper.h +++ b/chromium/webkit/browser/fileapi/async_file_test_helper.h @@ -23,6 +23,7 @@ class FileSystemURL; class AsyncFileTestHelper { public: typedef FileSystemOperation::FileEntryList FileEntryList; + typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; static const int64 kDontCheckSize; @@ -31,6 +32,13 @@ class AsyncFileTestHelper { const FileSystemURL& src, const FileSystemURL& dest); + // Same as Copy, but this supports |progress_callback|. + static base::PlatformFileError CopyWithProgress( + FileSystemContext* context, + const FileSystemURL& src, + const FileSystemURL& dest, + const CopyProgressCallback& progress_callback); + // Performs Move from |src| to |dest| and returns the status code. static base::PlatformFileError Move(FileSystemContext* context, const FileSystemURL& src, @@ -54,6 +62,13 @@ class AsyncFileTestHelper { static base::PlatformFileError CreateFile(FileSystemContext* context, const FileSystemURL& url); + // Creates a file at |url| and fills with |buf|. + static base::PlatformFileError CreateFileWithData( + FileSystemContext* context, + const FileSystemURL& url, + const char* buf, + int buf_size); + // Truncates the file |url| to |size|. static base::PlatformFileError TruncateFile(FileSystemContext* context, const FileSystemURL& url, diff --git a/chromium/webkit/browser/fileapi/async_file_util.h b/chromium/webkit/browser/fileapi/async_file_util.h index dc8216eaac0..84a033b7a4e 100644 --- a/chromium/webkit/browser/fileapi/async_file_util.h +++ b/chromium/webkit/browser/fileapi/async_file_util.h @@ -42,7 +42,7 @@ class FileSystemURL; // It is NOT valid to give null callback to this class, and implementors // can assume that they don't get any null callbacks. // -class WEBKIT_STORAGE_BROWSER_EXPORT AsyncFileUtil { +class AsyncFileUtil { public: typedef base::Callback< void(base::PlatformFileError result)> StatusCallback; @@ -76,6 +76,15 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AsyncFileUtil { const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref )> CreateSnapshotFileCallback; + + typedef base::Callback<void(int64 size)> CopyFileProgressCallback; + + // Creates an AsyncFileUtil instance which performs file operations on + // local native file system. The created instance assumes + // FileSystemURL::path() has the target platform path. + WEBKIT_STORAGE_BROWSER_EXPORT static AsyncFileUtil* + CreateForLocalFileSystem(); + AsyncFileUtil() {} virtual ~AsyncFileUtil() {} @@ -198,6 +207,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AsyncFileUtil { // Copies a file from |src_url| to |dest_url|. // This must be called for files that belong to the same filesystem // (i.e. type() and origin() of the |src_url| and |dest_url| must match). + // |progress_callback| is a callback to report the progress update. + // See file_system_operations.h for details. This should be called on the + // same thread as where the method's called (IO thread). Calling this + // is optional. It is recommended to use this callback for heavier operations + // (such as file network downloading), so that, e.g., clients (UIs) can + // update its state to show progress to users. This may be a null callback. // // FileSystemOperationImpl::Copy calls this for same-filesystem copy case. // @@ -214,6 +229,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AsyncFileUtil { scoped_ptr<FileSystemOperationContext> context, const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback) = 0; // Moves a local file from |src_url| to |dest_url|. diff --git a/chromium/webkit/browser/fileapi/async_file_util_adapter.cc b/chromium/webkit/browser/fileapi/async_file_util_adapter.cc index 807c2e20227..54d67976dc7 100644 --- a/chromium/webkit/browser/fileapi/async_file_util_adapter.cc +++ b/chromium/webkit/browser/fileapi/async_file_util_adapter.cc @@ -253,7 +253,9 @@ void AsyncFileUtilAdapter::CopyFileLocal( scoped_ptr<FileSystemOperationContext> context, const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback) { + // TODO(hidehiko): Support progress_callback. FileSystemOperationContext* context_ptr = context.release(); const bool success = base::PostTaskAndReplyWithResult( context_ptr->task_runner(), FROM_HERE, diff --git a/chromium/webkit/browser/fileapi/async_file_util_adapter.h b/chromium/webkit/browser/fileapi/async_file_util_adapter.h index 9da3db9eac7..0122b11b9d5 100644 --- a/chromium/webkit/browser/fileapi/async_file_util_adapter.h +++ b/chromium/webkit/browser/fileapi/async_file_util_adapter.h @@ -22,8 +22,8 @@ class FileSystemFileUtil; // // This instance (as thus this->sync_file_util_) is guaranteed to be alive // as far as FileSystemOperationContext given to each operation is kept alive. -class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE AsyncFileUtilAdapter - : public AsyncFileUtil { +class WEBKIT_STORAGE_BROWSER_EXPORT AsyncFileUtilAdapter + : public NON_EXPORTED_BASE(AsyncFileUtil) { public: // Creates a new AsyncFileUtil for |sync_file_util|. This takes the // ownership of |sync_file_util|. (This doesn't take scoped_ptr<> just @@ -76,6 +76,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE AsyncFileUtilAdapter scoped_ptr<FileSystemOperationContext> context, const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback) OVERRIDE; virtual void MoveFileLocal( scoped_ptr<FileSystemOperationContext> context, diff --git a/chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc b/chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc index caecccfddfb..366efa3dad5 100644 --- a/chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc +++ b/chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc @@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/fileapi/async_file_test_helper.h" #include "webkit/browser/fileapi/copy_or_move_file_validator.h" @@ -46,7 +46,7 @@ class CopyOrMoveFileValidatorTestHelper { ~CopyOrMoveFileValidatorTestHelper() { file_system_context_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void SetUp() { @@ -68,7 +68,7 @@ class CopyOrMoveFileValidatorTestHelper { origin_, src_type_, OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&ExpectOk)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); ASSERT_EQ(base::PLATFORM_FILE_OK, CreateDirectory(SourceURL(""))); // Sets up dest. diff --git a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc index da1ef97b984..aba17b55d75 100644 --- a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc +++ b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc @@ -16,22 +16,293 @@ namespace fileapi { +class CopyOrMoveOperationDelegate::CopyOrMoveImpl { + public: + virtual ~CopyOrMoveImpl() {} + virtual void Run( + const CopyOrMoveOperationDelegate::StatusCallback& callback) = 0; + protected: + CopyOrMoveImpl() {} + DISALLOW_COPY_AND_ASSIGN(CopyOrMoveImpl); +}; + +namespace { + +// Copies a file on a (same) file system. Just delegate the operation to +// |operation_runner|. +class CopyOrMoveOnSameFileSystemImpl + : public CopyOrMoveOperationDelegate::CopyOrMoveImpl { + public: + CopyOrMoveOnSameFileSystemImpl( + FileSystemOperationRunner* operation_runner, + CopyOrMoveOperationDelegate::OperationType operation_type, + const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const FileSystemOperation::CopyFileProgressCallback& + file_progress_callback) + : operation_runner_(operation_runner), + operation_type_(operation_type), + src_url_(src_url), + dest_url_(dest_url), + file_progress_callback_(file_progress_callback) { + } + + virtual void Run( + const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE { + if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) { + operation_runner_->MoveFileLocal(src_url_, dest_url_, callback); + } else { + operation_runner_->CopyFileLocal( + src_url_, dest_url_, file_progress_callback_, callback); + } + } + + private: + FileSystemOperationRunner* operation_runner_; + CopyOrMoveOperationDelegate::OperationType operation_type_; + FileSystemURL src_url_; + FileSystemURL dest_url_; + FileSystemOperation::CopyFileProgressCallback file_progress_callback_; + DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOnSameFileSystemImpl); +}; + +// Specifically for cross file system copy/move operation, this class creates +// a snapshot file, validates it if necessary, runs copying process, +// validates the created file, and removes source file for move (noop for +// copy). +class SnapshotCopyOrMoveImpl + : public CopyOrMoveOperationDelegate::CopyOrMoveImpl { + public: + SnapshotCopyOrMoveImpl( + FileSystemOperationRunner* operation_runner, + CopyOrMoveOperationDelegate::OperationType operation_type, + const FileSystemURL& src_url, + const FileSystemURL& dest_url, + CopyOrMoveFileValidatorFactory* validator_factory, + const FileSystemOperation::CopyFileProgressCallback& + file_progress_callback) + : operation_runner_(operation_runner), + operation_type_(operation_type), + src_url_(src_url), + dest_url_(dest_url), + validator_factory_(validator_factory), + file_progress_callback_(file_progress_callback), + weak_factory_(this) { + } + + virtual void Run( + const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE { + file_progress_callback_.Run(0); + operation_runner_->CreateSnapshotFile( + src_url_, + base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCreateSnapshot, + weak_factory_.GetWeakPtr(), callback)); + } + + private: + void RunAfterCreateSnapshot( + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error, + const base::PlatformFileInfo& file_info, + const base::FilePath& platform_path, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { + if (error != base::PLATFORM_FILE_OK) { + callback.Run(error); + return; + } + + // For now we assume CreateSnapshotFile always return a valid local file + // path. + DCHECK(!platform_path.empty()); + + if (!validator_factory_) { + // No validation is needed. + RunAfterPreWriteValidation(platform_path, file_info, file_ref, callback, + base::PLATFORM_FILE_OK); + return; + } + + // Run pre write validation. + PreWriteValidation( + platform_path, + base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation, + weak_factory_.GetWeakPtr(), + platform_path, file_info, file_ref, callback)); + } + + void RunAfterPreWriteValidation( + const base::FilePath& platform_path, + const base::PlatformFileInfo& file_info, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error) { + if (error != base::PLATFORM_FILE_OK) { + callback.Run(error); + return; + } + + // |file_ref| is unused but necessary to keep the file alive until + // CopyInForeignFile() is completed. + operation_runner_->CopyInForeignFile( + platform_path, dest_url_, + base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile, + weak_factory_.GetWeakPtr(), file_info, file_ref, callback)); + } + + void RunAfterCopyInForeignFile( + const base::PlatformFileInfo& file_info, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error) { + if (error != base::PLATFORM_FILE_OK) { + callback.Run(error); + return; + } + + file_progress_callback_.Run(file_info.size); + + // |validator_| is NULL when the destination filesystem does not do + // validation. + if (!validator_) { + // No validation is needed. + RunAfterPostWriteValidation(callback, base::PLATFORM_FILE_OK); + return; + } + + PostWriteValidation( + base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPostWriteValidation, + weak_factory_.GetWeakPtr(), callback)); + } + + void RunAfterPostWriteValidation( + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error) { + if (error != base::PLATFORM_FILE_OK) { + // Failed to validate. Remove the destination file. + operation_runner_->Remove( + dest_url_, true /* recursive */, + base::Bind(&SnapshotCopyOrMoveImpl::DidRemoveDestForError, + weak_factory_.GetWeakPtr(), error, callback)); + return; + } + + if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) { + callback.Run(base::PLATFORM_FILE_OK); + return; + } + + DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_); + + // Remove the source for finalizing move operation. + operation_runner_->Remove( + src_url_, true /* recursive */, + base::Bind(&SnapshotCopyOrMoveImpl::RunAfterRemoveSourceForMove, + weak_factory_.GetWeakPtr(), callback)); + } + + void RunAfterRemoveSourceForMove( + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error) { + if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) + error = base::PLATFORM_FILE_OK; + callback.Run(error); + } + + void DidRemoveDestForError( + base::PlatformFileError prior_error, + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error) { + if (error != base::PLATFORM_FILE_OK) { + VLOG(1) << "Error removing destination file after validation error: " + << error; + } + callback.Run(prior_error); + } + + // Runs pre-write validation. + void PreWriteValidation( + const base::FilePath& platform_path, + const CopyOrMoveOperationDelegate::StatusCallback& callback) { + DCHECK(validator_factory_); + validator_.reset( + validator_factory_->CreateCopyOrMoveFileValidator( + src_url_, platform_path)); + validator_->StartPreWriteValidation(callback); + } + + // Runs post-write validation. + void PostWriteValidation( + const CopyOrMoveOperationDelegate::StatusCallback& callback) { + operation_runner_->CreateSnapshotFile( + dest_url_, + base::Bind( + &SnapshotCopyOrMoveImpl::PostWriteValidationAfterCreateSnapshotFile, + weak_factory_.GetWeakPtr(), callback)); + } + + void PostWriteValidationAfterCreateSnapshotFile( + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error, + const base::PlatformFileInfo& file_info, + const base::FilePath& platform_path, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { + if (error != base::PLATFORM_FILE_OK) { + callback.Run(error); + return; + } + + DCHECK(validator_); + // Note: file_ref passed here to keep the file alive until after + // the StartPostWriteValidation operation finishes. + validator_->StartPostWriteValidation( + platform_path, + base::Bind(&SnapshotCopyOrMoveImpl::DidPostWriteValidation, + weak_factory_.GetWeakPtr(), file_ref, callback)); + } + + // |file_ref| is unused; it is passed here to make sure the reference is + // alive until after post-write validation is complete. + void DidPostWriteValidation( + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, + const CopyOrMoveOperationDelegate::StatusCallback& callback, + base::PlatformFileError error) { + callback.Run(error); + } + + FileSystemOperationRunner* operation_runner_; + CopyOrMoveOperationDelegate::OperationType operation_type_; + FileSystemURL src_url_; + FileSystemURL dest_url_; + CopyOrMoveFileValidatorFactory* validator_factory_; + scoped_ptr<CopyOrMoveFileValidator> validator_; + FileSystemOperation::CopyFileProgressCallback file_progress_callback_; + + base::WeakPtrFactory<SnapshotCopyOrMoveImpl> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(SnapshotCopyOrMoveImpl); +}; + +} // namespace + + CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate( FileSystemContext* file_system_context, const FileSystemURL& src_root, const FileSystemURL& dest_root, OperationType operation_type, + const CopyProgressCallback& progress_callback, const StatusCallback& callback) : RecursiveOperationDelegate(file_system_context), src_root_(src_root), dest_root_(dest_root), operation_type_(operation_type), + progress_callback_(progress_callback), callback_(callback), weak_factory_(this) { same_file_system_ = src_root_.IsInSameFileSystem(dest_root_); } CopyOrMoveOperationDelegate::~CopyOrMoveOperationDelegate() { + STLDeleteElements(&running_copy_set_); } void CopyOrMoveOperationDelegate::Run() { @@ -54,239 +325,154 @@ void CopyOrMoveOperationDelegate::RunRecursively() { return; } - // First try to copy/move it as a file. - CopyOrMoveFile(URLPair(src_root_, dest_root_), - base::Bind(&CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile, - weak_factory_.GetWeakPtr())); -} - -void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url, - const StatusCallback& callback) { - CopyOrMoveFile(URLPair(src_url, CreateDestURL(src_url)), callback); -} - -void CopyOrMoveOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, - const StatusCallback& callback) { - FileSystemURL dest_url = CreateDestURL(src_url); - - // If operation_type == Move we may need to record directories and - // restore directory timestamps in the end, though it may have - // negative performance impact. - // See http://crbug.com/171284 for more details. - operation_runner()->CreateDirectory( - dest_url, false /* exclusive */, false /* recursive */, callback); -} - -void CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile( - base::PlatformFileError error) { - if (error == base::PLATFORM_FILE_OK || - error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { - callback_.Run(error); - return; - } - - // The src_root_ looks to be a directory. - // Try removing the dest_root_ to see if it exists and/or it is an - // empty directory. - operation_runner()->RemoveDirectory( - dest_root_, - base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot, - weak_factory_.GetWeakPtr())); -} - -void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot( - base::PlatformFileError error) { - if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { - callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); - return; - } - if (error != base::PLATFORM_FILE_OK && - error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { - callback_.Run(error); - return; - } - // Start to process the source directory recursively. // TODO(kinuko): This could be too expensive for same_file_system_==true // and operation==MOVE case, probably we can just rename the root directory. // http://crbug.com/172187 - StartRecursiveOperation( - src_root_, - base::Bind(&CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir, - weak_factory_.GetWeakPtr(), src_root_, callback_)); + StartRecursiveOperation(src_root_, callback_); } -void CopyOrMoveOperationDelegate::CopyOrMoveFile( - const URLPair& url_pair, +void CopyOrMoveOperationDelegate::ProcessFile( + const FileSystemURL& src_url, const StatusCallback& callback) { - // Same filesystem case. - if (same_file_system_) { - if (operation_type_ == OPERATION_MOVE) { - operation_runner()->MoveFileLocal(url_pair.src, url_pair.dest, callback); - } else { - operation_runner()->CopyFileLocal(url_pair.src, url_pair.dest, callback); - } - return; + if (!progress_callback_.is_null()) { + progress_callback_.Run( + FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0); } - // Cross filesystem case. - // Perform CreateSnapshotFile, CopyInForeignFile and then calls - // copy_callback which removes the source file if operation_type == MOVE. - StatusCallback copy_callback = - base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy, - weak_factory_.GetWeakPtr(), url_pair, callback); - operation_runner()->CreateSnapshotFile( - url_pair.src, - base::Bind(&CopyOrMoveOperationDelegate::DidCreateSnapshot, - weak_factory_.GetWeakPtr(), url_pair, copy_callback)); -} + FileSystemURL dest_url = CreateDestURL(src_url); + CopyOrMoveImpl* impl = NULL; + if (same_file_system_) { + impl = new CopyOrMoveOnSameFileSystemImpl( + operation_runner(), operation_type_, src_url, dest_url, + base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress, + weak_factory_.GetWeakPtr(), src_url)); + } else { + // Cross filesystem case. + // TODO(hidehiko): Support stream based copy. crbug.com/279287. + base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; + CopyOrMoveFileValidatorFactory* validator_factory = + file_system_context()->GetCopyOrMoveFileValidatorFactory( + dest_root_.type(), &error); + if (error != base::PLATFORM_FILE_OK) { + callback.Run(error); + return; + } -void CopyOrMoveOperationDelegate::DidCreateSnapshot( - const URLPair& url_pair, - const StatusCallback& callback, - base::PlatformFileError error, - const base::PlatformFileInfo& file_info, - const base::FilePath& platform_path, - const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { - if (error != base::PLATFORM_FILE_OK) { - callback.Run(error); - return; + impl = new SnapshotCopyOrMoveImpl( + operation_runner(), operation_type_, src_url, dest_url, + validator_factory, + base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress, + weak_factory_.GetWeakPtr(), src_url)); } - current_file_ref_ = file_ref; - // For now we assume CreateSnapshotFile always return a valid local file path. - // TODO(kinuko): Otherwise create a FileStreamReader to perform a copy/move. - DCHECK(!platform_path.empty()); + // Register the running task. + running_copy_set_.insert(impl); + impl->Run(base::Bind( + &CopyOrMoveOperationDelegate::DidCopyOrMoveFile, + weak_factory_.GetWeakPtr(), src_url, dest_url, callback, impl)); +} - CopyOrMoveFileValidatorFactory* factory = - file_system_context()->GetCopyOrMoveFileValidatorFactory( - dest_root_.type(), &error); - if (error != base::PLATFORM_FILE_OK) { - callback.Run(error); - return; - } - if (!factory) { - DidValidateFile(url_pair.dest, callback, file_info, platform_path, error); +void CopyOrMoveOperationDelegate::ProcessDirectory( + const FileSystemURL& src_url, + const StatusCallback& callback) { + if (src_url == src_root_) { + // The src_root_ looks to be a directory. + // Try removing the dest_root_ to see if it exists and/or it is an + // empty directory. + // We do not invoke |progress_callback_| for source root, because it is + // already called in ProcessFile(). + operation_runner()->RemoveDirectory( + dest_root_, + base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot, + weak_factory_.GetWeakPtr(), callback)); return; } - validator_.reset( - factory->CreateCopyOrMoveFileValidator(url_pair.src, platform_path)); - validator_->StartPreWriteValidation( - base::Bind(&CopyOrMoveOperationDelegate::DidValidateFile, - weak_factory_.GetWeakPtr(), - url_pair.dest, callback, file_info, platform_path)); -} - -void CopyOrMoveOperationDelegate::DidValidateFile( - const FileSystemURL& dest, - const StatusCallback& callback, - const base::PlatformFileInfo& file_info, - const base::FilePath& platform_path, - base::PlatformFileError error) { - if (error != base::PLATFORM_FILE_OK) { - callback.Run(error); - return; + if (!progress_callback_.is_null()) { + progress_callback_.Run( + FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0); } - operation_runner()->CopyInForeignFile(platform_path, dest, callback); + ProcessDirectoryInternal(src_url, CreateDestURL(src_url), callback); } -void CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir( - const FileSystemURL& src, - const StatusCallback& callback, - base::PlatformFileError error) { - if (error != base::PLATFORM_FILE_OK || - operation_type_ == OPERATION_COPY) { - callback.Run(error); +void CopyOrMoveOperationDelegate::PostProcessDirectory( + const FileSystemURL& src_url, + const StatusCallback& callback) { + if (operation_type_ == OPERATION_COPY) { + callback.Run(base::PLATFORM_FILE_OK); return; } DCHECK_EQ(OPERATION_MOVE, operation_type_); - // Remove the source for finalizing move operation. + // All files and subdirectories in the directory should be moved here, + // so remove the source directory for finalizing move operation. operation_runner()->Remove( - src, true /* recursive */, + src_url, false /* recursive */, base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove, weak_factory_.GetWeakPtr(), callback)); } -void CopyOrMoveOperationDelegate::DidFinishCopy( - const URLPair& url_pair, +void CopyOrMoveOperationDelegate::DidCopyOrMoveFile( + const FileSystemURL& src_url, + const FileSystemURL& dest_url, const StatusCallback& callback, + CopyOrMoveImpl* impl, base::PlatformFileError error) { - if (error != base::PLATFORM_FILE_OK) { - callback.Run(error); - return; - } + running_copy_set_.erase(impl); + delete impl; - // |validator_| is NULL in the same-filesystem case or when the destination - // filesystem does not do validation. - if (!validator_.get()) { - scoped_refptr<webkit_blob::ShareableFileReference> file_ref; - DidPostWriteValidation(url_pair, callback, file_ref, - base::PLATFORM_FILE_OK); - return; + if (!progress_callback_.is_null() && error == base::PLATFORM_FILE_OK) { + progress_callback_.Run( + FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0); } - DCHECK(!same_file_system_); - operation_runner()->CreateSnapshotFile( - url_pair.dest, - base::Bind(&CopyOrMoveOperationDelegate::DoPostWriteValidation, - weak_factory_.GetWeakPtr(), url_pair, callback)); + callback.Run(error); } -void CopyOrMoveOperationDelegate::DoPostWriteValidation( - const URLPair& url_pair, +void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot( const StatusCallback& callback, - base::PlatformFileError error, - const base::PlatformFileInfo& file_info, - const base::FilePath& platform_path, - const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { - if (error != base::PLATFORM_FILE_OK) { - operation_runner()->Remove( - url_pair.dest, true, - base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError, - weak_factory_.GetWeakPtr(), error, callback)); + base::PlatformFileError error) { + if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { + callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); + return; + } + if (error != base::PLATFORM_FILE_OK && + error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { + callback_.Run(error); return; } - DCHECK(validator_.get()); - // Note: file_ref passed here to keep the file alive until after - // the StartPostWriteValidation operation finishes. - validator_->StartPostWriteValidation( - platform_path, - base::Bind(&CopyOrMoveOperationDelegate::DidPostWriteValidation, - weak_factory_.GetWeakPtr(), url_pair, callback, file_ref)); + ProcessDirectoryInternal(src_root_, dest_root_, callback); +} + +void CopyOrMoveOperationDelegate::ProcessDirectoryInternal( + const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback) { + // If operation_type == Move we may need to record directories and + // restore directory timestamps in the end, though it may have + // negative performance impact. + // See http://crbug.com/171284 for more details. + operation_runner()->CreateDirectory( + dest_url, false /* exclusive */, false /* recursive */, + base::Bind(&CopyOrMoveOperationDelegate::DidCreateDirectory, + weak_factory_.GetWeakPtr(), src_url, dest_url, callback)); } -// |file_ref| is unused; it is passed here to make sure the reference is -// alive until after post-write validation is complete. -void CopyOrMoveOperationDelegate::DidPostWriteValidation( - const URLPair& url_pair, +void CopyOrMoveOperationDelegate::DidCreateDirectory( + const FileSystemURL& src_url, + const FileSystemURL& dest_url, const StatusCallback& callback, - const scoped_refptr<webkit_blob::ShareableFileReference>& /*file_ref*/, base::PlatformFileError error) { - if (error != base::PLATFORM_FILE_OK) { - operation_runner()->Remove( - url_pair.dest, true, - base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError, - weak_factory_.GetWeakPtr(), error, callback)); - return; + if (!progress_callback_.is_null() && error == base::PLATFORM_FILE_OK) { + progress_callback_.Run( + FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0); } - if (operation_type_ == OPERATION_COPY) { - callback.Run(error); - return; - } - - DCHECK_EQ(OPERATION_MOVE, operation_type_); - - // Remove the source for finalizing move operation. - operation_runner()->Remove( - url_pair.src, true /* recursive */, - base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove, - weak_factory_.GetWeakPtr(), callback)); + callback.Run(error); } void CopyOrMoveOperationDelegate::DidRemoveSourceForMove( @@ -297,6 +483,14 @@ void CopyOrMoveOperationDelegate::DidRemoveSourceForMove( callback.Run(error); } +void CopyOrMoveOperationDelegate::OnCopyFileProgress( + const FileSystemURL& src_url, int64 size) { + if (!progress_callback_.is_null()) { + progress_callback_.Run( + FileSystemOperation::PROGRESS, src_url, FileSystemURL(), size); + } +} + FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( const FileSystemURL& src_url) const { DCHECK_EQ(src_root_.type(), src_url.type()); @@ -311,15 +505,4 @@ FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( relative); } -void CopyOrMoveOperationDelegate::DidRemoveDestForError( - base::PlatformFileError prior_error, - const StatusCallback& callback, - base::PlatformFileError error) { - if (error != base::PLATFORM_FILE_OK) { - VLOG(1) << "Error removing destination file after validation error: " - << error; - } - callback.Run(prior_error); -} - } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h index ceceb971367..77d1a76efc6 100644 --- a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h +++ b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h @@ -23,6 +23,9 @@ class CopyOrMoveFileValidator; class CopyOrMoveOperationDelegate : public RecursiveOperationDelegate { public: + class CopyOrMoveImpl; + typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; + enum OperationType { OPERATION_COPY, OPERATION_MOVE @@ -33,6 +36,7 @@ class CopyOrMoveOperationDelegate const FileSystemURL& src_root, const FileSystemURL& dest_root, OperationType operation_type, + const CopyProgressCallback& progress_callback, const StatusCallback& callback); virtual ~CopyOrMoveOperationDelegate(); @@ -43,75 +47,38 @@ class CopyOrMoveOperationDelegate const StatusCallback& callback) OVERRIDE; virtual void ProcessDirectory(const FileSystemURL& url, const StatusCallback& callback) OVERRIDE; + virtual void PostProcessDirectory(const FileSystemURL& url, + const StatusCallback& callback) OVERRIDE; private: - struct URLPair { - URLPair(const FileSystemURL& src, const FileSystemURL& dest) - : src(src), - dest(dest) { - } - FileSystemURL src; - FileSystemURL dest; - }; - - void DidTryCopyOrMoveFile(base::PlatformFileError error); - void DidTryRemoveDestRoot(base::PlatformFileError error); - void CopyOrMoveFile( - const URLPair& url_pair, - const StatusCallback& callback); - void DidCreateSnapshot( - const URLPair& url_pair, - const StatusCallback& callback, - base::PlatformFileError error, - const base::PlatformFileInfo& file_info, - const base::FilePath& platform_path, - const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref); - void DidValidateFile( - const FileSystemURL& dest, - const StatusCallback& callback, - const base::PlatformFileInfo& file_info, - const base::FilePath& platform_path, - base::PlatformFileError error); - void DidFinishRecursiveCopyDir( - const FileSystemURL& src, - const StatusCallback& callback, - base::PlatformFileError error); - void DidFinishCopy( - const URLPair& url_pair, - const StatusCallback& callback, - base::PlatformFileError error); - void DoPostWriteValidation( - const URLPair& url_pair, - const StatusCallback& callback, - base::PlatformFileError error, - const base::PlatformFileInfo& file_info, - const base::FilePath& platform_path, - const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref); - void DidPostWriteValidation( - const URLPair& url_pair, - const StatusCallback& callback, - const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, - base::PlatformFileError error); - void DidRemoveSourceForMove( - const StatusCallback& callback, - base::PlatformFileError error); - void DidRemoveDestForError( - base::PlatformFileError prior_error, - const StatusCallback& callback, - base::PlatformFileError error); - + void DidCopyOrMoveFile(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback, + CopyOrMoveImpl* impl, + base::PlatformFileError error); + void DidTryRemoveDestRoot(const StatusCallback& callback, + base::PlatformFileError error); + void ProcessDirectoryInternal(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback); + void DidCreateDirectory(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback, + base::PlatformFileError error); + void DidRemoveSourceForMove(const StatusCallback& callback, + base::PlatformFileError error); + + void OnCopyFileProgress(const FileSystemURL& src_url, int64 size); FileSystemURL CreateDestURL(const FileSystemURL& src_url) const; FileSystemURL src_root_; FileSystemURL dest_root_; bool same_file_system_; OperationType operation_type_; + CopyProgressCallback progress_callback_; StatusCallback callback_; - scoped_refptr<webkit_blob::ShareableFileReference> current_file_ref_; - - scoped_ptr<CopyOrMoveFileValidator> validator_; - + std::set<CopyOrMoveImpl*> running_copy_set_; base::WeakPtrFactory<CopyOrMoveOperationDelegate> weak_factory_; DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOperationDelegate); diff --git a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc index 183becd7dbf..322341dc40f 100644 --- a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc +++ b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc @@ -93,6 +93,27 @@ class TestValidatorFactory : public CopyOrMoveFileValidatorFactory { }; }; +// Records CopyProgressCallback invocations. +struct ProgressRecord { + FileSystemOperation::CopyProgressType type; + FileSystemURL source_url; + FileSystemURL dest_url; + int64 size; +}; + +void RecordProgressCallback(std::vector<ProgressRecord>* records, + FileSystemOperation::CopyProgressType type, + const FileSystemURL& source_url, + const FileSystemURL& dest_url, + int64 size) { + ProgressRecord record; + record.type = type; + record.source_url = source_url; + record.dest_url = dest_url; + record.size = size; + records->push_back(record); +} + } // namespace class CopyOrMoveOperationTestHelper { @@ -110,7 +131,7 @@ class CopyOrMoveOperationTestHelper { quota_manager_proxy_->SimulateQuotaManagerDestroyed(); quota_manager_ = NULL; quota_manager_proxy_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void SetUp() { @@ -156,7 +177,7 @@ class CopyOrMoveOperationTestHelper { backend->OpenFileSystem(origin_, dest_type_, OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&ExpectOk)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // Grant relatively big quota initially. quota_manager_->SetQuota(origin_, @@ -194,6 +215,14 @@ class CopyOrMoveOperationTestHelper { return AsyncFileTestHelper::Copy(file_system_context_.get(), src, dest); } + base::PlatformFileError CopyWithProgress( + const FileSystemURL& src, + const FileSystemURL& dest, + const AsyncFileTestHelper::CopyProgressCallback& progress_callback) { + return AsyncFileTestHelper::CopyWithProgress( + file_system_context_.get(), src, dest, progress_callback); + } + base::PlatformFileError Move(const FileSystemURL& src, const FileSystemURL& dest) { return AsyncFileTestHelper::Move(file_system_context_.get(), src, dest); @@ -453,7 +482,10 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopyDirectory) { int64 src_increase = helper.GetSourceUsage() - src_initial_usage; // Copy it. - ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Copy(src, dest)); + ASSERT_EQ(base::PLATFORM_FILE_OK, + helper.CopyWithProgress( + src, dest, + AsyncFileTestHelper::CopyProgressCallback())); // Verify. ASSERT_TRUE(helper.DirectoryExists(src)); @@ -559,4 +591,75 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) { ASSERT_EQ(base::PLATFORM_FILE_ERROR_SECURITY, helper.Copy(src, dest)); } +TEST(LocalFileSystemCopyOrMoveOperationTest, ProgressCallback) { + CopyOrMoveOperationTestHelper helper(GURL("http://foo"), + kFileSystemTypeTemporary, + kFileSystemTypePersistent); + helper.SetUp(); + + FileSystemURL src = helper.SourceURL("a"); + FileSystemURL dest = helper.DestURL("b"); + + // Set up a source directory. + ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src)); + ASSERT_EQ(base::PLATFORM_FILE_OK, + helper.SetUpTestCaseFiles(src, + test::kRegularTestCases, + test::kRegularTestCaseSize)); + + std::vector<ProgressRecord> records; + ASSERT_EQ(base::PLATFORM_FILE_OK, + helper.CopyWithProgress(src, dest, + base::Bind(&RecordProgressCallback, + base::Unretained(&records)))); + + // Verify progress callback. + for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { + const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; + + FileSystemURL src_url = helper.SourceURL( + std::string("a/") + base::FilePath(test_case.path).AsUTF8Unsafe()); + FileSystemURL dest_url = helper.DestURL( + std::string("b/") + base::FilePath(test_case.path).AsUTF8Unsafe()); + + // Find the first and last progress record. + size_t begin_index = records.size(); + size_t end_index = records.size(); + for (size_t j = 0; j < records.size(); ++j) { + if (records[j].source_url == src_url) { + if (begin_index == records.size()) + begin_index = j; + end_index = j; + } + } + + // The record should be found. + ASSERT_NE(begin_index, records.size()); + ASSERT_NE(end_index, records.size()); + ASSERT_NE(begin_index, end_index); + + EXPECT_EQ(FileSystemOperation::BEGIN_COPY_ENTRY, + records[begin_index].type); + EXPECT_FALSE(records[begin_index].dest_url.is_valid()); + EXPECT_EQ(FileSystemOperation::END_COPY_ENTRY, records[end_index].type); + EXPECT_EQ(dest_url, records[end_index].dest_url); + + if (test_case.is_directory) { + // For directory copy, the progress shouldn't be interlaced. + EXPECT_EQ(begin_index + 1, end_index); + } else { + // PROGRESS event's size should be assending order. + int64 current_size = 0; + for (size_t j = begin_index + 1; j < end_index; ++j) { + if (records[j].source_url == src_url) { + EXPECT_EQ(FileSystemOperation::PROGRESS, records[j].type); + EXPECT_FALSE(records[j].dest_url.is_valid()); + EXPECT_GE(records[j].size, current_size); + current_size = records[j].size; + } + } + } + } +} + } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/isolated_file_util.cc b/chromium/webkit/browser/fileapi/dragged_file_util.cc index bd2dffc009e..b4536a70f9a 100644 --- a/chromium/webkit/browser/fileapi/isolated_file_util.cc +++ b/chromium/webkit/browser/fileapi/dragged_file_util.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 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 "webkit/browser/fileapi/isolated_file_util.h" +#include "webkit/browser/fileapi/dragged_file_util.h" #include <string> #include <vector> @@ -58,24 +58,6 @@ class SetFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { //------------------------------------------------------------------------- -IsolatedFileUtil::IsolatedFileUtil() {} - -PlatformFileError IsolatedFileUtil::GetLocalFilePath( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::FilePath* local_file_path) { - DCHECK(local_file_path); - DCHECK(url.is_valid()); - if (url.path().empty()) { - // Root direcory case, which should not be accessed. - return base::PLATFORM_FILE_ERROR_ACCESS_DENIED; - } - *local_file_path = url.path(); - return base::PLATFORM_FILE_OK; -} - -//------------------------------------------------------------------------- - DraggedFileUtil::DraggedFileUtil() {} PlatformFileError DraggedFileUtil::GetFileInfo( diff --git a/chromium/webkit/browser/fileapi/isolated_file_util.h b/chromium/webkit/browser/fileapi/dragged_file_util.h index e6f595572c4..22c538e1b34 100644 --- a/chromium/webkit/browser/fileapi/isolated_file_util.h +++ b/chromium/webkit/browser/fileapi/dragged_file_util.h @@ -1,9 +1,9 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 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. -#ifndef WEBKIT_BROWSER_FILEAPI_ISOLATED_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_ISOLATED_FILE_UTIL_H_ +#ifndef WEBKIT_BROWSER_FILEAPI_DRAGGED_FILE_UTIL_H_ +#define WEBKIT_BROWSER_FILEAPI_DRAGGED_FILE_UTIL_H_ #include "base/memory/scoped_ptr.h" #include "webkit/browser/fileapi/local_file_util.h" @@ -13,24 +13,11 @@ namespace fileapi { class FileSystemOperationContext; -class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE IsolatedFileUtil - : public LocalFileUtil { - public: - IsolatedFileUtil(); - virtual ~IsolatedFileUtil() {} - - // LocalFileUtil overrides. - virtual base::PlatformFileError GetLocalFilePath( - FileSystemOperationContext* context, - const FileSystemURL& file_system_url, - base::FilePath* local_file_path) OVERRIDE; -}; - -// Dragged file system is a specialized IsolatedFileUtil where read access to +// Dragged file system is a specialized LocalFileUtil where read access to // the virtual root directory (i.e. empty cracked path case) is allowed // and single isolated context may be associated with multiple file paths. class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE DraggedFileUtil - : public IsolatedFileUtil { + : public LocalFileUtil { public: DraggedFileUtil(); virtual ~DraggedFileUtil() {} @@ -51,4 +38,4 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE DraggedFileUtil } // namespace fileapi -#endif // WEBKIT_BROWSER_FILEAPI_ISOLATED_FILE_UTIL_H_ +#endif // WEBKIT_BROWSER_FILEAPI_DRAGGED_FILE_UTIL_H_ diff --git a/chromium/webkit/browser/fileapi/isolated_file_util_unittest.cc b/chromium/webkit/browser/fileapi/dragged_file_util_unittest.cc index fee8ed1497d..af15af8f9fd 100644 --- a/chromium/webkit/browser/fileapi/isolated_file_util_unittest.cc +++ b/chromium/webkit/browser/fileapi/dragged_file_util_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 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. @@ -17,10 +17,10 @@ #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/fileapi/async_file_test_helper.h" +#include "webkit/browser/fileapi/dragged_file_util.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/isolated_context.h" -#include "webkit/browser/fileapi/isolated_file_util.h" #include "webkit/browser/fileapi/local_file_util.h" #include "webkit/browser/fileapi/mock_file_system_context.h" #include "webkit/browser/fileapi/native_file_util.h" @@ -32,7 +32,7 @@ namespace { typedef AsyncFileTestHelper::FileEntryList FileEntryList; -// Used in IsolatedFileUtilTest::SimulateDropFiles(). +// Used in DraggedFileUtilTest::SimulateDropFiles(). // Random root paths in which we create each file/directory of the // RegularTestCases (so that we can simulate a drop with files/directories // from multiple directories). @@ -87,11 +87,9 @@ FileSystemURL GetOtherURL(FileSystemContext* file_system_context, } // namespace -// TODO(kinuko): we should have separate tests for DraggedFileUtil and -// IsolatedFileUtil. -class IsolatedFileUtilTest : public testing::Test { +class DraggedFileUtilTest : public testing::Test { public: - IsolatedFileUtilTest() {} + DraggedFileUtilTest() {} virtual void SetUp() { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); @@ -184,8 +182,8 @@ class IsolatedFileUtilTest : public testing::Test { EXPECT_NE(platform_path1, platform_path2); std::string content1, content2; - EXPECT_TRUE(file_util::ReadFileToString(platform_path1, &content1)); - EXPECT_TRUE(file_util::ReadFileToString(platform_path2, &content2)); + EXPECT_TRUE(base::ReadFileToString(platform_path1, &content1)); + EXPECT_TRUE(base::ReadFileToString(platform_path2, &content2)); EXPECT_EQ(content1, content2); } @@ -281,11 +279,11 @@ class IsolatedFileUtilTest : public testing::Test { std::string filesystem_id_; scoped_refptr<FileSystemContext> file_system_context_; std::map<base::FilePath, base::FilePath> toplevel_root_map_; - scoped_ptr<IsolatedFileUtil> file_util_; - DISALLOW_COPY_AND_ASSIGN(IsolatedFileUtilTest); + scoped_ptr<DraggedFileUtil> file_util_; + DISALLOW_COPY_AND_ASSIGN(DraggedFileUtilTest); }; -TEST_F(IsolatedFileUtilTest, BasicTest) { +TEST_F(DraggedFileUtilTest, BasicTest) { for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { SCOPED_TRACE(testing::Message() << "Testing RegularTestCases " << i); const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; @@ -310,7 +308,7 @@ TEST_F(IsolatedFileUtilTest, BasicTest) { } } -TEST_F(IsolatedFileUtilTest, UnregisteredPathsTest) { +TEST_F(DraggedFileUtilTest, UnregisteredPathsTest) { static const fileapi::test::TestCaseRecord kUnregisteredCases[] = { {true, FILE_PATH_LITERAL("nonexistent"), 0}, {true, FILE_PATH_LITERAL("nonexistent/dir foo"), 0}, @@ -345,7 +343,7 @@ TEST_F(IsolatedFileUtilTest, UnregisteredPathsTest) { } } -TEST_F(IsolatedFileUtilTest, ReadDirectoryTest) { +TEST_F(DraggedFileUtilTest, ReadDirectoryTest) { for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; if (!test_case.is_directory) @@ -404,7 +402,7 @@ TEST_F(IsolatedFileUtilTest, ReadDirectoryTest) { } } -TEST_F(IsolatedFileUtilTest, GetLocalFilePathTest) { +TEST_F(DraggedFileUtilTest, GetLocalFilePathTest) { for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path)); @@ -419,7 +417,7 @@ TEST_F(IsolatedFileUtilTest, GetLocalFilePathTest) { } } -TEST_F(IsolatedFileUtilTest, CopyOutFileTest) { +TEST_F(DraggedFileUtilTest, CopyOutFileTest) { FileSystemURL src_root = GetFileSystemURL(base::FilePath()); FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath()); @@ -460,7 +458,7 @@ TEST_F(IsolatedFileUtilTest, CopyOutFileTest) { } } -TEST_F(IsolatedFileUtilTest, CopyOutDirectoryTest) { +TEST_F(DraggedFileUtilTest, CopyOutDirectoryTest) { FileSystemURL src_root = GetFileSystemURL(base::FilePath()); FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath()); @@ -488,7 +486,7 @@ TEST_F(IsolatedFileUtilTest, CopyOutDirectoryTest) { } } -TEST_F(IsolatedFileUtilTest, TouchTest) { +TEST_F(DraggedFileUtilTest, TouchTest) { for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; if (test_case.is_directory) @@ -515,7 +513,7 @@ TEST_F(IsolatedFileUtilTest, TouchTest) { } } -TEST_F(IsolatedFileUtilTest, TruncateTest) { +TEST_F(DraggedFileUtilTest, TruncateTest) { for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; if (test_case.is_directory) diff --git a/chromium/webkit/browser/fileapi/file_stream_writer.h b/chromium/webkit/browser/fileapi/file_stream_writer.h index 7262cdf6ccd..1ebdfb9191a 100644 --- a/chromium/webkit/browser/fileapi/file_stream_writer.h +++ b/chromium/webkit/browser/fileapi/file_stream_writer.h @@ -9,6 +9,11 @@ #include "net/base/completion_callback.h" #include "webkit/browser/webkit_storage_browser_export.h" +namespace base { +class FilePath; +class TaskRunner; +} + namespace net { class IOBuffer; } @@ -16,8 +21,15 @@ class IOBuffer; namespace fileapi { // A generic interface for writing to a file-like object. -class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileStreamWriter { +class FileStreamWriter { public: + // Creates a writer for the existing file in the path |file_path| starting + // from |initial_offset|. Uses |task_runner| for async file operations. + WEBKIT_STORAGE_BROWSER_EXPORT static FileStreamWriter* CreateForLocalFile( + base::TaskRunner* task_runner, + const base::FilePath& file_path, + int64 initial_offset); + // Closes the file. If there's an in-flight operation, it is canceled (i.e., // the callback function associated with the operation is not called). virtual ~FileStreamWriter() {} diff --git a/chromium/webkit/browser/fileapi/file_system_backend.h b/chromium/webkit/browser/fileapi/file_system_backend.h index b368db6c928..2c8be930b3e 100644 --- a/chromium/webkit/browser/fileapi/file_system_backend.h +++ b/chromium/webkit/browser/fileapi/file_system_backend.h @@ -69,11 +69,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemBackend { OpenFileSystemMode mode, const OpenFileSystemCallback& callback) = 0; - // Returns the specialized FileSystemFileUtil for this backend. - // It is ok to return NULL if the filesystem doesn't support synchronous - // version of FileUtil. - virtual FileSystemFileUtil* GetFileUtil(FileSystemType type) = 0; - // Returns the specialized AsyncFileUtil for this backend. virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) = 0; diff --git a/chromium/webkit/browser/fileapi/file_system_context.cc b/chromium/webkit/browser/fileapi/file_system_context.cc index d43ba8a846e..9098649f245 100644 --- a/chromium/webkit/browser/fileapi/file_system_context.cc +++ b/chromium/webkit/browser/fileapi/file_system_context.cc @@ -27,6 +27,7 @@ #include "webkit/browser/fileapi/test_file_system_backend.h" #include "webkit/browser/quota/quota_manager.h" #include "webkit/browser/quota/special_storage_policy.h" +#include "webkit/common/fileapi/file_system_info.h" #include "webkit/common/fileapi/file_system_util.h" using quota::QuotaClient; @@ -49,6 +50,19 @@ void DidOpenFileSystem( callback.Run(error, filesystem_name, filesystem_root); } +void DidGetMetadataForResolveURL( + const base::FilePath& path, + const FileSystemContext::ResolveURLCallback& callback, + const FileSystemInfo& info, + base::PlatformFileError error, + const base::PlatformFileInfo& file_info) { + if (error != base::PLATFORM_FILE_OK) { + callback.Run(error, FileSystemInfo(), base::FilePath(), false); + return; + } + callback.Run(error, info, path, file_info.is_directory); +} + } // namespace // static @@ -108,24 +122,20 @@ FileSystemContext::FileSystemContext( : io_task_runner_(io_task_runner), default_file_task_runner_(file_task_runner), quota_manager_proxy_(quota_manager_proxy), - sandbox_context_(new SandboxContext( + sandbox_delegate_(new SandboxFileSystemBackendDelegate( quota_manager_proxy, file_task_runner, partition_path, special_storage_policy, options)), sandbox_backend_(new SandboxFileSystemBackend( - sandbox_context_.get())), + sandbox_delegate_.get())), isolated_backend_(new IsolatedFileSystemBackend()), additional_backends_(additional_backends.Pass()), external_mount_points_(external_mount_points), partition_path_(partition_path), + is_incognito_(options.is_incognito()), operation_runner_(new FileSystemOperationRunner(this)) { - if (quota_manager_proxy) { - quota_manager_proxy->RegisterClient(CreateQuotaClient( - this, options.is_incognito())); - } - RegisterBackend(sandbox_backend_.get()); RegisterBackend(isolated_backend_.get()); @@ -135,6 +145,12 @@ FileSystemContext::FileSystemContext( RegisterBackend(*iter); } + if (quota_manager_proxy) { + // Quota client assumes all backends have registered. + quota_manager_proxy->RegisterClient(CreateQuotaClient( + this, options.is_incognito())); + } + sandbox_backend_->Initialize(this); isolated_backend_->Initialize(this); for (ScopedVector<FileSystemBackend>::const_iterator iter = @@ -200,14 +216,6 @@ AsyncFileUtil* FileSystemContext::GetAsyncFileUtil( return backend->GetAsyncFileUtil(type); } -FileSystemFileUtil* FileSystemContext::GetFileUtil( - FileSystemType type) const { - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend) - return NULL; - return backend->GetFileUtil(type); -} - CopyOrMoveFileValidatorFactory* FileSystemContext::GetCopyOrMoveFileValidatorFactory( FileSystemType type, base::PlatformFileError* error_code) const { @@ -230,7 +238,8 @@ FileSystemBackend* FileSystemContext::GetFileSystemBackend( } bool FileSystemContext::IsSandboxFileSystem(FileSystemType type) const { - return GetQuotaUtil(type) != NULL; + FileSystemBackendMap::const_iterator found = backend_map_.find(type); + return found != backend_map_.end() && found->second->GetQuotaUtil(); } const UpdateObserverList* FileSystemContext::GetUpdateObservers( @@ -280,6 +289,26 @@ void FileSystemContext::OpenFileSystem( base::Bind(&DidOpenFileSystem, callback)); } +void FileSystemContext::ResolveURL( + const FileSystemURL& url, + const ResolveURLCallback& callback) { + DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(!callback.is_null()); + + FileSystemBackend* backend = GetFileSystemBackend(url.type()); + if (!backend) { + callback.Run(base::PLATFORM_FILE_ERROR_SECURITY, + FileSystemInfo(), base::FilePath(), false); + return; + } + + backend->OpenFileSystem( + url.origin(), url.type(), + OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, + base::Bind(&FileSystemContext::DidOpenFileSystemForResolveURL, + this, url, callback)); +} + void FileSystemContext::DeleteFileSystem( const GURL& origin_url, FileSystemType type, @@ -355,6 +384,16 @@ void FileSystemContext::EnableTemporaryFileSystemInIncognito() { } #endif +bool FileSystemContext::CanServeURLRequest(const FileSystemURL& url) const { +#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) + if (url.type() == kFileSystemTypeTemporary && + sandbox_backend_->enable_temporary_file_system_in_incognito()) { + return true; + } +#endif + return !is_incognito_ || !FileSystemContext::IsSandboxFileSystem(url.type()); +} + FileSystemContext::~FileSystemContext() { } @@ -417,8 +456,7 @@ FileSystemURL FileSystemContext::CrackFileSystemURL( return current; } -void FileSystemContext::RegisterBackend( - FileSystemBackend* backend) { +void FileSystemContext::RegisterBackend(FileSystemBackend* backend) { const FileSystemType mount_types[] = { kFileSystemTypeTemporary, kFileSystemTypePersistent, @@ -445,4 +483,35 @@ void FileSystemContext::RegisterBackend( } } +void FileSystemContext::DidOpenFileSystemForResolveURL( + const FileSystemURL& url, + const FileSystemContext::ResolveURLCallback& callback, + const GURL& filesystem_root, + const std::string& filesystem_name, + base::PlatformFileError error) { + DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); + + if (error != base::PLATFORM_FILE_OK) { + callback.Run(error, FileSystemInfo(), base::FilePath(), false); + return; + } + + fileapi::FileSystemInfo info( + filesystem_name, filesystem_root, url.mount_type()); + + // Extract the virtual path not containing a filesystem type part from |url|. + base::FilePath parent = + base::FilePath::FromUTF8Unsafe(filesystem_root.path()); + base::FilePath child = base::FilePath::FromUTF8Unsafe(url.ToGURL().path()); + base::FilePath path; + + if (parent != child) { + bool result = parent.AppendRelativePath(child, &path); + DCHECK(result); + } + + operation_runner()->GetMetadata( + url, base::Bind(&DidGetMetadataForResolveURL, path, callback, info)); +} + } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/file_system_context.h b/chromium/webkit/browser/fileapi/file_system_context.h index d6934ec7c68..21a31b89eb8 100644 --- a/chromium/webkit/browser/fileapi/file_system_context.h +++ b/chromium/webkit/browser/fileapi/file_system_context.h @@ -17,7 +17,7 @@ #include "base/sequenced_task_runner_helpers.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/open_file_system_mode.h" -#include "webkit/browser/fileapi/sandbox_context.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "webkit/browser/fileapi/task_runner_bound_observer_list.h" #include "webkit/browser/webkit_storage_browser_export.h" #include "webkit/common/fileapi/file_system_types.h" @@ -49,8 +49,8 @@ class CopyOrMoveFileValidatorFactory; class ExternalFileSystemBackend; class ExternalMountPoints; class FileStreamWriter; -class FileSystemFileUtil; class FileSystemBackend; +class FileSystemFileUtil; class FileSystemOperation; class FileSystemOperationRunner; class FileSystemOptions; @@ -61,6 +61,7 @@ class MountPoints; class SandboxFileSystemBackend; struct DefaultContextDeleter; +struct FileSystemInfo; // This class keeps and provides a file system context for FileSystem API. // An instance of this class is created and owned by profile. @@ -119,11 +120,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext // Returns the appropriate AsyncFileUtil instance for the given |type|. AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) const; - // Returns the appropriate FileUtil instance for the given |type|. - // This may return NULL if it is given an invalid type or the filesystem - // does not support synchronous file operations. - FileSystemFileUtil* GetFileUtil(FileSystemType type) const; - // Returns the appropriate CopyOrMoveFileValidatorFactory for the given // |type|. If |error_code| is PLATFORM_FILE_OK and the result is NULL, // then no validator is required. @@ -159,6 +155,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext const std::string& name, const GURL& root)> OpenFileSystemCallback; + // Used for ResolveURL. + typedef base::Callback<void(base::PlatformFileError result, + const FileSystemInfo& info, + const base::FilePath& file_path, + bool is_directory)> ResolveURLCallback; + // Used for DeleteFileSystem. typedef base::Callback<void(base::PlatformFileError result)> DeleteFileSystemCallback; @@ -174,8 +176,15 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext OpenFileSystemMode mode, const OpenFileSystemCallback& callback); + // Opens the filesystem for the given |url| as read-only, and then checks the + // existence of the file entry referred by the URL. This should be called on + // the IO thread. + void ResolveURL( + const FileSystemURL& url, + const ResolveURLCallback& callback); + // Deletes the filesystem for the given |origin_url| and |type|. This should - // be called on the IO Thread. + // be called on the IO thread. void DeleteFileSystem( const GURL& origin_url, FileSystemType type, @@ -228,7 +237,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext void EnableTemporaryFileSystemInIncognito(); #endif - SandboxContext* sandbox_context() { return sandbox_context_.get(); } + SandboxFileSystemBackendDelegate* sandbox_delegate() { + return sandbox_delegate_.get(); + } + + // Returns true if the requested url is ok to be served. + // (E.g. this returns false if the context is created for incognito mode) + bool CanServeURLRequest(const FileSystemURL& url) const; private: typedef std::map<FileSystemType, FileSystemBackend*> @@ -273,6 +288,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext // the constructor. void RegisterBackend(FileSystemBackend* backend); + void DidOpenFileSystemForResolveURL( + const FileSystemURL& url, + const ResolveURLCallback& callback, + const GURL& filesystem_root, + const std::string& filesystem_name, + base::PlatformFileError error); + // Returns a FileSystemBackend, used only by test code. SandboxFileSystemBackend* sandbox_backend() const { return sandbox_backend_.get(); @@ -283,7 +305,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_; - scoped_ptr<SandboxContext> sandbox_context_; + scoped_ptr<SandboxFileSystemBackendDelegate> sandbox_delegate_; // Regular file system backends. scoped_ptr<SandboxFileSystemBackend> sandbox_backend_; @@ -311,6 +333,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext // The base path of the storage partition for this context. const base::FilePath partition_path_; + bool is_incognito_; + scoped_ptr<FileSystemOperationRunner> operation_runner_; DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext); diff --git a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc b/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc index b91c7d00d9d..721a228b94e 100644 --- a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc +++ b/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc @@ -23,6 +23,7 @@ #include "webkit/browser/fileapi/file_system_operation_runner.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/common/fileapi/directory_entry.h" +#include "webkit/common/fileapi/file_system_util.h" using net::NetworkDelegate; using net::URLRequest; @@ -80,6 +81,19 @@ void FileSystemDirURLRequestJob::StartAsync() { if (!request_) return; url_ = file_system_context_->CrackURL(request_->url()); + if (!file_system_context_->CanServeURLRequest(url_)) { + // In incognito mode the API is not usable and there should be no data. + if (url_.is_valid() && VirtualPath::IsRootPath(url_.virtual_path())) { + // Return an empty directory if the filesystem root is queried. + DidReadDirectory(base::PLATFORM_FILE_OK, + std::vector<DirectoryEntry>(), + false); + return; + } + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + net::ERR_FILE_NOT_FOUND)); + return; + } file_system_context_->operation_runner()->ReadDirectory( url_, base::Bind(&FileSystemDirURLRequestJob::DidReadDirectory, this)); diff --git a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc index 1c197cd294d..e43ee4dfa3b 100644 --- a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc @@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/platform_file.h" +#include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "net/base/net_errors.h" @@ -57,7 +58,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test { OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&FileSystemDirURLRequestJobTest::OnOpenFileSystem, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); net::URLRequest::Deprecated::RegisterProtocolFactory( "filesystem", &FileSystemDirURLRequestJobFactory); @@ -78,12 +79,13 @@ class FileSystemDirURLRequestJobTest : public testing::Test { ASSERT_EQ(base::PLATFORM_FILE_OK, result); } - void TestRequestHelper(const GURL& url, bool run_to_completion) { + void TestRequestHelper(const GURL& url, bool run_to_completion, + FileSystemContext* file_system_context) { delegate_.reset(new net::TestDelegate()); delegate_->set_quit_on_redirect(true); request_.reset(empty_context_.CreateRequest(url, delegate_.get())); job_ = new FileSystemDirURLRequestJob( - request_.get(), NULL, file_system_context_.get()); + request_.get(), NULL, file_system_context); request_->Start(); ASSERT_TRUE(request_->is_pending()); // verify that we're starting async @@ -92,11 +94,16 @@ class FileSystemDirURLRequestJobTest : public testing::Test { } void TestRequest(const GURL& url) { - TestRequestHelper(url, true); + TestRequestHelper(url, true, file_system_context_.get()); + } + + void TestRequestWithContext(const GURL& url, + FileSystemContext* file_system_context) { + TestRequestHelper(url, true, file_system_context); } void TestRequestNoRun(const GURL& url) { - TestRequestHelper(url, false); + TestRequestHelper(url, false, file_system_context_.get()); } FileSystemURL CreateURL(const base::FilePath& file_path) { @@ -199,7 +206,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test { } FileSystemFileUtil* file_util() { - return file_system_context_->GetFileUtil(kFileSystemTypeTemporary); + return file_system_context_->sandbox_delegate()->sync_file_util(); } // Put the message loop at the top, so that it's the last thing deleted. @@ -282,9 +289,32 @@ TEST_F(FileSystemDirURLRequestJobTest, Cancel) { TestRequestNoRun(CreateFileSystemURL("foo/")); // Run StartAsync() and only StartAsync(). base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // If we get here, success! we didn't crash! } +TEST_F(FileSystemDirURLRequestJobTest, Incognito) { + CreateDirectory("foo"); + + scoped_refptr<FileSystemContext> file_system_context = + CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path()); + + TestRequestWithContext(CreateFileSystemURL("/"), + file_system_context.get()); + ASSERT_FALSE(request_->is_pending()); + ASSERT_TRUE(request_->status().is_success()); + + std::istringstream in(delegate_->data_received()); + std::string line; + EXPECT_TRUE(std::getline(in, line)); + EXPECT_FALSE(std::getline(in, line)); + + TestRequestWithContext(CreateFileSystemURL("foo"), + file_system_context.get()); + ASSERT_FALSE(request_->is_pending()); + ASSERT_FALSE(request_->status().is_success()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error()); +} + } // namespace (anonymous) } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc b/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc index 71b38278186..d3697c201e5 100644 --- a/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc +++ b/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc @@ -10,11 +10,29 @@ #include "net/base/file_stream.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "webkit/browser/blob/local_file_stream_reader.h" +#include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_runner.h" -using webkit_blob::LocalFileStreamReader; +using webkit_blob::FileStreamReader; + +// TODO(kinuko): Remove this temporary namespace hack after we move both +// blob and fileapi into content namespace. +namespace webkit_blob { + +FileStreamReader* FileStreamReader::CreateForFileSystemFile( + fileapi::FileSystemContext* file_system_context, + const fileapi::FileSystemURL& url, + int64 initial_offset, + const base::Time& expected_modification_time) { + return new fileapi::FileSystemFileStreamReader( + file_system_context, + url, + initial_offset, + expected_modification_time); +} + +} // webkit_blob namespace fileapi { @@ -46,19 +64,6 @@ void Int64CallbackAdapter(const net::Int64CompletionCallback& callback, } // namespace -FileSystemFileStreamReader::FileSystemFileStreamReader( - FileSystemContext* file_system_context, - const FileSystemURL& url, - int64 initial_offset, - const base::Time& expected_modification_time) - : file_system_context_(file_system_context), - url_(url), - initial_offset_(initial_offset), - expected_modification_time_(expected_modification_time), - has_pending_create_snapshot_(false), - weak_factory_(this) { -} - FileSystemFileStreamReader::~FileSystemFileStreamReader() { } @@ -82,6 +87,19 @@ int64 FileSystemFileStreamReader::GetLength( base::Bind(&Int64CallbackAdapter, callback)); } +FileSystemFileStreamReader::FileSystemFileStreamReader( + FileSystemContext* file_system_context, + const FileSystemURL& url, + int64 initial_offset, + const base::Time& expected_modification_time) + : file_system_context_(file_system_context), + url_(url), + initial_offset_(initial_offset), + expected_modification_time_(expected_modification_time), + has_pending_create_snapshot_(false), + weak_factory_(this) { +} + int FileSystemFileStreamReader::CreateSnapshot( const base::Closure& callback, const net::CompletionCallback& error_callback) { @@ -116,7 +134,7 @@ void FileSystemFileStreamReader::DidCreateSnapshot( snapshot_ref_ = file_ref; local_file_reader_.reset( - new LocalFileStreamReader( + FileStreamReader::CreateForLocalFile( file_system_context_->default_file_task_runner(), platform_path, initial_offset_, expected_modification_time_)); diff --git a/chromium/webkit/browser/fileapi/file_system_file_stream_reader.h b/chromium/webkit/browser/fileapi/file_system_file_stream_reader.h index 634f5684c42..3a90663ed95 100644 --- a/chromium/webkit/browser/fileapi/file_system_file_stream_reader.h +++ b/chromium/webkit/browser/fileapi/file_system_file_stream_reader.h @@ -19,30 +19,18 @@ class FilePath; class SequencedTaskRunner; } -namespace webkit_blob { -class LocalFileStreamReader; -} - namespace fileapi { class FileSystemContext; -// TODO(kinaba,satorux): This generic implementation would work for any -// filesystems but remote filesystem should implement its own reader -// rather than relying on FileSystemOperation::GetSnapshotFile() which -// may force downloading the entire contents for remote files. +// Generic FileStreamReader implementation for FileSystem files. +// Note: This generic implementation would work for any filesystems but +// remote filesystem should implement its own reader rather than relying +// on FileSystemOperation::GetSnapshotFile() which may force downloading +// the entire contents for remote files. class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemFileStreamReader - : public webkit_blob::FileStreamReader { + : public NON_EXPORTED_BASE(webkit_blob::FileStreamReader) { public: - // Creates a new FileReader for a filesystem URL |url| form |initial_offset|. - // |expected_modification_time| specifies the expected last modification if - // the value is non-null, the reader will check the underlying file's actual - // modification time to see if the file has been modified, and if it does any - // succeeding read operations should fail with ERR_UPLOAD_FILE_CHANGED error. - FileSystemFileStreamReader(FileSystemContext* file_system_context, - const FileSystemURL& url, - int64 initial_offset, - const base::Time& expected_modification_time); virtual ~FileSystemFileStreamReader(); // FileStreamReader overrides. @@ -52,6 +40,14 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemFileStreamReader const net::Int64CompletionCallback& callback) OVERRIDE; private: + friend class webkit_blob::FileStreamReader; + friend class FileSystemFileStreamReaderTest; + + FileSystemFileStreamReader(FileSystemContext* file_system_context, + const FileSystemURL& url, + int64 initial_offset, + const base::Time& expected_modification_time); + int CreateSnapshot(const base::Closure& callback, const net::CompletionCallback& error_callback); void DidCreateSnapshot( @@ -66,7 +62,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemFileStreamReader FileSystemURL url_; const int64 initial_offset_; const base::Time expected_modification_time_; - scoped_ptr<webkit_blob::LocalFileStreamReader> local_file_reader_; + scoped_ptr<webkit_blob::FileStreamReader> local_file_reader_; scoped_refptr<webkit_blob::ShareableFileReference> snapshot_ref_; bool has_pending_create_snapshot_; base::WeakPtrFactory<FileSystemFileStreamReader> weak_factory_; diff --git a/chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc b/chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc index ca82338a5cc..0ce56585e42 100644 --- a/chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc @@ -9,16 +9,16 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/platform_file.h" +#include "base/run_loop.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/fileapi/async_file_test_helper.h" #include "webkit/browser/fileapi/external_mount_points.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/mock_file_system_context.h" namespace fileapi { @@ -73,14 +73,14 @@ class FileSystemFileStreamReaderTest : public testing::Test { GURL(kURLOrigin), kFileSystemTypeTemporary, OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&OnOpenFileSystem)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); WriteFile(kTestFileName, kTestData, kTestDataSize, &test_file_modification_time_); } virtual void TearDown() OVERRIDE { - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } protected: @@ -102,32 +102,16 @@ class FileSystemFileStreamReaderTest : public testing::Test { const char* buf, int buf_size, base::Time* modification_time) { - FileSystemFileUtil* file_util = file_system_context_->GetFileUtil( - kFileSystemTypeTemporary); FileSystemURL url = GetFileSystemURL(file_name); - FileSystemOperationContext context(file_system_context_.get()); - context.set_allowed_bytes_growth(1024); - - base::PlatformFile handle = base::kInvalidPlatformFileValue; - bool created = false; - ASSERT_EQ(base::PLATFORM_FILE_OK, file_util->CreateOrOpen( - &context, - url, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, - &handle, - &created)); - EXPECT_TRUE(created); - ASSERT_NE(base::kInvalidPlatformFileValue, handle); - ASSERT_EQ(buf_size, - base::WritePlatformFile(handle, 0 /* offset */, buf, buf_size)); - base::ClosePlatformFile(handle); + ASSERT_EQ(base::PLATFORM_FILE_OK, + fileapi::AsyncFileTestHelper::CreateFileWithData( + file_system_context_, url, buf, buf_size)); base::PlatformFileInfo file_info; - base::FilePath platform_path; ASSERT_EQ(base::PLATFORM_FILE_OK, - file_util->GetFileInfo(&context, url, &file_info, - &platform_path)); + AsyncFileTestHelper::GetMetadata( + file_system_context_, url, &file_info)); if (modification_time) *modification_time = file_info.last_modified; } diff --git a/chromium/webkit/browser/fileapi/file_system_operation.h b/chromium/webkit/browser/fileapi/file_system_operation.h index f1adc191a7e..99d3b3d6a97 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation.h +++ b/chromium/webkit/browser/fileapi/file_system_operation.h @@ -11,6 +11,8 @@ #include "base/files/file_path.h" #include "base/platform_file.h" #include "base/process/process.h" +#include "webkit/browser/fileapi/file_system_operation_context.h" +#include "webkit/browser/webkit_storage_browser_export.h" #include "webkit/common/fileapi/directory_entry.h" namespace base { @@ -29,9 +31,9 @@ class GURL; namespace fileapi { +class FileSystemContext; class FileSystemURL; class FileWriterDelegate; -class FileSystemOperationImpl; // The interface class for FileSystemOperation implementations. // @@ -56,6 +58,11 @@ class FileSystemOperationImpl; // it gets called. class FileSystemOperation { public: + WEBKIT_STORAGE_BROWSER_EXPORT static FileSystemOperation* Create( + const FileSystemURL& url, + FileSystemContext* file_system_context, + scoped_ptr<FileSystemOperationContext> operation_context); + virtual ~FileSystemOperation() {} // Used for CreateFile(), etc. |result| is the return code of the operation. @@ -115,6 +122,93 @@ class FileSystemOperation { const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref)> SnapshotFileCallback; + // Used for progress update callback for Copy(). + // + // BEGIN_COPY_ENTRY is fired for each copy creation beginning (for both + // file and directory). + // The |source_url| is the URL of the source entry. |size| should not be + // used. + // + // END_COPY_ENTRY is fired for each copy creation finishing (for both + // file and directory). + // The |source_url| is the URL of the source entry. The |destination_url| is + // the URL of the destination entry. |size| should not be used. + // + // PROGRESS is fired periodically during file copying (not fired for + // directory copy). + // The |source_url| is the URL of the source file. |size| is the number + // of cumulative copied bytes for the currently copied file. + // Both at beginning and ending of file copying, PROGRESS event should be + // called. At beginning, |size| should be 0. At ending, |size| should be + // the size of the file. + // + // Here is an example callback sequence of recursive copy. Suppose + // there are a/b/c.txt (100 bytes) and a/b/d.txt (200 bytes), and trying to + // copy a to x recursively, then the progress update sequence will be: + // + // BEGIN_COPY_ENTRY a (starting create "a" directory in x/). + // END_COPY_ENTRY a x/a (creating "a" directory in x/ is finished). + // + // BEGIN_COPY_ENTRY a/b (starting create "b" directory in x/a). + // END_COPY_ENTRY a/b x/a/b (creating "b" directory in x/a/ is finished). + // + // BEGIN_COPY_ENTRY a/b/c.txt (starting to copy "c.txt" in x/a/b/). + // PROGRESS a/b/c.txt 0 (The first PROGRESS's |size| should be 0). + // PROGRESS a/b/c.txt 10 + // : + // PROGRESS a/b/c.txt 90 + // PROGRESS a/b/c.txt 100 (The last PROGRESS's |size| should be the size of + // the file). + // END_COPY_ENTRY a/b/c.txt x/a/b/c.txt (copying "c.txt" is finished). + // + // BEGIN_COPY_ENTRY a/b/d.txt (starting to copy "d.txt" in x/a/b). + // PROGRESS a/b/d.txt 0 (The first PROGRESS's |size| should be 0). + // PROGRESS a/b/d.txt 10 + // : + // PROGRESS a/b/d.txt 190 + // PROGRESS a/b/d.txt 200 (The last PROGRESS's |size| should be the size of + // the file). + // END_COPY_ENTRY a/b/d.txt x/a/b/d.txt (copy "d.txt" is finished). + // + // Note that event sequence of a/b/c.txt and a/b/d.txt can be interlaced, + // because they can be done in parallel. Also PROGRESS events are optional, + // so they may not be appeared. + // All the progress callback invocation should be done before StatusCallback + // given to the Copy is called. Especially if an error is found before first + // progres callback invocation, the progress callback may NOT invoked for the + // copy. + // + // Note for future extension. Currently this callback is only supported on + // Copy(). We can extend this to Move(), because Move() is sometimes + // implemented as "copy then delete." + // In more precise, Move() usually can be implemented either 1) by updating + // the metadata of resource (e.g. root of moving directory tree), or 2) by + // copying directory tree and them removing the source tree. + // For 1)'s case, we can simply add BEGIN_MOVE_ENTRY and END_MOVE_ENTRY + // for root directory. + // For 2)'s case, we can add BEGIN_DELETE_ENTRY and END_DELETE_ENTRY for each + // entry. + // For both cases, we probably won't need to use PROGRESS event because + // these operations should be done quickly (at least much faster than copying + // usually). + enum CopyProgressType { + BEGIN_COPY_ENTRY, + END_COPY_ENTRY, + PROGRESS, + }; + typedef base::Callback<void(CopyProgressType type, + const FileSystemURL& source_url, + const FileSystemURL& destination_url, + int64 size)> + CopyProgressCallback; + + // Used for CopyFileLocal() to report progress update. + // |size| is the cumulative copied bytes for the copy. + // At the beginning the progress callback should be called with |size| = 0, + // and also at the ending the progress callback should be called with |size| + // set to the copied file size. + typedef base::Callback<void(int64 size)> CopyFileProgressCallback; + // Used for Write(). typedef base::Callback<void(base::PlatformFileError result, int64 bytes, @@ -139,12 +233,34 @@ class FileSystemOperation { // |src_path| is a directory, the contents of |src_path| are copied to // |dest_path| recursively. A new file or directory is created at // |dest_path| as needed. + // |progress_callback| is periodically called to report the progress + // update. See also the comment of CopyProgressCallback. This callback is + // optional. + // + // For recursive case this internally creates new FileSystemOperations and + // calls: + // - ReadDirectory, CopyFileLocal and CreateDirectory + // for same-filesystem case, or + // - ReadDirectory and CreateSnapshotFile on source filesystem and + // CopyInForeignFile and CreateDirectory on dest filesystem + // for cross-filesystem case. + // virtual void Copy(const FileSystemURL& src_path, const FileSystemURL& dest_path, + const CopyProgressCallback& progress_callback, const StatusCallback& callback) = 0; // Moves a file or directory from |src_path| to |dest_path|. A new file // or directory is created at |dest_path| as needed. + // + // For recursive case this internally creates new FileSystemOperations and + // calls: + // - ReadDirectory, MoveFileLocal, CreateDirectory and Remove + // for same-filesystem case, or + // - ReadDirectory, CreateSnapshotFile and Remove on source filesystem and + // CopyInForeignFile and CreateDirectory on dest filesystem + // for cross-filesystem case. + // virtual void Move(const FileSystemURL& src_path, const FileSystemURL& dest_path, const StatusCallback& callback) = 0; @@ -230,11 +346,6 @@ class FileSystemOperation { base::ProcessHandle peer_handle, const OpenFileCallback& callback) = 0; - // For downcasting to FileSystemOperationImpl. - // TODO(kinuko): this hack should go away once appropriate upload-stream - // handling based on element types is supported. - virtual FileSystemOperationImpl* AsFileSystemOperationImpl() = 0; - // Creates a local snapshot file for a given |path| and returns the // metadata and platform path of the snapshot file via |callback|. // In local filesystem cases the implementation may simply return @@ -246,6 +357,86 @@ class FileSystemOperation { virtual void CreateSnapshotFile(const FileSystemURL& path, const SnapshotFileCallback& callback) = 0; + // Copies in a single file from a different filesystem. + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_file_path| + // or the parent directory of |dest_url| does not exist. + // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and + // is not a file. + // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and + // its parent path is a file. + // + virtual void CopyInForeignFile(const base::FilePath& src_local_disk_path, + const FileSystemURL& dest_url, + const StatusCallback& callback) = 0; + + // Removes a single file. + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. + // - PLATFORM_FILE_ERROR_NOT_A_FILE if |url| is not a file. + // + virtual void RemoveFile(const FileSystemURL& url, + const StatusCallback& callback) = 0; + + // Removes a single empty directory. + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. + // - PLATFORM_FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory. + // - PLATFORM_FILE_ERROR_NOT_EMPTY if |url| is not empty. + // + virtual void RemoveDirectory(const FileSystemURL& url, + const StatusCallback& callback) = 0; + + // Copies a file from |src_url| to |dest_url|. + // This must be called for files that belong to the same filesystem + // (i.e. type() and origin() of the |src_url| and |dest_url| must match). + // |progress_callback| is periodically called to report the progress + // update. See also the comment of CopyFileProgressCallback. This callback is + // optional. + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url| + // or the parent directory of |dest_url| does not exist. + // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. + // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and + // is not a file. + // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and + // its parent path is a file. + // + virtual void CopyFileLocal(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, + const StatusCallback& callback) = 0; + + // Moves a local file from |src_url| to |dest_url|. + // This must be called for files that belong to the same filesystem + // (i.e. type() and origin() of the |src_url| and |dest_url| must match). + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url| + // or the parent directory of |dest_url| does not exist. + // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. + // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and + // is not a file. + // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and + // its parent path is a file. + // + virtual void MoveFileLocal(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback) = 0; + + // Synchronously gets the platform path for the given |url|. + // This may fail if the given |url|'s filesystem type is neither + // temporary nor persistent. + // In such a case, base::PLATFORM_FILE_ERROR_INVALID_OPERATION will be + // returned. + virtual base::PlatformFileError SyncGetPlatformPath( + const FileSystemURL& url, + base::FilePath* platform_path) = 0; + protected: // Used only for internal assertions. enum OperationType { diff --git a/chromium/webkit/browser/fileapi/file_system_operation_context.h b/chromium/webkit/browser/fileapi/file_system_operation_context.h index 4d175108482..decdecbb5ca 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation_context.h +++ b/chromium/webkit/browser/fileapi/file_system_operation_context.h @@ -52,7 +52,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemOperationContext int64 allowed_bytes_growth() const { return allowed_bytes_growth_; } quota::QuotaLimitType quota_limit_type() const { return quota_limit_type_; } base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } - const base::FilePath& root_path() const { return root_path_; } ChangeObserverList* change_observers() { return &change_observers_; } UpdateObserverList* update_observers() { return &update_observers_; } @@ -72,10 +71,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemOperationContext DCHECK(setter_thread_checker_.CalledOnValidThread()); quota_limit_type_ = limit_type; } - void set_root_path(const base::FilePath& root_path) { - DCHECK(setter_thread_checker_.CalledOnValidThread()); - root_path_ = root_path; - } private: scoped_refptr<FileSystemContext> file_system_context_; @@ -91,9 +86,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemOperationContext ChangeObserverList change_observers_; UpdateObserverList update_observers_; - // Root path for the operation, used by LocalFileUtil. - base::FilePath root_path_; - // Used to check its setters are not called on arbitrary thread. base::ThreadChecker setter_thread_checker_; diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl.cc b/chromium/webkit/browser/fileapi/file_system_operation_impl.cc index 60f79901923..c9e75eb9acd 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation_impl.cc +++ b/chromium/webkit/browser/fileapi/file_system_operation_impl.cc @@ -20,7 +20,7 @@ #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/file_writer_delegate.h" #include "webkit/browser/fileapi/remove_operation_delegate.h" -#include "webkit/browser/fileapi/sandbox_file_stream_writer.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend.h" #include "webkit/browser/quota/quota_manager.h" #include "webkit/common/blob/shareable_file_reference.h" #include "webkit/common/fileapi/file_system_types.h" @@ -31,19 +31,12 @@ using webkit_blob::ScopedFile; namespace fileapi { -FileSystemOperationImpl::FileSystemOperationImpl( +FileSystemOperation* FileSystemOperation::Create( const FileSystemURL& url, FileSystemContext* file_system_context, - scoped_ptr<FileSystemOperationContext> operation_context) - : file_system_context_(file_system_context), - operation_context_(operation_context.Pass()), - async_file_util_(NULL), - peer_handle_(base::kNullProcessHandle), - pending_operation_(kOperationNone) { - DCHECK(operation_context_.get()); - operation_context_->DetachUserDataThread(); - async_file_util_ = file_system_context_->GetAsyncFileUtil(url.type()); - DCHECK(async_file_util_); + scoped_ptr<FileSystemOperationContext> operation_context) { + return new FileSystemOperationImpl(url, file_system_context, + operation_context.Pass()); } FileSystemOperationImpl::~FileSystemOperationImpl() { @@ -56,7 +49,7 @@ void FileSystemOperationImpl::CreateFile(const FileSystemURL& url, GetUsageAndQuotaThenRunTask( url, base::Bind(&FileSystemOperationImpl::DoCreateFile, - AsWeakPtr(), url, callback, exclusive), + weak_factory_.GetWeakPtr(), url, callback, exclusive), base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED)); } @@ -68,22 +61,28 @@ void FileSystemOperationImpl::CreateDirectory(const FileSystemURL& url, GetUsageAndQuotaThenRunTask( url, base::Bind(&FileSystemOperationImpl::DoCreateDirectory, - AsWeakPtr(), url, callback, exclusive, recursive), + weak_factory_.GetWeakPtr(), url, callback, + exclusive, recursive), base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED)); } -void FileSystemOperationImpl::Copy(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback) { +void FileSystemOperationImpl::Copy( + const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const CopyProgressCallback& progress_callback, + const StatusCallback& callback) { DCHECK(SetPendingOperationType(kOperationCopy)); DCHECK(!recursive_operation_delegate_); + + // TODO(hidehiko): Support |progress_callback|. (crbug.com/278038). recursive_operation_delegate_.reset( new CopyOrMoveOperationDelegate( file_system_context(), src_url, dest_url, CopyOrMoveOperationDelegate::OPERATION_COPY, + progress_callback, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback))); + weak_factory_.GetWeakPtr(), callback))); recursive_operation_delegate_->RunRecursively(); } @@ -97,8 +96,9 @@ void FileSystemOperationImpl::Move(const FileSystemURL& src_url, file_system_context(), src_url, dest_url, CopyOrMoveOperationDelegate::OPERATION_MOVE, + FileSystemOperation::CopyProgressCallback(), base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback))); + weak_factory_.GetWeakPtr(), callback))); recursive_operation_delegate_->RunRecursively(); } @@ -108,7 +108,7 @@ void FileSystemOperationImpl::DirectoryExists(const FileSystemURL& url, async_file_util_->GetFileInfo( operation_context_.Pass(), url, base::Bind(&FileSystemOperationImpl::DidDirectoryExists, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::FileExists(const FileSystemURL& url, @@ -117,7 +117,7 @@ void FileSystemOperationImpl::FileExists(const FileSystemURL& url, async_file_util_->GetFileInfo( operation_context_.Pass(), url, base::Bind(&FileSystemOperationImpl::DidFileExists, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::GetMetadata( @@ -146,7 +146,7 @@ void FileSystemOperationImpl::Remove(const FileSystemURL& url, async_file_util_->DeleteRecursively( operation_context_.Pass(), url, base::Bind(&FileSystemOperationImpl::DidDeleteRecursively, - AsWeakPtr(), url, callback)); + weak_factory_.GetWeakPtr(), url, callback)); return; } @@ -154,7 +154,7 @@ void FileSystemOperationImpl::Remove(const FileSystemURL& url, new RemoveOperationDelegate( file_system_context(), url, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback))); + weak_factory_.GetWeakPtr(), callback))); recursive_operation_delegate_->Run(); } @@ -167,8 +167,8 @@ void FileSystemOperationImpl::Write( file_writer_delegate_ = writer_delegate.Pass(); file_writer_delegate_->Start( blob_request.Pass(), - base::Bind(&FileSystemOperationImpl::DidWrite, AsWeakPtr(), - url, callback)); + base::Bind(&FileSystemOperationImpl::DidWrite, + weak_factory_.GetWeakPtr(), url, callback)); } void FileSystemOperationImpl::Truncate(const FileSystemURL& url, int64 length, @@ -177,7 +177,7 @@ void FileSystemOperationImpl::Truncate(const FileSystemURL& url, int64 length, GetUsageAndQuotaThenRunTask( url, base::Bind(&FileSystemOperationImpl::DoTruncate, - AsWeakPtr(), url, callback, length), + weak_factory_.GetWeakPtr(), url, callback, length), base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED)); } @@ -190,7 +190,7 @@ void FileSystemOperationImpl::TouchFile(const FileSystemURL& url, operation_context_.Pass(), url, last_access_time, last_modified_time, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::OpenFile(const FileSystemURL& url, @@ -212,7 +212,7 @@ void FileSystemOperationImpl::OpenFile(const FileSystemURL& url, GetUsageAndQuotaThenRunTask( url, base::Bind(&FileSystemOperationImpl::DoOpenFile, - AsWeakPtr(), + weak_factory_.GetWeakPtr(), url, callback, file_flags), base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED, base::kInvalidPlatformFileValue, @@ -230,6 +230,9 @@ void FileSystemOperationImpl::Cancel(const StatusCallback& cancel_callback) { DCHECK_EQ(kOperationWrite, pending_operation_); // This will call DidWrite() with ABORT status code. file_writer_delegate_->Cancel(); + } else if (recursive_operation_delegate_) { + // This will call DidFinishOperation() with ABORT status code. + recursive_operation_delegate_->Cancel(); } else { // For truncate we have no way to cancel the inflight operation (for now). // Let it just run and dispatch cancel callback later. @@ -237,22 +240,6 @@ void FileSystemOperationImpl::Cancel(const StatusCallback& cancel_callback) { } } -FileSystemOperationImpl* FileSystemOperationImpl::AsFileSystemOperationImpl() { - return this; -} - -base::PlatformFileError FileSystemOperationImpl::SyncGetPlatformPath( - const FileSystemURL& url, - base::FilePath* platform_path) { - DCHECK(SetPendingOperationType(kOperationGetLocalPath)); - FileSystemFileUtil* file_util = file_system_context()->GetFileUtil( - url.type()); - if (!file_util) - return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; - file_util->GetLocalFilePath(operation_context_.get(), url, platform_path); - return base::PLATFORM_FILE_OK; -} - void FileSystemOperationImpl::CreateSnapshotFile( const FileSystemURL& url, const SnapshotFileCallback& callback) { @@ -269,7 +256,7 @@ void FileSystemOperationImpl::CopyInForeignFile( GetUsageAndQuotaThenRunTask( dest_url, base::Bind(&FileSystemOperationImpl::DoCopyInForeignFile, - AsWeakPtr(), src_local_disk_file_path, dest_url, + weak_factory_.GetWeakPtr(), src_local_disk_file_path, dest_url, callback), base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED)); } @@ -281,7 +268,7 @@ void FileSystemOperationImpl::RemoveFile( async_file_util_->DeleteFile( operation_context_.Pass(), url, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::RemoveDirectory( @@ -291,19 +278,22 @@ void FileSystemOperationImpl::RemoveDirectory( async_file_util_->DeleteDirectory( operation_context_.Pass(), url, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::CopyFileLocal( const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback) { DCHECK(SetPendingOperationType(kOperationCopy)); DCHECK(src_url.IsInSameFileSystem(dest_url)); + GetUsageAndQuotaThenRunTask( dest_url, base::Bind(&FileSystemOperationImpl::DoCopyFileLocal, - AsWeakPtr(), src_url, dest_url, callback), + weak_factory_.GetWeakPtr(), src_url, dest_url, + progress_callback, callback), base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED)); } @@ -316,10 +306,38 @@ void FileSystemOperationImpl::MoveFileLocal( GetUsageAndQuotaThenRunTask( dest_url, base::Bind(&FileSystemOperationImpl::DoMoveFileLocal, - AsWeakPtr(), src_url, dest_url, callback), + weak_factory_.GetWeakPtr(), src_url, dest_url, callback), base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED)); } +base::PlatformFileError FileSystemOperationImpl::SyncGetPlatformPath( + const FileSystemURL& url, + base::FilePath* platform_path) { + DCHECK(SetPendingOperationType(kOperationGetLocalPath)); + if (!file_system_context()->IsSandboxFileSystem(url.type())) + return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; + FileSystemFileUtil* file_util = + file_system_context()->sandbox_delegate()->sync_file_util(); + file_util->GetLocalFilePath(operation_context_.get(), url, platform_path); + return base::PLATFORM_FILE_OK; +} + +FileSystemOperationImpl::FileSystemOperationImpl( + const FileSystemURL& url, + FileSystemContext* file_system_context, + scoped_ptr<FileSystemOperationContext> operation_context) + : file_system_context_(file_system_context), + operation_context_(operation_context.Pass()), + async_file_util_(NULL), + peer_handle_(base::kNullProcessHandle), + pending_operation_(kOperationNone), + weak_factory_(this) { + DCHECK(operation_context_.get()); + operation_context_->DetachUserDataThread(); + async_file_util_ = file_system_context_->GetAsyncFileUtil(url.type()); + DCHECK(async_file_util_); +} + void FileSystemOperationImpl::GetUsageAndQuotaThenRunTask( const FileSystemURL& url, const base::Closure& task, @@ -341,7 +359,7 @@ void FileSystemOperationImpl::GetUsageAndQuotaThenRunTask( url.origin(), FileSystemTypeToQuotaStorageType(url.type()), base::Bind(&FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask, - AsWeakPtr(), task, error_callback)); + weak_factory_.GetWeakPtr(), task, error_callback)); } void FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask( @@ -369,7 +387,7 @@ void FileSystemOperationImpl::DoCreateFile( exclusive ? &FileSystemOperationImpl::DidEnsureFileExistsExclusive : &FileSystemOperationImpl::DidEnsureFileExistsNonExclusive, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::DoCreateDirectory( @@ -380,17 +398,18 @@ void FileSystemOperationImpl::DoCreateDirectory( operation_context_.Pass(), url, exclusive, recursive, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::DoCopyFileLocal( const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback) { async_file_util_->CopyFileLocal( - operation_context_.Pass(), src_url, dest_url, + operation_context_.Pass(), src_url, dest_url, progress_callback, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::DoMoveFileLocal( @@ -400,7 +419,7 @@ void FileSystemOperationImpl::DoMoveFileLocal( async_file_util_->MoveFileLocal( operation_context_.Pass(), src_url, dest_url, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::DoCopyInForeignFile( @@ -411,7 +430,7 @@ void FileSystemOperationImpl::DoCopyInForeignFile( operation_context_.Pass(), src_local_disk_file_path, dest_url, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::DoTruncate(const FileSystemURL& url, @@ -420,7 +439,7 @@ void FileSystemOperationImpl::DoTruncate(const FileSystemURL& url, async_file_util_->Truncate( operation_context_.Pass(), url, length, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::DoOpenFile(const FileSystemURL& url, @@ -429,7 +448,7 @@ void FileSystemOperationImpl::DoOpenFile(const FileSystemURL& url, async_file_util_->CreateOrOpen( operation_context_.Pass(), url, file_flags, base::Bind(&FileSystemOperationImpl::DidOpenFile, - AsWeakPtr(), callback)); + weak_factory_.GetWeakPtr(), callback)); } void FileSystemOperationImpl::DidEnsureFileExistsExclusive( @@ -452,11 +471,13 @@ void FileSystemOperationImpl::DidFinishOperation( const StatusCallback& callback, base::PlatformFileError rv) { if (!cancel_callback_.is_null()) { - DCHECK_EQ(kOperationTruncate, pending_operation_); - StatusCallback cancel_callback = cancel_callback_; - callback.Run(base::PLATFORM_FILE_ERROR_ABORT); - cancel_callback.Run(base::PLATFORM_FILE_OK); + callback.Run(rv); + + // Return OK only if we succeeded to stop the operation. + cancel_callback.Run(rv == base::PLATFORM_FILE_ERROR_ABORT ? + base::PLATFORM_FILE_OK : + base::PLATFORM_FILE_ERROR_INVALID_OPERATION); } else { callback.Run(rv); } @@ -491,7 +512,7 @@ void FileSystemOperationImpl::DidDeleteRecursively( new RemoveOperationDelegate( file_system_context(), url, base::Bind(&FileSystemOperationImpl::DidFinishOperation, - AsWeakPtr(), callback))); + weak_factory_.GetWeakPtr(), callback))); recursive_operation_delegate_->RunRecursively(); return; } diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl.h b/chromium/webkit/browser/fileapi/file_system_operation_impl.h index 293ac5178d8..8433479f881 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation_impl.h +++ b/chromium/webkit/browser/fileapi/file_system_operation_impl.h @@ -26,18 +26,8 @@ class RecursiveOperationDelegate; // The default implementation of FileSystemOperation for file systems. class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl - : public NON_EXPORTED_BASE(FileSystemOperation), - public base::SupportsWeakPtr<FileSystemOperationImpl> { + : public NON_EXPORTED_BASE(FileSystemOperation) { public: - // NOTE: This constructor should not be called outside FileSystemBackends; - // instead please consider using - // file_system_context->CreateFileSystemOperation() to instantiate - // an appropriate FileSystemOperation. - FileSystemOperationImpl( - const FileSystemURL& url, - FileSystemContext* file_system_context, - scoped_ptr<FileSystemOperationContext> operation_context); - virtual ~FileSystemOperationImpl(); // FileSystemOperation overrides. @@ -50,6 +40,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl const StatusCallback& callback) OVERRIDE; virtual void Copy(const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyProgressCallback& progress_callback, const StatusCallback& callback) OVERRIDE; virtual void Move(const FileSystemURL& src_url, const FileSystemURL& dest_url, @@ -79,90 +70,39 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl base::ProcessHandle peer_handle, const OpenFileCallback& callback) OVERRIDE; virtual void Cancel(const StatusCallback& cancel_callback) OVERRIDE; - virtual FileSystemOperationImpl* AsFileSystemOperationImpl() OVERRIDE; virtual void CreateSnapshotFile( const FileSystemURL& path, const SnapshotFileCallback& callback) OVERRIDE; - - // Copies in a single file from a different filesystem. - // - // This returns: - // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_file_path| - // or the parent directory of |dest_url| does not exist. - // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // virtual void CopyInForeignFile(const base::FilePath& src_local_disk_path, const FileSystemURL& dest_url, - const StatusCallback& callback); - - // Removes a single file. - // - // This returns: - // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. - // - PLATFORM_FILE_ERROR_NOT_A_FILE if |url| is not a file. - // - void RemoveFile(const FileSystemURL& url, - const StatusCallback& callback); - - // Removes a single empty directory. - // - // This returns: - // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. - // - PLATFORM_FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory. - // - PLATFORM_FILE_ERROR_NOT_EMPTY if |url| is not empty. - // - void RemoveDirectory(const FileSystemURL& url, - const StatusCallback& callback); - - // Copies a file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // - // This returns: - // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - void CopyFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback); - - // Moves a local file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // - // This returns: - // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - void MoveFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback); - - // Synchronously gets the platform path for the given |url|. - // This may fail if |file_system_context| returns NULL on GetFileUtil(). - // In such a case, base::PLATFORM_FILE_ERROR_INVALID_OPERATION will be - // returned. - base::PlatformFileError SyncGetPlatformPath(const FileSystemURL& url, - base::FilePath* platform_path); + const StatusCallback& callback) OVERRIDE; + virtual void RemoveFile(const FileSystemURL& url, + const StatusCallback& callback) OVERRIDE; + virtual void RemoveDirectory(const FileSystemURL& url, + const StatusCallback& callback) OVERRIDE; + virtual void CopyFileLocal(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, + const StatusCallback& callback) OVERRIDE; + virtual void MoveFileLocal(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback) OVERRIDE; + virtual base::PlatformFileError SyncGetPlatformPath( + const FileSystemURL& url, + base::FilePath* platform_path) OVERRIDE; FileSystemContext* file_system_context() const { return file_system_context_.get(); } - protected: + private: + friend class FileSystemOperation; + + FileSystemOperationImpl( + const FileSystemURL& url, + FileSystemContext* file_system_context, + scoped_ptr<FileSystemOperationContext> operation_context); + // Queries the quota and usage and then runs the given |task|. // If an error occurs during the quota query it runs |error_callback| instead. void GetUsageAndQuotaThenRunTask( @@ -191,6 +131,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl bool recursive); void DoCopyFileLocal(const FileSystemURL& src, const FileSystemURL& dest, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback); void DoMoveFileLocal(const FileSystemURL& src, const FileSystemURL& dest, @@ -255,6 +196,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl // A flag to make sure we call operation only once per instance. OperationType pending_operation_; + base::WeakPtrFactory<FileSystemOperationImpl> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImpl); }; diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc b/chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc index 083fdeb7dbd..7443aa066d1 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc @@ -10,7 +10,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -226,7 +226,7 @@ class FileSystemOperationImplTest sandbox_file_system_.type(), usage, quota); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); ASSERT_EQ(quota::kQuotaStatusOk, status); } @@ -239,7 +239,7 @@ class FileSystemOperationImplTest operation_runner()->Remove(url, false /* recursive */, base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); change_observer()->ResetCount(); int64 total_usage; @@ -297,7 +297,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDoesntExist) { change_observer()->ResetCount(); operation_runner()->Move(URLForPath("a"), URLForPath("b"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -307,7 +307,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureContainsPath) { FileSystemURL dest_dir(CreateDirectory("src/dest")); operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -319,7 +319,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDirExistsDestFile) { FileSystemURL dest_file(CreateFile("dest/file")); operation_runner()->Move(src_dir, dest_file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -332,7 +332,7 @@ TEST_F(FileSystemOperationImplTest, FileSystemURL dest_file(CreateFile("dest/file")); operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -344,7 +344,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcFileExistsDestDir) { FileSystemURL dest_dir(CreateDirectory("dest")); operation_runner()->Move(src_file, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -354,7 +354,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureDestParentDoesntExist) { FileSystemURL src_dir(CreateDirectory("src")); operation_runner()->Move(src_dir, URLForPath("nonexistent/deset"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -364,7 +364,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) { FileSystemURL dest_file(CreateFile("dest")); operation_runner()->Move(src_file, dest_file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists("dest")); @@ -379,7 +379,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndNew) { FileSystemURL src_file(CreateFile("src")); operation_runner()->Move(src_file, URLForPath("new"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists("new")); @@ -393,7 +393,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndOverwrite) { FileSystemURL dest_dir(CreateDirectory("dest")); operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists("src")); @@ -412,7 +412,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndNew) { operation_runner()->Move(src_dir, URLForPath("dest/new"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists("src")); EXPECT_TRUE(DirectoryExists("dest/new")); @@ -430,7 +430,7 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) { FileSystemURL dest_dir(CreateDirectory("dest")); operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists("dest/dir")); EXPECT_TRUE(FileExists("dest/dir/sub")); @@ -444,8 +444,9 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) { TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDoesntExist) { operation_runner()->Copy(URLForPath("a"), URLForPath("b"), + FileSystemOperationRunner::CopyProgressCallback(), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -454,8 +455,10 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureContainsPath) { FileSystemURL src_dir(CreateDirectory("src")); FileSystemURL dest_dir(CreateDirectory("src/dir")); - operation_runner()->Copy(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_dir, dest_dir, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -466,8 +469,10 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDirExistsDestFile) { FileSystemURL dest_dir(CreateDirectory("dest")); FileSystemURL dest_file(CreateFile("dest/file")); - operation_runner()->Copy(src_dir, dest_file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_dir, dest_file, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -479,8 +484,10 @@ TEST_F(FileSystemOperationImplTest, FileSystemURL dest_dir(CreateDirectory("dest")); FileSystemURL dest_file(CreateFile("dest/file")); - operation_runner()->Copy(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_dir, dest_dir, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -490,8 +497,10 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcFileExistsDestDir) { FileSystemURL src_file(CreateFile("src")); FileSystemURL dest_dir(CreateDirectory("dest")); - operation_runner()->Copy(src_file, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_file, dest_dir, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -501,8 +510,9 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureDestParentDoesntExist) { FileSystemURL src_dir(CreateDirectory("src")); operation_runner()->Copy(src_dir, URLForPath("nonexistent/dest"), + FileSystemOperationRunner::CopyProgressCallback(), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -512,7 +522,7 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) { FileSystemURL src_file(CreateFile("src/file")); FileSystemURL dest_dir(CreateDirectory("dest")); operation_runner()->Truncate(src_file, 6, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_EQ(6, GetFileSize("src/file")); @@ -521,8 +531,10 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) { GrantQuotaForCurrentUsage(); AddQuota(6 + dest_path_cost - 1); - operation_runner()->Copy(src_file, dest_file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_file, dest_file, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status()); EXPECT_FALSE(FileExists("dest/file")); } @@ -531,8 +543,10 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndOverwrite) { FileSystemURL src_file(CreateFile("src")); FileSystemURL dest_file(CreateFile("dest")); - operation_runner()->Copy(src_file, dest_file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_file, dest_file, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists("dest")); EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count()); @@ -545,8 +559,9 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndNew) { FileSystemURL src_file(CreateFile("src")); operation_runner()->Copy(src_file, URLForPath("new"), + FileSystemOperationRunner::CopyProgressCallback(), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists("new")); EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count()); @@ -559,8 +574,10 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndOverwrite) { FileSystemURL src_dir(CreateDirectory("src")); FileSystemURL dest_dir(CreateDirectory("dest")); - operation_runner()->Copy(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_dir, dest_dir, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); // Make sure we've overwritten but not copied the source under the |dest_dir|. @@ -577,8 +594,10 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndNew) { FileSystemURL src_dir(CreateDirectory("src")); FileSystemURL dest_dir_new(URLForPath("dest")); - operation_runner()->Copy(src_dir, dest_dir_new, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_dir, dest_dir_new, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists("dest")); EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 2); @@ -594,8 +613,10 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) { FileSystemURL dest_dir(CreateDirectory("dest")); - operation_runner()->Copy(src_dir, dest_dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + operation_runner()->Copy(src_dir, dest_dir, + FileSystemOperationRunner::CopyProgressCallback(), + RecordStatusCallback()); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists("dest/dir")); @@ -626,7 +647,7 @@ TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) { operation_runner()->CopyInForeignFile(src_local_disk_file_path, URLForPath("dest/file"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, change_observer()->create_file_count()); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); @@ -656,7 +677,7 @@ TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) { operation_runner()->CopyInForeignFile(src_local_disk_file_path, URLForPath("dest/file"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(FileExists("dest/file")); EXPECT_EQ(0, change_observer()->create_file_count()); @@ -667,7 +688,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateFileFailure) { // Already existing file and exclusive true. FileSystemURL file(CreateFile("file")); operation_runner()->CreateFile(file, true, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -676,7 +697,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) { // Already existing file and exclusive false. FileSystemURL file(CreateFile("file")); operation_runner()->CreateFile(file, false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists("file")); @@ -688,7 +709,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessExclusive) { // File doesn't exist but exclusive is true. operation_runner()->CreateFile(URLForPath("new"), true, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists("new")); EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); @@ -698,7 +719,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileDoesntExist) { // Non existing file. operation_runner()->CreateFile(URLForPath("nonexistent"), false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); } @@ -709,7 +730,7 @@ TEST_F(FileSystemOperationImplTest, operation_runner()->CreateDirectory( URLForPath("nonexistent/dir"), false, false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -719,7 +740,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateDirFailureDirExists) { FileSystemURL dir(CreateDirectory("dir")); operation_runner()->CreateDirectory(dir, true, false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -729,7 +750,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateDirFailureFileExists) { FileSystemURL file(CreateFile("file")); operation_runner()->CreateDirectory(file, true, false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -739,14 +760,14 @@ TEST_F(FileSystemOperationImplTest, TestCreateDirSuccess) { FileSystemURL dir(CreateDirectory("dir")); operation_runner()->CreateDirectory(dir, false, false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(change_observer()->HasNoChange()); // Dir doesn't exist. operation_runner()->CreateDirectory(URLForPath("new"), false, false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists("new")); EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); @@ -756,7 +777,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) { // Dir doesn't exist. operation_runner()->CreateDirectory(URLForPath("new"), true, false, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists("new")); EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); @@ -766,17 +787,17 @@ TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) { TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataFailure) { operation_runner()->GetMetadata(URLForPath("nonexistent"), RecordMetadataCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); operation_runner()->FileExists(URLForPath("nonexistent"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); operation_runner()->DirectoryExists(URLForPath("nonexistent"), RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -787,23 +808,23 @@ TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) { int read_access = 0; operation_runner()->DirectoryExists(dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); ++read_access; operation_runner()->GetMetadata(dir, RecordMetadataCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(info().is_directory); ++read_access; operation_runner()->FileExists(file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); ++read_access; operation_runner()->GetMetadata(file, RecordMetadataCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(info().is_directory); ++read_access; @@ -816,12 +837,12 @@ TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) { TEST_F(FileSystemOperationImplTest, TestTypeMismatchErrors) { FileSystemURL dir(CreateDirectory("dir")); operation_runner()->FileExists(dir, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE, status()); FileSystemURL file(CreateFile("file")); operation_runner()->DirectoryExists(file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, status()); } @@ -829,13 +850,13 @@ TEST_F(FileSystemOperationImplTest, TestReadDirFailure) { // Path doesn't exist operation_runner()->ReadDirectory(URLForPath("nonexistent"), RecordReadDirectoryCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); // File exists. FileSystemURL file(CreateFile("file")); operation_runner()->ReadDirectory(file, RecordReadDirectoryCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -850,7 +871,7 @@ TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) { FileSystemURL child_file(CreateFile("dir/child_file")); operation_runner()->ReadDirectory(parent_dir, RecordReadDirectoryCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_EQ(2u, entries().size()); @@ -868,7 +889,7 @@ TEST_F(FileSystemOperationImplTest, TestRemoveFailure) { // Path doesn't exist. operation_runner()->Remove(URLForPath("nonexistent"), false /* recursive */, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); // It's an error to try to remove a non-empty directory if recursive flag @@ -883,7 +904,7 @@ TEST_F(FileSystemOperationImplTest, TestRemoveFailure) { operation_runner()->Remove(parent_dir, false /* recursive */, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status()); EXPECT_TRUE(change_observer()->HasNoChange()); } @@ -893,7 +914,7 @@ TEST_F(FileSystemOperationImplTest, TestRemoveSuccess) { EXPECT_TRUE(DirectoryExists("empty_dir")); operation_runner()->Remove(empty_dir, false /* recursive */, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists("empty_dir")); @@ -919,7 +940,7 @@ TEST_F(FileSystemOperationImplTest, TestRemoveSuccessRecursive) { operation_runner()->Remove(parent_dir, true /* recursive */, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists("parent_dir")); @@ -939,7 +960,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncate) { // Check that its length is the size of the data written. operation_runner()->GetMetadata(file, RecordMetadataCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(info().is_directory); EXPECT_EQ(data_size, info().size); @@ -947,7 +968,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncate) { // Extend the file by truncating it. int length = 17; operation_runner()->Truncate(file, length, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); @@ -968,7 +989,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncate) { // Shorten the file by truncating it. length = 3; operation_runner()->Truncate(file, length, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); @@ -993,7 +1014,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) { AddQuota(10); operation_runner()->Truncate(file, 10, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); EXPECT_TRUE(change_observer()->HasNoChange()); @@ -1001,7 +1022,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) { EXPECT_EQ(10, GetFileSize("dir/file")); operation_runner()->Truncate(file, 11, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status()); EXPECT_TRUE(change_observer()->HasNoChange()); @@ -1027,7 +1048,7 @@ TEST_F(FileSystemOperationImplTest, TestTouchFile) { operation_runner()->TouchFile(file, new_accessed_time, new_modified_time, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(change_observer()->HasNoChange()); @@ -1046,7 +1067,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) { operation_runner()->DirectoryExists(dir, RecordStatusCallback()); FileSystemURL file(CreateFile("dir/file")); operation_runner()->FileExists(file, RecordStatusCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); // See if we can get a 'snapshot' file info for the file. @@ -1054,7 +1075,7 @@ TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) { // directory it should just returns the same metadata and platform_path // as the file itself. operation_runner()->CreateSnapshotFile(file, RecordSnapshotFileCallback()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(info().is_directory); EXPECT_EQ(PlatformPath("dir/file"), path()); @@ -1092,7 +1113,7 @@ TEST_F(FileSystemOperationImplTest, operation_runner()->Truncate( grandchild_file2, 2, base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 all_file_size = 5000 + 400 + 30 + 2; EXPECT_EQ(all_file_size, GetDataSizeOnDisk()); @@ -1101,7 +1122,7 @@ TEST_F(FileSystemOperationImplTest, operation_runner()->Move( src, dest, base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(DirectoryExists("src/dir")); EXPECT_FALSE(FileExists("src/dir/file2")); @@ -1145,7 +1166,7 @@ TEST_F(FileSystemOperationImplTest, operation_runner()->Truncate( grandchild_file2, 5, base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 child_file_size = 8000 + 700; const int64 grandchild_file_size = 60 + 5; @@ -1159,8 +1180,9 @@ TEST_F(FileSystemOperationImplTest, // Copy src to dest1. operation_runner()->Copy( src, dest1, + FileSystemOperationRunner::CopyProgressCallback(), base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); expected_usage += all_file_size + child_path_cost + grandchild_path_cost; EXPECT_TRUE(DirectoryExists("src/dir")); @@ -1174,8 +1196,9 @@ TEST_F(FileSystemOperationImplTest, // Copy src/dir to dest2. operation_runner()->Copy( child_dir, dest2, + FileSystemOperationRunner::CopyProgressCallback(), base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); expected_usage += grandchild_file_size + grandchild_path_cost; usage = GetUsage(); diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc b/chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc index d8ecc280fc8..7fb9aa4ae86 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc @@ -7,15 +7,15 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job.h" #include "net/url_request/url_request_job_factory_impl.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -#include "webkit/browser/blob/blob_storage_controller.h" +#include "webkit/browser/blob/blob_storage_context.h" #include "webkit/browser/blob/blob_url_request_job.h" #include "webkit/browser/blob/mock_blob_url_request_context.h" #include "webkit/browser/fileapi/file_system_context.h" @@ -88,7 +88,7 @@ class FileSystemOperationImplWriteTest virtual void TearDown() { quota_manager_ = NULL; file_system_context_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } base::PlatformFileError status() const { return status_; } @@ -174,11 +174,12 @@ class FileSystemOperationImplWriteTest }; TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) { - const GURL blob_url("blob:success"); - ScopedTextBlob blob(url_request_context(), blob_url, "Hello, world!\n"); - + ScopedTextBlob blob(url_request_context(), + "blob-id:success", + "Hello, world!\n"); file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), blob_url, + &url_request_context(), URLForPath(virtual_path_), + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); @@ -190,19 +191,12 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) { } TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) { - GURL blob_url("blob:zero"); - scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData()); - - url_request_context().blob_storage_controller() - ->AddFinishedBlob(blob_url, blob_data.get()); - + ScopedTextBlob blob(url_request_context(), "blob_id:zero", ""); file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_path_), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); - url_request_context().blob_storage_controller()->RemoveBlob(blob_url); - EXPECT_EQ(0, bytes_written()); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(complete()); @@ -210,10 +204,12 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) { EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); } + TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) { + scoped_ptr<webkit_blob::BlobDataHandle> null_handle; file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_path_), - GURL("blob:invalid"), 0, RecordWriteCallback()); + null_handle.Pass(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(0, bytes_written()); @@ -224,14 +220,12 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) { } TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidFile) { - GURL blob_url("blob:writeinvalidfile"); - ScopedTextBlob blob(url_request_context(), blob_url, + ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile", "It\'ll not be written."); - file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(0, bytes_written()); @@ -248,13 +242,11 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) { true /* exclusive */, false /* recursive */, base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK)); - GURL blob_url("blob:writedir"); - ScopedTextBlob blob(url_request_context(), blob_url, + ScopedTextBlob blob(url_request_context(), "blob:writedir", "It\'ll not be written, too."); - file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_dir_path), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(0, bytes_written()); @@ -269,14 +261,13 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) { } TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) { - GURL blob_url("blob:success"); - ScopedTextBlob blob(url_request_context(), blob_url, "Hello, world!\n"); - + ScopedTextBlob blob(url_request_context(), "blob:success", + "Hello, world!\n"); quota_manager_->SetQuota( kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10); file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), blob_url, - 0, RecordWriteCallback()); + &url_request_context(), URLForPath(virtual_path_), + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::MessageLoop::current()->Run(); EXPECT_EQ(10, bytes_written()); @@ -287,18 +278,17 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) { } TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) { - GURL blob_url("blob:success"); - ScopedTextBlob blob(url_request_context(), blob_url, "Hello, world!\n"); - + ScopedTextBlob blob(url_request_context(), "blob:success", + "Hello, world!\n"); FileSystemOperationRunner::OperationID id = file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(virtual_path_), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback()); // We use RunAllPendings() instead of Run() here, because we won't dispatch // callbacks after Cancel() is issued (so no chance to Quit) nor do we need // to run another write cycle. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // Issued Cancel() before receiving any response from Write(), // so nothing should have happen. @@ -311,20 +301,18 @@ TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) { } TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelFailingWrite) { - GURL blob_url("blob:writeinvalidfile"); - ScopedTextBlob blob(url_request_context(), blob_url, + ScopedTextBlob blob(url_request_context(), "blob:writeinvalidfile", "It\'ll not be written."); - FileSystemOperationRunner::OperationID id = file_system_context_->operation_runner()->Write( &url_request_context(), URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))), - blob_url, 0, RecordWriteCallback()); + blob.GetBlobDataHandle(), 0, RecordWriteCallback()); file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback()); // We use RunAllPendings() instead of Run() here, because we won't dispatch // callbacks after Cancel() is issued (so no chance to Quit) nor do we need // to run another write cycle. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // Issued Cancel() before receiving any response from Write(), // so nothing should have happen. diff --git a/chromium/webkit/browser/fileapi/file_system_operation_runner.cc b/chromium/webkit/browser/fileapi/file_system_operation_runner.cc index 351536b6226..5a31ecc44ec 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation_runner.cc +++ b/chromium/webkit/browser/fileapi/file_system_operation_runner.cc @@ -5,11 +5,14 @@ #include "webkit/browser/fileapi/file_system_operation_runner.h" #include "base/bind.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/stl_util.h" #include "net/url_request/url_request_context.h" +#include "webkit/browser/blob/blob_url_request_job_factory.h" #include "webkit/browser/fileapi/file_observers.h" #include "webkit/browser/fileapi/file_stream_writer.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_impl.h" +#include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_writer_delegate.h" #include "webkit/common/blob/shareable_file_reference.h" @@ -17,7 +20,17 @@ namespace fileapi { typedef FileSystemOperationRunner::OperationID OperationID; -const OperationID FileSystemOperationRunner::kErrorOperationID = -1; +class FileSystemOperationRunner::BeginOperationScoper + : public base::SupportsWeakPtr< + FileSystemOperationRunner::BeginOperationScoper> { + public: + BeginOperationScoper() {} + private: + DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper); +}; + +FileSystemOperationRunner::OperationHandle::OperationHandle() {} +FileSystemOperationRunner::OperationHandle::~OperationHandle() {} FileSystemOperationRunner::~FileSystemOperationRunner() { } @@ -33,17 +46,19 @@ OperationID FileSystemOperationRunner::CreateFile( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForWrite(id, url); + PrepareForWrite(handle.id, url); operation->CreateFile( url, exclusive, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::CreateDirectory( @@ -54,38 +69,45 @@ OperationID FileSystemOperationRunner::CreateDirectory( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForWrite(id, url); + PrepareForWrite(handle.id, url); operation->CreateDirectory( url, exclusive, recursive, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::Copy( const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyProgressCallback& progress_callback, const StatusCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(dest_url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForWrite(id, dest_url); - PrepareForRead(id, src_url); + PrepareForWrite(handle.id, dest_url); + PrepareForRead(handle.id, src_url); operation->Copy( src_url, dest_url, + progress_callback.is_null() ? + CopyProgressCallback() : + base::Bind(&FileSystemOperationRunner::OnCopyProgress, AsWeakPtr(), + handle, progress_callback), base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::Move( @@ -95,18 +117,19 @@ OperationID FileSystemOperationRunner::Move( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(dest_url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForWrite(id, dest_url); - PrepareForWrite(id, src_url); + PrepareForWrite(handle.id, dest_url); + PrepareForWrite(handle.id, src_url); operation->Move( src_url, dest_url, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::DirectoryExists( @@ -115,17 +138,18 @@ OperationID FileSystemOperationRunner::DirectoryExists( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForRead(id, url); + PrepareForRead(handle.id, url); operation->DirectoryExists( url, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::FileExists( @@ -134,17 +158,18 @@ OperationID FileSystemOperationRunner::FileExists( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForRead(id, url); + PrepareForRead(handle.id, url); operation->FileExists( url, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::GetMetadata( @@ -153,17 +178,18 @@ OperationID FileSystemOperationRunner::GetMetadata( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error, base::PlatformFileInfo()); - return kErrorOperationID; + DidGetMetadata(handle, callback, error, base::PlatformFileInfo()); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForRead(id, url); + PrepareForRead(handle.id, url); operation->GetMetadata( url, base::Bind(&FileSystemOperationRunner::DidGetMetadata, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::ReadDirectory( @@ -172,17 +198,19 @@ OperationID FileSystemOperationRunner::ReadDirectory( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error, std::vector<DirectoryEntry>(), false); - return kErrorOperationID; + DidReadDirectory(handle, callback, error, std::vector<DirectoryEntry>(), + false); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForRead(id, url); + PrepareForRead(handle.id, url); operation->ReadDirectory( url, base::Bind(&FileSystemOperationRunner::DidReadDirectory, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::Remove( @@ -191,54 +219,60 @@ OperationID FileSystemOperationRunner::Remove( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForWrite(id, url); + PrepareForWrite(handle.id, url); operation->Remove( url, recursive, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::Write( const net::URLRequestContext* url_request_context, const FileSystemURL& url, - const GURL& blob_url, + scoped_ptr<webkit_blob::BlobDataHandle> blob, int64 offset, const WriteCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error, 0, true); - return kErrorOperationID; + DidWrite(handle, callback, error, 0, true); + return handle.id; } scoped_ptr<FileStreamWriter> writer( file_system_context_->CreateFileStreamWriter(url, offset)); if (!writer) { // Write is not supported. - callback.Run(base::PLATFORM_FILE_ERROR_SECURITY, 0, true); - return kErrorOperationID; + DidWrite(handle, callback, base::PLATFORM_FILE_ERROR_SECURITY, 0, true); + return handle.id; } - DCHECK(blob_url.is_valid()); scoped_ptr<FileWriterDelegate> writer_delegate( new FileWriterDelegate(writer.Pass())); - scoped_ptr<net::URLRequest> blob_request(url_request_context->CreateRequest( - blob_url, writer_delegate.get())); - OperationID id = operations_.Add(operation); - PrepareForWrite(id, url); + scoped_ptr<net::URLRequest> blob_request( + webkit_blob::BlobProtocolHandler::CreateBlobRequest( + blob.Pass(), + url_request_context, + writer_delegate.get())); + + PrepareForWrite(handle.id, url); operation->Write( url, writer_delegate.Pass(), blob_request.Pass(), base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::Truncate( @@ -247,25 +281,31 @@ OperationID FileSystemOperationRunner::Truncate( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForWrite(id, url); + PrepareForWrite(handle.id, url); operation->Truncate( url, length, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } void FileSystemOperationRunner::Cancel( OperationID id, const StatusCallback& callback) { + if (ContainsKey(finished_operations_, id)) { + DCHECK(!ContainsKey(stray_cancel_callbacks_, id)); + stray_cancel_callbacks_[id] = callback; + return; + } FileSystemOperation* operation = operations_.Lookup(id); if (!operation) { - // The operation is already finished; report that we failed to stop it. + // There is no operation with |id|. callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); return; } @@ -280,17 +320,18 @@ OperationID FileSystemOperationRunner::TouchFile( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForWrite(id, url); + PrepareForWrite(handle.id, url); operation->TouchFile( url, last_access_time, last_modified_time, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::OpenFile( @@ -301,27 +342,28 @@ OperationID FileSystemOperationRunner::OpenFile( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error, base::kInvalidPlatformFileValue, - base::Closure(), base::ProcessHandle()); - return kErrorOperationID; + DidOpenFile(handle, callback, error, base::kInvalidPlatformFileValue, + base::Closure(), base::ProcessHandle()); + return handle.id; } - OperationID id = operations_.Add(operation); if (file_flags & (base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_OPEN_TRUNCATED | base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_WRITE | base::PLATFORM_FILE_DELETE_ON_CLOSE | base::PLATFORM_FILE_WRITE_ATTRIBUTES)) { - PrepareForWrite(id, url); + PrepareForWrite(handle.id, url); } else { - PrepareForRead(id, url); + PrepareForRead(handle.id, url); } operation->OpenFile( url, file_flags, peer_handle, base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::CreateSnapshotFile( @@ -330,17 +372,19 @@ OperationID FileSystemOperationRunner::CreateSnapshotFile( base::PlatformFileError error = base::PLATFORM_FILE_OK; FileSystemOperation* operation = file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error, base::PlatformFileInfo(), base::FilePath(), NULL); - return kErrorOperationID; + DidCreateSnapshot(handle, callback, error, base::PlatformFileInfo(), + base::FilePath(), NULL); + return handle.id; } - OperationID id = operations_.Add(operation); - PrepareForRead(id, url); + PrepareForRead(handle.id, url); operation->CreateSnapshotFile( url, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::CopyInForeignFile( @@ -348,71 +392,78 @@ OperationID FileSystemOperationRunner::CopyInForeignFile( const FileSystemURL& dest_url, const StatusCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; - FileSystemOperation* operation = CreateFileSystemOperationImpl( - dest_url, &error); + FileSystemOperation* operation = + file_system_context_->CreateFileSystemOperation(dest_url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - operation->AsFileSystemOperationImpl()->CopyInForeignFile( + operation->CopyInForeignFile( src_local_disk_path, dest_url, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::RemoveFile( const FileSystemURL& url, const StatusCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; - FileSystemOperation* operation = CreateFileSystemOperationImpl(url, &error); + FileSystemOperation* operation = + file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - operation->AsFileSystemOperationImpl()->RemoveFile( + operation->RemoveFile( url, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::RemoveDirectory( const FileSystemURL& url, const StatusCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; - FileSystemOperation* operation = CreateFileSystemOperationImpl(url, &error); + FileSystemOperation* operation = + file_system_context_->CreateFileSystemOperation(url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - operation->AsFileSystemOperationImpl()->RemoveDirectory( + operation->RemoveDirectory( url, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::CopyFileLocal( const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; - FileSystemOperation* operation = CreateFileSystemOperationImpl( - src_url, &error); + FileSystemOperation* operation = + file_system_context_->CreateFileSystemOperation(src_url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - operation->AsFileSystemOperationImpl()->CopyFileLocal( - src_url, dest_url, + operation->CopyFileLocal( + src_url, dest_url, progress_callback, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } OperationID FileSystemOperationRunner::MoveFileLocal( @@ -420,30 +471,30 @@ OperationID FileSystemOperationRunner::MoveFileLocal( const FileSystemURL& dest_url, const StatusCallback& callback) { base::PlatformFileError error = base::PLATFORM_FILE_OK; - FileSystemOperation* operation = CreateFileSystemOperationImpl( - src_url, &error); + FileSystemOperation* operation = + file_system_context_->CreateFileSystemOperation(src_url, &error); + BeginOperationScoper scope; + OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); if (!operation) { - callback.Run(error); - return kErrorOperationID; + DidFinish(handle, callback, error); + return handle.id; } - OperationID id = operations_.Add(operation); - operation->AsFileSystemOperationImpl()->MoveFileLocal( + operation->MoveFileLocal( src_url, dest_url, base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - id, callback)); - return id; + handle, callback)); + return handle.id; } base::PlatformFileError FileSystemOperationRunner::SyncGetPlatformPath( const FileSystemURL& url, base::FilePath* platform_path) { base::PlatformFileError error = base::PLATFORM_FILE_OK; - FileSystemOperation* operation = CreateFileSystemOperationImpl(url, &error); + FileSystemOperation* operation = + file_system_context_->CreateFileSystemOperation(url, &error); if (!operation) return error; - - return operation->AsFileSystemOperationImpl()->SyncGetPlatformPath( - url, platform_path); + return operation->SyncGetPlatformPath(url, platform_path); } FileSystemOperationRunner::FileSystemOperationRunner( @@ -451,79 +502,126 @@ FileSystemOperationRunner::FileSystemOperationRunner( : file_system_context_(file_system_context) {} void FileSystemOperationRunner::DidFinish( - OperationID id, + const OperationHandle& handle, const StatusCallback& callback, base::PlatformFileError rv) { + if (handle.scope) { + finished_operations_.insert(handle.id); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(&FileSystemOperationRunner::DidFinish, + AsWeakPtr(), handle, callback, rv)); + return; + } callback.Run(rv); - FinishOperation(id); + FinishOperation(handle.id); } void FileSystemOperationRunner::DidGetMetadata( - OperationID id, + const OperationHandle& handle, const GetMetadataCallback& callback, base::PlatformFileError rv, const base::PlatformFileInfo& file_info) { + if (handle.scope) { + finished_operations_.insert(handle.id); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(&FileSystemOperationRunner::DidGetMetadata, + AsWeakPtr(), handle, callback, rv, file_info)); + return; + } callback.Run(rv, file_info); - FinishOperation(id); + FinishOperation(handle.id); } void FileSystemOperationRunner::DidReadDirectory( - OperationID id, + const OperationHandle& handle, const ReadDirectoryCallback& callback, base::PlatformFileError rv, const std::vector<DirectoryEntry>& entries, bool has_more) { + if (handle.scope) { + finished_operations_.insert(handle.id); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(&FileSystemOperationRunner::DidReadDirectory, + AsWeakPtr(), handle, callback, rv, + entries, has_more)); + return; + } callback.Run(rv, entries, has_more); if (rv != base::PLATFORM_FILE_OK || !has_more) - FinishOperation(id); + FinishOperation(handle.id); } void FileSystemOperationRunner::DidWrite( - OperationID id, + const OperationHandle& handle, const WriteCallback& callback, base::PlatformFileError rv, int64 bytes, bool complete) { + if (handle.scope) { + finished_operations_.insert(handle.id); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(), + handle, callback, rv, bytes, complete)); + return; + } callback.Run(rv, bytes, complete); if (rv != base::PLATFORM_FILE_OK || complete) - FinishOperation(id); + FinishOperation(handle.id); } void FileSystemOperationRunner::DidOpenFile( - OperationID id, + const OperationHandle& handle, const OpenFileCallback& callback, base::PlatformFileError rv, base::PlatformFile file, const base::Closure& on_close_callback, base::ProcessHandle peer_handle) { + if (handle.scope) { + finished_operations_.insert(handle.id); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile, + AsWeakPtr(), handle, callback, rv, file, + on_close_callback, peer_handle)); + return; + } callback.Run(rv, file, on_close_callback, peer_handle); - FinishOperation(id); + FinishOperation(handle.id); } void FileSystemOperationRunner::DidCreateSnapshot( - OperationID id, + const OperationHandle& handle, const SnapshotFileCallback& callback, base::PlatformFileError rv, const base::PlatformFileInfo& file_info, const base::FilePath& platform_path, const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { + if (handle.scope) { + finished_operations_.insert(handle.id); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, + AsWeakPtr(), handle, callback, rv, file_info, + platform_path, file_ref)); + return; + } callback.Run(rv, file_info, platform_path, file_ref); - FinishOperation(id); + FinishOperation(handle.id); } -FileSystemOperation* -FileSystemOperationRunner::CreateFileSystemOperationImpl( - const FileSystemURL& url, base::PlatformFileError* error) { - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, error); - if (!operation) - return NULL; - if (!operation->AsFileSystemOperationImpl()) { - *error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; - delete operation; - return NULL; +void FileSystemOperationRunner::OnCopyProgress( + const OperationHandle& handle, + const CopyProgressCallback& callback, + FileSystemOperation::CopyProgressType type, + const FileSystemURL& source_url, + const FileSystemURL& dest_url, + int64 size) { + if (handle.scope) { + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind( + &FileSystemOperationRunner::OnCopyProgress, + AsWeakPtr(), handle, callback, type, source_url, dest_url, size)); + return; } - return operation; + callback.Run(type, source_url, dest_url, size); } void FileSystemOperationRunner::PrepareForWrite(OperationID id, @@ -543,6 +641,16 @@ void FileSystemOperationRunner::PrepareForRead(OperationID id, } } +FileSystemOperationRunner::OperationHandle +FileSystemOperationRunner::BeginOperation( + FileSystemOperation* operation, + base::WeakPtr<BeginOperationScoper> scope) { + OperationHandle handle; + handle.id = operations_.Add(operation); + handle.scope = scope; + return handle; +} + void FileSystemOperationRunner::FinishOperation(OperationID id) { OperationToURLSet::iterator found = write_target_urls_.find(id); if (found != write_target_urls_.end()) { @@ -556,8 +664,22 @@ void FileSystemOperationRunner::FinishOperation(OperationID id) { } write_target_urls_.erase(found); } - DCHECK(operations_.Lookup(id)); + + // IDMap::Lookup fails if the operation is NULL, so we don't check + // operations_.Lookup(id) here. + operations_.Remove(id); + finished_operations_.erase(id); + + // Dispatch stray cancel callback if exists. + std::map<OperationID, StatusCallback>::iterator found_cancel = + stray_cancel_callbacks_.find(id); + if (found_cancel != stray_cancel_callbacks_.end()) { + // This cancel has been requested after the operation has finished, + // so report that we failed to stop it. + found_cancel->second.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); + stray_cancel_callbacks_.erase(found_cancel); + } } } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/file_system_operation_runner.h b/chromium/webkit/browser/fileapi/file_system_operation_runner.h index 67f30b89b17..ea93f38e1fc 100644 --- a/chromium/webkit/browser/fileapi/file_system_operation_runner.h +++ b/chromium/webkit/browser/fileapi/file_system_operation_runner.h @@ -11,6 +11,7 @@ #include "base/id_map.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "webkit/browser/blob/blob_data_handle.h" #include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/webkit_storage_browser_export.h" @@ -31,12 +32,6 @@ class FileSystemContext; // operation fails, in addition to dispatching the callback with an error // code (therefore in most cases the caller does not need to check the // returned operation ID). -// -// Some operations (e.g. CopyInForeignFile, RemoveFile, RemoveDirectory, -// CopyFileLocal, MoveFileLocal and SyncGetPlatformPath) are only supported -// by filesystems which implement FileSystemOperationImpl. -// If they are called on other filesystems -// base::PLATFORM_FILE_ERROR_INVALID_OPERATION is returned via callback. class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner : public base::SupportsWeakPtr<FileSystemOperationRunner> { public: @@ -46,11 +41,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner typedef FileSystemOperation::StatusCallback StatusCallback; typedef FileSystemOperation::WriteCallback WriteCallback; typedef FileSystemOperation::OpenFileCallback OpenFileCallback; + typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; + typedef FileSystemOperation::CopyFileProgressCallback + CopyFileProgressCallback; typedef int OperationID; - static const OperationID kErrorOperationID; - virtual ~FileSystemOperationRunner(); // Cancels all inflight operations. @@ -71,8 +67,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner // |src_url| is a directory, the contents of |src_url| are copied to // |dest_url| recursively. A new file or directory is created at // |dest_url| as needed. + // For |progress_callback|, see file_system_operation.h for details. OperationID Copy(const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyProgressCallback& progress_callback, const StatusCallback& callback); // Moves a file or directory from |src_url| to |dest_url|. A new file @@ -103,10 +101,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner const StatusCallback& callback); // Writes contents of |blob_url| to |url| at |offset|. - // |url_request_context| is used to read contents in |blob_url|. + // |url_request_context| is used to read contents in |blob|. OperationID Write(const net::URLRequestContext* url_request_context, const FileSystemURL& url, - const GURL& blob_url, + scoped_ptr<webkit_blob::BlobDataHandle> blob, int64 offset, const WriteCallback& callback); @@ -190,6 +188,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner // Copies a file from |src_url| to |dest_url|. // This must be called for files that belong to the same filesystem // (i.e. type() and origin() of the |src_url| and |dest_url| must match). + // For |progress_callback|, see file_system_operation.h for details. // // This returns: // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url| @@ -202,6 +201,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner // OperationID CopyFileLocal(const FileSystemURL& src_url, const FileSystemURL& dest_url, + const CopyFileProgressCallback& progress_callback, const StatusCallback& callback); // Moves a local file from |src_url| to |dest_url|. @@ -228,54 +228,65 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner base::FilePath* platform_path); private: + class BeginOperationScoper; + + struct OperationHandle { + OperationID id; + base::WeakPtr<BeginOperationScoper> scope; + + OperationHandle(); + ~OperationHandle(); + }; + friend class FileSystemContext; explicit FileSystemOperationRunner(FileSystemContext* file_system_context); - void DidFinish(OperationID id, + void DidFinish(const OperationHandle& handle, const StatusCallback& callback, base::PlatformFileError rv); - void DidGetMetadata(OperationID id, + void DidGetMetadata(const OperationHandle& handle, const GetMetadataCallback& callback, base::PlatformFileError rv, const base::PlatformFileInfo& file_info); - void DidReadDirectory(OperationID id, + void DidReadDirectory(const OperationHandle& handle, const ReadDirectoryCallback& callback, base::PlatformFileError rv, const std::vector<DirectoryEntry>& entries, bool has_more); - void DidWrite(OperationID id, + void DidWrite(const OperationHandle& handle, const WriteCallback& callback, base::PlatformFileError rv, int64 bytes, bool complete); void DidOpenFile( - OperationID id, + const OperationHandle& handle, const OpenFileCallback& callback, base::PlatformFileError rv, base::PlatformFile file, const base::Closure& on_close_callback, base::ProcessHandle peer_handle); void DidCreateSnapshot( - OperationID id, + const OperationHandle& handle, const SnapshotFileCallback& callback, base::PlatformFileError rv, const base::PlatformFileInfo& file_info, const base::FilePath& platform_path, const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref); - // A helper method for creating FileSystemOperationImpl for operations - // that are supported only in FileSystemOperationImpl. - // Note that this returns FileSystemOperation, so the caller needs to - // call AsFileSystemOperationImpl() (which is guaranteed to be non-null - // if this method returns without error). - FileSystemOperation* CreateFileSystemOperationImpl( - const FileSystemURL& url, - base::PlatformFileError* error); + void OnCopyProgress( + const OperationHandle& handle, + const CopyProgressCallback& callback, + FileSystemOperation::CopyProgressType type, + const FileSystemURL& source_url, + const FileSystemURL& dest_url, + int64 size); void PrepareForWrite(OperationID id, const FileSystemURL& url); void PrepareForRead(OperationID id, const FileSystemURL& url); - // This must be called at the end of any async operations. + // These must be called at the beginning and end of any async operations. + OperationHandle BeginOperation(FileSystemOperation* operation, + base::WeakPtr<BeginOperationScoper> scope); void FinishOperation(OperationID id); // Not owned; file_system_context owns this. @@ -289,6 +300,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner typedef std::map<OperationID, FileSystemURLSet> OperationToURLSet; OperationToURLSet write_target_urls_; + // Operations that are finished but not yet fire their callbacks. + std::set<OperationID> finished_operations_; + + // Callbacks for stray cancels whose target operation is already finished. + std::map<OperationID, StatusCallback> stray_cancel_callbacks_; + DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunner); }; diff --git a/chromium/webkit/browser/fileapi/file_system_operation_runner_unittest.cc b/chromium/webkit/browser/fileapi/file_system_operation_runner_unittest.cc new file mode 100644 index 00000000000..086c9999ad5 --- /dev/null +++ b/chromium/webkit/browser/fileapi/file_system_operation_runner_unittest.cc @@ -0,0 +1,162 @@ +// Copyright 2013 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 "base/basictypes.h" +#include "base/files/file_path.h" +#include "base/files/scoped_temp_dir.h" +#include "base/platform_file.h" +#include "base/run_loop.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/fileapi/file_system_context.h" +#include "webkit/browser/fileapi/file_system_operation_runner.h" +#include "webkit/browser/fileapi/mock_file_system_context.h" + +namespace fileapi { + +void GetStatus(bool* done, + base::PlatformFileError *status_out, + base::PlatformFileError status) { + ASSERT_FALSE(*done); + *done = true; + *status_out = status; +} + +void GetCancelStatus(bool* operation_done, + bool* cancel_done, + base::PlatformFileError *status_out, + base::PlatformFileError status) { + // Cancel callback must be always called after the operation's callback. + ASSERT_TRUE(*operation_done); + ASSERT_FALSE(*cancel_done); + *cancel_done = true; + *status_out = status; +} + +class FileSystemOperationRunnerTest : public testing::Test { + protected: + FileSystemOperationRunnerTest() {} + virtual ~FileSystemOperationRunnerTest() {} + + virtual void SetUp() OVERRIDE { + ASSERT_TRUE(base_.CreateUniqueTempDir()); + base::FilePath base_dir = base_.path(); + file_system_context_ = + CreateFileSystemContextForTesting(NULL, base_dir); + } + + virtual void TearDown() OVERRIDE { + file_system_context_ = NULL; + base::RunLoop().RunUntilIdle(); + } + + FileSystemURL URL(const std::string& path) { + return file_system_context_->CreateCrackedFileSystemURL( + GURL("http://example.com"), kFileSystemTypeTemporary, + base::FilePath::FromUTF8Unsafe(path)); + } + + FileSystemOperationRunner* operation_runner() { + return file_system_context_->operation_runner(); + } + + private: + base::ScopedTempDir base_; + base::MessageLoop message_loop_; + scoped_refptr<FileSystemContext> file_system_context_; + + DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunnerTest); +}; + +TEST_F(FileSystemOperationRunnerTest, NotFoundError) { + bool done = false; + base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED; + + // Regular NOT_FOUND error, which is called asynchronously. + operation_runner()->Truncate(URL("foo"), 0, + base::Bind(&GetStatus, &done, &status)); + ASSERT_FALSE(done); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(done); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status); +} + +TEST_F(FileSystemOperationRunnerTest, InvalidURLError) { + bool done = false; + base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED; + + // Invalid URL error, which calls DidFinish synchronously. + operation_runner()->Truncate(FileSystemURL(), 0, + base::Bind(&GetStatus, &done, &status)); + // The error call back shouldn't be fired synchronously. + ASSERT_FALSE(done); + + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(done); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_URL, status); +} + +TEST_F(FileSystemOperationRunnerTest, NotFoundErrorAndCancel) { + bool done = false; + bool cancel_done = false; + base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED; + base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED; + + // Call Truncate with non-existent URL, and try to cancel it immediately + // after that (before its callback is fired). + FileSystemOperationRunner::OperationID id = + operation_runner()->Truncate(URL("foo"), 0, + base::Bind(&GetStatus, &done, &status)); + operation_runner()->Cancel(id, base::Bind(&GetCancelStatus, + &done, &cancel_done, + &cancel_status)); + + ASSERT_FALSE(done); + ASSERT_FALSE(cancel_done); + base::RunLoop().RunUntilIdle(); + + ASSERT_TRUE(done); + ASSERT_TRUE(cancel_done); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status); +} + +TEST_F(FileSystemOperationRunnerTest, InvalidURLErrorAndCancel) { + bool done = false; + bool cancel_done = false; + base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED; + base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED; + + // Call Truncate with invalid URL, and try to cancel it immediately + // after that (before its callback is fired). + FileSystemOperationRunner::OperationID id = + operation_runner()->Truncate(FileSystemURL(), 0, + base::Bind(&GetStatus, &done, &status)); + operation_runner()->Cancel(id, base::Bind(&GetCancelStatus, + &done, &cancel_done, + &cancel_status)); + + ASSERT_FALSE(done); + ASSERT_FALSE(cancel_done); + base::RunLoop().RunUntilIdle(); + + ASSERT_TRUE(done); + ASSERT_TRUE(cancel_done); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_URL, status); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status); +} + +TEST_F(FileSystemOperationRunnerTest, CancelWithInvalidId) { + const FileSystemOperationRunner::OperationID kInvalidId = -1; + bool done = true; // The operation is not running. + bool cancel_done = false; + base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED; + operation_runner()->Cancel(kInvalidId, base::Bind(&GetCancelStatus, + &done, &cancel_done, + &cancel_status)); + + ASSERT_TRUE(cancel_done); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status); +} + +} // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/file_system_quota_client.cc b/chromium/webkit/browser/fileapi/file_system_quota_client.cc index 343a6e6ee5c..76725df31a8 100644 --- a/chromium/webkit/browser/fileapi/file_system_quota_client.cc +++ b/chromium/webkit/browser/fileapi/file_system_quota_client.cc @@ -197,6 +197,12 @@ void FileSystemQuotaClient::DeleteOriginData( callback); } +bool FileSystemQuotaClient::DoesSupport(quota::StorageType storage_type) const { + FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); + DCHECK(type != kFileSystemTypeUnknown); + return file_system_context_->IsSandboxFileSystem(type); +} + base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const { return file_system_context_->default_file_task_runner(); } diff --git a/chromium/webkit/browser/fileapi/file_system_quota_client.h b/chromium/webkit/browser/fileapi/file_system_quota_client.h index f2168043f1b..f3cf68ddf13 100644 --- a/chromium/webkit/browser/fileapi/file_system_quota_client.h +++ b/chromium/webkit/browser/fileapi/file_system_quota_client.h @@ -56,6 +56,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemQuotaClient const GURL& origin, quota::StorageType type, const DeletionCallback& callback) OVERRIDE; + virtual bool DoesSupport(quota::StorageType type) const OVERRIDE; private: base::SequencedTaskRunner* file_task_runner() const; diff --git a/chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc b/chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc index 477bb77e95e..1a9121c1a7a 100644 --- a/chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc @@ -6,13 +6,13 @@ #include "base/bind.h" #include "base/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" #include "base/platform_file.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +#include "webkit/browser/fileapi/async_file_test_helper.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/file_system_quota_client.h" #include "webkit/browser/fileapi/file_system_usage_cache.h" #include "webkit/browser/fileapi/mock_file_system_context.h" @@ -74,7 +74,7 @@ class FileSystemQuotaClientTest : public testing::Test { const std::string& origin_url, quota::StorageType type) { GetOriginUsageAsync(quota_client, origin_url, type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return usage_; } @@ -85,7 +85,7 @@ class FileSystemQuotaClientTest : public testing::Test { type, base::Bind(&FileSystemQuotaClientTest::OnGetOrigins, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return origins_; } @@ -97,7 +97,7 @@ class FileSystemQuotaClientTest : public testing::Test { type, host, base::Bind(&FileSystemQuotaClientTest::OnGetOrigins, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); return origins_; } @@ -110,32 +110,16 @@ class FileSystemQuotaClientTest : public testing::Test { weak_factory_.GetWeakPtr())); } - FileSystemOperationContext* CreateFileSystemOperationContext( - FileSystemType type) { - FileSystemOperationContext* context = - new FileSystemOperationContext(file_system_context_.get()); - context->set_allowed_bytes_growth(100000000); - context->set_update_observers( - *file_system_context_->GetUpdateObservers(type)); - return context; - } - bool CreateFileSystemDirectory(const base::FilePath& file_path, const std::string& origin_url, quota::StorageType storage_type) { FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); - FileSystemFileUtil* file_util = file_system_context_->GetFileUtil(type); - FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( GURL(origin_url), type, file_path); - scoped_ptr<FileSystemOperationContext> context( - CreateFileSystemOperationContext(type)); base::PlatformFileError result = - file_util->CreateDirectory(context.get(), url, false, false); - if (result != base::PLATFORM_FILE_OK) - return false; - return true; + AsyncFileTestHelper::CreateDirectory(file_system_context_, url); + return result == base::PLATFORM_FILE_OK; } bool CreateFileSystemFile(const base::FilePath& file_path, @@ -146,22 +130,17 @@ class FileSystemQuotaClientTest : public testing::Test { return false; FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); - FileSystemFileUtil* file_util = file_system_context_->GetFileUtil(type); - FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( GURL(origin_url), type, file_path); - scoped_ptr<FileSystemOperationContext> context( - CreateFileSystemOperationContext(type)); - bool created = false; - if (base::PLATFORM_FILE_OK != - file_util->EnsureFileExists(context.get(), url, &created)) - return false; - EXPECT_TRUE(created); - if (base::PLATFORM_FILE_OK != - file_util->Truncate(context.get(), url, file_size)) + base::PlatformFileError result = + AsyncFileTestHelper::CreateFile(file_system_context_, url); + if (result != base::PLATFORM_FILE_OK) return false; - return true; + + result = AsyncFileTestHelper::TruncateFile( + file_system_context_, url, file_size); + return result == base::PLATFORM_FILE_OK; } void InitializeOriginFiles(FileSystemQuotaClient* quota_client, @@ -428,7 +407,7 @@ TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) { GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary); RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(11 + 22 + file_paths_cost, usage()); EXPECT_EQ(2, additional_callback_count()); @@ -437,7 +416,7 @@ TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) { RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary); RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(11 + 22 + file_paths_cost, usage()); EXPECT_EQ(2, additional_callback_count()); } @@ -539,15 +518,15 @@ TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) { "https://bar.com/", kPersistent); DeleteOriginData(quota_client.get(), "http://foo.com/", kTemporary); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(quota::kQuotaStatusOk, status()); DeleteOriginData(quota_client.get(), "http://bar.com/", kPersistent); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(quota::kQuotaStatusOk, status()); DeleteOriginData(quota_client.get(), "http://buz.com/", kTemporary); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(quota::kQuotaStatusOk, status()); EXPECT_EQ(0, GetOriginUsage( diff --git a/chromium/webkit/browser/fileapi/file_system_quota_util.h b/chromium/webkit/browser/fileapi/file_system_quota_util.h index be98936c2f5..5f3c7dd77ae 100644 --- a/chromium/webkit/browser/fileapi/file_system_quota_util.h +++ b/chromium/webkit/browser/fileapi/file_system_quota_util.h @@ -56,11 +56,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemQuotaUtil { const GURL& origin_url, fileapi::FileSystemType type) = 0; - virtual void InvalidateUsageCache(const GURL& origin_url, - fileapi::FileSystemType type) = 0; - virtual void StickyInvalidateUsageCache(const GURL& origin, - fileapi::FileSystemType type) = 0; - virtual void AddFileUpdateObserver( FileSystemType type, FileUpdateObserver* observer, @@ -73,6 +68,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemQuotaUtil { FileSystemType type, FileAccessObserver* observer, base::SequencedTaskRunner* task_runner) = 0; + + // Returns the observer list for |type|, or returns NULL if any observers + // have not been registered on |type|. virtual const UpdateObserverList* GetUpdateObservers( FileSystemType type) const = 0; virtual const ChangeObserverList* GetChangeObservers( diff --git a/chromium/webkit/browser/fileapi/file_system_url.cc b/chromium/webkit/browser/fileapi/file_system_url.cc index 6269296a684..2f8875a701b 100644 --- a/chromium/webkit/browser/fileapi/file_system_url.cc +++ b/chromium/webkit/browser/fileapi/file_system_url.cc @@ -46,9 +46,6 @@ bool FileSystemURL::ParseFileSystemSchemeURL( if (!url.is_valid() || !url.SchemeIsFileSystem()) return false; - DCHECK(url.inner_url()); - - std::string inner_path = url.inner_url()->path(); const struct { FileSystemType type; @@ -61,8 +58,11 @@ bool FileSystemURL::ParseFileSystemSchemeURL( { kFileSystemTypeTest, kTestDir }, }; + // A path of the inner_url contains only mount type part (e.g. "/temporary"). + DCHECK(url.inner_url()); + std::string inner_path = url.inner_url()->path(); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidTypes); ++i) { - if (StartsWithASCII(inner_path, kValidTypes[i].dir, true)) { + if (inner_path == kValidTypes[i].dir) { file_system_type = kValidTypes[i].type; break; } @@ -135,6 +135,20 @@ FileSystemURL::FileSystemURL(const GURL& origin, FileSystemURL::~FileSystemURL() {} +GURL FileSystemURL::ToGURL() const { + if (!is_valid_) + return GURL(); + + std::string url = GetFileSystemRootURI(origin_, mount_type_).spec(); + if (url.empty()) + return GURL(); + + url.append(virtual_path_.AsUTF8Unsafe()); + + // Build nested GURL. + return GURL(url); +} + std::string FileSystemURL::DebugString() const { if (!is_valid_) return "invalid filesystem: URL"; diff --git a/chromium/webkit/browser/fileapi/file_system_url.h b/chromium/webkit/browser/fileapi/file_system_url.h index 6ac875d6310..d6443e69189 100644 --- a/chromium/webkit/browser/fileapi/file_system_url.h +++ b/chromium/webkit/browser/fileapi/file_system_url.h @@ -118,6 +118,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemURL { FileSystemType mount_type() const { return mount_type_; } + // Returns the formatted URL of this instance. + GURL ToGURL() const; + std::string DebugString() const; // Returns true if this URL is a strict parent of the |child|. @@ -127,6 +130,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemURL { bool operator==(const FileSystemURL& that) const; + bool operator!=(const FileSystemURL& that) const { + return !(*this == that); + } + struct WEBKIT_STORAGE_BROWSER_EXPORT Comparator { bool operator() (const FileSystemURL& lhs, const FileSystemURL& rhs) const; }; diff --git a/chromium/webkit/browser/fileapi/file_system_url_request_job.cc b/chromium/webkit/browser/fileapi/file_system_url_request_job.cc index d93c14089f2..7d1f8613138 100644 --- a/chromium/webkit/browser/fileapi/file_system_url_request_job.cc +++ b/chromium/webkit/browser/fileapi/file_system_url_request_job.cc @@ -157,6 +157,11 @@ void FileSystemURLRequestJob::StartAsync() { return; DCHECK(!reader_.get()); url_ = file_system_context_->CrackURL(request_->url()); + if (!file_system_context_->CanServeURLRequest(url_)) { + // In incognito mode the API is not usable and there should be no data. + NotifyFailed(net::ERR_FILE_NOT_FOUND); + return; + } file_system_context_->operation_runner()->GetMetadata( url_, base::Bind(&FileSystemURLRequestJob::DidGetMetadata, diff --git a/chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc b/chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc index a8f6cabbffe..8f54e62b984 100644 --- a/chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2013 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. @@ -16,6 +16,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/platform_file.h" #include "base/rand_util.h" +#include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -28,9 +29,10 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/fileapi/async_file_test_helper.h" +#include "webkit/browser/fileapi/external_mount_points.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/mock_file_system_context.h" namespace fileapi { @@ -66,7 +68,7 @@ class FileSystemURLRequestJobTest : public testing::Test { OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&FileSystemURLRequestJobTest::OnOpenFileSystem, weak_factory_.GetWeakPtr())); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); net::URLRequest::Deprecated::RegisterProtocolFactory( "filesystem", &FileSystemURLRequestJobFactory); @@ -80,7 +82,7 @@ class FileSystemURLRequestJobTest : public testing::Test { pending_job_ = NULL; } // FileReader posts a task to close the file in destructor. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void OnOpenFileSystem(base::PlatformFileError result, @@ -91,7 +93,8 @@ class FileSystemURLRequestJobTest : public testing::Test { void TestRequestHelper(const GURL& url, const net::HttpRequestHeaders* headers, - bool run_to_completion) { + bool run_to_completion, + FileSystemContext* file_system_context) { delegate_.reset(new net::TestDelegate()); // Make delegate_ exit the MessageLoop when the request is done. delegate_->set_quit_on_complete(true); @@ -101,7 +104,7 @@ class FileSystemURLRequestJobTest : public testing::Test { request_->SetExtraRequestHeaders(*headers); ASSERT_TRUE(!job_); job_ = new FileSystemURLRequestJob( - request_.get(), NULL, file_system_context_.get()); + request_.get(), NULL, file_system_context); pending_job_ = job_; request_->Start(); @@ -111,61 +114,41 @@ class FileSystemURLRequestJobTest : public testing::Test { } void TestRequest(const GURL& url) { - TestRequestHelper(url, NULL, true); + TestRequestHelper(url, NULL, true, file_system_context_.get()); + } + + void TestRequestWithContext(const GURL& url, + FileSystemContext* file_system_context) { + TestRequestHelper(url, NULL, true, file_system_context); } void TestRequestWithHeaders(const GURL& url, const net::HttpRequestHeaders* headers) { - TestRequestHelper(url, headers, true); + TestRequestHelper(url, headers, true, file_system_context_.get()); } void TestRequestNoRun(const GURL& url) { - TestRequestHelper(url, NULL, false); + TestRequestHelper(url, NULL, false, file_system_context_.get()); } void CreateDirectory(const base::StringPiece& dir_name) { - FileSystemFileUtil* file_util = file_system_context_->GetFileUtil( - kFileSystemTypeTemporary); FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( GURL("http://remote"), kFileSystemTypeTemporary, base::FilePath().AppendASCII(dir_name)); - - FileSystemOperationContext context(file_system_context_.get()); - context.set_allowed_bytes_growth(1024); - - ASSERT_EQ(base::PLATFORM_FILE_OK, file_util->CreateDirectory( - &context, - url, - false /* exclusive */, - false /* recursive */)); + ASSERT_EQ(base::PLATFORM_FILE_OK, AsyncFileTestHelper::CreateDirectory( + file_system_context_, url)); } void WriteFile(const base::StringPiece& file_name, const char* buf, int buf_size) { - FileSystemFileUtil* file_util = file_system_context_->GetFileUtil( - kFileSystemTypeTemporary); FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( GURL("http://remote"), kFileSystemTypeTemporary, base::FilePath().AppendASCII(file_name)); - - FileSystemOperationContext context(file_system_context_.get()); - context.set_allowed_bytes_growth(1024); - - base::PlatformFile handle = base::kInvalidPlatformFileValue; - bool created = false; - ASSERT_EQ(base::PLATFORM_FILE_OK, file_util->CreateOrOpen( - &context, - url, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, - &handle, - &created)); - EXPECT_TRUE(created); - ASSERT_NE(base::kInvalidPlatformFileValue, handle); - ASSERT_EQ(buf_size, - base::WritePlatformFile(handle, 0 /* offset */, buf, buf_size)); - base::ClosePlatformFile(handle); + ASSERT_EQ(base::PLATFORM_FILE_OK, + AsyncFileTestHelper::CreateFileWithData( + file_system_context_, url, buf, buf_size)); } GURL CreateFileSystemURL(const std::string& path) { @@ -335,7 +318,7 @@ TEST_F(FileSystemURLRequestJobTest, Cancel) { // Run StartAsync() and only StartAsync(). base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // If we get here, success! we didn't crash! } @@ -357,5 +340,26 @@ TEST_F(FileSystemURLRequestJobTest, GetMimeType) { EXPECT_EQ(mime_type_direct, mime_type_from_job); } +TEST_F(FileSystemURLRequestJobTest, Incognito) { + WriteFile("file", kTestFileData, arraysize(kTestFileData) - 1); + + // Creates a new filesystem context for incognito mode. + scoped_refptr<FileSystemContext> file_system_context = + CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path()); + + // The request should return NOT_FOUND error if it's in incognito mode. + TestRequestWithContext(CreateFileSystemURL("file"), + file_system_context.get()); + ASSERT_FALSE(request_->is_pending()); + EXPECT_TRUE(delegate_->request_failed()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error()); + + // Make sure it returns success with regular (non-incognito) context. + TestRequest(CreateFileSystemURL("file")); + ASSERT_FALSE(request_->is_pending()); + EXPECT_EQ(kTestFileData, delegate_->data_received()); + EXPECT_EQ(200, request_->GetResponseCode()); +} + } // namespace } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/file_system_url_unittest.cc b/chromium/webkit/browser/fileapi/file_system_url_unittest.cc index ace67007cb3..c5a632c735c 100644 --- a/chromium/webkit/browser/fileapi/file_system_url_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_system_url_unittest.cc @@ -84,6 +84,8 @@ TEST(FileSystemURLTest, UnescapePath) { TEST(FileSystemURLTest, RejectBadType) { EXPECT_FALSE(CreateFileSystemURL( "filesystem:http://c.org/foobar/file").is_valid()); + EXPECT_FALSE(CreateFileSystemURL( + "filesystem:http://c.org/temporaryfoo/file").is_valid()); } TEST(FileSystemURLTest, RejectMalformedURL) { @@ -156,6 +158,23 @@ TEST(FileSystemURLTest, IsParent) { CreateFileSystemURL(root3 + child))); } +TEST(FileSystemURLTest, ToGURL) { + EXPECT_TRUE(FileSystemURL().ToGURL().is_empty()); + const char* kTestURL[] = { + "filesystem:http://chromium.org/persistent/directory/file0", + "filesystem:http://chromium.org/temporary/directory/file1", + "filesystem:http://chromium.org/isolated/directory/file2", + "filesystem:http://chromium.org/external/directory/file2", + "filesystem:http://chromium.org/test/directory/file3", + }; + + for (size_t i = 0; i < arraysize(kTestURL); ++i) { + EXPECT_EQ( + kTestURL[i], + FileSystemURL::CreateForTest(GURL(kTestURL[i])).ToGURL().spec()); + } +} + TEST(FileSystemURLTest, DebugString) { const GURL kOrigin("http://example.com"); const base::FilePath kPath(FPL("dir/file")); diff --git a/chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc b/chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc index 340fcb0120e..28c93e8a0db 100644 --- a/chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc +++ b/chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc @@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "net/base/io_buffer.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" @@ -17,9 +17,8 @@ #include "net/url_request/url_request_status.h" #include "testing/platform_test.h" #include "url/gurl.h" +#include "webkit/browser/fileapi/async_file_test_helper.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/file_system_quota_util.h" #include "webkit/browser/fileapi/file_writer_delegate.h" #include "webkit/browser/fileapi/mock_file_system_context.h" @@ -80,10 +79,6 @@ class FileWriterDelegateTest : public PlatformTest { virtual void SetUp() OVERRIDE; virtual void TearDown() OVERRIDE; - FileSystemFileUtil* file_util() { - return file_system_context_->GetFileUtil(kFileSystemType); - } - int64 usage() { return file_system_context_->GetQuotaUtil(kFileSystemType) ->GetOriginUsageOnFileThread( @@ -94,14 +89,13 @@ class FileWriterDelegateTest : public PlatformTest { // There might be in-flight flush/write. base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&base::DoNothing)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); FileSystemURL url = GetFileSystemURL(test_file_path); base::PlatformFileInfo file_info; - base::FilePath platform_path; EXPECT_EQ(base::PLATFORM_FILE_OK, - file_util()->GetFileInfo(NewOperationContext().get(), url, - &file_info, &platform_path)); + AsyncFileTestHelper::GetMetadata( + file_system_context_, url, &file_info)); return file_info.size; } @@ -110,15 +104,6 @@ class FileWriterDelegateTest : public PlatformTest { kOrigin, kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name)); } - scoped_ptr<FileSystemOperationContext> NewOperationContext() { - FileSystemOperationContext* context = - new FileSystemOperationContext(file_system_context_.get()); - context->set_update_observers( - *file_system_context_->GetUpdateObservers(kFileSystemType)); - context->set_root_path(dir_.path()); - return make_scoped_ptr(context); - } - FileWriterDelegate* CreateWriterDelegate( const char* test_file_path, int64 offset, @@ -231,23 +216,16 @@ void FileWriterDelegateTest::SetUp() { file_system_context_ = CreateFileSystemContextForTesting( NULL, dir_.path()); - - bool created = false; - scoped_ptr<FileSystemOperationContext> context = NewOperationContext(); - context->set_allowed_bytes_growth(kint64max); - base::PlatformFileError error = file_util()->EnsureFileExists( - context.get(), - GetFileSystemURL("test"), - &created); - ASSERT_EQ(base::PLATFORM_FILE_OK, error); - ASSERT_TRUE(created); + ASSERT_EQ(base::PLATFORM_FILE_OK, + AsyncFileTestHelper::CreateFile( + file_system_context_, GetFileSystemURL("test"))); net::URLRequest::Deprecated::RegisterProtocolFactory("blob", &Factory); } void FileWriterDelegateTest::TearDown() { net::URLRequest::Deprecated::RegisterProtocolFactory("blob", NULL); file_system_context_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) { @@ -336,11 +314,9 @@ TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) { scoped_ptr<FileWriterDelegate> file_writer_delegate2; scoped_ptr<net::URLRequest> request2; - bool created = false; - file_util()->EnsureFileExists(NewOperationContext().get(), - GetFileSystemURL("test2"), - &created); - ASSERT_TRUE(created); + ASSERT_EQ(base::PLATFORM_FILE_OK, + AsyncFileTestHelper::CreateFile( + file_system_context_, GetFileSystemURL("test2"))); const GURL kBlobURL("blob:nolimitconcurrent"); const GURL kBlobURL2("blob:nolimitconcurrent2"); diff --git a/chromium/webkit/browser/fileapi/isolated_file_system_backend.cc b/chromium/webkit/browser/fileapi/isolated_file_system_backend.cc index db59e35c857..f83ae15d8f3 100644 --- a/chromium/webkit/browser/fileapi/isolated_file_system_backend.cc +++ b/chromium/webkit/browser/fileapi/isolated_file_system_backend.cc @@ -13,16 +13,15 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/platform_file.h" #include "base/sequenced_task_runner.h" -#include "webkit/browser/blob/local_file_stream_reader.h" +#include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/async_file_util_adapter.h" #include "webkit/browser/fileapi/copy_or_move_file_validator.h" +#include "webkit/browser/fileapi/dragged_file_util.h" +#include "webkit/browser/fileapi/file_stream_writer.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_file_stream_reader.h" +#include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_operation_impl.h" #include "webkit/browser/fileapi/isolated_context.h" -#include "webkit/browser/fileapi/isolated_file_util.h" -#include "webkit/browser/fileapi/local_file_stream_writer.h" #include "webkit/browser/fileapi/native_file_util.h" #include "webkit/browser/fileapi/transient_file_util.h" #include "webkit/common/fileapi/file_system_types.h" @@ -31,7 +30,7 @@ namespace fileapi { IsolatedFileSystemBackend::IsolatedFileSystemBackend() - : isolated_file_util_(new AsyncFileUtilAdapter(new IsolatedFileUtil())), + : isolated_file_util_(new AsyncFileUtilAdapter(new LocalFileUtil())), dragged_file_util_(new AsyncFileUtilAdapter(new DraggedFileUtil())), transient_file_util_(new AsyncFileUtilAdapter(new TransientFileUtil())) { } @@ -72,21 +71,6 @@ void IsolatedFileSystemBackend::OpenFileSystem( base::PLATFORM_FILE_ERROR_SECURITY)); } -FileSystemFileUtil* IsolatedFileSystemBackend::GetFileUtil( - FileSystemType type) { - switch (type) { - case kFileSystemTypeNativeLocal: - return isolated_file_util_->sync_file_util(); - case kFileSystemTypeDragged: - return dragged_file_util_->sync_file_util(); - case kFileSystemTypeForTransientFile: - return transient_file_util_->sync_file_util(); - default: - NOTREACHED(); - } - return NULL; -} - AsyncFileUtil* IsolatedFileSystemBackend::GetAsyncFileUtil( FileSystemType type) { switch (type) { @@ -114,7 +98,7 @@ FileSystemOperation* IsolatedFileSystemBackend::CreateFileSystemOperation( const FileSystemURL& url, FileSystemContext* context, base::PlatformFileError* error_code) const { - return new FileSystemOperationImpl( + return FileSystemOperation::Create( url, context, make_scoped_ptr(new FileSystemOperationContext(context))); } @@ -125,7 +109,7 @@ IsolatedFileSystemBackend::CreateFileStreamReader( const base::Time& expected_modification_time, FileSystemContext* context) const { return scoped_ptr<webkit_blob::FileStreamReader>( - new webkit_blob::LocalFileStreamReader( + webkit_blob::FileStreamReader::CreateForLocalFile( context->default_file_task_runner(), url.path(), offset, expected_modification_time)); } @@ -134,7 +118,7 @@ scoped_ptr<FileStreamWriter> IsolatedFileSystemBackend::CreateFileStreamWriter( const FileSystemURL& url, int64 offset, FileSystemContext* context) const { - return scoped_ptr<FileStreamWriter>(new LocalFileStreamWriter( + return scoped_ptr<FileStreamWriter>(FileStreamWriter::CreateForLocalFile( context->default_file_task_runner(), url.path(), offset)); } diff --git a/chromium/webkit/browser/fileapi/isolated_file_system_backend.h b/chromium/webkit/browser/fileapi/isolated_file_system_backend.h index cdc70969214..aa038442dc6 100644 --- a/chromium/webkit/browser/fileapi/isolated_file_system_backend.h +++ b/chromium/webkit/browser/fileapi/isolated_file_system_backend.h @@ -25,7 +25,6 @@ class IsolatedFileSystemBackend : public FileSystemBackend { FileSystemType type, OpenFileSystemMode mode, const OpenFileSystemCallback& callback) OVERRIDE; - virtual FileSystemFileUtil* GetFileUtil(FileSystemType type) OVERRIDE; virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, diff --git a/chromium/webkit/browser/fileapi/local_file_stream_writer.cc b/chromium/webkit/browser/fileapi/local_file_stream_writer.cc index 3f779c969ed..75c2cad8bae 100644 --- a/chromium/webkit/browser/fileapi/local_file_stream_writer.cc +++ b/chromium/webkit/browser/fileapi/local_file_stream_writer.cc @@ -20,14 +20,12 @@ const int kOpenFlagsForWrite = base::PLATFORM_FILE_OPEN | } // namespace -LocalFileStreamWriter::LocalFileStreamWriter(base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset) - : file_path_(file_path), - initial_offset_(initial_offset), - has_pending_operation_(false), - weak_factory_(this), - task_runner_(task_runner) {} +FileStreamWriter* FileStreamWriter::CreateForLocalFile( + base::TaskRunner* task_runner, + const base::FilePath& file_path, + int64 initial_offset) { + return new LocalFileStreamWriter(task_runner, file_path, initial_offset); +} LocalFileStreamWriter::~LocalFileStreamWriter() { // Invalidate weak pointers so that we won't receive any callbacks from @@ -81,6 +79,15 @@ int LocalFileStreamWriter::Flush(const net::CompletionCallback& callback) { return result; } +LocalFileStreamWriter::LocalFileStreamWriter(base::TaskRunner* task_runner, + const base::FilePath& file_path, + int64 initial_offset) + : file_path_(file_path), + initial_offset_(initial_offset), + has_pending_operation_(false), + weak_factory_(this), + task_runner_(task_runner) {} + int LocalFileStreamWriter::InitiateOpen( const net::CompletionCallback& error_callback, const base::Closure& main_operation) { diff --git a/chromium/webkit/browser/fileapi/local_file_stream_writer.h b/chromium/webkit/browser/fileapi/local_file_stream_writer.h index 08e12e80e41..dce428a56bd 100644 --- a/chromium/webkit/browser/fileapi/local_file_stream_writer.h +++ b/chromium/webkit/browser/fileapi/local_file_stream_writer.h @@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" +#include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/platform_file.h" @@ -24,13 +25,9 @@ class FileStream; namespace fileapi { // This class is a thin wrapper around net::FileStream for writing local files. -class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE LocalFileStreamWriter - : public FileStreamWriter { +class WEBKIT_STORAGE_BROWSER_EXPORT LocalFileStreamWriter + : public NON_EXPORTED_BASE(FileStreamWriter) { public: - // Creates a writer for the existing file in the path |file_path| starting - // from |initial_offset|. Uses |task_runner| for async file operations. - LocalFileStreamWriter(base::TaskRunner* task_runner, - const base::FilePath& file_path, int64 initial_offset); virtual ~LocalFileStreamWriter(); // FileStreamWriter overrides. @@ -40,6 +37,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE LocalFileStreamWriter virtual int Flush(const net::CompletionCallback& callback) OVERRIDE; private: + friend class FileStreamWriter; + friend class LocalFileStreamWriterTest; + LocalFileStreamWriter(base::TaskRunner* task_runner, + const base::FilePath& file_path, + int64 initial_offset); + // Opens |file_path_| and if it succeeds, proceeds to InitiateSeek(). // If failed, the error code is returned by calling |error_callback|. int InitiateOpen(const net::CompletionCallback& error_callback, diff --git a/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc b/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc index bed037d7b09..cf3c06a18cd 100644 --- a/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc +++ b/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc @@ -12,14 +12,13 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "base/threading/thread.h" #include "net/base/io_buffer.h" #include "net/base/test_completion_callback.h" #include "testing/gtest/include/gtest/gtest.h" -namespace { - -using fileapi::LocalFileStreamWriter; +namespace fileapi { class LocalFileStreamWriterTest : public testing::Test { public: @@ -34,9 +33,9 @@ class LocalFileStreamWriterTest : public testing::Test { virtual void TearDown() OVERRIDE { // Give another chance for deleted streams to perform Close. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); file_thread_.Stop(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } protected: @@ -65,7 +64,7 @@ class LocalFileStreamWriterTest : public testing::Test { std::string GetFileContent(const base::FilePath& path) { std::string content; - file_util::ReadFileToString(path, &content); + base::ReadFileToString(path, &content); return content; } @@ -80,6 +79,11 @@ class LocalFileStreamWriterTest : public testing::Test { return file_thread_.message_loop_proxy().get(); } + LocalFileStreamWriter* CreateWriter(const base::FilePath& path, + int64 offset) { + return new LocalFileStreamWriter(file_task_runner(), path, offset); + } + private: base::MessageLoop message_loop_; base::Thread file_thread_; @@ -90,38 +94,33 @@ void NeverCalled(int unused) { ADD_FAILURE(); } -} // namespace - TEST_F(LocalFileStreamWriterTest, Write) { base::FilePath path = CreateFileWithContent("file_a", std::string()); - scoped_ptr<LocalFileStreamWriter> writer( - new LocalFileStreamWriter(file_task_runner(), path, 0)); + scoped_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0)); EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo")); EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "bar")); writer.reset(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(base::PathExists(path)); EXPECT_EQ("foobar", GetFileContent(path)); } TEST_F(LocalFileStreamWriterTest, WriteMiddle) { base::FilePath path = CreateFileWithContent("file_a", "foobar"); - scoped_ptr<LocalFileStreamWriter> writer( - new LocalFileStreamWriter(file_task_runner(), path, 2)); + scoped_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 2)); EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx")); writer.reset(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(base::PathExists(path)); EXPECT_EQ("foxxxr", GetFileContent(path)); } TEST_F(LocalFileStreamWriterTest, WriteEnd) { base::FilePath path = CreateFileWithContent("file_a", "foobar"); - scoped_ptr<LocalFileStreamWriter> writer( - new LocalFileStreamWriter(file_task_runner(), path, 6)); + scoped_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 6)); EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx")); writer.reset(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(base::PathExists(path)); EXPECT_EQ("foobarxxx", GetFileContent(path)); } @@ -129,18 +128,16 @@ TEST_F(LocalFileStreamWriterTest, WriteEnd) { TEST_F(LocalFileStreamWriterTest, WriteFailForNonexistingFile) { base::FilePath path = Path("file_a"); ASSERT_FALSE(base::PathExists(path)); - scoped_ptr<LocalFileStreamWriter> writer( - new LocalFileStreamWriter(file_task_runner(), path, 0)); + scoped_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0)); EXPECT_EQ(net::ERR_FILE_NOT_FOUND, WriteStringToWriter(writer.get(), "foo")); writer.reset(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(base::PathExists(path)); } TEST_F(LocalFileStreamWriterTest, CancelBeforeOperation) { base::FilePath path = Path("file_a"); - scoped_ptr<LocalFileStreamWriter> writer( - new LocalFileStreamWriter(file_task_runner(), path, 0)); + scoped_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0)); // Cancel immediately fails when there's no in-flight operation. int cancel_result = writer->Cancel(base::Bind(&NeverCalled)); EXPECT_EQ(net::ERR_UNEXPECTED, cancel_result); @@ -148,8 +145,7 @@ TEST_F(LocalFileStreamWriterTest, CancelBeforeOperation) { TEST_F(LocalFileStreamWriterTest, CancelAfterFinishedOperation) { base::FilePath path = CreateFileWithContent("file_a", std::string()); - scoped_ptr<LocalFileStreamWriter> writer( - new LocalFileStreamWriter(file_task_runner(), path, 0)); + scoped_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0)); EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo")); // Cancel immediately fails when there's no in-flight operation. @@ -157,7 +153,7 @@ TEST_F(LocalFileStreamWriterTest, CancelAfterFinishedOperation) { EXPECT_EQ(net::ERR_UNEXPECTED, cancel_result); writer.reset(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // Write operation is already completed. EXPECT_TRUE(base::PathExists(path)); EXPECT_EQ("foo", GetFileContent(path)); @@ -165,8 +161,7 @@ TEST_F(LocalFileStreamWriterTest, CancelAfterFinishedOperation) { TEST_F(LocalFileStreamWriterTest, CancelWrite) { base::FilePath path = CreateFileWithContent("file_a", "foobar"); - scoped_ptr<LocalFileStreamWriter> writer( - new LocalFileStreamWriter(file_task_runner(), path, 0)); + scoped_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0)); scoped_refptr<net::StringIOBuffer> buffer(new net::StringIOBuffer("xxx")); int result = @@ -178,3 +173,5 @@ TEST_F(LocalFileStreamWriterTest, CancelWrite) { int cancel_result = callback.WaitForResult(); EXPECT_EQ(net::OK, cancel_result); } + +} // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/local_file_util.cc b/chromium/webkit/browser/fileapi/local_file_util.cc index f13af8d207f..d2d653ac78c 100644 --- a/chromium/webkit/browser/fileapi/local_file_util.cc +++ b/chromium/webkit/browser/fileapi/local_file_util.cc @@ -8,6 +8,7 @@ #include "base/files/file_enumerator.h" #include "base/files/file_util_proxy.h" #include "url/gurl.h" +#include "webkit/browser/fileapi/async_file_util_adapter.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/file_system_url.h" @@ -17,6 +18,10 @@ namespace fileapi { +AsyncFileUtil* AsyncFileUtil::CreateForLocalFileSystem() { + return new AsyncFileUtilAdapter(new LocalFileUtil()); +} + using base::PlatformFileError; class LocalFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { @@ -69,11 +74,9 @@ bool LocalFileEnumerator::IsDirectory() { return file_util_info_.IsDirectory(); } -LocalFileUtil::LocalFileUtil() { -} +LocalFileUtil::LocalFileUtil() {} -LocalFileUtil::~LocalFileUtil() { -} +LocalFileUtil::~LocalFileUtil() {} PlatformFileError LocalFileUtil::CreateOrOpen( FileSystemOperationContext* context, @@ -157,10 +160,13 @@ PlatformFileError LocalFileUtil::GetLocalFilePath( FileSystemOperationContext* context, const FileSystemURL& url, base::FilePath* local_file_path) { - base::FilePath root = context->root_path(); - if (root.empty()) - return base::PLATFORM_FILE_ERROR_NOT_FOUND; - *local_file_path = root.Append(url.path()); + DCHECK(local_file_path); + DCHECK(url.is_valid()); + if (url.path().empty()) { + // Root direcory case, which should not be accessed. + return base::PLATFORM_FILE_ERROR_ACCESS_DENIED; + } + *local_file_path = url.path(); return base::PLATFORM_FILE_OK; } diff --git a/chromium/webkit/browser/fileapi/local_file_util.h b/chromium/webkit/browser/fileapi/local_file_util.h index abd6b54e1c3..38f285a6b04 100644 --- a/chromium/webkit/browser/fileapi/local_file_util.h +++ b/chromium/webkit/browser/fileapi/local_file_util.h @@ -6,13 +6,13 @@ #define WEBKIT_BROWSER_FILEAPI_LOCAL_FILE_UTIL_H_ #include "base/compiler_specific.h" +#include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/platform_file.h" #include "webkit/browser/fileapi/file_system_file_util.h" #include "webkit/browser/webkit_storage_browser_export.h" namespace base { -class FilePath; class Time; } @@ -24,7 +24,7 @@ class FileSystemOperationContext; class FileSystemURL; // An instance of this class is created and owned by *FileSystemBackend. -class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE LocalFileUtil +class WEBKIT_STORAGE_BROWSER_EXPORT LocalFileUtil : public FileSystemFileUtil { public: LocalFileUtil(); diff --git a/chromium/webkit/browser/fileapi/local_file_util_unittest.cc b/chromium/webkit/browser/fileapi/local_file_util_unittest.cc index b0b52e718db..bdd2d879925 100644 --- a/chromium/webkit/browser/fileapi/local_file_util_unittest.cc +++ b/chromium/webkit/browser/fileapi/local_file_util_unittest.cc @@ -7,13 +7,14 @@ #include "base/file_util.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" #include "base/platform_file.h" +#include "base/run_loop.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/fileapi/async_file_test_helper.h" +#include "webkit/browser/fileapi/async_file_util_adapter.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_file_util.h" #include "webkit/browser/fileapi/file_system_operation_context.h" @@ -43,7 +44,7 @@ class LocalFileUtilTest : public testing::Test { virtual void TearDown() { file_system_context_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } protected: @@ -52,13 +53,13 @@ class LocalFileUtilTest : public testing::Test { new FileSystemOperationContext(file_system_context_.get()); context->set_update_observers( *file_system_context_->GetUpdateObservers(kFileSystemType)); - context->set_root_path(data_dir_.path()); return context; } LocalFileUtil* file_util() { - return static_cast<LocalFileUtil*>( - file_system_context_->GetFileUtil(kFileSystemType)); + AsyncFileUtilAdapter* adapter = static_cast<AsyncFileUtilAdapter*>( + file_system_context_->GetAsyncFileUtil(kFileSystemType)); + return static_cast<LocalFileUtil*>(adapter->sync_file_util()); } FileSystemURL CreateURL(const std::string& file_name) { diff --git a/chromium/webkit/browser/fileapi/mock_file_system_context.cc b/chromium/webkit/browser/fileapi/mock_file_system_context.cc index e2556d5da13..ed1715c2bbe 100644 --- a/chromium/webkit/browser/fileapi/mock_file_system_context.cc +++ b/chromium/webkit/browser/fileapi/mock_file_system_context.cc @@ -39,4 +39,19 @@ FileSystemContext* CreateFileSystemContextWithAdditionalProvidersForTesting( CreateAllowFileAccessOptions()); } +FileSystemContext* CreateIncognitoFileSystemContextForTesting( + quota::QuotaManagerProxy* quota_manager_proxy, + const base::FilePath& base_path) { + ScopedVector<FileSystemBackend> additional_providers; + return new FileSystemContext( + base::MessageLoopProxy::current().get(), + base::MessageLoopProxy::current().get(), + ExternalMountPoints::CreateRefCounted().get(), + make_scoped_refptr(new quota::MockSpecialStoragePolicy()).get(), + quota_manager_proxy, + additional_providers.Pass(), + base_path, + CreateIncognitoFileSystemOptions()); +} + } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/mock_file_system_context.h b/chromium/webkit/browser/fileapi/mock_file_system_context.h index bf01ba1594d..83b904d6fde 100644 --- a/chromium/webkit/browser/fileapi/mock_file_system_context.h +++ b/chromium/webkit/browser/fileapi/mock_file_system_context.h @@ -29,6 +29,10 @@ FileSystemContext* CreateFileSystemContextWithAdditionalProvidersForTesting( ScopedVector<FileSystemBackend> additional_providers, const base::FilePath& base_path); +FileSystemContext* CreateIncognitoFileSystemContextForTesting( + quota::QuotaManagerProxy* quota_manager_proxy, + const base::FilePath& base_path); + } // namespace fileapi #endif // WEBKIT_BROWSER_FILEAPI_MOCK_FILE_SYSTEM_CONTEXT_H_ diff --git a/chromium/webkit/browser/fileapi/obfuscated_file_util.cc b/chromium/webkit/browser/fileapi/obfuscated_file_util.cc index 77e2d86a7e7..341f7d0a8bb 100644 --- a/chromium/webkit/browser/fileapi/obfuscated_file_util.cc +++ b/chromium/webkit/browser/fileapi/obfuscated_file_util.cc @@ -12,6 +12,7 @@ #include "base/format_macros.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" +#include "base/metrics/histogram.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -99,6 +100,12 @@ const base::FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t" const base::FilePath::CharType kPersistentDirectoryName[] = FILE_PATH_LITERAL("p"); const base::FilePath::CharType kSyncableDirectoryName[] = FILE_PATH_LITERAL("s"); +enum IsolatedOriginStatus { + kIsolatedOriginMatch, + kIsolatedOriginDontMatch, + kIsolatedOriginStatusMax, +}; + } // namespace using base::PlatformFile; @@ -276,7 +283,7 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen( file_flags & base::PLATFORM_FILE_WRITE && context->quota_limit_type() == quota::kQuotaLimitTypeUnlimited) { DCHECK_EQ(base::PLATFORM_FILE_OK, error); - context->file_system_context()->GetQuotaUtil(url.type())-> + context->file_system_context()->sandbox_delegate()-> StickyInvalidateUsageCache(url.origin(), url.type()); } return error; @@ -380,10 +387,9 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory( int64 growth = UsageForPath(file_info.name.size()); if (!AllocateQuota(context, growth)) return base::PLATFORM_FILE_ERROR_NO_SPACE; - if (!db->AddFileInfo(file_info, &parent_id)) { - NOTREACHED(); - return base::PLATFORM_FILE_ERROR_FAILED; - } + base::PlatformFileError error = db->AddFileInfo(file_info, &parent_id); + if (error != base::PLATFORM_FILE_OK) + return error; UpdateUsage(context, url, growth); context->change_observers()->Notify( &FileChangeObserver::OnCreateDirectory, MakeTuple(url)); @@ -1123,6 +1129,7 @@ PlatformFileError ObfuscatedFileUtil::CreateFile( DCHECK_NE(base::kInvalidPlatformFileValue, *handle); base::ClosePlatformFile(*handle); base::DeleteFile(dest_local_path, false /* recursive */); + *handle = base::kInvalidPlatformFileValue; } return base::PLATFORM_FILE_ERROR_FAILED; } @@ -1133,13 +1140,15 @@ PlatformFileError ObfuscatedFileUtil::CreateFile( dest_local_path.value().substr(root.value().length() + 1)); FileId file_id; - if (!db->AddFileInfo(*dest_file_info, &file_id)) { + error = db->AddFileInfo(*dest_file_info, &file_id); + if (error != base::PLATFORM_FILE_OK) { if (handle) { DCHECK_NE(base::kInvalidPlatformFileValue, *handle); base::ClosePlatformFile(*handle); + *handle = base::kInvalidPlatformFileValue; } base::DeleteFile(dest_local_path, false /* recursive */); - return base::PLATFORM_FILE_ERROR_FAILED; + return error; } TouchDirectory(db, dest_file_info->parent_id); @@ -1261,7 +1270,7 @@ void ObfuscatedFileUtil::InvalidateUsageCache( FileSystemOperationContext* context, const GURL& origin, FileSystemType type) { - context->file_system_context()->GetQuotaUtil(type)-> + context->file_system_context()->sandbox_delegate()-> InvalidateUsageCache(origin, type); } @@ -1436,6 +1445,15 @@ bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) { isolated_origin_ = origin; // Record isolated_origin_, but always disable for now. // crbug.com/264429 + if (isolated_origin_ != origin) { + UMA_HISTOGRAM_ENUMERATION("FileSystem.IsolatedOriginStatus", + kIsolatedOriginDontMatch, + kIsolatedOriginStatusMax); + } else { + UMA_HISTOGRAM_ENUMERATION("FileSystem.IsolatedOriginStatus", + kIsolatedOriginMatch, + kIsolatedOriginStatusMax); + } return false; } return false; diff --git a/chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc b/chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc index c4f409f76ed..c37b17caa23 100644 --- a/chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc +++ b/chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc @@ -11,8 +11,8 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/platform_file.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/fileapi/async_file_test_helper.h" #include "webkit/browser/fileapi/external_mount_points.h" @@ -248,7 +248,7 @@ class ObfuscatedFileUtilTest : public testing::Test { } int64 SizeInUsageFile() { - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 usage = 0; return usage_cache()->GetUsage( sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1; @@ -375,7 +375,7 @@ class ObfuscatedFileUtilTest : public testing::Test { expected_usage_(expected_usage) {} ~UsageVerifyHelper() { - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); Check(); } @@ -2269,7 +2269,7 @@ TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) { // Callback to Drop DB is called while ObfuscatedFileUtilTest is still alive. file_util.db_flush_delay_seconds_ = 0; file_util.MarkUsed(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); ASSERT_TRUE(file_util.origin_database_ == NULL); } @@ -2287,7 +2287,7 @@ TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) { } // At this point the callback is still in the message queue but OFU is gone. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) { @@ -2367,9 +2367,37 @@ TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) { // Check we see the same contents in the new origin directory. std::string origin_db_data; EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy"))); - EXPECT_TRUE(file_util::ReadFileToString( + EXPECT_TRUE(base::ReadFileToString( origin_directory.AppendASCII("dummy"), &origin_db_data)); EXPECT_EQ(kFakeDirectoryData, origin_db_data); } +TEST_F(ObfuscatedFileUtilTest, OpenPathInNonDirectory) { + FileSystemURL file(CreateURLFromUTF8("file")); + FileSystemURL path_in_file(CreateURLFromUTF8("file/file")); + bool created; + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created)); + ASSERT_TRUE(created); + + created = false; + base::PlatformFile file_handle = base::kInvalidPlatformFileValue; + int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE; + ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, + ofu()->CreateOrOpen(UnlimitedContext().get(), + path_in_file, + file_flags, + &file_handle, + &created)); + ASSERT_FALSE(created); + ASSERT_EQ(base::kInvalidPlatformFileValue, file_handle); + + ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, + ofu()->CreateDirectory(UnlimitedContext().get(), + path_in_file, + false /* exclusive */, + false /* recursive */)); +} + } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc b/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc index c91c74cf148..81f26ff1c71 100644 --- a/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc +++ b/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc @@ -18,79 +18,88 @@ const int kMaxInflightOperations = 5; RecursiveOperationDelegate::RecursiveOperationDelegate( FileSystemContext* file_system_context) : file_system_context_(file_system_context), - inflight_operations_(0) { + inflight_operations_(0), + canceled_(false) { } RecursiveOperationDelegate::~RecursiveOperationDelegate() { } +void RecursiveOperationDelegate::Cancel() { + canceled_ = true; +} + void RecursiveOperationDelegate::StartRecursiveOperation( const FileSystemURL& root, const StatusCallback& callback) { + DCHECK(pending_directory_stack_.empty()); + DCHECK(pending_files_.empty()); + DCHECK_EQ(0, inflight_operations_); + callback_ = callback; - pending_directories_.push(root); - ProcessNextDirectory(); + ++inflight_operations_; + ProcessFile( + root, + base::Bind(&RecursiveOperationDelegate::DidTryProcessFile, + AsWeakPtr(), root)); } FileSystemOperationRunner* RecursiveOperationDelegate::operation_runner() { return file_system_context_->operation_runner(); } -void RecursiveOperationDelegate::ProcessNextDirectory() { +void RecursiveOperationDelegate::DidTryProcessFile( + const FileSystemURL& root, + base::PlatformFileError error) { + DCHECK(pending_directory_stack_.empty()); DCHECK(pending_files_.empty()); - if (inflight_operations_ > 0) - return; - if (pending_directories_.empty()) { - callback_.Run(base::PLATFORM_FILE_OK); - return; - } - FileSystemURL url = pending_directories_.front(); - pending_directories_.pop(); - inflight_operations_++; - ProcessDirectory( - url, base::Bind(&RecursiveOperationDelegate::DidProcessDirectory, - AsWeakPtr(), url)); -} + DCHECK_EQ(1, inflight_operations_); -void RecursiveOperationDelegate::ProcessPendingFiles() { - if (pending_files_.empty()) { - ProcessNextDirectory(); + --inflight_operations_; + if (canceled_ || error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { + Done(error); return; } - while (!pending_files_.empty() && - inflight_operations_ < kMaxInflightOperations) { - FileSystemURL url = pending_files_.front(); - pending_files_.pop(); - inflight_operations_++; - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, - base::Bind(&RecursiveOperationDelegate::ProcessFile, - AsWeakPtr(), url, - base::Bind(&RecursiveOperationDelegate::DidProcessFile, - AsWeakPtr()))); - } + + pending_directory_stack_.push(std::queue<FileSystemURL>()); + pending_directory_stack_.top().push(root); + ProcessNextDirectory(); } -void RecursiveOperationDelegate::DidProcessFile(base::PlatformFileError error) { - inflight_operations_--; - DCHECK_GE(inflight_operations_, 0); - if (error != base::PLATFORM_FILE_OK) { - callback_.Run(error); - return; - } - ProcessPendingFiles(); +void RecursiveOperationDelegate::ProcessNextDirectory() { + DCHECK(pending_files_.empty()); + DCHECK(!pending_directory_stack_.empty()); + DCHECK(!pending_directory_stack_.top().empty()); + DCHECK_EQ(0, inflight_operations_); + + const FileSystemURL& url = pending_directory_stack_.top().front(); + + ++inflight_operations_; + ProcessDirectory( + url, + base::Bind( + &RecursiveOperationDelegate::DidProcessDirectory, AsWeakPtr())); } void RecursiveOperationDelegate::DidProcessDirectory( - const FileSystemURL& url, base::PlatformFileError error) { - if (error != base::PLATFORM_FILE_OK) { - callback_.Run(error); + DCHECK(pending_files_.empty()); + DCHECK(!pending_directory_stack_.empty()); + DCHECK(!pending_directory_stack_.top().empty()); + DCHECK_EQ(1, inflight_operations_); + + --inflight_operations_; + if (canceled_ || error != base::PLATFORM_FILE_OK) { + Done(error); return; } + + const FileSystemURL& parent = pending_directory_stack_.top().front(); + pending_directory_stack_.push(std::queue<FileSystemURL>()); operation_runner()->ReadDirectory( - url, base::Bind(&RecursiveOperationDelegate::DidReadDirectory, - AsWeakPtr(), url)); + parent, + base::Bind(&RecursiveOperationDelegate::DidReadDirectory, + AsWeakPtr(), parent)); } void RecursiveOperationDelegate::DidReadDirectory( @@ -98,44 +107,130 @@ void RecursiveOperationDelegate::DidReadDirectory( base::PlatformFileError error, const FileEntryList& entries, bool has_more) { - if (error != base::PLATFORM_FILE_OK) { - if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { - // The given path may have been a file, so try RemoveFile now. - ProcessFile(parent, - base::Bind(&RecursiveOperationDelegate::DidTryProcessFile, - AsWeakPtr(), error)); - return; - } - callback_.Run(error); + DCHECK(pending_files_.empty()); + DCHECK(!pending_directory_stack_.empty()); + DCHECK_EQ(0, inflight_operations_); + + if (canceled_ || error != base::PLATFORM_FILE_OK) { + Done(error); return; } + for (size_t i = 0; i < entries.size(); i++) { FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( parent.origin(), parent.mount_type(), parent.virtual_path().Append(entries[i].name)); if (entries[i].is_directory) - pending_directories_.push(url); + pending_directory_stack_.top().push(url); else pending_files_.push(url); } + + // Wait for next entries. if (has_more) return; - inflight_operations_--; - DCHECK_GE(inflight_operations_, 0); ProcessPendingFiles(); } -void RecursiveOperationDelegate::DidTryProcessFile( - base::PlatformFileError previous_error, +void RecursiveOperationDelegate::ProcessPendingFiles() { + DCHECK(!pending_directory_stack_.empty()); + + if ((pending_files_.empty() || canceled_) && inflight_operations_ == 0) { + ProcessSubDirectory(); + return; + } + + // Do not post any new tasks. + if (canceled_) + return; + + // Run ProcessFile in parallel (upto kMaxInflightOperations). + scoped_refptr<base::MessageLoopProxy> current_message_loop = + base::MessageLoopProxy::current(); + while (!pending_files_.empty() && + inflight_operations_ < kMaxInflightOperations) { + ++inflight_operations_; + current_message_loop->PostTask( + FROM_HERE, + base::Bind(&RecursiveOperationDelegate::ProcessFile, + AsWeakPtr(), pending_files_.front(), + base::Bind(&RecursiveOperationDelegate::DidProcessFile, + AsWeakPtr()))); + pending_files_.pop(); + } +} + +void RecursiveOperationDelegate::DidProcessFile( + base::PlatformFileError error) { + --inflight_operations_; + if (error != base::PLATFORM_FILE_OK) { + // If an error occurs, invoke Done immediately (even if there remain + // running operations). It is because in the callback, this instance is + // deleted. + Done(error); + return; + } + + ProcessPendingFiles(); +} + +void RecursiveOperationDelegate::ProcessSubDirectory() { + DCHECK(pending_files_.empty()); + DCHECK(!pending_directory_stack_.empty()); + DCHECK_EQ(0, inflight_operations_); + + if (canceled_) { + Done(base::PLATFORM_FILE_ERROR_ABORT); + return; + } + + if (!pending_directory_stack_.top().empty()) { + // There remain some sub directories. Process them first. + ProcessNextDirectory(); + return; + } + + // All subdirectories are processed. + pending_directory_stack_.pop(); + if (pending_directory_stack_.empty()) { + // All files/directories are processed. + Done(base::PLATFORM_FILE_OK); + return; + } + + DCHECK(!pending_directory_stack_.top().empty()); + ++inflight_operations_; + PostProcessDirectory( + pending_directory_stack_.top().front(), + base::Bind(&RecursiveOperationDelegate::DidPostProcessDirectory, + AsWeakPtr())); +} + +void RecursiveOperationDelegate::DidPostProcessDirectory( base::PlatformFileError error) { - if (error == base::PLATFORM_FILE_ERROR_NOT_A_FILE) { - // It wasn't a file either; returns with the previous error. - callback_.Run(previous_error); + DCHECK(pending_files_.empty()); + DCHECK(!pending_directory_stack_.empty()); + DCHECK(!pending_directory_stack_.top().empty()); + DCHECK_EQ(1, inflight_operations_); + + --inflight_operations_; + pending_directory_stack_.top().pop(); + if (canceled_ || error != base::PLATFORM_FILE_OK) { + Done(error); return; } - DidProcessFile(error); + + ProcessSubDirectory(); +} + +void RecursiveOperationDelegate::Done(base::PlatformFileError error) { + if (canceled_ && error == base::PLATFORM_FILE_OK) { + callback_.Run(base::PLATFORM_FILE_ERROR_ABORT); + } else { + callback_.Run(error); + } } } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/recursive_operation_delegate.h b/chromium/webkit/browser/fileapi/recursive_operation_delegate.h index 551d875d125..a5266777341 100644 --- a/chromium/webkit/browser/fileapi/recursive_operation_delegate.h +++ b/chromium/webkit/browser/fileapi/recursive_operation_delegate.h @@ -6,6 +6,7 @@ #define WEBKIT_BROWSER_FILEAPI_RECURSIVE_OPERATION_DELEGATE_H_ #include <queue> +#include <stack> #include "base/basictypes.h" #include "base/callback.h" @@ -19,23 +20,16 @@ class FileSystemContext; class FileSystemOperationRunner; // A base class for recursive operation delegates. -// This also provides some convenient default implementations for subclasses -// like StartRecursiveOperation() and NewNestedOperation(). // // In short, each subclass should override ProcessFile and ProcessDirectory // to process a directory or a file. To start the recursive operation it // should also call StartRecursiveOperation. -// -// Each subclass can call NewNestedOperation to create a new file system -// operation to perform a sub-operations, e.g. can call RemoveFile for -// recursive Remove. -class RecursiveOperationDelegate +class WEBKIT_STORAGE_BROWSER_EXPORT RecursiveOperationDelegate : public base::SupportsWeakPtr<RecursiveOperationDelegate> { public: typedef FileSystemOperation::StatusCallback StatusCallback; typedef FileSystemOperation::FileEntryList FileEntryList; - RecursiveOperationDelegate(FileSystemContext* file_system_context); virtual ~RecursiveOperationDelegate(); // This is called when the consumer of this instance starts a non-recursive @@ -56,10 +50,58 @@ class RecursiveOperationDelegate virtual void ProcessDirectory(const FileSystemURL& url, const StatusCallback& callback) = 0; + + // This is called each time after files and subdirectories for a + // directory is processed while recursively performing an operation. + virtual void PostProcessDirectory(const FileSystemURL& url, + const StatusCallback& callback) = 0; + + // Cancels the currently running operation. + void Cancel(); + protected: + explicit RecursiveOperationDelegate(FileSystemContext* file_system_context); + // Starts to process files/directories recursively from the given |root|. - // This will call ProcessFile and ProcessDirectory on each directory or file. - // If the given |root| is a file this simply calls ProcessFile and exits. + // This will call ProcessFile and ProcessDirectory on each file or directory. + // + // First, this tries to call ProcessFile with |root| regardless whether it is + // actually a file or a directory. If it is a directory, ProcessFile should + // return PLATFORM_FILE_NOT_A_FILE. + // + // For each directory, the recursive operation works as follows: + // ProcessDirectory is called first for the directory. + // Then the directory contents are read (to obtain its sub directories and + // files in it). + // ProcessFile is called for found files. This may run in parallel. + // The same step is recursively applied to each subdirectory. + // After all files and subdirectories in a directory are processed, + // PostProcessDirectory is called for the directory. + // Here is an example; + // a_dir/ -+- b1_dir/ -+- c1_dir/ -+- d1_file + // | | | + // | +- c2_file +- d2_file + // | + // +- b2_dir/ --- e_dir/ + // | + // +- b3_file + // | + // +- b4_file + // Then traverse order is: + // ProcessFile(a_dir) (This should return PLATFORM_FILE_NOT_A_FILE). + // ProcessDirectory(a_dir). + // ProcessFile(b3_file), ProcessFile(b4_file). (in parallel). + // ProcessDirectory(b1_dir). + // ProcessFile(c2_file) + // ProcessDirectory(c1_dir). + // ProcessFile(d1_file), ProcessFile(d2_file). (in parallel). + // PostProcessDirectory(c1_dir) + // PostProcessDirectory(b1_dir). + // ProcessDirectory(b2_dir) + // ProcessDirectory(e_dir) + // PostProcessDirectory(e_dir) + // PostProcessDirectory(b2_dir) + // PostProcessDirectory(a_dir) // // |callback| is fired with base::PLATFORM_FILE_OK when every file/directory // under |root| is processed, or fired earlier when any suboperation fails. @@ -74,24 +116,29 @@ class RecursiveOperationDelegate FileSystemOperationRunner* operation_runner(); private: + void DidTryProcessFile(const FileSystemURL& root, + base::PlatformFileError error); void ProcessNextDirectory(); + void DidProcessDirectory(base::PlatformFileError error); + void DidReadDirectory(const FileSystemURL& parent, + base::PlatformFileError error, + const FileEntryList& entries, + bool has_more); void ProcessPendingFiles(); void DidProcessFile(base::PlatformFileError error); - void DidProcessDirectory(const FileSystemURL& url, - base::PlatformFileError error); - void DidReadDirectory( - const FileSystemURL& parent, - base::PlatformFileError error, - const FileEntryList& entries, - bool has_more); - void DidTryProcessFile(base::PlatformFileError previous_error, - base::PlatformFileError error); + void ProcessSubDirectory(); + void DidPostProcessDirectory(base::PlatformFileError error); + + // Called when all recursive operation is done (or an error occurs). + void Done(base::PlatformFileError error); FileSystemContext* file_system_context_; StatusCallback callback_; - std::queue<FileSystemURL> pending_directories_; + std::stack<FileSystemURL> pending_directories_; + std::stack<std::queue<FileSystemURL> > pending_directory_stack_; std::queue<FileSystemURL> pending_files_; int inflight_operations_; + bool canceled_; DISALLOW_COPY_AND_ASSIGN(RecursiveOperationDelegate); }; diff --git a/chromium/webkit/browser/fileapi/recursive_operation_delegate_unittest.cc b/chromium/webkit/browser/fileapi/recursive_operation_delegate_unittest.cc new file mode 100644 index 00000000000..b3842279420 --- /dev/null +++ b/chromium/webkit/browser/fileapi/recursive_operation_delegate_unittest.cc @@ -0,0 +1,280 @@ +// Copyright 2013 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 "webkit/browser/fileapi/recursive_operation_delegate.h" + +#include <vector> + +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/scoped_temp_dir.h" +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/fileapi/file_system_file_util.h" +#include "webkit/browser/fileapi/file_system_operation.h" +#include "webkit/browser/fileapi/file_system_operation_runner.h" +#include "webkit/browser/fileapi/sandbox_file_system_test_helper.h" + +namespace fileapi { +namespace { + +class LoggingRecursiveOperation : public RecursiveOperationDelegate { + public: + struct LogEntry { + enum Type { + PROCESS_FILE, + PROCESS_DIRECTORY, + POST_PROCESS_DIRECTORY + }; + Type type; + FileSystemURL url; + }; + + LoggingRecursiveOperation(FileSystemContext* file_system_context, + const FileSystemURL& root, + const StatusCallback& callback) + : RecursiveOperationDelegate(file_system_context), + root_(root), + callback_(callback), + weak_factory_(this) { + } + virtual ~LoggingRecursiveOperation() {} + + const std::vector<LogEntry>& log_entries() const { return log_entries_; } + + // RecursiveOperationDelegate overrides. + virtual void Run() OVERRIDE { + NOTREACHED(); + } + + virtual void RunRecursively() OVERRIDE { + StartRecursiveOperation(root_, callback_); + } + + virtual void ProcessFile(const FileSystemURL& url, + const StatusCallback& callback) OVERRIDE { + RecordLogEntry(LogEntry::PROCESS_FILE, url); + operation_runner()->GetMetadata( + url, + base::Bind(&LoggingRecursiveOperation::DidGetMetadata, + weak_factory_.GetWeakPtr(), callback)); + } + + virtual void ProcessDirectory(const FileSystemURL& url, + const StatusCallback& callback) OVERRIDE { + RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url); + callback.Run(base::PLATFORM_FILE_OK); + } + + virtual void PostProcessDirectory(const FileSystemURL& url, + const StatusCallback& callback) OVERRIDE { + RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url); + callback.Run(base::PLATFORM_FILE_OK); + } + + private: + void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) { + LogEntry entry; + entry.type = type; + entry.url = url; + log_entries_.push_back(entry); + } + + void DidGetMetadata(const StatusCallback& callback, + base::PlatformFileError result, + const base::PlatformFileInfo& file_info) { + if (result != base::PLATFORM_FILE_OK) { + callback.Run(result); + return; + } + + callback.Run(file_info.is_directory ? + base::PLATFORM_FILE_ERROR_NOT_A_FILE : + base::PLATFORM_FILE_OK); + } + + FileSystemURL root_; + StatusCallback callback_; + std::vector<LogEntry> log_entries_; + + base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation); +}; + +void ReportStatus(base::PlatformFileError* out_error, + base::PlatformFileError error) { + DCHECK(out_error); + *out_error = error; +} + +// To test the Cancel() during operation, calls Cancel() of |operation| +// after |counter| times message posting. +void CallCancelLater(RecursiveOperationDelegate* operation, int counter) { + if (counter > 0) { + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, + base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1)); + return; + } + + operation->Cancel(); +} + +} // namespace + +class RecursiveOperationDelegateTest : public testing::Test { + protected: + virtual void SetUp() OVERRIDE { + EXPECT_TRUE(base_.CreateUniqueTempDir()); + sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem")); + } + + virtual void TearDown() OVERRIDE { + sandbox_file_system_.TearDown(); + } + + scoped_ptr<FileSystemOperationContext> NewContext() { + FileSystemOperationContext* context = + sandbox_file_system_.NewOperationContext(); + // Grant enough quota for all test cases. + context->set_allowed_bytes_growth(1000000); + return make_scoped_ptr(context); + } + + FileSystemFileUtil* file_util() { + return sandbox_file_system_.file_util(); + } + + FileSystemURL URLForPath(const std::string& path) const { + return sandbox_file_system_.CreateURLFromUTF8(path); + } + + FileSystemURL CreateFile(const std::string& path) { + FileSystemURL url = URLForPath(path); + bool created = false; + EXPECT_EQ(base::PLATFORM_FILE_OK, + file_util()->EnsureFileExists(NewContext().get(), + url, &created)); + EXPECT_TRUE(created); + return url; + } + + FileSystemURL CreateDirectory(const std::string& path) { + FileSystemURL url = URLForPath(path); + EXPECT_EQ(base::PLATFORM_FILE_OK, + file_util()->CreateDirectory(NewContext().get(), url, + false /* exclusive */, true)); + return url; + } + + private: + base::MessageLoop message_loop_; + + // Common temp base for nondestructive uses. + base::ScopedTempDir base_; + SandboxFileSystemTestHelper sandbox_file_system_; +}; + +TEST_F(RecursiveOperationDelegateTest, RootIsFile) { + FileSystemURL src_file(CreateFile("src")); + + base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; + scoped_ptr<FileSystemOperationContext> context = NewContext(); + scoped_ptr<LoggingRecursiveOperation> operation( + new LoggingRecursiveOperation( + context->file_system_context(), src_file, + base::Bind(&ReportStatus, &error))); + operation->RunRecursively(); + base::RunLoop().RunUntilIdle(); + ASSERT_EQ(base::PLATFORM_FILE_OK, error); + + const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries = + operation->log_entries(); + ASSERT_EQ(1U, log_entries.size()); + const LoggingRecursiveOperation::LogEntry& entry = log_entries[0]; + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type); + EXPECT_EQ(src_file, entry.url); +} + +TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) { + FileSystemURL src_root(CreateDirectory("src")); + FileSystemURL src_dir1(CreateDirectory("src/dir1")); + FileSystemURL src_file1(CreateFile("src/file1")); + FileSystemURL src_file2(CreateFile("src/dir1/file2")); + FileSystemURL src_file3(CreateFile("src/dir1/file3")); + + base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; + scoped_ptr<FileSystemOperationContext> context = NewContext(); + scoped_ptr<LoggingRecursiveOperation> operation( + new LoggingRecursiveOperation( + context->file_system_context(), src_root, + base::Bind(&ReportStatus, &error))); + operation->RunRecursively(); + base::RunLoop().RunUntilIdle(); + ASSERT_EQ(base::PLATFORM_FILE_OK, error); + + const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries = + operation->log_entries(); + ASSERT_EQ(8U, log_entries.size()); + + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, + log_entries[0].type); + EXPECT_EQ(src_root, log_entries[0].url); + + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY, + log_entries[1].type); + EXPECT_EQ(src_root, log_entries[1].url); + + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, + log_entries[2].type); + EXPECT_EQ(src_file1, log_entries[2].url); + + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY, + log_entries[3].type); + EXPECT_EQ(src_dir1, log_entries[3].url); + + // The order of src/dir1/file2 and src/dir1/file3 depends on the file system + // implementation (can be swapped). + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, + log_entries[4].type); + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, + log_entries[5].type); + EXPECT_TRUE((src_file2 == log_entries[4].url && + src_file3 == log_entries[5].url) || + (src_file3 == log_entries[4].url && + src_file2 == log_entries[5].url)); + + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY, + log_entries[6].type); + EXPECT_EQ(src_dir1, log_entries[6].url); + + EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY, + log_entries[7].type); + EXPECT_EQ(src_root, log_entries[7].url); +} + +TEST_F(RecursiveOperationDelegateTest, Cancel) { + FileSystemURL src_root(CreateDirectory("src")); + FileSystemURL src_dir1(CreateDirectory("src/dir1")); + FileSystemURL src_file1(CreateFile("src/file1")); + FileSystemURL src_file2(CreateFile("src/dir1/file2")); + + base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; + scoped_ptr<FileSystemOperationContext> context = NewContext(); + scoped_ptr<LoggingRecursiveOperation> operation( + new LoggingRecursiveOperation( + context->file_system_context(), src_root, + base::Bind(&ReportStatus, &error))); + operation->RunRecursively(); + + // Invoke Cancel(), after 5 times message posting. + CallCancelLater(operation.get(), 5); + base::RunLoop().RunUntilIdle(); + ASSERT_EQ(base::PLATFORM_FILE_ERROR_ABORT, error); +} + +} // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/remove_operation_delegate.cc b/chromium/webkit/browser/fileapi/remove_operation_delegate.cc index fcd9ba9cee2..4819f0164e5 100644 --- a/chromium/webkit/browser/fileapi/remove_operation_delegate.cc +++ b/chromium/webkit/browser/fileapi/remove_operation_delegate.cc @@ -28,38 +28,47 @@ void RemoveOperationDelegate::Run() { } void RemoveOperationDelegate::RunRecursively() { - StartRecursiveOperation( - url_, - base::Bind(&RemoveOperationDelegate::RemoveNextDirectory, - weak_factory_.GetWeakPtr())); + StartRecursiveOperation(url_, callback_); } void RemoveOperationDelegate::ProcessFile(const FileSystemURL& url, const StatusCallback& callback) { - if (to_remove_directories_.size() == 1u && - to_remove_directories_.top() == url) { - // We seem to have been re-directed from ProcessDirectory. - to_remove_directories_.pop(); - } - operation_runner()->RemoveFile(url, base::Bind( - &RemoveOperationDelegate::DidRemoveFile, - weak_factory_.GetWeakPtr(), callback)); + operation_runner()->RemoveFile( + url, + base::Bind(&RemoveOperationDelegate::DidRemoveFile, + weak_factory_.GetWeakPtr(), callback)); } void RemoveOperationDelegate::ProcessDirectory(const FileSystemURL& url, const StatusCallback& callback) { - to_remove_directories_.push(url); callback.Run(base::PLATFORM_FILE_OK); } +void RemoveOperationDelegate::PostProcessDirectory( + const FileSystemURL& url, const StatusCallback& callback) { + operation_runner()->RemoveDirectory(url, callback); +} + void RemoveOperationDelegate::DidTryRemoveFile( base::PlatformFileError error) { - if (error == base::PLATFORM_FILE_OK || - error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { + if (error != base::PLATFORM_FILE_ERROR_NOT_A_FILE && + error != base::PLATFORM_FILE_ERROR_SECURITY) { callback_.Run(error); return; } - operation_runner()->RemoveDirectory(url_, callback_); + operation_runner()->RemoveDirectory( + url_, + base::Bind(&RemoveOperationDelegate::DidTryRemoveDirectory, + weak_factory_.GetWeakPtr(), error)); +} + +void RemoveOperationDelegate::DidTryRemoveDirectory( + base::PlatformFileError remove_file_error, + base::PlatformFileError remove_directory_error) { + callback_.Run( + remove_directory_error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY ? + remove_file_error : + remove_directory_error); } void RemoveOperationDelegate::DidRemoveFile(const StatusCallback& callback, @@ -71,18 +80,4 @@ void RemoveOperationDelegate::DidRemoveFile(const StatusCallback& callback, callback.Run(error); } -void RemoveOperationDelegate::RemoveNextDirectory( - base::PlatformFileError error) { - if (error != base::PLATFORM_FILE_OK || - to_remove_directories_.empty()) { - callback_.Run(error); - return; - } - FileSystemURL url = to_remove_directories_.top(); - to_remove_directories_.pop(); - operation_runner()->RemoveDirectory(url, base::Bind( - &RemoveOperationDelegate::RemoveNextDirectory, - weak_factory_.GetWeakPtr())); -} - } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/remove_operation_delegate.h b/chromium/webkit/browser/fileapi/remove_operation_delegate.h index ef9e1a09409..22d25cb9833 100644 --- a/chromium/webkit/browser/fileapi/remove_operation_delegate.h +++ b/chromium/webkit/browser/fileapi/remove_operation_delegate.h @@ -11,8 +11,7 @@ namespace fileapi { -class RemoveOperationDelegate - : public RecursiveOperationDelegate { +class RemoveOperationDelegate : public RecursiveOperationDelegate { public: RemoveOperationDelegate(FileSystemContext* file_system_context, const FileSystemURL& url, @@ -26,20 +25,19 @@ class RemoveOperationDelegate const StatusCallback& callback) OVERRIDE; virtual void ProcessDirectory(const FileSystemURL& url, const StatusCallback& callback) OVERRIDE; + virtual void PostProcessDirectory(const FileSystemURL& url, + const StatusCallback& callback) OVERRIDE; private: void DidTryRemoveFile(base::PlatformFileError error); + void DidTryRemoveDirectory(base::PlatformFileError remove_file_error, + base::PlatformFileError remove_directory_error); void DidRemoveFile(const StatusCallback& callback, base::PlatformFileError error); - void RemoveNextDirectory(base::PlatformFileError error); FileSystemURL url_; StatusCallback callback_; - - std::stack<FileSystemURL> to_remove_directories_; - base::WeakPtrFactory<RemoveOperationDelegate> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(RemoveOperationDelegate); }; diff --git a/chromium/webkit/browser/fileapi/sandbox_directory_database.cc b/chromium/webkit/browser/fileapi/sandbox_directory_database.cc index 8a90bd33479..06ab1e50acf 100644 --- a/chromium/webkit/browser/fileapi/sandbox_directory_database.cc +++ b/chromium/webkit/browser/fileapi/sandbox_directory_database.cc @@ -518,10 +518,10 @@ bool SandboxDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { return false; } -bool SandboxDirectoryDatabase::AddFileInfo( +base::PlatformFileError SandboxDirectoryDatabase::AddFileInfo( const FileInfo& info, FileId* file_id) { if (!Init(REPAIR_ON_CORRUPTION)) - return false; + return base::PLATFORM_FILE_ERROR_FAILED; DCHECK(file_id); std::string child_key = GetChildLookupKey(info.parent_id, info.name); std::string child_id_string; @@ -529,36 +529,36 @@ bool SandboxDirectoryDatabase::AddFileInfo( db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); if (status.ok()) { LOG(ERROR) << "File exists already!"; - return false; + return base::PLATFORM_FILE_ERROR_EXISTS; } if (!status.IsNotFound()) { HandleError(FROM_HERE, status); - return false; + return base::PLATFORM_FILE_ERROR_NOT_FOUND; } if (!VerifyIsDirectory(info.parent_id)) - return false; + return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; // This would be a fine place to limit the number of files in a directory, if // we decide to add that restriction. FileId temp_id; if (!GetLastFileId(&temp_id)) - return false; + return base::PLATFORM_FILE_ERROR_FAILED; ++temp_id; leveldb::WriteBatch batch; if (!AddFileInfoHelper(info, temp_id, &batch)) - return false; + return base::PLATFORM_FILE_ERROR_FAILED; batch.Put(LastFileIdKey(), base::Int64ToString(temp_id)); status = db_->Write(leveldb::WriteOptions(), &batch); if (!status.ok()) { HandleError(FROM_HERE, status); - return false; + return base::PLATFORM_FILE_ERROR_FAILED; } *file_id = temp_id; - return true; + return base::PLATFORM_FILE_OK; } bool SandboxDirectoryDatabase::RemoveFileInfo(FileId file_id) { @@ -715,7 +715,7 @@ bool SandboxDirectoryDatabase::Init(RecoveryOption recovery_option) { FilePathToString(filesystem_data_directory_.Append( kDirectoryDatabaseName)); leveldb::Options options; - options.max_open_files = 64; // Use minimum. + options.max_open_files = 0; // Use minimum. options.create_if_missing = true; leveldb::DB* db; leveldb::Status status = leveldb::DB::Open(options, path, &db); @@ -763,7 +763,7 @@ bool SandboxDirectoryDatabase::Init(RecoveryOption recovery_option) { bool SandboxDirectoryDatabase::RepairDatabase(const std::string& db_path) { DCHECK(!db_.get()); leveldb::Options options; - options.max_open_files = 64; // Use minimum. + options.max_open_files = 0; // Use minimum. if (!leveldb::RepairDB(db_path, options).ok()) return false; if (!Init(FAIL_ON_CORRUPTION)) diff --git a/chromium/webkit/browser/fileapi/sandbox_directory_database.h b/chromium/webkit/browser/fileapi/sandbox_directory_database.h index 4cbd43b6cbd..0ad948d630f 100644 --- a/chromium/webkit/browser/fileapi/sandbox_directory_database.h +++ b/chromium/webkit/browser/fileapi/sandbox_directory_database.h @@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" +#include "base/platform_file.h" #include "base/time/time.h" #include "webkit/browser/webkit_storage_browser_export.h" @@ -68,7 +69,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxDirectoryDatabase { // exist. bool ListChildren(FileId parent_id, std::vector<FileId>* children); bool GetFileInfo(FileId file_id, FileInfo* info); - bool AddFileInfo(const FileInfo& info, FileId* file_id); + base::PlatformFileError AddFileInfo(const FileInfo& info, FileId* file_id); bool RemoveFileInfo(FileId file_id); // This does a full update of the FileInfo, and is what you'd use for moves // and renames. If you just want to update the modification_time, use diff --git a/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc index 593ead96efb..9281446e2fd 100644 --- a/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc +++ b/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc @@ -51,7 +51,8 @@ class SandboxDirectoryDatabaseTest : public testing::Test { db_.reset(); } - bool AddFileInfo(FileId parent_id, const base::FilePath::StringType& name) { + base::PlatformFileError AddFileInfo( + FileId parent_id, const base::FilePath::StringType& name) { FileId file_id; FileInfo info; info.parent_id = parent_id; @@ -65,7 +66,7 @@ class SandboxDirectoryDatabaseTest : public testing::Test { FileInfo info; info.parent_id = parent_id; info.name = name; - ASSERT_TRUE(db_->AddFileInfo(info, file_id_out)); + ASSERT_EQ(base::PLATFORM_FILE_OK, db_->AddFileInfo(info, file_id_out)); } void CreateFile(FileId parent_id, @@ -78,7 +79,7 @@ class SandboxDirectoryDatabaseTest : public testing::Test { info.parent_id = parent_id; info.name = name; info.data_path = base::FilePath(data_path).NormalizePathSeparators(); - ASSERT_TRUE(db_->AddFileInfo(info, &file_id)); + ASSERT_EQ(base::PLATFORM_FILE_OK, db_->AddFileInfo(info, &file_id)); base::FilePath local_path = path().Append(data_path); if (!base::DirectoryExists(local_path.DirName())) @@ -160,7 +161,8 @@ TEST_F(SandboxDirectoryDatabaseTest, TestGetRootFileInfoBeforeCreate) { TEST_F(SandboxDirectoryDatabaseTest, TestMissingParentAddFileInfo) { FileId parent_id = 7; - EXPECT_FALSE(AddFileInfo(parent_id, FILE_PATH_LITERAL("foo"))); + EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, + AddFileInfo(parent_id, FILE_PATH_LITERAL("foo"))); } TEST_F(SandboxDirectoryDatabaseTest, TestAddNameClash) { @@ -168,21 +170,21 @@ TEST_F(SandboxDirectoryDatabaseTest, TestAddNameClash) { FileId file_id; info.parent_id = 0; info.name = FILE_PATH_LITERAL("dir 0"); - EXPECT_TRUE(db()->AddFileInfo(info, &file_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id)); // Check for name clash in the root directory. base::FilePath::StringType name = info.name; - EXPECT_FALSE(AddFileInfo(0, name)); + EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, AddFileInfo(0, name)); name = FILE_PATH_LITERAL("dir 1"); - EXPECT_TRUE(AddFileInfo(0, name)); + EXPECT_EQ(base::PLATFORM_FILE_OK, AddFileInfo(0, name)); name = FILE_PATH_LITERAL("subdir 0"); - EXPECT_TRUE(AddFileInfo(file_id, name)); + EXPECT_EQ(base::PLATFORM_FILE_OK, AddFileInfo(file_id, name)); // Check for name clash in a subdirectory. - EXPECT_FALSE(AddFileInfo(file_id, name)); + EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, AddFileInfo(file_id, name)); name = FILE_PATH_LITERAL("subdir 1"); - EXPECT_TRUE(AddFileInfo(file_id, name)); + EXPECT_EQ(base::PLATFORM_FILE_OK, AddFileInfo(file_id, name)); } TEST_F(SandboxDirectoryDatabaseTest, TestRenameNoMoveNameClash) { @@ -193,8 +195,8 @@ TEST_F(SandboxDirectoryDatabaseTest, TestRenameNoMoveNameClash) { base::FilePath::StringType name2 = FILE_PATH_LITERAL("bas"); info.parent_id = 0; info.name = name0; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); - EXPECT_TRUE(AddFileInfo(0, name1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, AddFileInfo(0, name1)); info.name = name1; EXPECT_FALSE(db()->UpdateFileInfo(file_id0, info)); info.name = name2; @@ -209,9 +211,9 @@ TEST_F(SandboxDirectoryDatabaseTest, TestMoveSameNameNameClash) { base::FilePath::StringType name1 = FILE_PATH_LITERAL("bar"); info.parent_id = 0; info.name = name0; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id0)); info.parent_id = file_id0; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id1)); info.parent_id = 0; EXPECT_FALSE(db()->UpdateFileInfo(file_id1, info)); info.name = name1; @@ -227,10 +229,10 @@ TEST_F(SandboxDirectoryDatabaseTest, TestMoveRenameNameClash) { base::FilePath::StringType name2 = FILE_PATH_LITERAL("bas"); info.parent_id = 0; info.name = name0; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id0)); info.parent_id = file_id0; info.name = name1; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id1)); info.parent_id = 0; info.name = name0; EXPECT_FALSE(db()->UpdateFileInfo(file_id1, info)); @@ -248,9 +250,9 @@ TEST_F(SandboxDirectoryDatabaseTest, TestRemoveWithChildren) { FileId file_id1; info.parent_id = 0; info.name = FILE_PATH_LITERAL("foo"); - EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id0)); info.parent_id = file_id0; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id1)); EXPECT_FALSE(db()->RemoveFileInfo(file_id0)); EXPECT_TRUE(db()->RemoveFileInfo(file_id1)); EXPECT_TRUE(db()->RemoveFileInfo(file_id0)); @@ -264,10 +266,10 @@ TEST_F(SandboxDirectoryDatabaseTest, TestGetChildWithName) { base::FilePath::StringType name1 = FILE_PATH_LITERAL("bar"); info.parent_id = 0; info.name = name0; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id0)); info.parent_id = file_id0; info.name = name1; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id1)); EXPECT_NE(file_id0, file_id1); FileId check_file_id; @@ -290,14 +292,14 @@ TEST_F(SandboxDirectoryDatabaseTest, TestGetFileWithPath) { info.parent_id = 0; info.name = name0; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id0)); info.parent_id = file_id0; info.name = name1; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id1)); EXPECT_NE(file_id0, file_id1); info.parent_id = file_id1; info.name = name2; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id2)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id2)); EXPECT_NE(file_id0, file_id2); EXPECT_NE(file_id1, file_id2); @@ -326,7 +328,7 @@ TEST_F(SandboxDirectoryDatabaseTest, TestListChildren) { FileInfo info; info.parent_id = 0; info.name = FILE_PATH_LITERAL("foo"); - EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id0)); EXPECT_TRUE(db()->ListChildren(0, &children)); EXPECT_EQ(children.size(), 1UL); EXPECT_EQ(children[0], file_id0); @@ -334,7 +336,7 @@ TEST_F(SandboxDirectoryDatabaseTest, TestListChildren) { // Two children in the root. FileId file_id1; info.name = FILE_PATH_LITERAL("bar"); - EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id1)); EXPECT_TRUE(db()->ListChildren(0, &children)); EXPECT_EQ(2UL, children.size()); if (children[0] == file_id0) { @@ -353,14 +355,14 @@ TEST_F(SandboxDirectoryDatabaseTest, TestListChildren) { info.name = FILE_PATH_LITERAL("foo"); FileId file_id2; FileId file_id3; - EXPECT_TRUE(db()->AddFileInfo(info, &file_id2)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id2)); EXPECT_TRUE(db()->ListChildren(file_id0, &children)); EXPECT_EQ(1UL, children.size()); EXPECT_EQ(children[0], file_id2); // Two children in a subdirectory. info.name = FILE_PATH_LITERAL("bar"); - EXPECT_TRUE(db()->AddFileInfo(info, &file_id3)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info, &file_id3)); EXPECT_TRUE(db()->ListChildren(file_id0, &children)); EXPECT_EQ(2UL, children.size()); if (children[0] == file_id2) { @@ -378,7 +380,7 @@ TEST_F(SandboxDirectoryDatabaseTest, TestUpdateModificationTime) { info0.name = FILE_PATH_LITERAL("name"); info0.data_path = base::FilePath(FILE_PATH_LITERAL("fake path")); info0.modification_time = base::Time::Now(); - EXPECT_TRUE(db()->AddFileInfo(info0, &file_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info0, &file_id)); FileInfo info1; EXPECT_TRUE(db()->GetFileInfo(file_id, &info1)); EXPECT_EQ(info0.name, info1.name); @@ -409,7 +411,7 @@ TEST_F(SandboxDirectoryDatabaseTest, TestSimpleFileOperations) { info0.data_path = base::FilePath(FILE_PATH_LITERAL("foo")); info0.name = FILE_PATH_LITERAL("file name"); info0.modification_time = base::Time::Now(); - EXPECT_TRUE(db()->AddFileInfo(info0, &file_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info0, &file_id)); FileInfo info1; EXPECT_TRUE(db()->GetFileInfo(file_id, &info1)); EXPECT_EQ(info0.parent_id, info1.parent_id); @@ -426,7 +428,7 @@ TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileSrcDirectory) { info0.parent_id = 0; info0.name = FILE_PATH_LITERAL("directory"); info0.modification_time = base::Time::Now(); - EXPECT_TRUE(db()->AddFileInfo(info0, &directory_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info0, &directory_id)); FileId file_id; FileInfo info1; @@ -434,7 +436,7 @@ TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileSrcDirectory) { info1.data_path = base::FilePath(FILE_PATH_LITERAL("bar")); info1.name = FILE_PATH_LITERAL("file"); info1.modification_time = base::Time::UnixEpoch(); - EXPECT_TRUE(db()->AddFileInfo(info1, &file_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info1, &file_id)); EXPECT_FALSE(db()->OverwritingMoveFile(directory_id, file_id)); } @@ -446,14 +448,14 @@ TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileDestDirectory) { info0.name = FILE_PATH_LITERAL("file"); info0.data_path = base::FilePath(FILE_PATH_LITERAL("bar")); info0.modification_time = base::Time::Now(); - EXPECT_TRUE(db()->AddFileInfo(info0, &file_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info0, &file_id)); FileId directory_id; FileInfo info1; info1.parent_id = 0; info1.name = FILE_PATH_LITERAL("directory"); info1.modification_time = base::Time::UnixEpoch(); - EXPECT_TRUE(db()->AddFileInfo(info1, &directory_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info1, &directory_id)); EXPECT_FALSE(db()->OverwritingMoveFile(file_id, directory_id)); } @@ -465,13 +467,13 @@ TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileSuccess) { info0.data_path = base::FilePath(FILE_PATH_LITERAL("foo")); info0.name = FILE_PATH_LITERAL("file name 0"); info0.modification_time = base::Time::Now(); - EXPECT_TRUE(db()->AddFileInfo(info0, &file_id0)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info0, &file_id0)); FileInfo dir_info; FileId dir_id; dir_info.parent_id = 0; dir_info.name = FILE_PATH_LITERAL("directory name"); - EXPECT_TRUE(db()->AddFileInfo(dir_info, &dir_id)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(dir_info, &dir_id)); FileId file_id1; FileInfo info1; @@ -479,7 +481,7 @@ TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileSuccess) { info1.data_path = base::FilePath(FILE_PATH_LITERAL("bar")); info1.name = FILE_PATH_LITERAL("file name 1"); info1.modification_time = base::Time::UnixEpoch(); - EXPECT_TRUE(db()->AddFileInfo(info1, &file_id1)); + EXPECT_EQ(base::PLATFORM_FILE_OK, db()->AddFileInfo(info1, &file_id1)); EXPECT_TRUE(db()->OverwritingMoveFile(file_id0, file_id1)); diff --git a/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.cc b/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.cc index 2e075ce39fe..24fe1c947b1 100644 --- a/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.cc +++ b/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.cc @@ -9,11 +9,11 @@ #include "base/sequenced_task_runner.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "webkit/browser/blob/local_file_stream_reader.h" +#include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/file_observers.h" +#include "webkit/browser/fileapi/file_stream_writer.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_runner.h" -#include "webkit/browser/fileapi/local_file_stream_writer.h" #include "webkit/browser/quota/quota_manager.h" #include "webkit/common/fileapi/file_system_util.h" @@ -137,7 +137,7 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile( initial_offset_ = file_size_; } DCHECK(!local_file_writer_.get()); - local_file_writer_.reset(new LocalFileStreamWriter( + local_file_writer_.reset(FileStreamWriter::CreateForLocalFile( file_system_context_->default_file_task_runner(), platform_path, initial_offset_)); diff --git a/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.h b/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.h index 43fb0cd7743..81123376f50 100644 --- a/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.h +++ b/chromium/webkit/browser/fileapi/sandbox_file_stream_writer.h @@ -21,10 +21,10 @@ namespace fileapi { class FileSystemContext; class FileSystemQuotaUtil; -class LocalFileStreamWriter; +class FileStreamWriter; class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxFileStreamWriter - : public FileStreamWriter { + : public NON_EXPORTED_BASE(FileStreamWriter) { public: SandboxFileStreamWriter(FileSystemContext* file_system_context, const FileSystemURL& url, @@ -72,7 +72,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxFileStreamWriter scoped_refptr<FileSystemContext> file_system_context_; FileSystemURL url_; int64 initial_offset_; - scoped_ptr<LocalFileStreamWriter> local_file_writer_; + scoped_ptr<FileStreamWriter> local_file_writer_; net::CompletionCallback cancel_callback_; UpdateObserverList observers_; diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc index 20f732989d4..a5adc63e85d 100644 --- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc +++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc @@ -10,17 +10,17 @@ #include "base/metrics/histogram.h" #include "base/task_runner_util.h" #include "url/gurl.h" +#include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/async_file_util_adapter.h" #include "webkit/browser/fileapi/copy_or_move_file_validator.h" +#include "webkit/browser/fileapi/file_stream_writer.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_file_stream_reader.h" +#include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_operation_impl.h" #include "webkit/browser/fileapi/file_system_options.h" #include "webkit/browser/fileapi/file_system_usage_cache.h" #include "webkit/browser/fileapi/obfuscated_file_util.h" -#include "webkit/browser/fileapi/sandbox_context.h" -#include "webkit/browser/fileapi/sandbox_file_stream_writer.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "webkit/browser/fileapi/sandbox_quota_observer.h" #include "webkit/browser/quota/quota_manager.h" #include "webkit/common/fileapi/file_system_types.h" @@ -31,16 +31,9 @@ using quota::SpecialStoragePolicy; namespace fileapi { -namespace { - -const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; -const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; - -} // anonymous namespace - SandboxFileSystemBackend::SandboxFileSystemBackend( - SandboxContext* sandbox_context) - : sandbox_context_(sandbox_context), + SandboxFileSystemBackendDelegate* delegate) + : delegate_(delegate), enable_temporary_file_system_in_incognito_(false) { } @@ -53,12 +46,24 @@ bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { } void SandboxFileSystemBackend::Initialize(FileSystemContext* context) { + DCHECK(delegate_); + // Set quota observers. - update_observers_ = update_observers_.AddObserver( - sandbox_context_->quota_observer(), - sandbox_context_->file_task_runner()); - access_observers_ = access_observers_.AddObserver( - sandbox_context_->quota_observer(), NULL); + delegate_->AddFileUpdateObserver( + fileapi::kFileSystemTypeTemporary, + delegate_->quota_observer(), + delegate_->file_task_runner()); + delegate_->AddFileAccessObserver( + fileapi::kFileSystemTypeTemporary, + delegate_->quota_observer(), NULL); + + delegate_->AddFileUpdateObserver( + fileapi::kFileSystemTypePersistent, + delegate_->quota_observer(), + delegate_->file_task_runner()); + delegate_->AddFileAccessObserver( + fileapi::kFileSystemTypePersistent, + delegate_->quota_observer(), NULL); } void SandboxFileSystemBackend::OpenFileSystem( @@ -67,8 +72,8 @@ void SandboxFileSystemBackend::OpenFileSystem( OpenFileSystemMode mode, const OpenFileSystemCallback& callback) { DCHECK(CanHandleType(type)); - DCHECK(sandbox_context_); - if (sandbox_context_->file_system_options().is_incognito() && + DCHECK(delegate_); + if (delegate_->file_system_options().is_incognito() && !(type == kFileSystemTypeTemporary && enable_temporary_file_system_in_incognito_)) { // TODO(kinuko): return an isolated temporary directory. @@ -76,20 +81,15 @@ void SandboxFileSystemBackend::OpenFileSystem( return; } - sandbox_context_->OpenFileSystem( + delegate_->OpenFileSystem( origin_url, type, mode, callback, GetFileSystemRootURI(origin_url, type)); } -FileSystemFileUtil* SandboxFileSystemBackend::GetFileUtil( - FileSystemType type) { - return sandbox_context_->sync_file_util(); -} - AsyncFileUtil* SandboxFileSystemBackend::GetAsyncFileUtil( FileSystemType type) { - DCHECK(sandbox_context_); - return sandbox_context_->file_util(); + DCHECK(delegate_); + return delegate_->file_util(); } CopyOrMoveFileValidatorFactory* @@ -106,24 +106,21 @@ FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( FileSystemContext* context, base::PlatformFileError* error_code) const { DCHECK(CanHandleType(url.type())); - DCHECK(sandbox_context_); - if (!sandbox_context_->IsAccessValid(url)) { - *error_code = base::PLATFORM_FILE_ERROR_SECURITY; - return NULL; - } + DCHECK(error_code); - scoped_ptr<FileSystemOperationContext> operation_context( - new FileSystemOperationContext(context)); - operation_context->set_update_observers(update_observers_); - operation_context->set_change_observers(change_observers_); + DCHECK(delegate_); + scoped_ptr<FileSystemOperationContext> operation_context = + delegate_->CreateFileSystemOperationContext(url, context, error_code); + if (!operation_context) + return NULL; - SpecialStoragePolicy* policy = sandbox_context_->special_storage_policy(); + SpecialStoragePolicy* policy = delegate_->special_storage_policy(); if (policy && policy->IsStorageUnlimited(url.origin())) operation_context->set_quota_limit_type(quota::kQuotaLimitTypeUnlimited); else operation_context->set_quota_limit_type(quota::kQuotaLimitTypeLimited); - return new FileSystemOperationImpl(url, context, operation_context.Pass()); + return FileSystemOperation::Create(url, context, operation_context.Pass()); } scoped_ptr<webkit_blob::FileStreamReader> @@ -133,12 +130,9 @@ SandboxFileSystemBackend::CreateFileStreamReader( const base::Time& expected_modification_time, FileSystemContext* context) const { DCHECK(CanHandleType(url.type())); - DCHECK(sandbox_context_); - if (!sandbox_context_->IsAccessValid(url)) - return scoped_ptr<webkit_blob::FileStreamReader>(); - return scoped_ptr<webkit_blob::FileStreamReader>( - new FileSystemFileStreamReader( - context, url, offset, expected_modification_time)); + DCHECK(delegate_); + return delegate_->CreateFileStreamReader( + url, offset, expected_modification_time, context); } scoped_ptr<fileapi::FileStreamWriter> @@ -147,128 +141,18 @@ SandboxFileSystemBackend::CreateFileStreamWriter( int64 offset, FileSystemContext* context) const { DCHECK(CanHandleType(url.type())); - DCHECK(sandbox_context_); - if (!sandbox_context_->IsAccessValid(url)) - return scoped_ptr<fileapi::FileStreamWriter>(); - return scoped_ptr<fileapi::FileStreamWriter>( - new SandboxFileStreamWriter(context, url, offset, update_observers_)); + DCHECK(delegate_); + return delegate_->CreateFileStreamWriter(url, offset, context, url.type()); } FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { - return this; + return delegate_; } -SandboxContext::OriginEnumerator* +SandboxFileSystemBackendDelegate::OriginEnumerator* SandboxFileSystemBackend::CreateOriginEnumerator() { - DCHECK(sandbox_context_); - return sandbox_context_->CreateOriginEnumerator(); -} - -base::PlatformFileError -SandboxFileSystemBackend::DeleteOriginDataOnFileThread( - FileSystemContext* file_system_context, - QuotaManagerProxy* proxy, - const GURL& origin_url, - fileapi::FileSystemType type) { - DCHECK(CanHandleType(type)); - DCHECK(sandbox_context_); - return sandbox_context_->DeleteOriginDataOnFileThread( - file_system_context, proxy, origin_url, type); -} - -void SandboxFileSystemBackend::GetOriginsForTypeOnFileThread( - fileapi::FileSystemType type, std::set<GURL>* origins) { - DCHECK(CanHandleType(type)); - DCHECK(sandbox_context_); - sandbox_context_->GetOriginsForTypeOnFileThread(type, origins); - switch (type) { - case kFileSystemTypeTemporary: - UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); - break; - case kFileSystemTypePersistent: - UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); - break; - default: - break; - } -} - -void SandboxFileSystemBackend::GetOriginsForHostOnFileThread( - fileapi::FileSystemType type, const std::string& host, - std::set<GURL>* origins) { - DCHECK(CanHandleType(type)); - DCHECK(sandbox_context_); - sandbox_context_->GetOriginsForHostOnFileThread(type, host, origins); -} - -int64 SandboxFileSystemBackend::GetOriginUsageOnFileThread( - FileSystemContext* file_system_context, - const GURL& origin_url, - fileapi::FileSystemType type) { - DCHECK(CanHandleType(type)); - DCHECK(sandbox_context_); - return sandbox_context_->GetOriginUsageOnFileThread( - file_system_context, origin_url, type); -} - -void SandboxFileSystemBackend::InvalidateUsageCache( - const GURL& origin, - fileapi::FileSystemType type) { - DCHECK(CanHandleType(type)); - DCHECK(sandbox_context_); - sandbox_context_->InvalidateUsageCache(origin, type); -} - -void SandboxFileSystemBackend::StickyInvalidateUsageCache( - const GURL& origin, - fileapi::FileSystemType type) { - DCHECK(CanHandleType(type)); - DCHECK(sandbox_context_); - sandbox_context_->StickyInvalidateUsageCache(origin, type); -} - -void SandboxFileSystemBackend::AddFileUpdateObserver( - FileSystemType type, - FileUpdateObserver* observer, - base::SequencedTaskRunner* task_runner) { - DCHECK(CanHandleType(type)); - UpdateObserverList* list = &update_observers_; - *list = list->AddObserver(observer, task_runner); -} - -void SandboxFileSystemBackend::AddFileChangeObserver( - FileSystemType type, - FileChangeObserver* observer, - base::SequencedTaskRunner* task_runner) { - DCHECK(CanHandleType(type)); - ChangeObserverList* list = &change_observers_; - *list = list->AddObserver(observer, task_runner); -} - -void SandboxFileSystemBackend::AddFileAccessObserver( - FileSystemType type, - FileAccessObserver* observer, - base::SequencedTaskRunner* task_runner) { - DCHECK(CanHandleType(type)); - access_observers_ = access_observers_.AddObserver(observer, task_runner); -} - -const UpdateObserverList* SandboxFileSystemBackend::GetUpdateObservers( - FileSystemType type) const { - DCHECK(CanHandleType(type)); - return &update_observers_; -} - -const ChangeObserverList* SandboxFileSystemBackend::GetChangeObservers( - FileSystemType type) const { - DCHECK(CanHandleType(type)); - return &change_observers_; -} - -const AccessObserverList* SandboxFileSystemBackend::GetAccessObservers( - FileSystemType type) const { - DCHECK(CanHandleType(type)); - return &access_observers_; + DCHECK(delegate_); + return delegate_->CreateOriginEnumerator(); } } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend.h b/chromium/webkit/browser/fileapi/sandbox_file_system_backend.h index 3e7ff60b529..8531cf862bf 100644 --- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend.h +++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend.h @@ -14,7 +14,7 @@ #include "base/memory/scoped_ptr.h" #include "webkit/browser/fileapi/file_system_backend.h" #include "webkit/browser/fileapi/file_system_quota_util.h" -#include "webkit/browser/fileapi/sandbox_context.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "webkit/browser/fileapi/task_runner_bound_observer_list.h" #include "webkit/browser/quota/special_storage_policy.h" #include "webkit/browser/webkit_storage_browser_export.h" @@ -27,10 +27,9 @@ namespace fileapi { // This interface also lets one enumerate and remove storage for the origins // that use the filesystem. class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackend - : public FileSystemBackend, - public FileSystemQuotaUtil { + : public FileSystemBackend { public: - explicit SandboxFileSystemBackend(SandboxContext* sandbox_context); + explicit SandboxFileSystemBackend(SandboxFileSystemBackendDelegate* delegate); virtual ~SandboxFileSystemBackend(); // FileSystemBackend overrides. @@ -41,7 +40,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackend FileSystemType type, OpenFileSystemMode mode, const OpenFileSystemCallback& callback) OVERRIDE; - virtual FileSystemFileUtil* GetFileUtil(FileSystemType type) OVERRIDE; virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, @@ -63,64 +61,21 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackend // Returns an origin enumerator of this backend. // This method can only be called on the file thread. - SandboxContext::OriginEnumerator* CreateOriginEnumerator(); - - // FileSystemQuotaUtil overrides. - virtual base::PlatformFileError DeleteOriginDataOnFileThread( - FileSystemContext* context, - quota::QuotaManagerProxy* proxy, - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void GetOriginsForTypeOnFileThread( - FileSystemType type, - std::set<GURL>* origins) OVERRIDE; - virtual void GetOriginsForHostOnFileThread( - FileSystemType type, - const std::string& host, - std::set<GURL>* origins) OVERRIDE; - virtual int64 GetOriginUsageOnFileThread( - FileSystemContext* context, - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void InvalidateUsageCache( - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void StickyInvalidateUsageCache( - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void AddFileUpdateObserver( - FileSystemType type, - FileUpdateObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual void AddFileChangeObserver( - FileSystemType type, - FileChangeObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual void AddFileAccessObserver( - FileSystemType type, - FileAccessObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual const UpdateObserverList* GetUpdateObservers( - FileSystemType type) const OVERRIDE; - virtual const ChangeObserverList* GetChangeObservers( - FileSystemType type) const OVERRIDE; - virtual const AccessObserverList* GetAccessObservers( - FileSystemType type) const OVERRIDE; + SandboxFileSystemBackendDelegate::OriginEnumerator* CreateOriginEnumerator(); void set_enable_temporary_file_system_in_incognito(bool enable) { enable_temporary_file_system_in_incognito_ = enable; } + bool enable_temporary_file_system_in_incognito() const { + return enable_temporary_file_system_in_incognito_; + } + private: - SandboxContext* sandbox_context_; // Not owned. + SandboxFileSystemBackendDelegate* delegate_; // Not owned. bool enable_temporary_file_system_in_incognito_; - // Observers. - UpdateObserverList update_observers_; - ChangeObserverList change_observers_; - AccessObserverList access_observers_; - DISALLOW_COPY_AND_ASSIGN(SandboxFileSystemBackend); }; diff --git a/chromium/webkit/browser/fileapi/sandbox_context.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc index d8b7293b6a4..1cb61bb3d60 100644 --- a/chromium/webkit/browser/fileapi/sandbox_context.cc +++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webkit/browser/fileapi/sandbox_context.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "base/command_line.h" #include "base/file_util.h" @@ -10,12 +10,14 @@ #include "base/stl_util.h" #include "base/task_runner_util.h" #include "net/base/net_util.h" +#include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/async_file_util_adapter.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/file_system_usage_cache.h" #include "webkit/browser/fileapi/obfuscated_file_util.h" +#include "webkit/browser/fileapi/sandbox_file_stream_writer.h" #include "webkit/browser/fileapi/sandbox_file_system_backend.h" #include "webkit/browser/fileapi/sandbox_quota_observer.h" #include "webkit/browser/quota/quota_manager.h" @@ -25,6 +27,9 @@ namespace fileapi { namespace { +const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; +const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; + const char kOpenFileSystemLabel[] = "FileSystem.OpenFileSystem"; const char kOpenFileSystemDetailLabel[] = "FileSystem.OpenFileSystemDetail"; const char kOpenFileSystemDetailNonThrottledLabel[] = @@ -53,7 +58,7 @@ const base::FilePath::CharType kRestrictedChars[] = { }; class ObfuscatedOriginEnumerator - : public SandboxContext::OriginEnumerator { + : public SandboxFileSystemBackendDelegate::OriginEnumerator { public: explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) { enum_.reset(file_util->CreateOriginEnumerator()); @@ -64,7 +69,7 @@ class ObfuscatedOriginEnumerator return enum_->Next(); } - virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { + virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE { return enum_->HasFileSystemType(type); } @@ -94,20 +99,21 @@ void OpenFileSystemOnFileThread( } void DidOpenFileSystem( - base::WeakPtr<SandboxContext> sandbox_context, + base::WeakPtr<SandboxFileSystemBackendDelegate> delegate, const base::Callback<void(base::PlatformFileError error)>& callback, base::PlatformFileError* error) { - if (sandbox_context.get()) - sandbox_context.get()->CollectOpenFileSystemMetrics(*error); + if (delegate.get()) + delegate.get()->CollectOpenFileSystemMetrics(*error); callback.Run(*error); } } // namespace const base::FilePath::CharType -SandboxContext::kFileSystemDirectory[] = FILE_PATH_LITERAL("File System"); +SandboxFileSystemBackendDelegate::kFileSystemDirectory[] = + FILE_PATH_LITERAL("File System"); -SandboxContext::SandboxContext( +SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate( quota::QuotaManagerProxy* quota_manager_proxy, base::SequencedTaskRunner* file_task_runner, const base::FilePath& profile_path, @@ -123,16 +129,18 @@ SandboxContext::SandboxContext( quota_observer_(new SandboxQuotaObserver( quota_manager_proxy, file_task_runner, - sync_file_util(), + obfuscated_file_util(), usage_cache())), special_storage_policy_(special_storage_policy), file_system_options_(file_system_options), + is_filesystem_opened_(false), weak_factory_(this) { } -SandboxContext::~SandboxContext() { +SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() { + io_thread_checker_.DetachFromThread(); if (!file_task_runner_->RunsTasksOnCurrentThread()) { - AsyncFileUtilAdapter* sandbox_file_util = sandbox_file_util_.release(); + AsyncFileUtil* sandbox_file_util = sandbox_file_util_.release(); SandboxQuotaObserver* quota_observer = quota_observer_.release(); FileSystemUsageCache* file_system_usage_cache = file_system_usage_cache_.release(); @@ -145,7 +153,8 @@ SandboxContext::~SandboxContext() { } } -bool SandboxContext::IsAccessValid(const FileSystemURL& url) const { +bool SandboxFileSystemBackendDelegate::IsAccessValid( + const FileSystemURL& url) const { if (!IsAllowedScheme(url.origin())) return false; @@ -176,10 +185,10 @@ bool SandboxContext::IsAccessValid(const FileSystemURL& url) const { return true; } -bool SandboxContext::IsAllowedScheme(const GURL& url) const { +bool SandboxFileSystemBackendDelegate::IsAllowedScheme(const GURL& url) const { // Basically we only accept http or https. We allow file:// URLs // only if --allow-file-access-from-files flag is given. - if (url.SchemeIs("http") || url.SchemeIs("https")) + if (url.SchemeIsHTTPOrHTTPS()) return true; if (url.SchemeIsFileSystem()) return url.inner_url() && IsAllowedScheme(*url.inner_url()); @@ -194,23 +203,27 @@ bool SandboxContext::IsAllowedScheme(const GURL& url) const { return false; } -SandboxContext::OriginEnumerator* SandboxContext::CreateOriginEnumerator() { - return new ObfuscatedOriginEnumerator(sync_file_util()); +SandboxFileSystemBackendDelegate::OriginEnumerator* +SandboxFileSystemBackendDelegate::CreateOriginEnumerator() { + return new ObfuscatedOriginEnumerator(obfuscated_file_util()); } -base::FilePath SandboxContext::GetBaseDirectoryForOriginAndType( - const GURL& origin_url, fileapi::FileSystemType type, bool create) { +base::FilePath +SandboxFileSystemBackendDelegate::GetBaseDirectoryForOriginAndType( + const GURL& origin_url, + FileSystemType type, + bool create) { base::PlatformFileError error = base::PLATFORM_FILE_OK; - base::FilePath path = sync_file_util()->GetDirectoryForOriginAndType( + base::FilePath path = obfuscated_file_util()->GetDirectoryForOriginAndType( origin_url, type, create, &error); if (error != base::PLATFORM_FILE_OK) return base::FilePath(); return path; } -void SandboxContext::OpenFileSystem( +void SandboxFileSystemBackendDelegate::OpenFileSystem( const GURL& origin_url, - fileapi::FileSystemType type, + FileSystemType type, OpenFileSystemMode mode, const OpenFileSystemCallback& callback, const GURL& root_url) { @@ -225,23 +238,77 @@ void SandboxContext::OpenFileSystem( file_task_runner_->PostTaskAndReply( FROM_HERE, base::Bind(&OpenFileSystemOnFileThread, - sync_file_util(), origin_url, type, mode, + obfuscated_file_util(), origin_url, type, mode, base::Unretained(error_ptr)), base::Bind(&DidOpenFileSystem, weak_factory_.GetWeakPtr(), base::Bind(callback, root_url, name), base::Owned(error_ptr))); + + io_thread_checker_.DetachFromThread(); + is_filesystem_opened_ = true; +} + +scoped_ptr<FileSystemOperationContext> +SandboxFileSystemBackendDelegate::CreateFileSystemOperationContext( + const FileSystemURL& url, + FileSystemContext* context, + base::PlatformFileError* error_code) const { + if (!IsAccessValid(url)) { + *error_code = base::PLATFORM_FILE_ERROR_SECURITY; + return scoped_ptr<FileSystemOperationContext>(); + } + + const UpdateObserverList* update_observers = GetUpdateObservers(url.type()); + const ChangeObserverList* change_observers = GetChangeObservers(url.type()); + DCHECK(update_observers); + + scoped_ptr<FileSystemOperationContext> operation_context( + new FileSystemOperationContext(context)); + operation_context->set_update_observers(*update_observers); + operation_context->set_change_observers( + change_observers ? *change_observers : ChangeObserverList()); + + return operation_context.Pass(); } -base::PlatformFileError SandboxContext::DeleteOriginDataOnFileThread( +scoped_ptr<webkit_blob::FileStreamReader> +SandboxFileSystemBackendDelegate::CreateFileStreamReader( + const FileSystemURL& url, + int64 offset, + const base::Time& expected_modification_time, + FileSystemContext* context) const { + if (!IsAccessValid(url)) + return scoped_ptr<webkit_blob::FileStreamReader>(); + return scoped_ptr<webkit_blob::FileStreamReader>( + webkit_blob::FileStreamReader::CreateForFileSystemFile( + context, url, offset, expected_modification_time)); +} + +scoped_ptr<FileStreamWriter> +SandboxFileSystemBackendDelegate::CreateFileStreamWriter( + const FileSystemURL& url, + int64 offset, + FileSystemContext* context, + FileSystemType type) const { + if (!IsAccessValid(url)) + return scoped_ptr<FileStreamWriter>(); + const UpdateObserverList* observers = GetUpdateObservers(type); + DCHECK(observers); + return scoped_ptr<FileStreamWriter>( + new SandboxFileStreamWriter(context, url, offset, *observers)); +} + +base::PlatformFileError +SandboxFileSystemBackendDelegate::DeleteOriginDataOnFileThread( FileSystemContext* file_system_context, quota::QuotaManagerProxy* proxy, const GURL& origin_url, - fileapi::FileSystemType type) { + FileSystemType type) { int64 usage = GetOriginUsageOnFileThread( file_system_context, origin_url, type); usage_cache()->CloseCacheFiles(); - bool result = sync_file_util()->DeleteDirectoryForOriginAndType( + bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType( origin_url, type); if (result && proxy) { proxy->NotifyStorageModified( @@ -256,8 +323,8 @@ base::PlatformFileError SandboxContext::DeleteOriginDataOnFileThread( return base::PLATFORM_FILE_ERROR_FAILED; } -void SandboxContext::GetOriginsForTypeOnFileThread( - fileapi::FileSystemType type, std::set<GURL>* origins) { +void SandboxFileSystemBackendDelegate::GetOriginsForTypeOnFileThread( + FileSystemType type, std::set<GURL>* origins) { DCHECK(origins); scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); GURL origin; @@ -265,10 +332,20 @@ void SandboxContext::GetOriginsForTypeOnFileThread( if (enumerator->HasFileSystemType(type)) origins->insert(origin); } + switch (type) { + case kFileSystemTypeTemporary: + UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); + break; + case kFileSystemTypePersistent: + UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); + break; + default: + break; + } } -void SandboxContext::GetOriginsForHostOnFileThread( - fileapi::FileSystemType type, const std::string& host, +void SandboxFileSystemBackendDelegate::GetOriginsForHostOnFileThread( + FileSystemType type, const std::string& host, std::set<GURL>* origins) { DCHECK(origins); scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); @@ -280,10 +357,10 @@ void SandboxContext::GetOriginsForHostOnFileThread( } } -int64 SandboxContext::GetOriginUsageOnFileThread( +int64 SandboxFileSystemBackendDelegate::GetOriginUsageOnFileThread( FileSystemContext* file_system_context, const GURL& origin_url, - fileapi::FileSystemType type) { + FileSystemType type) { // Don't use usage cache and return recalculated usage for sticky invalidated // origins. if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type))) @@ -318,41 +395,101 @@ int64 SandboxContext::GetOriginUsageOnFileThread( return usage; } -void SandboxContext::InvalidateUsageCache( +void SandboxFileSystemBackendDelegate::AddFileUpdateObserver( + FileSystemType type, + FileUpdateObserver* observer, + base::SequencedTaskRunner* task_runner) { + DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread()); + update_observers_[type] = + update_observers_[type].AddObserver(observer, task_runner); +} + +void SandboxFileSystemBackendDelegate::AddFileChangeObserver( + FileSystemType type, + FileChangeObserver* observer, + base::SequencedTaskRunner* task_runner) { + DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread()); + change_observers_[type] = + change_observers_[type].AddObserver(observer, task_runner); +} + +void SandboxFileSystemBackendDelegate::AddFileAccessObserver( + FileSystemType type, + FileAccessObserver* observer, + base::SequencedTaskRunner* task_runner) { + DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread()); + access_observers_[type] = + access_observers_[type].AddObserver(observer, task_runner); +} + +const UpdateObserverList* SandboxFileSystemBackendDelegate::GetUpdateObservers( + FileSystemType type) const { + std::map<FileSystemType, UpdateObserverList>::const_iterator iter = + update_observers_.find(type); + if (iter == update_observers_.end()) + return NULL; + return &iter->second; +} + +const ChangeObserverList* SandboxFileSystemBackendDelegate::GetChangeObservers( + FileSystemType type) const { + std::map<FileSystemType, ChangeObserverList>::const_iterator iter = + change_observers_.find(type); + if (iter == change_observers_.end()) + return NULL; + return &iter->second; +} + +const AccessObserverList* SandboxFileSystemBackendDelegate::GetAccessObservers( + FileSystemType type) const { + std::map<FileSystemType, AccessObserverList>::const_iterator iter = + access_observers_.find(type); + if (iter == access_observers_.end()) + return NULL; + return &iter->second; +} + +void SandboxFileSystemBackendDelegate::InvalidateUsageCache( const GURL& origin, - fileapi::FileSystemType type) { + FileSystemType type) { base::PlatformFileError error = base::PLATFORM_FILE_OK; base::FilePath usage_file_path = GetUsageCachePathForOriginAndType( - sync_file_util(), origin, type, &error); + obfuscated_file_util(), origin, type, &error); if (error != base::PLATFORM_FILE_OK) return; usage_cache()->IncrementDirty(usage_file_path); } -void SandboxContext::StickyInvalidateUsageCache( +void SandboxFileSystemBackendDelegate::StickyInvalidateUsageCache( const GURL& origin, - fileapi::FileSystemType type) { + FileSystemType type) { sticky_dirty_origins_.insert(std::make_pair(origin, type)); quota_observer()->SetUsageCacheEnabled(origin, type, false); InvalidateUsageCache(origin, type); } -base::FilePath SandboxContext::GetUsageCachePathForOriginAndType( +FileSystemFileUtil* SandboxFileSystemBackendDelegate::sync_file_util() { + return static_cast<AsyncFileUtilAdapter*>(file_util())->sync_file_util(); +} + +base::FilePath +SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( const GURL& origin_url, FileSystemType type) { base::PlatformFileError error; base::FilePath path = GetUsageCachePathForOriginAndType( - sync_file_util(), origin_url, type, &error); + obfuscated_file_util(), origin_url, type, &error); if (error != base::PLATFORM_FILE_OK) return base::FilePath(); return path; } // static -base::FilePath SandboxContext::GetUsageCachePathForOriginAndType( +base::FilePath +SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( ObfuscatedFileUtil* sandbox_file_util, const GURL& origin_url, - fileapi::FileSystemType type, + FileSystemType type, base::PlatformFileError* error_out) { DCHECK(error_out); *error_out = base::PLATFORM_FILE_OK; @@ -363,14 +500,16 @@ base::FilePath SandboxContext::GetUsageCachePathForOriginAndType( return base_path.Append(FileSystemUsageCache::kUsageFileName); } -int64 SandboxContext::RecalculateUsage(FileSystemContext* context, - const GURL& origin, - FileSystemType type) { +int64 SandboxFileSystemBackendDelegate::RecalculateUsage( + FileSystemContext* context, + const GURL& origin, + FileSystemType type) { FileSystemOperationContext operation_context(context); FileSystemURL url = context->CreateCrackedFileSystemURL( origin, type, base::FilePath()); scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( - sync_file_util()->CreateFileEnumerator(&operation_context, url, true)); + obfuscated_file_util()->CreateFileEnumerator( + &operation_context, url, true)); base::FilePath file_path_each; int64 usage = 0; @@ -383,7 +522,7 @@ int64 SandboxContext::RecalculateUsage(FileSystemContext* context, return usage; } -void SandboxContext::CollectOpenFileSystemMetrics( +void SandboxFileSystemBackendDelegate::CollectOpenFileSystemMetrics( base::PlatformFileError error_code) { base::Time now = base::Time::Now(); bool throttled = now < next_release_time_for_open_filesystem_stat_; @@ -420,8 +559,8 @@ void SandboxContext::CollectOpenFileSystemMetrics( #undef REPORT } -ObfuscatedFileUtil* SandboxContext::sync_file_util() { - return static_cast<ObfuscatedFileUtil*>(file_util()->sync_file_util()); +ObfuscatedFileUtil* SandboxFileSystemBackendDelegate::obfuscated_file_util() { + return static_cast<ObfuscatedFileUtil*>(sync_file_util()); } } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/sandbox_context.h b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h index c765077b8d3..33d791e5920 100644 --- a/chromium/webkit/browser/fileapi/sandbox_context.h +++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBKIT_BROWSER_FILEAPI_SANDBOX_CONTEXT_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_CONTEXT_H_ +#ifndef WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_DELEGATE_H_ +#define WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_DELEGATE_H_ +#include <map> #include <set> #include <string> #include <utility> @@ -13,6 +14,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" #include "base/time/time.h" #include "webkit/browser/fileapi/file_system_backend.h" #include "webkit/browser/fileapi/file_system_options.h" @@ -28,9 +30,16 @@ class QuotaManagerProxy; class SpecialStoragePolicy; } +namespace webkit_blob { +class FileStreamReader; +} + namespace fileapi { -class AsyncFileUtilAdapter; +class AsyncFileUtil; +class FileStreamWriter; +class FileSystemFileUtil; +class FileSystemOperationContext; class FileSystemURL; class FileSystemUsageCache; class ObfuscatedFileUtil; @@ -38,9 +47,10 @@ class SandboxFileSystemBackend; class SandboxFileSystemTestHelper; class SandboxQuotaObserver; -// This class keeps and provides a sandbox file system context. +// Delegate implementation of the some methods in Sandbox/SyncFileSystemBackend. // An instance of this class is created and owned by FileSystemContext. -class WEBKIT_STORAGE_BROWSER_EXPORT SandboxContext { +class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackendDelegate + : public FileSystemQuotaUtil { public: typedef FileSystemBackend::OpenFileSystemCallback OpenFileSystemCallback; @@ -60,14 +70,14 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxContext { virtual bool HasFileSystemType(FileSystemType type) const = 0; }; - SandboxContext( + SandboxFileSystemBackendDelegate( quota::QuotaManagerProxy* quota_manager_proxy, base::SequencedTaskRunner* file_task_runner, const base::FilePath& profile_path, quota::SpecialStoragePolicy* special_storage_policy, const FileSystemOptions& file_system_options); - ~SandboxContext(); + virtual ~SandboxFileSystemBackendDelegate(); // Performs API-specific validity checks on the given path |url|. // Returns true if access to |url| is valid in this filesystem. @@ -99,30 +109,61 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxContext { OpenFileSystemMode mode, const OpenFileSystemCallback& callback, const GURL& root_url); + scoped_ptr<FileSystemOperationContext> CreateFileSystemOperationContext( + const FileSystemURL& url, + FileSystemContext* context, + base::PlatformFileError* error_code) const; + scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader( + const FileSystemURL& url, + int64 offset, + const base::Time& expected_modification_time, + FileSystemContext* context) const; + scoped_ptr<FileStreamWriter> CreateFileStreamWriter( + const FileSystemURL& url, + int64 offset, + FileSystemContext* context, + FileSystemType type) const; - // FileSystemQuotaUtil helpers. - base::PlatformFileError DeleteOriginDataOnFileThread( + // FileSystemQuotaUtil overrides. + virtual base::PlatformFileError DeleteOriginDataOnFileThread( FileSystemContext* context, quota::QuotaManagerProxy* proxy, const GURL& origin_url, - FileSystemType type); - void GetOriginsForTypeOnFileThread( + FileSystemType type) OVERRIDE; + virtual void GetOriginsForTypeOnFileThread( FileSystemType type, - std::set<GURL>* origins); - void GetOriginsForHostOnFileThread( + std::set<GURL>* origins) OVERRIDE; + virtual void GetOriginsForHostOnFileThread( FileSystemType type, const std::string& host, - std::set<GURL>* origins); - int64 GetOriginUsageOnFileThread( + std::set<GURL>* origins) OVERRIDE; + virtual int64 GetOriginUsageOnFileThread( FileSystemContext* context, const GURL& origin_url, - FileSystemType type); - void InvalidateUsageCache( - const GURL& origin_url, - FileSystemType type); - void StickyInvalidateUsageCache( - const GURL& origin_url, - FileSystemType type); + FileSystemType type) OVERRIDE; + virtual void AddFileUpdateObserver( + FileSystemType type, + FileUpdateObserver* observer, + base::SequencedTaskRunner* task_runner) OVERRIDE; + virtual void AddFileChangeObserver( + FileSystemType type, + FileChangeObserver* observer, + base::SequencedTaskRunner* task_runner) OVERRIDE; + virtual void AddFileAccessObserver( + FileSystemType type, + FileAccessObserver* observer, + base::SequencedTaskRunner* task_runner) OVERRIDE; + virtual const UpdateObserverList* GetUpdateObservers( + FileSystemType type) const OVERRIDE; + virtual const ChangeObserverList* GetChangeObservers( + FileSystemType type) const OVERRIDE; + virtual const AccessObserverList* GetAccessObservers( + FileSystemType type) const OVERRIDE; + + void InvalidateUsageCache(const GURL& origin_url, + FileSystemType type); + void StickyInvalidateUsageCache(const GURL& origin_url, + FileSystemType type); void CollectOpenFileSystemMetrics(base::PlatformFileError error_code); @@ -130,17 +171,19 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxContext { return file_task_runner_.get(); } - AsyncFileUtilAdapter* file_util() { return sandbox_file_util_.get(); } + AsyncFileUtil* file_util() { return sandbox_file_util_.get(); } FileSystemUsageCache* usage_cache() { return file_system_usage_cache_.get(); } - SandboxQuotaObserver* quota_observer() { return quota_observer_.get(); }; + SandboxQuotaObserver* quota_observer() { return quota_observer_.get(); } quota::SpecialStoragePolicy* special_storage_policy() { return special_storage_policy_.get(); } - FileSystemOptions file_system_options() { return file_system_options_; } + const FileSystemOptions& file_system_options() const { + return file_system_options_; + } - ObfuscatedFileUtil* sync_file_util(); + FileSystemFileUtil* sync_file_util(); private: friend class SandboxQuotaObserver; @@ -162,9 +205,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxContext { const GURL& origin, FileSystemType type); + ObfuscatedFileUtil* obfuscated_file_util(); + scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - scoped_ptr<AsyncFileUtilAdapter> sandbox_file_util_; + scoped_ptr<AsyncFileUtil> sandbox_file_util_; scoped_ptr<FileSystemUsageCache> file_system_usage_cache_; scoped_ptr<SandboxQuotaObserver> quota_observer_; @@ -172,18 +217,25 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxContext { FileSystemOptions file_system_options_; - // Acccessed only on the file thread. + bool is_filesystem_opened_; + base::ThreadChecker io_thread_checker_; + + // Accessed only on the file thread. std::set<GURL> visited_origins_; std::set<std::pair<GURL, FileSystemType> > sticky_dirty_origins_; + std::map<FileSystemType, UpdateObserverList> update_observers_; + std::map<FileSystemType, ChangeObserverList> change_observers_; + std::map<FileSystemType, AccessObserverList> access_observers_; + base::Time next_release_time_for_open_filesystem_stat_; - base::WeakPtrFactory<SandboxContext> weak_factory_; + base::WeakPtrFactory<SandboxFileSystemBackendDelegate> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(SandboxContext); + DISALLOW_COPY_AND_ASSIGN(SandboxFileSystemBackendDelegate); }; } // namespace fileapi -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_CONTEXT_H_ +#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_DELEGATE_H_ diff --git a/chromium/webkit/browser/fileapi/sandbox_context_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc index 841e10b5b83..48c3b8c4e70 100644 --- a/chromium/webkit/browser/fileapi/sandbox_context_unittest.cc +++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webkit/browser/fileapi/sandbox_context.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "base/basictypes.h" #include "base/file_util.h" @@ -27,11 +27,11 @@ FileSystemURL CreateFileSystemURL(const char* path) { } // namespace -class SandboxContextTest : public testing::Test { +class SandboxFileSystemBackendDelegateTest : public testing::Test { protected: virtual void SetUp() { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - context_.reset(new SandboxContext( + delegate_.reset(new SandboxFileSystemBackendDelegate( NULL /* quota_manager_proxy */, base::MessageLoopProxy::current().get(), data_dir_.path(), @@ -41,42 +41,42 @@ class SandboxContextTest : public testing::Test { base::ScopedTempDir data_dir_; base::MessageLoop message_loop_; - scoped_ptr<SandboxContext> context_; + scoped_ptr<SandboxFileSystemBackendDelegate> delegate_; }; -TEST_F(SandboxContextTest, IsAccessValid) { +TEST_F(SandboxFileSystemBackendDelegateTest, IsAccessValid) { // Normal case. - EXPECT_TRUE(context_->IsAccessValid(CreateFileSystemURL("a"))); + EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("a"))); // Access to a path with parent references ('..') should be disallowed. - EXPECT_FALSE(context_->IsAccessValid(CreateFileSystemURL("a/../b"))); + EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("a/../b"))); // Access from non-allowed scheme should be disallowed. - EXPECT_FALSE(context_->IsAccessValid( + EXPECT_FALSE(delegate_->IsAccessValid( FileSystemURL::CreateForTest( GURL("unknown://bar"), kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("foo")))); // Access with restricted name should be disallowed. - EXPECT_FALSE(context_->IsAccessValid(CreateFileSystemURL("."))); - EXPECT_FALSE(context_->IsAccessValid(CreateFileSystemURL(".."))); + EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("."))); + EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(".."))); // This is also disallowed due to Windows XP parent path handling. - EXPECT_FALSE(context_->IsAccessValid(CreateFileSystemURL("..."))); + EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("..."))); // These are identified as unsafe cases due to weird path handling // on Windows. - EXPECT_FALSE(context_->IsAccessValid(CreateFileSystemURL(" .."))); - EXPECT_FALSE(context_->IsAccessValid(CreateFileSystemURL(".. "))); + EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(" .."))); + EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(".. "))); // Similar but safe cases. - EXPECT_TRUE(context_->IsAccessValid(CreateFileSystemURL(" ."))); - EXPECT_TRUE(context_->IsAccessValid(CreateFileSystemURL(". "))); - EXPECT_TRUE(context_->IsAccessValid(CreateFileSystemURL("b."))); - EXPECT_TRUE(context_->IsAccessValid(CreateFileSystemURL(".b"))); + EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(" ."))); + EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(". "))); + EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("b."))); + EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(".b"))); // A path that looks like a drive letter. - EXPECT_TRUE(context_->IsAccessValid(CreateFileSystemURL("c:"))); + EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("c:"))); } } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc index ec213a36386..ed06d17ad70 100644 --- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc +++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc @@ -10,14 +10,14 @@ #include "base/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" #include "webkit/browser/fileapi/file_system_backend.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/mock_file_system_options.h" -#include "webkit/browser/fileapi/sandbox_context.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "webkit/common/fileapi/file_system_util.h" // PS stands for path separator. @@ -85,11 +85,11 @@ class SandboxFileSystemBackendTest : public testing::Test { protected: virtual void SetUp() { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - SetUpNewSandboxContext(CreateAllowFileAccessOptions()); + SetUpNewDelegate(CreateAllowFileAccessOptions()); } - void SetUpNewSandboxContext(const FileSystemOptions& options) { - context_.reset(new SandboxContext( + void SetUpNewDelegate(const FileSystemOptions& options) { + delegate_.reset(new SandboxFileSystemBackendDelegate( NULL /* quota_manager_proxy */, base::MessageLoopProxy::current().get(), data_dir_.path(), @@ -98,17 +98,18 @@ class SandboxFileSystemBackendTest : public testing::Test { } void SetUpNewBackend(const FileSystemOptions& options) { - SetUpNewSandboxContext(options); - backend_.reset(new SandboxFileSystemBackend(context_.get())); + SetUpNewDelegate(options); + backend_.reset(new SandboxFileSystemBackend(delegate_.get())); } - SandboxContext::OriginEnumerator* CreateOriginEnumerator() const { + SandboxFileSystemBackendDelegate::OriginEnumerator* + CreateOriginEnumerator() const { return backend_->CreateOriginEnumerator(); } void CreateOriginTypeDirectory(const GURL& origin, fileapi::FileSystemType type) { - base::FilePath target = context_-> + base::FilePath target = delegate_-> GetBaseDirectoryForOriginAndType(origin, type, true); ASSERT_TRUE(!target.empty()); ASSERT_TRUE(base::DirectoryExists(target)); @@ -122,11 +123,11 @@ class SandboxFileSystemBackendTest : public testing::Test { backend_->OpenFileSystem( origin_url, type, mode, base::Bind(&DidOpenFileSystem, &error)); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); if (error != base::PLATFORM_FILE_OK) return false; base::FilePath returned_root_path = - context_->GetBaseDirectoryForOriginAndType( + delegate_->GetBaseDirectoryForOriginAndType( origin_url, type, false /* create */); if (root_path) *root_path = returned_root_path; @@ -134,18 +135,19 @@ class SandboxFileSystemBackendTest : public testing::Test { } base::FilePath file_system_path() const { - return data_dir_.path().Append(SandboxContext::kFileSystemDirectory); + return data_dir_.path().Append( + SandboxFileSystemBackendDelegate::kFileSystemDirectory); } base::ScopedTempDir data_dir_; base::MessageLoop message_loop_; - scoped_ptr<SandboxContext> context_; + scoped_ptr<SandboxFileSystemBackendDelegate> delegate_; scoped_ptr<SandboxFileSystemBackend> backend_; }; TEST_F(SandboxFileSystemBackendTest, Empty) { SetUpNewBackend(CreateAllowFileAccessOptions()); - scoped_ptr<SandboxContext::OriginEnumerator> enumerator( + scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator( CreateOriginEnumerator()); ASSERT_TRUE(enumerator->Next().is_empty()); } @@ -178,7 +180,7 @@ TEST_F(SandboxFileSystemBackendTest, EnumerateOrigins) { persistent_set.insert(GURL(persistent_origins[i])); } - scoped_ptr<SandboxContext::OriginEnumerator> enumerator( + scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator( CreateOriginEnumerator()); size_t temporary_actual_size = 0; size_t persistent_actual_size = 0; diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc index 179bf9b2c1a..df579e488e4 100644 --- a/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc +++ b/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc @@ -5,8 +5,8 @@ #include "webkit/browser/fileapi/sandbox_file_system_test_helper.h" #include "base/file_util.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "url/gurl.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_file_util.h" @@ -57,11 +57,11 @@ void SandboxFileSystemTestHelper::SetUp( void SandboxFileSystemTestHelper::TearDown() { file_system_context_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } base::FilePath SandboxFileSystemTestHelper::GetOriginRootPath() { - return file_system_context_->sandbox_context()-> + return file_system_context_->sandbox_delegate()-> GetBaseDirectoryForOriginAndType(origin_, type_, false); } @@ -80,8 +80,8 @@ base::FilePath SandboxFileSystemTestHelper::GetLocalPathFromASCII( } base::FilePath SandboxFileSystemTestHelper::GetUsageCachePath() const { - return file_system_context_-> - sandbox_context()->GetUsageCachePathForOriginAndType(origin_, type_); + return file_system_context_->sandbox_delegate()-> + GetUsageCachePathForOriginAndType(origin_, type_); } FileSystemURL SandboxFileSystemTestHelper::CreateURL( @@ -124,23 +124,23 @@ SandboxFileSystemTestHelper::NewOperationContext() { void SandboxFileSystemTestHelper::AddFileChangeObserver( FileChangeObserver* observer) { - file_system_context_->sandbox_backend()-> + file_system_context_->sandbox_backend()->GetQuotaUtil()-> AddFileChangeObserver(type_, observer, NULL); } FileSystemUsageCache* SandboxFileSystemTestHelper::usage_cache() { - return file_system_context()->sandbox_context()->usage_cache(); + return file_system_context()->sandbox_delegate()->usage_cache(); } void SandboxFileSystemTestHelper::SetUpFileSystem() { DCHECK(file_system_context_.get()); DCHECK(file_system_context_->sandbox_backend()->CanHandleType(type_)); - file_util_ = file_system_context_->GetFileUtil(type_); + file_util_ = file_system_context_->sandbox_delegate()->sync_file_util(); DCHECK(file_util_); // Prepare the origin's root directory. - file_system_context_->sandbox_context()-> + file_system_context_->sandbox_delegate()-> GetBaseDirectoryForOriginAndType(origin_, type_, true /* create */); // Initialize the usage cache file. diff --git a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc index 7eeab2185b6..aad2c7e6cc3 100644 --- a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc +++ b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc @@ -76,7 +76,7 @@ TEST(SandboxIsolatedOriginDatabaseTest, MigrationTest) { base::FilePath directory_db_path = dir.path().Append(path); EXPECT_TRUE(base::DirectoryExists(directory_db_path)); EXPECT_TRUE(base::PathExists(directory_db_path.AppendASCII("dummy"))); - EXPECT_TRUE(file_util::ReadFileToString( + EXPECT_TRUE(base::ReadFileToString( directory_db_path.AppendASCII("dummy"), &origin_db_data)); EXPECT_EQ(kFakeDirectoryData, origin_db_data); diff --git a/chromium/webkit/browser/fileapi/sandbox_origin_database.cc b/chromium/webkit/browser/fileapi/sandbox_origin_database.cc index 9ca399673fd..4ce83017cc0 100644 --- a/chromium/webkit/browser/fileapi/sandbox_origin_database.cc +++ b/chromium/webkit/browser/fileapi/sandbox_origin_database.cc @@ -76,7 +76,7 @@ bool SandboxOriginDatabase::Init(InitOption init_option, std::string path = FilePathToString(db_path); leveldb::Options options; - options.max_open_files = 64; // Use minimum. + options.max_open_files = 0; // Use minimum. options.create_if_missing = true; leveldb::DB* db; leveldb::Status status = leveldb::DB::Open(options, path, &db); @@ -122,7 +122,7 @@ bool SandboxOriginDatabase::Init(InitOption init_option, bool SandboxOriginDatabase::RepairDatabase(const std::string& db_path) { DCHECK(!db_.get()); leveldb::Options options; - options.max_open_files = 64; // Use minimum. + options.max_open_files = 0; // Use minimum. if (!leveldb::RepairDB(db_path, options).ok() || !Init(FAIL_IF_NONEXISTENT, FAIL_ON_CORRUPTION)) { LOG(WARNING) << "Failed to repair SandboxOriginDatabase."; diff --git a/chromium/webkit/browser/fileapi/sandbox_quota_observer.cc b/chromium/webkit/browser/fileapi/sandbox_quota_observer.cc index 02a47ee255c..fe5ee3796fb 100644 --- a/chromium/webkit/browser/fileapi/sandbox_quota_observer.cc +++ b/chromium/webkit/browser/fileapi/sandbox_quota_observer.cc @@ -7,7 +7,7 @@ #include "base/sequenced_task_runner.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/file_system_usage_cache.h" -#include "webkit/browser/fileapi/sandbox_context.h" +#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "webkit/browser/fileapi/timed_task_helper.h" #include "webkit/browser/quota/quota_client.h" #include "webkit/browser/quota/quota_manager.h" @@ -107,7 +107,7 @@ base::FilePath SandboxQuotaObserver::GetUsageCachePath( DCHECK(sandbox_file_util_); base::PlatformFileError error = base::PLATFORM_FILE_OK; base::FilePath path = - SandboxContext::GetUsageCachePathForOriginAndType( + SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( sandbox_file_util_, url.origin(), url.type(), &error); if (error != base::PLATFORM_FILE_OK) { LOG(WARNING) << "Could not get usage cache path for: " diff --git a/chromium/webkit/browser/fileapi/test_file_system_backend.cc b/chromium/webkit/browser/fileapi/test_file_system_backend.cc index 584e2e3a10d..44109cf6148 100644 --- a/chromium/webkit/browser/fileapi/test_file_system_backend.cc +++ b/chromium/webkit/browser/fileapi/test_file_system_backend.cc @@ -10,11 +10,11 @@ #include "base/file_util.h" #include "base/sequenced_task_runner.h" +#include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/copy_or_move_file_validator.h" #include "webkit/browser/fileapi/file_observers.h" -#include "webkit/browser/fileapi/file_system_file_stream_reader.h" +#include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_operation_impl.h" #include "webkit/browser/fileapi/file_system_quota_util.h" #include "webkit/browser/fileapi/local_file_util.h" #include "webkit/browser/fileapi/native_file_util.h" @@ -24,6 +24,29 @@ namespace fileapi { +namespace { + +class TestFileUtil : public LocalFileUtil { + public: + explicit TestFileUtil(const base::FilePath& base_path) + : base_path_(base_path) {} + virtual ~TestFileUtil() {} + + // LocalFileUtil overrides. + virtual base::PlatformFileError GetLocalFilePath( + FileSystemOperationContext* context, + const FileSystemURL& file_system_url, + base::FilePath* local_file_path) OVERRIDE { + *local_file_path = base_path_.Append(file_system_url.path()); + return base::PLATFORM_FILE_OK; + } + + private: + base::FilePath base_path_; +}; + +} // namespace + // This only supports single origin. class TestFileSystemBackend::QuotaUtil : public FileSystemQuotaUtil, @@ -66,17 +89,6 @@ class TestFileSystemBackend::QuotaUtil return usage_; } - virtual void InvalidateUsageCache(const GURL& origin_url, - FileSystemType type) OVERRIDE { - // Do nothing. - } - - virtual void StickyInvalidateUsageCache( - const GURL& origin, - FileSystemType type) OVERRIDE { - // Do nothing. - } - virtual void AddFileUpdateObserver( FileSystemType type, FileUpdateObserver* observer, @@ -136,7 +148,7 @@ TestFileSystemBackend::TestFileSystemBackend( base::SequencedTaskRunner* task_runner, const base::FilePath& base_path) : base_path_(base_path), - local_file_util_(new AsyncFileUtilAdapter(new LocalFileUtil())), + file_util_(new AsyncFileUtilAdapter(new TestFileUtil(base_path))), quota_util_(new QuotaUtil(task_runner)), require_copy_or_move_validator_(false) { } @@ -161,13 +173,8 @@ void TestFileSystemBackend::OpenFileSystem( base::PLATFORM_FILE_OK); } -FileSystemFileUtil* TestFileSystemBackend::GetFileUtil(FileSystemType type) { - DCHECK(local_file_util_.get()); - return local_file_util_->sync_file_util(); -} - AsyncFileUtil* TestFileSystemBackend::GetAsyncFileUtil(FileSystemType type) { - return local_file_util_.get(); + return file_util_.get(); } CopyOrMoveFileValidatorFactory* @@ -198,8 +205,7 @@ FileSystemOperation* TestFileSystemBackend::CreateFileSystemOperation( operation_context->set_update_observers(*GetUpdateObservers(url.type())); operation_context->set_change_observers( *quota_util_->GetChangeObservers(url.type())); - operation_context->set_root_path(base_path_); - return new FileSystemOperationImpl(url, context, operation_context.Pass()); + return FileSystemOperation::Create(url, context, operation_context.Pass()); } scoped_ptr<webkit_blob::FileStreamReader> @@ -209,7 +215,7 @@ TestFileSystemBackend::CreateFileStreamReader( const base::Time& expected_modification_time, FileSystemContext* context) const { return scoped_ptr<webkit_blob::FileStreamReader>( - new FileSystemFileStreamReader( + webkit_blob::FileStreamReader::CreateForFileSystemFile( context, url, offset, expected_modification_time)); } diff --git a/chromium/webkit/browser/fileapi/test_file_system_backend.h b/chromium/webkit/browser/fileapi/test_file_system_backend.h index ef252c13118..dc1cbce2298 100644 --- a/chromium/webkit/browser/fileapi/test_file_system_backend.h +++ b/chromium/webkit/browser/fileapi/test_file_system_backend.h @@ -41,7 +41,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE TestFileSystemBackend FileSystemType type, OpenFileSystemMode mode, const OpenFileSystemCallback& callback) OVERRIDE; - virtual FileSystemFileUtil* GetFileUtil(FileSystemType type) OVERRIDE; virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, @@ -81,7 +80,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE TestFileSystemBackend base::FilePath base_path_; scoped_refptr<base::SequencedTaskRunner> task_runner_; - scoped_ptr<AsyncFileUtilAdapter> local_file_util_; + scoped_ptr<AsyncFileUtilAdapter> file_util_; scoped_ptr<QuotaUtil> quota_util_; bool require_copy_or_move_validator_; diff --git a/chromium/webkit/browser/fileapi/timed_task_helper_unittest.cc b/chromium/webkit/browser/fileapi/timed_task_helper_unittest.cc index 6966c614c3d..fa3e84d523d 100644 --- a/chromium/webkit/browser/fileapi/timed_task_helper_unittest.cc +++ b/chromium/webkit/browser/fileapi/timed_task_helper_unittest.cc @@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/location.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/fileapi/timed_task_helper.h" @@ -51,7 +51,7 @@ TEST(TimedTaskHelper, FireTimerWhenAlive) { embedder.timer()->Reset(); ASSERT_TRUE(embedder.timer()->IsRunning()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); ASSERT_TRUE(embedder.timer_fired()); } @@ -77,7 +77,7 @@ TEST(TimedTaskHelper, FireTimerWhenAlreadyDeleted) { // At this point the callback is still in the message queue but // embedder is gone. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } } // namespace fileapi diff --git a/chromium/webkit/browser/fileapi/transient_file_util.h b/chromium/webkit/browser/fileapi/transient_file_util.h index d3d56c1c173..1e67c852027 100644 --- a/chromium/webkit/browser/fileapi/transient_file_util.h +++ b/chromium/webkit/browser/fileapi/transient_file_util.h @@ -6,7 +6,7 @@ #define WEBKIT_BROWSER_FILEAPI_TRANSIENT_FILE_UTIL_H_ #include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/isolated_file_util.h" +#include "webkit/browser/fileapi/local_file_util.h" #include "webkit/browser/webkit_storage_browser_export.h" namespace fileapi { @@ -14,12 +14,12 @@ namespace fileapi { class FileSystemOperationContext; class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE TransientFileUtil - : public IsolatedFileUtil { + : public LocalFileUtil { public: TransientFileUtil() {} virtual ~TransientFileUtil() {} - // IsolatedFileUtil overrides. + // LocalFileUtil overrides. virtual webkit_blob::ScopedFile CreateSnapshotFile( FileSystemOperationContext* context, const FileSystemURL& url, diff --git a/chromium/webkit/browser/fileapi/transient_file_util_unittest.cc b/chromium/webkit/browser/fileapi/transient_file_util_unittest.cc index 2a809a30779..3b6e284070d 100644 --- a/chromium/webkit/browser/fileapi/transient_file_util_unittest.cc +++ b/chromium/webkit/browser/fileapi/transient_file_util_unittest.cc @@ -7,8 +7,8 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/platform_file.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_context.h" @@ -34,7 +34,7 @@ class TransientFileUtilTest : public testing::Test { virtual void TearDown() OVERRIDE { file_system_context_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void CreateAndRegisterTemporaryFile( @@ -110,7 +110,7 @@ TEST_F(TransientFileUtilTest, TransientFile) { } // The file's now scoped out. - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // Now the temporary file and the transient filesystem must be gone too. ASSERT_FALSE(base::PathExists(temp_path)); diff --git a/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc b/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc index e6e0d4cd2b4..429edf2fe05 100644 --- a/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc +++ b/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc @@ -5,13 +5,13 @@ #include "webkit/browser/fileapi/upload_file_system_file_element_reader.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "net/base/io_buffer.h" #include "net/base/test_completion_callback.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/fileapi/async_file_test_helper.h" #include "webkit/browser/fileapi/file_system_backend.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_file_util.h" #include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/mock_file_system_context.h" @@ -43,7 +43,7 @@ class UploadFileSystemFileElementReaderTest : public testing::Test { OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem, base::Unretained(this))); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); ASSERT_TRUE(file_system_root_url_.is_valid()); // Prepare a file on file system. @@ -71,7 +71,7 @@ class UploadFileSystemFileElementReaderTest : public testing::Test { virtual void TearDown() OVERRIDE { reader_.reset(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } protected: @@ -89,31 +89,14 @@ class UploadFileSystemFileElementReaderTest : public testing::Test { kFileSystemType, base::FilePath().AppendASCII(filename)); - fileapi::FileSystemFileUtil* file_util = - file_system_context_->GetFileUtil(kFileSystemType); - - fileapi::FileSystemOperationContext context(file_system_context_.get()); - context.set_allowed_bytes_growth(1024); - - base::PlatformFile handle = base::kInvalidPlatformFileValue; - bool created = false; - ASSERT_EQ(base::PLATFORM_FILE_OK, file_util->CreateOrOpen( - &context, - url, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, - &handle, - &created)); - EXPECT_TRUE(created); - ASSERT_NE(base::kInvalidPlatformFileValue, handle); - ASSERT_EQ(buf_size, - base::WritePlatformFile(handle, 0 /* offset */, buf, buf_size)); - base::ClosePlatformFile(handle); + ASSERT_EQ(base::PLATFORM_FILE_OK, + AsyncFileTestHelper::CreateFileWithData( + file_system_context_, url, buf, buf_size)); base::PlatformFileInfo file_info; - base::FilePath platform_path; ASSERT_EQ(base::PLATFORM_FILE_OK, - file_util->GetFileInfo(&context, url, &file_info, - &platform_path)); + AsyncFileTestHelper::GetMetadata( + file_system_context_, url, &file_info)); *modification_time = file_info.last_modified; } diff --git a/chromium/webkit/browser/quota/mock_quota_manager_unittest.cc b/chromium/webkit/browser/quota/mock_quota_manager_unittest.cc index d05addc9dba..fb3047d6e47 100644 --- a/chromium/webkit/browser/quota/mock_quota_manager_unittest.cc +++ b/chromium/webkit/browser/quota/mock_quota_manager_unittest.cc @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - #include <set> #include "base/bind.h" #include "base/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/quota/mock_quota_manager.h" #include "webkit/browser/quota/mock_special_storage_policy.h" @@ -52,7 +51,7 @@ class MockQuotaManagerTest : public testing::Test { virtual void TearDown() { // Make sure the quota manager cleans up correctly. manager_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void GetModifiedOrigins(StorageType type, base::Time since) { @@ -161,7 +160,7 @@ TEST_F(MockQuotaManagerTest, OriginDeletion) { base::Time::Now()); DeleteOriginData(kOrigin2, kTemporary, kClientFile); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, deletion_callback_count()); EXPECT_TRUE(manager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); @@ -171,7 +170,7 @@ TEST_F(MockQuotaManagerTest, OriginDeletion) { EXPECT_TRUE(manager()->OriginHasData(kOrigin3, kTemporary, kClientDB)); DeleteOriginData(kOrigin3, kTemporary, kClientFile | kClientDB); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, deletion_callback_count()); EXPECT_TRUE(manager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); @@ -188,13 +187,13 @@ TEST_F(MockQuotaManagerTest, ModifiedOrigins) { base::TimeDelta a_minute = base::TimeDelta::FromMilliseconds(60000); GetModifiedOrigins(kTemporary, then); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(origins().empty()); manager()->AddOrigin(kOrigin1, kTemporary, kClientFile, now - an_hour); GetModifiedOrigins(kTemporary, then); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kTemporary, type()); EXPECT_EQ(1UL, origins().size()); @@ -204,7 +203,7 @@ TEST_F(MockQuotaManagerTest, ModifiedOrigins) { manager()->AddOrigin(kOrigin2, kTemporary, kClientFile, now); GetModifiedOrigins(kTemporary, then); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kTemporary, type()); EXPECT_EQ(2UL, origins().size()); @@ -212,7 +211,7 @@ TEST_F(MockQuotaManagerTest, ModifiedOrigins) { EXPECT_EQ(1UL, origins().count(kOrigin2)); GetModifiedOrigins(kTemporary, now - a_minute); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kTemporary, type()); EXPECT_EQ(1UL, origins().size()); diff --git a/chromium/webkit/browser/quota/mock_storage_client.cc b/chromium/webkit/browser/quota/mock_storage_client.cc index 7e25654bd2b..61fd667a85a 100644 --- a/chromium/webkit/browser/quota/mock_storage_client.cc +++ b/chromium/webkit/browser/quota/mock_storage_client.cc @@ -121,6 +121,10 @@ void MockStorageClient::DeleteOriginData( weak_factory_.GetWeakPtr(), origin, type, callback)); } +bool MockStorageClient::DoesSupport(quota::StorageType type) const { + return true; +} + void MockStorageClient::RunGetOriginUsage( const GURL& origin_url, StorageType type, const GetUsageCallback& callback) { diff --git a/chromium/webkit/browser/quota/mock_storage_client.h b/chromium/webkit/browser/quota/mock_storage_client.h index 4b3d03fcc85..42c6162de49 100644 --- a/chromium/webkit/browser/quota/mock_storage_client.h +++ b/chromium/webkit/browser/quota/mock_storage_client.h @@ -59,6 +59,7 @@ class MockStorageClient : public QuotaClient { virtual void DeleteOriginData(const GURL& origin, StorageType type, const DeletionCallback& callback) OVERRIDE; + virtual bool DoesSupport(quota::StorageType type) const OVERRIDE; private: void RunGetOriginUsage(const GURL& origin_url, diff --git a/chromium/webkit/browser/quota/quota_client.h b/chromium/webkit/browser/quota/quota_client.h index eff1f1e8a87..5c0da46d87e 100644 --- a/chromium/webkit/browser/quota/quota_client.h +++ b/chromium/webkit/browser/quota/quota_client.h @@ -69,6 +69,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT QuotaClient { virtual void DeleteOriginData(const GURL& origin, StorageType type, const DeletionCallback& callback) = 0; + + virtual bool DoesSupport(StorageType type) const = 0; }; // TODO(dmikurube): Replace it to std::vector for efficiency. diff --git a/chromium/webkit/browser/quota/quota_manager_unittest.cc b/chromium/webkit/browser/quota/quota_manager_unittest.cc index 3b1d0680aa6..cb9ffea28e9 100644 --- a/chromium/webkit/browser/quota/quota_manager_unittest.cc +++ b/chromium/webkit/browser/quota/quota_manager_unittest.cc @@ -11,8 +11,8 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "base/stl_util.h" #include "base/sys_info.h" #include "base/time/time.h" @@ -69,7 +69,7 @@ class QuotaManagerTest : public testing::Test { virtual void TearDown() { // Make sure the quota manager cleans up correctly. quota_manager_ = NULL; - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } protected: @@ -456,7 +456,7 @@ TEST_F(QuotaManagerTest, GetUsageInfo) { QuotaClient::kDatabase)); GetUsageInfo(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(4U, usage_info().size()); for (size_t i = 0; i < usage_info().size(); ++i) { @@ -485,20 +485,20 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) { QuotaClient::kFileSystem)); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(80, usage()); EXPECT_EQ(0, quota()); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); EXPECT_LE(0, quota()); int64 quota_returned_for_foo = quota(); GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(quota_returned_for_foo, quota()); @@ -506,30 +506,30 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) { TEST_F(QuotaManagerTest, GetUsage_NoClient) { GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); EXPECT_EQ(0, unlimited_usage()); GetGlobalUsage(kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); EXPECT_EQ(0, unlimited_usage()); } @@ -537,30 +537,30 @@ TEST_F(QuotaManagerTest, GetUsage_NoClient) { TEST_F(QuotaManagerTest, GetUsage_EmptyClient) { RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem)); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); EXPECT_EQ(0, unlimited_usage()); GetGlobalUsage(kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); EXPECT_EQ(0, unlimited_usage()); } @@ -579,12 +579,12 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) { // This time explicitly sets a temporary global quota. SetTemporaryGlobalQuota(100); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(100, quota()); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -595,7 +595,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) { EXPECT_EQ(kPerHostQuota, quota()); GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(5 + 7, usage()); EXPECT_EQ(kPerHostQuota, quota()); @@ -626,52 +626,52 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) { GetAvailableDiskSpaceForTest(base::FilePath()) / kPerHostTemporaryPortion; GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(1 + 128, usage()); GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(4, usage()); GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(512, usage()); EXPECT_EQ(std::min(kAvailableSpaceForApp, kTempQuotaBase) + usage(), quota()); GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(8, usage()); EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); GetAvailableSpace(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_LE(0, available_space()); GetUsageAndQuotaForWebApps(GURL("http://installed/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(1024, usage()); EXPECT_EQ(std::min(kAvailableSpaceForApp, kTempQuotaBase) + usage(), quota()); GetUsageAndQuotaForWebApps(GURL("http://installed/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(16, usage()); EXPECT_EQ(usage(), quota()); // Over-budget case. GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(1 + 2 + 128 + 512 + 1024, usage()); EXPECT_EQ(512, unlimited_usage()); GetGlobalUsage(kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(4 + 8 + 16 + 256, usage()); EXPECT_EQ(8, unlimited_usage()); @@ -687,7 +687,7 @@ void QuotaManagerTest::GetUsage_WithModifyTestBody(const StorageType type) { RegisterClient(client); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -696,19 +696,19 @@ void QuotaManagerTest::GetUsage_WithModifyTestBody(const StorageType type) { client->AddOriginAndNotify(GURL("https://foo.com/"), type, 1); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20 + 30 - 5 + 1, usage()); int foo_usage = usage(); client->AddOriginAndNotify(GURL("http://bar.com/"), type, 40); GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(40, usage()); GetGlobalUsage(type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(foo_usage + 40, usage()); EXPECT_EQ(0, unlimited_usage()); } @@ -727,14 +727,14 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData), QuotaClient::kFileSystem)); SetTemporaryGlobalQuota(100); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int kPerHostQuota = 100 / QuotaManager::kPerHostTemporaryPortion; GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(kPerHostQuota, quota()); @@ -744,7 +744,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { kTemp); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(kPerHostQuota, quota()); @@ -761,7 +761,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) { RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData), QuotaClient::kFileSystem)); SetTemporaryGlobalQuota(100); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); set_additional_callback_count(0); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); @@ -775,7 +775,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) { // Nuke before waiting for callbacks. set_quota_manager(NULL); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaErrorAbort, status()); } @@ -788,24 +788,24 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Overbudget) { RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData), QuotaClient::kFileSystem)); SetTemporaryGlobalQuota(100); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int kPerHostQuota = 100 / QuotaManager::kPerHostTemporaryPortion; GetUsageAndQuotaForWebApps(GURL("http://usage1/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(1, usage()); EXPECT_EQ(1, quota()); // should be clamped to our current usage GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(10, quota()); GetUsageAndQuotaForWebApps(GURL("http://usage200/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(200, usage()); EXPECT_EQ(kPerHostQuota, quota()); // should be clamped to the nominal quota @@ -824,10 +824,10 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { // Test when not overbugdet. SetTemporaryGlobalQuota(1000); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(10 + 50 + 4000, usage()); EXPECT_EQ(4000, unlimited_usage()); @@ -835,56 +835,56 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { 1000 / QuotaManager::kPerHostTemporaryPortion; GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor1000, quota()); GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor1000, quota()); GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(QuotaManager::kNoLimit, quota()); // Test when overbugdet. SetTemporaryGlobalQuota(100); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int kPerHostQuotaFor100 = 100 / QuotaManager::kPerHostTemporaryPortion; GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(QuotaManager::kNoLimit, quota()); @@ -894,30 +894,30 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { mock_special_storage_policy()->NotifyCleared(); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(10 + 50 + 4000, usage()); EXPECT_EQ(0, unlimited_usage()); GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(10, quota()); // should be clamped to our current usage GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); @@ -949,11 +949,11 @@ TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) { RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem)); GetPersistentHostQuota("foo.com"); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, quota()); SetPersistentHostQuota("foo.com", 100); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(100, quota()); GetPersistentHostQuota("foo.com"); @@ -961,7 +961,7 @@ TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) { GetPersistentHostQuota("foo.com"); SetPersistentHostQuota("foo.com", 300000000000ll); GetPersistentHostQuota("foo.com"); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(300000000000ll, quota()); } @@ -969,14 +969,14 @@ TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem)); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(0, quota()); SetPersistentHostQuota("foo.com", 100); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(100, quota()); @@ -985,19 +985,19 @@ TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { mock_special_storage_policy()->GrantQueryDiskSize(GURL("http://installed/")); SetPersistentHostQuota("installed", kAvailableSpaceForApp + 100); GetUsageAndQuotaForWebApps(GURL("http://installed/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kAvailableSpaceForApp, quota()); // Ditto for unlimited apps. mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kAvailableSpaceForApp, quota()); // GetUsageAndQuotaForStorageClient should just return 0 usage and // kNoLimit quota. GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, usage()); EXPECT_EQ(QuotaManager::kNoLimit, quota()); } @@ -1014,7 +1014,7 @@ TEST_F(QuotaManagerTest, GetSyncableQuota) { // kAvailableSpaceForApp as syncable quota (because of the pre-condition). mock_special_storage_policy()->GrantQueryDiskSize(GURL("http://installed/")); GetUsageAndQuotaForWebApps(GURL("http://installed/"), kSync); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(kAvailableSpaceForApp, quota()); @@ -1022,7 +1022,7 @@ TEST_F(QuotaManagerTest, GetSyncableQuota) { // If it's not installed (which shouldn't happen in real case) it // should just return the default host quota for syncable. GetUsageAndQuotaForWebApps(GURL("http://foo/"), kSync); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(QuotaManager::kSyncableStorageDefaultHostQuota, quota()); @@ -1044,7 +1044,7 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_MultiOrigins) { SetPersistentHostQuota("foo.com", 100); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20 + 13 + 19, usage()); EXPECT_EQ(100, quota()); @@ -1068,7 +1068,7 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) { GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(100, quota()); @@ -1078,7 +1078,7 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) { kPerm); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(2, additional_callback_count()); @@ -1102,7 +1102,7 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_NukeManager) { // Nuke before waiting for callbacks. set_quota_manager(NULL); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaErrorAbort, status()); } @@ -1120,21 +1120,21 @@ TEST_F(QuotaManagerTest, GetUsage_Simple) { QuotaClient::kFileSystem)); GetGlobalUsage(kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 1 + 20 + 600000); EXPECT_EQ(0, unlimited_usage()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000); EXPECT_EQ(0, unlimited_usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 1 + 20); GetHostUsage("buz.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 4000 + 50000); } @@ -1154,7 +1154,7 @@ TEST_F(QuotaManagerTest, GetUsage_WithModification) { RegisterClient(client); GetGlobalUsage(kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 1 + 20 + 600000); EXPECT_EQ(0, unlimited_usage()); @@ -1162,12 +1162,12 @@ TEST_F(QuotaManagerTest, GetUsage_WithModification) { GURL("http://foo.com/"), kPerm, 80000000); GetGlobalUsage(kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 1 + 20 + 600000 + 80000000); EXPECT_EQ(0, unlimited_usage()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000); EXPECT_EQ(0, unlimited_usage()); @@ -1175,19 +1175,19 @@ TEST_F(QuotaManagerTest, GetUsage_WithModification) { GURL("http://foo.com/"), kTemp, 1); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000 + 1); EXPECT_EQ(0, unlimited_usage()); GetHostUsage("buz.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 4000 + 50000); client->ModifyOriginAndNotify( GURL("http://buz.com/"), kTemp, 900000000); GetHostUsage("buz.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(usage(), 4000 + 50000 + 900000000); } @@ -1203,38 +1203,38 @@ TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) { RegisterClient(client); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_global_tmp = usage(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_tmp = usage(); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_pers = usage(); DeleteClientOriginData(client, GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_global_tmp - 1, usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_tmp - 1, usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_pers, usage()); } TEST_F(QuotaManagerTest, GetAvailableSpaceTest) { GetAvailableSpace(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_LE(0, available_space()); } @@ -1261,15 +1261,15 @@ TEST_F(QuotaManagerTest, EvictOriginData) { RegisterClient(client2); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_global_tmp = usage(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_tmp = usage(); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_pers = usage(); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData1); ++i) @@ -1278,13 +1278,13 @@ TEST_F(QuotaManagerTest, EvictOriginData) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData2); ++i) quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, GURL(kData2[i].origin), kData2[i].type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EvictOriginData(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); DumpOriginInfoTable(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); typedef OriginInfoTableEntries::const_iterator iterator; for (iterator itr(origin_info_entries().begin()), @@ -1295,15 +1295,15 @@ TEST_F(QuotaManagerTest, EvictOriginData) { } GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_global_tmp - (1 + 50000), usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_tmp - (1 + 50000), usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_pers, usage()); } @@ -1320,20 +1320,20 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) { RegisterClient(client); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_global_tmp = usage(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_tmp = usage(); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_pers = usage(); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData); ++i) NotifyStorageAccessed(client, GURL(kData[i].origin), kData[i].type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); client->AddOriginToErrorSet(GURL("http://foo.com/"), kTemp); @@ -1341,12 +1341,12 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) { i < QuotaManager::kThresholdOfErrorsToBeBlacklisted + 1; ++i) { EvictOriginData(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaErrorInvalidModification, status()); } DumpOriginInfoTable(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); bool found_origin_in_database = false; typedef OriginInfoTableEntries::const_iterator iterator; @@ -1364,31 +1364,31 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) { for (size_t i = 0; i < kNumberOfTemporaryOrigins - 1; ++i) { GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(lru_origin().is_empty()); // The origin "http://foo.com/" should not be in the LRU list. EXPECT_NE(std::string("http://foo.com/"), lru_origin().spec()); DeleteOriginFromDatabase(lru_origin(), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } // Now the LRU list must be empty. GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lru_origin().is_empty()); // Deleting origins from the database should not affect the results of the // following checks. GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_global_tmp, usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_tmp, usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_pers, usage()); } @@ -1406,10 +1406,10 @@ TEST_F(QuotaManagerTest, GetUsageAndQuotaForEviction) { RegisterClient(client); SetTemporaryGlobalQuota(10000000); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetUsageAndQuotaForEviction(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(21, limited_usage()); EXPECT_EQ(10000000, quota()); @@ -1425,47 +1425,47 @@ TEST_F(QuotaManagerTest, DeleteHostDataSimple) { RegisterClient(client); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_global_tmp = usage(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_tmp = usage(); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); int64 predelete_host_pers = usage(); DeleteHostData(std::string(), kTemp, kAllClients); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_global_tmp, usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_tmp, usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_pers, usage()); DeleteHostData("foo.com", kTemp, kAllClients); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_global_tmp - 1, usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_tmp - 1, usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_host_pers, usage()); } @@ -1491,35 +1491,35 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultiple) { RegisterClient(client2); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_global_tmp = usage(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_tmp = usage(); GetHostUsage("bar.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_bar_tmp = usage(); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_pers = usage(); GetHostUsage("bar.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_bar_pers = usage(); reset_status_callback_count(); DeleteHostData("foo.com", kTemp, kAllClients); DeleteHostData("bar.com", kTemp, kAllClients); DeleteHostData("foo.com", kTemp, kAllClients); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(3, status_callback_count()); DumpOriginInfoTable(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); typedef OriginInfoTableEntries::const_iterator iterator; for (iterator itr(origin_info_entries().begin()), @@ -1534,24 +1534,24 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultiple) { } GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_global_tmp - (1 + 20 + 4000 + 50000 + 6000 + 80 + 9), usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - (1 + 20 + 50000 + 6000 + 80), usage()); GetHostUsage("bar.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_bar_tmp - (4000 + 9), usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_pers, usage()); GetHostUsage("bar.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_bar_pers, usage()); } @@ -1579,23 +1579,23 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) { RegisterClient(client2); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_global_tmp = usage(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_tmp = usage(); GetHostUsage("bar.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_bar_tmp = usage(); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_pers = usage(); GetHostUsage("bar.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_bar_pers = usage(); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData1); ++i) @@ -1604,18 +1604,18 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData2); ++i) quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, GURL(kData2[i].origin), kData2[i].type); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); reset_status_callback_count(); DeleteOriginData(GURL("http://foo.com/"), kTemp, kAllClients); DeleteOriginData(GURL("http://bar.com/"), kTemp, kAllClients); DeleteOriginData(GURL("http://foo.com/"), kTemp, kAllClients); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(3, status_callback_count()); DumpOriginInfoTable(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); typedef OriginInfoTableEntries::const_iterator iterator; for (iterator itr(origin_info_entries().begin()), @@ -1628,23 +1628,23 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) { } GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_global_tmp - (1 + 4000 + 50000 + 9), usage()); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - (1 + 50000), usage()); GetHostUsage("bar.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_bar_tmp - (4000 + 9), usage()); GetHostUsage("foo.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_pers, usage()); GetHostUsage("bar.com", kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_bar_pers, usage()); } @@ -1668,12 +1668,12 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) { // No matter how we make queries the quota manager tries to cache all // the origins at startup. GetHostUsage("a.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetCachedOrigins(kTemp, &origins); EXPECT_EQ(3U, origins.size()); GetHostUsage("b.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetCachedOrigins(kTemp, &origins); EXPECT_EQ(3U, origins.size()); @@ -1681,7 +1681,7 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) { EXPECT_TRUE(origins.empty()); GetGlobalUsage(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetCachedOrigins(kTemp, &origins); EXPECT_EQ(3U, origins.size()); @@ -1705,29 +1705,29 @@ TEST_F(QuotaManagerTest, NotifyAndLRUOrigin) { GURL origin; GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lru_origin().is_empty()); NotifyStorageAccessed(client, GURL("http://a.com/"), kTemp); GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ("http://a.com/", lru_origin().spec()); NotifyStorageAccessed(client, GURL("http://b.com/"), kPerm); NotifyStorageAccessed(client, GURL("https://a.com/"), kTemp); NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp); GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ("http://a.com/", lru_origin().spec()); DeleteOriginFromDatabase(lru_origin(), kTemp); GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ("https://a.com/", lru_origin().spec()); DeleteOriginFromDatabase(lru_origin(), kTemp); GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ("http://c.com/", lru_origin().spec()); } @@ -1745,7 +1745,7 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) { GURL origin; GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lru_origin().is_empty()); NotifyStorageAccessed(client, GURL("http://a.com/"), kTemp); @@ -1754,19 +1754,19 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) { NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp); GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ("http://a.com/", lru_origin().spec()); // Notify origin http://a.com is in use. NotifyOriginInUse(GURL("http://a.com/")); GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ("https://a.com/", lru_origin().spec()); // Notify origin https://a.com is in use while GetLRUOrigin is running. GetLRUOrigin(kTemp); NotifyOriginInUse(GURL("https://a.com/")); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // Post-filtering must have excluded the returned origin, so we will // see empty result here. EXPECT_TRUE(lru_origin().is_empty()); @@ -1774,7 +1774,7 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) { // Notify access for http://c.com while GetLRUOrigin is running. GetLRUOrigin(kTemp); NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); // Post-filtering must have excluded the returned origin, so we will // see empty result here. EXPECT_TRUE(lru_origin().is_empty()); @@ -1782,7 +1782,7 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) { NotifyOriginNoLongerInUse(GURL("http://a.com/")); NotifyOriginNoLongerInUse(GURL("https://a.com/")); GetLRUOrigin(kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ("http://a.com/", lru_origin().spec()); } @@ -1799,7 +1799,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) { RegisterClient(client); GetOriginsModifiedSince(kTemp, base::Time()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(modified_origins().empty()); EXPECT_EQ(modified_origins_type(), kTemp); @@ -1813,7 +1813,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) { base::Time time3 = client->IncrementMockTime(); GetOriginsModifiedSince(kTemp, time1); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(4U, modified_origins().size()); EXPECT_EQ(modified_origins_type(), kTemp); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData); ++i) { @@ -1822,18 +1822,18 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) { } GetOriginsModifiedSince(kTemp, time2); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(2U, modified_origins().size()); GetOriginsModifiedSince(kTemp, time3); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(modified_origins().empty()); EXPECT_EQ(modified_origins_type(), kTemp); client->ModifyOriginAndNotify(GURL("http://a.com/"), kTemp, 10); GetOriginsModifiedSince(kTemp, time3); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1U, modified_origins().size()); EXPECT_EQ(1U, modified_origins().count(GURL("http://a.com/"))); EXPECT_EQ(modified_origins_type(), kTemp); @@ -1843,10 +1843,10 @@ TEST_F(QuotaManagerTest, DumpQuotaTable) { SetPersistentHostQuota("example1.com", 1); SetPersistentHostQuota("example2.com", 20); SetPersistentHostQuota("example3.com", 300); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); DumpQuotaTable(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const QuotaTableEntry kEntries[] = { QuotaTableEntry("example1.com", kPerm, 1), @@ -1882,10 +1882,10 @@ TEST_F(QuotaManagerTest, DumpOriginInfoTable) { QuotaClient::kUnknown, GURL("http://example.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); DumpOriginInfoTable(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); typedef std::pair<GURL, StorageType> TypedOrigin; typedef std::pair<TypedOrigin, int> Entry; @@ -1913,12 +1913,12 @@ TEST_F(QuotaManagerTest, DumpOriginInfoTable) { TEST_F(QuotaManagerTest, QuotaForEmptyHost) { GetPersistentHostQuota(std::string()); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, quota()); SetPersistentHostQuota(std::string(), 10); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaErrorNotSupported, status()); } @@ -1949,32 +1949,32 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleOrigin) { RegisterClient(client4); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_tmp = usage(); DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kFileSystem); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 1, usage()); DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kAppcache); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage()); DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kDatabase); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage()); DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kIndexedDatabase); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); } @@ -2005,31 +2005,31 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleHost) { RegisterClient(client4); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_tmp = usage(); DeleteHostData("foo.com", kTemp, QuotaClient::kFileSystem); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 1, usage()); DeleteHostData("foo.com", kTemp, QuotaClient::kAppcache); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage()); DeleteHostData("foo.com", kTemp, QuotaClient::kDatabase); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage()); DeleteHostData("foo.com", kTemp, QuotaClient::kIndexedDatabase); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); } @@ -2060,21 +2060,21 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleOrigin) { RegisterClient(client4); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_tmp = usage(); DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kFileSystem | QuotaClient::kDatabase); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage()); DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kAppcache | QuotaClient::kIndexedDatabase); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); } @@ -2105,21 +2105,21 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleHost) { RegisterClient(client4); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); const int64 predelete_foo_tmp = usage(); DeleteHostData("foo.com", kTemp, QuotaClient::kFileSystem | QuotaClient::kAppcache); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage()); DeleteHostData("foo.com", kTemp, QuotaClient::kDatabase | QuotaClient::kIndexedDatabase); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); GetHostUsage("foo.com", kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); } @@ -2134,14 +2134,14 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Incognito) { QuotaClient::kFileSystem)); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(80, usage()); EXPECT_EQ(0, quota()); SetTemporaryGlobalQuota(100); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); EXPECT_LE(std::min(static_cast<int64>(100 / kPerHostTemporaryPortion), @@ -2149,13 +2149,13 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Incognito) { mock_special_storage_policy()->AddUnlimited(GURL("http://foo.com/")); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(80, usage()); EXPECT_EQ(QuotaManager::kIncognitoDefaultQuotaLimit, quota()); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(QuotaManager::kIncognitoDefaultQuotaLimit, quota()); diff --git a/chromium/webkit/browser/quota/quota_temporary_storage_evictor_unittest.cc b/chromium/webkit/browser/quota/quota_temporary_storage_evictor_unittest.cc index e540a98df04..941facf5267 100644 --- a/chromium/webkit/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/chromium/webkit/browser/quota/quota_temporary_storage_evictor_unittest.cc @@ -10,8 +10,8 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/quota/mock_storage_client.h" #include "webkit/browser/quota/quota_manager.h" @@ -131,7 +131,7 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler { base::Closure task_for_get_usage_and_quota_; }; -} // anonymous namespace +} // namespace class QuotaTemporaryStorageEvictorTest : public testing::Test { public: @@ -150,7 +150,7 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test { virtual void TearDown() { temporary_storage_evictor_.reset(); quota_eviction_handler_.reset(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void TaskForRepeatedEvictionTest( @@ -234,7 +234,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) { EXPECT_EQ(3000 + 200 + 500, quota_eviction_handler()->GetUsage()); set_repeated_eviction(false); temporary_storage_evictor()->Start(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(200 + 500, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_evicting_origin); @@ -254,7 +254,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) { EXPECT_EQ(20 + 2900 + 450 + 400, quota_eviction_handler()->GetUsage()); set_repeated_eviction(false); temporary_storage_evictor()->Start(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(450 + 400, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_evicting_origin); @@ -286,7 +286,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionTest) { initial_total_size - d_size + e_size - c_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); temporary_storage_evictor()->Start(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(initial_total_size - d_size + e_size - c_size - b_size, quota_eviction_handler()->GetUsage()); EXPECT_EQ(5, num_get_usage_and_quota_for_eviction()); @@ -318,7 +318,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionSkippedTest) { EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); set_repeated_eviction(true); temporary_storage_evictor()->Start(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(initial_total_size - d_size, quota_eviction_handler()->GetUsage()); EXPECT_EQ(4, num_get_usage_and_quota_for_eviction()); @@ -352,7 +352,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) { initial_total_size - d_size + e_size - b_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); temporary_storage_evictor()->Start(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(initial_total_size - d_size + e_size - b_size - a_size, quota_eviction_handler()->GetUsage()); EXPECT_EQ(5, num_get_usage_and_quota_for_eviction()); @@ -374,7 +374,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceNonEvictionTest) { reset_min_available_disk_space_to_start_eviction(); set_repeated_eviction(false); temporary_storage_evictor()->Start(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(414 + 450, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_evicting_origin); @@ -397,7 +397,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) { default_min_available_disk_space_to_start_eviction()); set_repeated_eviction(false); temporary_storage_evictor()->Start(); - base::MessageLoop::current()->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(150 + 300, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_evicting_origin); diff --git a/chromium/webkit/browser/quota/usage_tracker.cc b/chromium/webkit/browser/quota/usage_tracker.cc index 4bf64880c3c..57b5e0d24ea 100644 --- a/chromium/webkit/browser/quota/usage_tracker.cc +++ b/chromium/webkit/browser/quota/usage_tracker.cc @@ -78,8 +78,10 @@ UsageTracker::UsageTracker(const QuotaClientList& clients, for (QuotaClientList::const_iterator iter = clients.begin(); iter != clients.end(); ++iter) { - client_tracker_map_[(*iter)->id()] = - new ClientUsageTracker(this, *iter, type, special_storage_policy); + if ((*iter)->DoesSupport(type)) { + client_tracker_map_[(*iter)->id()] = + new ClientUsageTracker(this, *iter, type, special_storage_policy); + } } } diff --git a/chromium/webkit/browser/quota/usage_tracker_unittest.cc b/chromium/webkit/browser/quota/usage_tracker_unittest.cc index 985db2d8258..4eaf68b1b2f 100644 --- a/chromium/webkit/browser/quota/usage_tracker_unittest.cc +++ b/chromium/webkit/browser/quota/usage_tracker_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/bind.h" -#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "net/base/net_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/browser/quota/mock_special_storage_policy.h" @@ -89,6 +89,10 @@ class MockQuotaClient : public QuotaClient { FROM_HERE, base::Bind(callback, kQuotaStatusOk)); } + virtual bool DoesSupport(quota::StorageType type) const OVERRIDE { + return type == quota::kStorageTypeTemporary; + } + int64 GetUsage(const GURL& origin) { UsageMap::const_iterator found = usage_map_.find(origin); if (found == usage_map_.end()) @@ -129,7 +133,7 @@ class UsageTrackerTest : public testing::Test { void UpdateUsage(const GURL& origin, int64 delta) { quota_client_.UpdateUsage(origin, delta); usage_tracker_.UpdateUsageCache(quota_client_.id(), origin, delta); - message_loop_.RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void UpdateUsageWithoutNotification(const GURL& origin, int64 delta) { @@ -140,7 +144,7 @@ class UsageTrackerTest : public testing::Test { bool done = false; usage_tracker_.GetGlobalLimitedUsage(base::Bind( &DidGetUsage, &done, limited_usage)); - message_loop_.RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(done); } @@ -150,7 +154,7 @@ class UsageTrackerTest : public testing::Test { usage_tracker_.GetGlobalUsage(base::Bind( &DidGetGlobalUsage, &done, usage, unlimited_usage)); - message_loop_.RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(done); } @@ -158,7 +162,7 @@ class UsageTrackerTest : public testing::Test { void GetHostUsage(const std::string& host, int64* usage) { bool done = false; usage_tracker_.GetHostUsage(host, base::Bind(&DidGetUsage, &done, usage)); - message_loop_.RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(done); } |