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

Side by Side Diff: content/browser/indexed_db/indexed_db_backing_store.cc

Issue 333533002: Check File snapshots and Blob byte counts when writing to IDB (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Build fix Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_backing_store.h" 5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
(...skipping 2142 matching lines...) Expand 10 before | Expand all | Expand 10 after
2153 return s; 2153 return s;
2154 } 2154 }
2155 2155
2156 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl 2156 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
2157 : public IndexedDBBackingStore::Transaction::ChainedBlobWriter { 2157 : public IndexedDBBackingStore::Transaction::ChainedBlobWriter {
2158 public: 2158 public:
2159 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec 2159 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
2160 WriteDescriptorVec; 2160 WriteDescriptorVec;
2161 ChainedBlobWriterImpl( 2161 ChainedBlobWriterImpl(
2162 int64 database_id, 2162 int64 database_id,
2163 IndexedDBBackingStore* backingStore, 2163 IndexedDBBackingStore* backing_store,
2164 WriteDescriptorVec& blobs, 2164 WriteDescriptorVec& blobs,
2165 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback) 2165 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
2166 : waiting_for_callback_(false), 2166 : waiting_for_callback_(false),
2167 database_id_(database_id), 2167 database_id_(database_id),
2168 backing_store_(backingStore), 2168 backing_store_(backing_store),
2169 callback_(callback), 2169 callback_(callback),
2170 aborted_(false) { 2170 aborted_(false) {
2171 blobs_.swap(blobs); 2171 blobs_.swap(blobs);
2172 iter_ = blobs_.begin(); 2172 iter_ = blobs_.begin();
2173 WriteNextFile(); 2173 backing_store->task_runner()->PostTask(
2174 FROM_HERE, base::Bind(&ChainedBlobWriterImpl::WriteNextFile, this));
2174 } 2175 }
2175 2176
2176 virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE { 2177 virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE {
2177 delegate_.reset(delegate.release()); 2178 delegate_.reset(delegate.release());
2178 } 2179 }
2179 2180
2180 virtual void ReportWriteCompletion(bool succeeded, 2181 virtual void ReportWriteCompletion(bool succeeded,
2181 int64 bytes_written) OVERRIDE { 2182 int64 bytes_written) OVERRIDE {
2182 // TODO(ericu): Check bytes_written against the blob's snapshot value.
2183 DCHECK(waiting_for_callback_); 2183 DCHECK(waiting_for_callback_);
2184 DCHECK(!succeeded || bytes_written >= 0); 2184 DCHECK(!succeeded || bytes_written >= 0);
2185 waiting_for_callback_ = false; 2185 waiting_for_callback_ = false;
2186 if (delegate_.get()) // Only present for Blob, not File. 2186 if (delegate_.get()) // Only present for Blob, not File.
2187 content::BrowserThread::DeleteSoon( 2187 content::BrowserThread::DeleteSoon(
2188 content::BrowserThread::IO, FROM_HERE, delegate_.release()); 2188 content::BrowserThread::IO, FROM_HERE, delegate_.release());
2189 if (aborted_) { 2189 if (aborted_) {
2190 self_ref_ = NULL; 2190 self_ref_ = NULL;
2191 return; 2191 return;
2192 } 2192 }
2193 if (succeeded) 2193 if (iter_->size() != -1 && iter_->size() != bytes_written)
2194 succeeded = false;
2195 if (succeeded) {
2196 ++iter_;
2194 WriteNextFile(); 2197 WriteNextFile();
2195 else 2198 } else {
2196 callback_->Run(false); 2199 callback_->Run(false);
2200 }
2197 } 2201 }
2198 2202
2199 virtual void Abort() OVERRIDE { 2203 virtual void Abort() OVERRIDE {
2200 if (!waiting_for_callback_) 2204 if (!waiting_for_callback_)
2201 return; 2205 return;
2202 self_ref_ = this; 2206 self_ref_ = this;
2203 aborted_ = true; 2207 aborted_ = true;
2204 } 2208 }
2205 2209
2206 private: 2210 private:
2207 virtual ~ChainedBlobWriterImpl() {} 2211 virtual ~ChainedBlobWriterImpl() {}
2208 2212
2209 void WriteNextFile() { 2213 void WriteNextFile() {
2210 DCHECK(!waiting_for_callback_); 2214 DCHECK(!waiting_for_callback_);
2211 DCHECK(!aborted_); 2215 DCHECK(!aborted_);
2212 if (iter_ == blobs_.end()) { 2216 if (iter_ == blobs_.end()) {
2213 DCHECK(!self_ref_); 2217 DCHECK(!self_ref_);
2214 callback_->Run(true); 2218 callback_->Run(true);
2215 return; 2219 return;
2216 } else { 2220 } else {
2217 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) { 2221 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
2218 callback_->Run(false); 2222 callback_->Run(false);
2219 return; 2223 return;
2220 } 2224 }
2221 waiting_for_callback_ = true; 2225 waiting_for_callback_ = true;
2222 ++iter_;
2223 } 2226 }
2224 } 2227 }
2225 2228
2226 bool waiting_for_callback_; 2229 bool waiting_for_callback_;
2227 scoped_refptr<ChainedBlobWriterImpl> self_ref_; 2230 scoped_refptr<ChainedBlobWriterImpl> self_ref_;
2228 WriteDescriptorVec blobs_; 2231 WriteDescriptorVec blobs_;
2229 WriteDescriptorVec::const_iterator iter_; 2232 WriteDescriptorVec::const_iterator iter_;
2230 int64 database_id_; 2233 int64 database_id_;
2231 IndexedDBBackingStore* backing_store_; 2234 IndexedDBBackingStore* backing_store_;
2232 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_; 2235 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
2233 scoped_ptr<FileWriterDelegate> delegate_; 2236 scoped_ptr<FileWriterDelegate> delegate_;
2234 bool aborted_; 2237 bool aborted_;
2235 2238
2236 DISALLOW_COPY_AND_ASSIGN(ChainedBlobWriterImpl); 2239 DISALLOW_COPY_AND_ASSIGN(ChainedBlobWriterImpl);
2237 }; 2240 };
2238 2241
2239 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback, 2242 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
2240 public base::RefCounted<LocalWriteClosure> { 2243 public base::RefCounted<LocalWriteClosure> {
2241 public: 2244 public:
2242 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter* 2245 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
2243 chained_blob_writer, 2246 chained_blob_writer,
2244 base::TaskRunner* task_runner) 2247 base::TaskRunner* task_runner)
2245 : chained_blob_writer_(chained_blob_writer), 2248 : chained_blob_writer_(chained_blob_writer),
2246 task_runner_(task_runner), 2249 task_runner_(task_runner),
2247 bytes_written_(-1) {} 2250 bytes_written_(0) {}
2248 2251
2249 void Run(base::File::Error rv, 2252 void Run(base::File::Error rv,
2250 int64 bytes, 2253 int64 bytes,
2251 FileWriterDelegate::WriteProgressStatus write_status) { 2254 FileWriterDelegate::WriteProgressStatus write_status) {
2255 DCHECK_GE(bytes, 0);
2256 bytes_written_ += bytes;
2252 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING) 2257 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
2253 return; // We don't care about progress events. 2258 return; // We don't care about progress events.
2254 if (rv == base::File::FILE_OK) { 2259 if (rv == base::File::FILE_OK) {
2255 DCHECK_GE(bytes, 0);
2256 DCHECK_EQ(write_status, FileWriterDelegate::SUCCESS_COMPLETED); 2260 DCHECK_EQ(write_status, FileWriterDelegate::SUCCESS_COMPLETED);
2257 bytes_written_ = bytes;
2258 } else { 2261 } else {
2259 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED || 2262 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
2260 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED); 2263 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
2261 } 2264 }
2262 task_runner_->PostTask( 2265 task_runner_->PostTask(
2263 FROM_HERE, 2266 FROM_HERE,
2264 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner, 2267 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner,
2265 this, 2268 this,
2266 write_status == FileWriterDelegate::SUCCESS_COMPLETED)); 2269 write_status == FileWriterDelegate::SUCCESS_COMPLETED));
2267 } 2270 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2313 2316
2314 FilePath path = GetBlobFileName(database_id, descriptor.key()); 2317 FilePath path = GetBlobFileName(database_id, descriptor.key());
2315 2318
2316 if (descriptor.is_file()) { 2319 if (descriptor.is_file()) {
2317 DCHECK(!descriptor.file_path().empty()); 2320 DCHECK(!descriptor.file_path().empty());
2318 if (!base::CopyFile(descriptor.file_path(), path)) 2321 if (!base::CopyFile(descriptor.file_path(), path))
2319 return false; 2322 return false;
2320 2323
2321 base::File::Info info; 2324 base::File::Info info;
2322 if (base::GetFileInfo(descriptor.file_path(), &info)) { 2325 if (base::GetFileInfo(descriptor.file_path(), &info)) {
2323 // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor 2326 if (descriptor.size() != -1) {
2324 // to include snapshot date and file size, and check both. 2327 if (descriptor.size() != info.size)
2328 return false;
2329 // 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
2330 int64 delta = (descriptor.last_modified() -
2331 info.last_modified).InMilliseconds();
2332 if (std::abs(delta) > 1)
2333 return false;
2334 }
2325 if (!base::TouchFile(path, info.last_accessed, info.last_modified)) { 2335 if (!base::TouchFile(path, info.last_accessed, info.last_modified)) {
2326 // TODO(ericu): Complain quietly; timestamp's probably not vital. 2336 // TODO(ericu): Complain quietly; timestamp's probably not vital.
2327 } 2337 }
2328 } else { 2338 } else {
2329 // TODO(ericu): Complain quietly; timestamp's probably not vital. 2339 // TODO(ericu): Complain quietly; timestamp's probably not vital.
2330 } 2340 }
2331 2341
2332 task_runner_->PostTask( 2342 task_runner_->PostTask(
2333 FROM_HERE, 2343 FROM_HERE,
2334 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion, 2344 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
(...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after
3869 int64 next_blob_key = -1; 3879 int64 next_blob_key = -1;
3870 bool result = GetBlobKeyGeneratorCurrentNumber( 3880 bool result = GetBlobKeyGeneratorCurrentNumber(
3871 pre_transaction.get(), database_id_, &next_blob_key); 3881 pre_transaction.get(), database_id_, &next_blob_key);
3872 if (!result || next_blob_key < 0) 3882 if (!result || next_blob_key < 0)
3873 return InternalInconsistencyStatus(); 3883 return InternalInconsistencyStatus();
3874 BlobJournalEntryType journal_entry = 3884 BlobJournalEntryType journal_entry =
3875 std::make_pair(database_id_, next_blob_key); 3885 std::make_pair(database_id_, next_blob_key);
3876 journal.push_back(journal_entry); 3886 journal.push_back(journal_entry);
3877 if (info_iter->is_file()) { 3887 if (info_iter->is_file()) {
3878 new_files_to_write->push_back( 3888 new_files_to_write->push_back(
3879 WriteDescriptor(info_iter->file_path(), next_blob_key)); 3889 WriteDescriptor(info_iter->file_path(),
3890 next_blob_key,
3891 info_iter->size(),
3892 info_iter->last_modified()));
3880 } else { 3893 } else {
3881 new_files_to_write->push_back(WriteDescriptor( 3894 new_files_to_write->push_back(
3882 getURLFromUUID(info_iter->uuid()), next_blob_key)); 3895 WriteDescriptor(getURLFromUUID(info_iter->uuid()),
3896 next_blob_key,
3897 info_iter->size()));
3883 } 3898 }
3884 info_iter->set_key(next_blob_key); 3899 info_iter->set_key(next_blob_key);
3885 new_blob_keys.push_back(&*info_iter); 3900 new_blob_keys.push_back(&*info_iter);
3886 result = UpdateBlobKeyGeneratorCurrentNumber( 3901 result = UpdateBlobKeyGeneratorCurrentNumber(
3887 pre_transaction.get(), database_id_, next_blob_key + 1); 3902 pre_transaction.get(), database_id_, next_blob_key + 1);
3888 if (!result) 3903 if (!result)
3889 return InternalInconsistencyStatus(); 3904 return InternalInconsistencyStatus();
3890 } 3905 }
3891 BlobEntryKey blob_entry_key; 3906 BlobEntryKey blob_entry_key;
3892 StringPiece key_piece(iter->second->key()); 3907 StringPiece key_piece(iter->second->key());
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
4059 4074
4060 4075
4061 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper 4076 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
4062 : public IndexedDBBackingStore::BlobWriteCallback { 4077 : public IndexedDBBackingStore::BlobWriteCallback {
4063 public: 4078 public:
4064 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, 4079 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
4065 scoped_refptr<BlobWriteCallback> callback) 4080 scoped_refptr<BlobWriteCallback> callback)
4066 : transaction_(transaction), callback_(callback) {} 4081 : transaction_(transaction), callback_(callback) {}
4067 virtual void Run(bool succeeded) OVERRIDE { 4082 virtual void Run(bool succeeded) OVERRIDE {
4068 callback_->Run(succeeded); 4083 callback_->Run(succeeded);
4069 transaction_->chained_blob_writer_ = NULL; 4084 if (succeeded) // Else it's already been deleted during rollback.
4085 transaction_->chained_blob_writer_ = NULL;
4070 } 4086 }
4071 4087
4072 private: 4088 private:
4073 virtual ~BlobWriteCallbackWrapper() {} 4089 virtual ~BlobWriteCallbackWrapper() {}
4074 friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>; 4090 friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>;
4075 4091
4076 IndexedDBBackingStore::Transaction* transaction_; 4092 IndexedDBBackingStore::Transaction* transaction_;
4077 scoped_refptr<BlobWriteCallback> callback_; 4093 scoped_refptr<BlobWriteCallback> callback_;
4078 4094
4079 DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper); 4095 DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
4206 record = it->second; 4222 record = it->second;
4207 } 4223 }
4208 DCHECK_EQ(record->object_store_id(), object_store_id); 4224 DCHECK_EQ(record->object_store_id(), object_store_id);
4209 record->SetBlobInfo(blob_info); 4225 record->SetBlobInfo(blob_info);
4210 record->SetHandles(handles); 4226 record->SetHandles(handles);
4211 DCHECK(!handles || !handles->size()); 4227 DCHECK(!handles || !handles->size());
4212 } 4228 }
4213 4229
4214 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( 4230 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
4215 const GURL& url, 4231 const GURL& url,
4216 int64_t key) 4232 int64_t key,
4217 : is_file_(false), url_(url), key_(key) {} 4233 int64_t size)
4234 : is_file_(false), url_(url), key_(key), size_(size) {
4235 }
4218 4236
4219 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( 4237 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
4220 const FilePath& file_path, 4238 const FilePath& file_path,
4221 int64_t key) 4239 int64_t key,
4222 : is_file_(true), file_path_(file_path), key_(key) {} 4240 int64_t size,
4241 base::Time last_modified)
4242 : is_file_(true),
4243 file_path_(file_path),
4244 key_(key),
4245 size_(size),
4246 last_modified_(last_modified) {
4247 }
4223 4248
4224 } // namespace content 4249 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698