Chromium Code Reviews| Index: content/browser/indexed_db/indexed_db_transaction.cc |
| diff --git a/content/browser/indexed_db/indexed_db_transaction.cc b/content/browser/indexed_db/indexed_db_transaction.cc |
| index 457a7807726c54bac4326ca933793ec79c38d5d4..fe29ef70a201cf7af92b160ba4dfad3a8c2b66d1 100644 |
| --- a/content/browser/indexed_db/indexed_db_transaction.cc |
| +++ b/content/browser/indexed_db/indexed_db_transaction.cc |
| @@ -88,7 +88,7 @@ IndexedDBTransaction::~IndexedDBTransaction() { |
| void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type, |
| Operation task) { |
| - if (state_ == FINISHED) |
| + if (IsStatePastStarted()) |
|
jsbell
2014/05/28 21:29:15
Since Abort() is synchronous, should be able to DC
ericu
2014/05/28 22:50:42
Does the front end guarantee that we never get any
jsbell
2014/05/28 23:35:18
Yes; the front-end tries to commit when it goes in
|
| return; |
| timeout_timer_.Stop(); |
| @@ -206,14 +206,43 @@ void IndexedDBTransaction::Start() { |
| RunTasksIfStarted(); |
| } |
| +class BlobWriteCallbackImpl : public IndexedDBBackingStore::BlobWriteCallback { |
| + public: |
| + BlobWriteCallbackImpl(scoped_refptr<IndexedDBTransaction> transaction) |
| + : transaction_(transaction) {} |
| + virtual void Run(bool succeeded) OVERRIDE { |
| + transaction_->BlobWriteComplete(succeeded); |
| + } |
| + |
| + protected: |
| + virtual ~BlobWriteCallbackImpl() {} |
| + |
| + private: |
| + scoped_refptr<IndexedDBTransaction> transaction_; |
| +}; |
| + |
| +void IndexedDBTransaction::BlobWriteComplete(bool success) { |
| + IDB_TRACE("IndexedDBTransaction::BlobWriteComplete"); |
| + if (state_ == FINISHED) // aborted |
| + return; |
| + DCHECK_EQ(state_, COMMITTING); |
| + if (success) |
| + CommitPhaseTwo(); |
| + else |
| + Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError, |
| + "Failed to write blobs.")); |
| +} |
| + |
| void IndexedDBTransaction::Commit() { |
| IDB_TRACE("IndexedDBTransaction::Commit"); |
| // In multiprocess ports, front-end may have requested a commit but |
| // an abort has already been initiated asynchronously by the |
| // back-end. |
| - if (state_ == FINISHED) |
| + if (IsStatePastStarted()) { |
| + DCHECK(state_ == FINISHED); |
| return; |
| + } |
| DCHECK(!used_ || state_ == STARTED); |
| commit_pending_ = true; |
| @@ -224,6 +253,28 @@ void IndexedDBTransaction::Commit() { |
| if (HasPendingTasks()) |
| return; |
| + state_ = COMMITTING; |
| + |
| + if (!used_) |
| + CommitPhaseTwo(); |
| + else { |
| + scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback( |
| + new BlobWriteCallbackImpl(this)); |
| + // CommitPhaseOne will call the callback synchronously if there are no blobs |
| + // to write. |
| + if (!transaction_->CommitPhaseOne(callback).ok()) |
| + Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError, |
| + "Error processing blob journal.")); |
| + } |
| +} |
| + |
| +void IndexedDBTransaction::CommitPhaseTwo() { |
| + // Abort may have been called just as the blob write completed. |
| + if (state_ == FINISHED) |
| + return; |
| + |
| + DCHECK_EQ(state_, COMMITTING); |
| + |
| // The last reference to this object may be released while performing the |
| // commit steps below. We therefore take a self reference to keep ourselves |
| // alive while executing this method. |
| @@ -233,7 +284,7 @@ void IndexedDBTransaction::Commit() { |
| state_ = FINISHED; |
| - bool committed = !used_ || transaction_->Commit().ok(); |
| + bool committed = !used_ || transaction_->CommitPhaseTwo().ok(); |
| // Backing store resources (held via cursors) must be released |
| // before script callbacks are fired, as the script callbacks may |
| @@ -288,8 +339,8 @@ void IndexedDBTransaction::ProcessTaskQueue() { |
| TaskQueue* task_queue = |
| pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; |
| - while (!task_queue->empty() && state_ != FINISHED) { |
| - DCHECK_EQ(STARTED, state_); |
| + while (!task_queue->empty() && !IsStatePastStarted()) { |
| + DCHECK_EQ(state_, STARTED); |
| Operation task(task_queue->pop()); |
| task.Run(this); |
| if (!pending_preemptive_events_) { |
| @@ -304,7 +355,7 @@ void IndexedDBTransaction::ProcessTaskQueue() { |
| // If there are no pending tasks, we haven't already committed/aborted, |
| // and the front-end requested a commit, it is now safe to do so. |
| - if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) { |
| + if (!HasPendingTasks() && !IsStatePastStarted() && commit_pending_) { |
|
jsbell
2014/05/28 21:29:15
Should be able to DCHECK_NE(state_, COMMITTING) ab
ericu
2014/05/28 22:50:42
Is it the case that the only way IsStatePastStarte
jsbell
2014/05/28 23:35:18
Yes. To get into the method we must have tasks, so
ericu
2014/05/28 23:49:13
Removed.
|
| Commit(); |
| return; |
| } |