diff options
author | cmumford <cmumford@chromium.org> | 2015-03-13 19:39:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-14 02:39:58 +0000 |
commit | 3a61739491730a1acd96c09a6ae7b79825eb445f (patch) | |
tree | 1afa956d9d8c9f922cff38e997b06a06b22a9e7e /content/browser/indexed_db | |
parent | e3b16f181ab489621ca9866f472e012e33b6e9c0 (diff) | |
download | chromium_src-3a61739491730a1acd96c09a6ae7b79825eb445f.zip chromium_src-3a61739491730a1acd96c09a6ae7b79825eb445f.tar.gz chromium_src-3a61739491730a1acd96c09a6ae7b79825eb445f.tar.bz2 |
IndexedDB: Fixed support for empty blobs.
This solution allows empty blobs (and files) to be created.
Most tests for this change are Blink layout tests, so will land
in a separate CL.
BUG=399323
Review URL: https://codereview.chromium.org/942633004
Cr-Commit-Position: refs/heads/master@{#320636}
Diffstat (limited to 'content/browser/indexed_db')
4 files changed, 72 insertions, 2 deletions
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index 4ae9ed4..22bd411 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc @@ -2339,8 +2339,12 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback, } bool success = write_status == FileWriterDelegate::SUCCESS_COMPLETED; - - if (success && !last_modified_.is_null()) { + if (success && !bytes_written_) { + // LocalFileStreamWriter only creates a file if data is actually written. + // If none was then create one now. + task_runner_->PostTask( + FROM_HERE, base::Bind(&LocalWriteClosure::CreateEmptyFile, this)); + } else if (success && !last_modified_.is_null()) { task_runner_->PostTask( FROM_HERE, base::Bind(&LocalWriteClosure::UpdateTimeStamp, this)); } else { @@ -2403,6 +2407,20 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback, chained_blob_writer_->ReportWriteCompletion(true, bytes_written_); } + // Create an empty file. + void CreateEmptyFile() { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + base::File file(file_path_, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + bool success = file.created(); + if (success && !last_modified_.is_null() && + !file.SetTimes(last_modified_, last_modified_)) { + // TODO(cmumford): Complain quietly; timestamp's probably not vital. + } + file.Close(); + chained_blob_writer_->ReportWriteCompletion(success, bytes_written_); + } + scoped_refptr<IndexedDBBackingStore::Transaction::ChainedBlobWriter> chained_blob_writer_; scoped_refptr<base::SequencedTaskRunner> task_runner_; diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index fbe35bf..9bfad25 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc @@ -150,6 +150,22 @@ class IndexedDBBrowserTest : public ContentBrowserTest { return disk_usage_; } + virtual int RequestBlobFileCount() { + PostTaskAndReplyWithResult( + GetContext()->TaskRunner(), FROM_HERE, + base::Bind(&IndexedDBContextImpl::GetOriginBlobFileCount, GetContext(), + GURL("file:///")), + base::Bind(&IndexedDBBrowserTest::DidGetBlobFileCount, this)); + scoped_refptr<base::ThreadTestHelper> helper( + new base::ThreadTestHelper(BrowserMainLoop::GetInstance() + ->indexed_db_thread() + ->message_loop_proxy())); + EXPECT_TRUE(helper->Run()); + // Wait for DidGetBlobFileCount to be called. + base::MessageLoop::current()->RunUntilIdle(); + return blob_file_count_; + } + private: static MockBrowserTestIndexedDBClassFactory* GetTestClassFactory() { static ::base::LazyInstance<MockBrowserTestIndexedDBClassFactory>::Leaky @@ -165,7 +181,10 @@ class IndexedDBBrowserTest : public ContentBrowserTest { disk_usage_ = bytes; } + virtual void DidGetBlobFileCount(int count) { blob_file_count_ = count; } + int64 disk_usage_; + int blob_file_count_ = 0; DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTest); }; @@ -405,6 +424,25 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) { SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html")); } +IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, EmptyBlob) { + // First delete all IDB's for the test origin + GetContext()->TaskRunner()->PostTask( + FROM_HERE, base::Bind(&IndexedDBContextImpl::DeleteForOrigin, + GetContext(), GURL("file:///"))); + EXPECT_EQ(0, RequestBlobFileCount()); // Start with no blob files. + const GURL test_url = GetTestUrl("indexeddb", "empty_blob.html"); + // For some reason Android's futimes fails (EPERM) in this test. Do not assert + // file times on Android, but do so on other platforms. crbug.com/467247 + // TODO(cmumford): Figure out why this is the case and fix if possible. +#if defined(OS_ANDROID) + SimpleTest(GURL(test_url.spec() + "#ignoreTimes")); +#else + SimpleTest(GURL(test_url.spec())); +#endif + // Test stores one blob and one file to disk, so expect two files. + EXPECT_EQ(2, RequestBlobFileCount()); +} + IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, BlobDidAck) { SimpleTest(GetTestUrl("indexeddb", "blob_did_ack.html")); // Wait for idle so that the blob ack has time to be received/processed by diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc index f1357fd..2a6a4b4 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.cc +++ b/content/browser/indexed_db/indexed_db_context_impl.cc @@ -273,6 +273,19 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() { return list.release(); } +int IndexedDBContextImpl::GetOriginBlobFileCount(const GURL& origin_url) { + DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); + int count = 0; + base::FileEnumerator file_enumerator( + GetBlobPath(storage::GetIdentifierFromOrigin(origin_url)), true, + base::FileEnumerator::FILES); + for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty(); + file_path = file_enumerator.Next()) { + count++; + } + return count; +} + int64 IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); if (data_path_.empty() || !IsInOriginSet(origin_url)) diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h index da2878b..2955a3a 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.h +++ b/content/browser/indexed_db/indexed_db_context_impl.h @@ -101,6 +101,7 @@ class CONTENT_EXPORT IndexedDBContextImpl return set->find(origin_url) != set->end(); } size_t GetConnectionCount(const GURL& origin_url); + int GetOriginBlobFileCount(const GURL& origin_url); // For unit tests allow to override the |data_path_|. void set_data_path_for_testing(const base::FilePath& data_path) { |