Chromium Code Reviews| Index: content/browser/indexed_db/indexed_db_backing_store.cc |
| diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc |
| index f19e2e8f9949cca126ea2532a3c5d7100ea2d222..0a83a914f84de9848c8354a09911a9ae64ea6edd 100644 |
| --- a/content/browser/indexed_db/indexed_db_backing_store.cc |
| +++ b/content/browser/indexed_db/indexed_db_backing_store.cc |
| @@ -2160,17 +2160,18 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl |
| WriteDescriptorVec; |
| ChainedBlobWriterImpl( |
| int64 database_id, |
| - IndexedDBBackingStore* backingStore, |
| + IndexedDBBackingStore* backing_store, |
| WriteDescriptorVec& blobs, |
| scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback) |
| : waiting_for_callback_(false), |
| database_id_(database_id), |
| - backing_store_(backingStore), |
| + backing_store_(backing_store), |
| callback_(callback), |
| aborted_(false) { |
| blobs_.swap(blobs); |
| iter_ = blobs_.begin(); |
| - WriteNextFile(); |
| + backing_store->task_runner()->PostTask( |
| + FROM_HERE, base::Bind(&ChainedBlobWriterImpl::WriteNextFile, this)); |
| } |
| virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE { |
| @@ -2179,7 +2180,6 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl |
| virtual void ReportWriteCompletion(bool succeeded, |
| int64 bytes_written) OVERRIDE { |
| - // TODO(ericu): Check bytes_written against the blob's snapshot value. |
| DCHECK(waiting_for_callback_); |
| DCHECK(!succeeded || bytes_written >= 0); |
| waiting_for_callback_ = false; |
| @@ -2190,10 +2190,14 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl |
| self_ref_ = NULL; |
| return; |
| } |
| - if (succeeded) |
| + if (iter_->size() != -1 && iter_->size() != bytes_written) |
| + succeeded = false; |
| + if (succeeded) { |
| + ++iter_; |
| WriteNextFile(); |
| - else |
| + } else { |
| callback_->Run(false); |
| + } |
| } |
| virtual void Abort() OVERRIDE { |
| @@ -2219,7 +2223,6 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl |
| return; |
| } |
| waiting_for_callback_ = true; |
| - ++iter_; |
| } |
| } |
| @@ -2244,17 +2247,17 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback, |
| base::TaskRunner* task_runner) |
| : chained_blob_writer_(chained_blob_writer), |
| task_runner_(task_runner), |
| - bytes_written_(-1) {} |
| + bytes_written_(0) {} |
| void Run(base::File::Error rv, |
| int64 bytes, |
| FileWriterDelegate::WriteProgressStatus write_status) { |
| + DCHECK_GE(bytes, 0); |
| + bytes_written_ += bytes; |
| if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING) |
| return; // We don't care about progress events. |
| if (rv == base::File::FILE_OK) { |
| - DCHECK_GE(bytes, 0); |
| DCHECK_EQ(write_status, FileWriterDelegate::SUCCESS_COMPLETED); |
| - bytes_written_ = bytes; |
| } else { |
| DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED || |
| write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED); |
| @@ -2320,8 +2323,15 @@ bool IndexedDBBackingStore::WriteBlobFile( |
| base::File::Info info; |
| if (base::GetFileInfo(descriptor.file_path(), &info)) { |
| - // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor |
| - // to include snapshot date and file size, and check both. |
| + if (descriptor.size() != -1) { |
| + if (descriptor.size() != info.size) |
| + return false; |
| + // The round-trip can be lossy; round to nearest millisecond. |
|
jsbell
2014/06/18 23:26:10
This is because we've asked the filesystem for the
ericu
2014/06/18 23:28:44
I believe that's the case. I've hit this before i
|
| + int64 delta = (descriptor.last_modified() - |
| + info.last_modified).InMilliseconds(); |
| + if (std::abs(delta) > 1) |
| + return false; |
| + } |
| if (!base::TouchFile(path, info.last_accessed, info.last_modified)) { |
| // TODO(ericu): Complain quietly; timestamp's probably not vital. |
| } |
| @@ -3876,10 +3886,15 @@ leveldb::Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction( |
| journal.push_back(journal_entry); |
| if (info_iter->is_file()) { |
| new_files_to_write->push_back( |
| - WriteDescriptor(info_iter->file_path(), next_blob_key)); |
| + WriteDescriptor(info_iter->file_path(), |
| + next_blob_key, |
| + info_iter->size(), |
| + info_iter->last_modified())); |
| } else { |
| - new_files_to_write->push_back(WriteDescriptor( |
| - getURLFromUUID(info_iter->uuid()), next_blob_key)); |
| + new_files_to_write->push_back( |
| + WriteDescriptor(getURLFromUUID(info_iter->uuid()), |
| + next_blob_key, |
| + info_iter->size())); |
| } |
| info_iter->set_key(next_blob_key); |
| new_blob_keys.push_back(&*info_iter); |
| @@ -4066,7 +4081,8 @@ class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper |
| : transaction_(transaction), callback_(callback) {} |
| virtual void Run(bool succeeded) OVERRIDE { |
| callback_->Run(succeeded); |
| - transaction_->chained_blob_writer_ = NULL; |
| + if (succeeded) // Else it's already been deleted during rollback. |
| + transaction_->chained_blob_writer_ = NULL; |
| } |
| private: |
| @@ -4213,12 +4229,21 @@ void IndexedDBBackingStore::Transaction::PutBlobInfo( |
| IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
| const GURL& url, |
| - int64_t key) |
| - : is_file_(false), url_(url), key_(key) {} |
| + int64_t key, |
| + int64_t size) |
| + : is_file_(false), url_(url), key_(key), size_(size) { |
| +} |
| IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
| const FilePath& file_path, |
| - int64_t key) |
| - : is_file_(true), file_path_(file_path), key_(key) {} |
| + int64_t key, |
| + int64_t size, |
| + base::Time last_modified) |
| + : is_file_(true), |
| + file_path_(file_path), |
| + key_(key), |
| + size_(size), |
| + last_modified_(last_modified) { |
| +} |
| } // namespace content |