Index: content/browser/indexed_db/indexed_db_cursor.cc |
diff --git a/content/browser/indexed_db/indexed_db_cursor.cc b/content/browser/indexed_db/indexed_db_cursor.cc |
index f4b2c5fd6f99287c7752f1e0e70c80975af8c0bf..ffd094bdd7273a19bd7cc82d9811487f78efaff3 100644 |
--- a/content/browser/indexed_db/indexed_db_cursor.cc |
+++ b/content/browser/indexed_db/indexed_db_cursor.cc |
@@ -18,6 +18,42 @@ |
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h" |
namespace content { |
+namespace { |
+// This should never be script visible: the cursor should either be closed when |
+// it hits the end of the range (and script throws an error before the call |
+// could be made), if the transaction has finished (ditto), or if there's an |
+// incoming request from the front end but the transaction has aborted on the |
+// back end; in that case the tx will already have sent an abort to the request |
+// so this would be ignored. |
+IndexedDBDatabaseError CreateCursorClosedError() { |
+ return IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
+ "The cursor has been closed."); |
+} |
+ |
+leveldb::Status InvokeOrSucceed(base::WeakPtr<IndexedDBCursor> weak_cursor, |
+ IndexedDBTransaction::Operation operation, |
+ IndexedDBTransaction* transaction) { |
+ if (weak_cursor) |
+ return operation.Run(transaction); |
+ return leveldb::Status::OK(); |
+} |
+ |
+// This allows us to bind a function with a return value to a weak ptr, and if |
+// the weak pointer is invalidated then we just return a default (success). |
+template <typename Functor, typename... Args> |
+IndexedDBTransaction::Operation BindWeakOperation( |
+ Functor&& functor, |
+ base::WeakPtr<IndexedDBCursor> weak_cursor, |
+ Args&&... args) { |
+ DCHECK(weak_cursor); |
+ IndexedDBCursor* cursor_ptr = weak_cursor.get(); |
+ return base::Bind( |
+ &InvokeOrSucceed, std::move(weak_cursor), |
+ base::Bind(std::forward<Functor>(functor), base::Unretained(cursor_ptr), |
+ std::forward<Args>(args)...)); |
+} |
+ |
+} // namespace |
IndexedDBCursor::IndexedDBCursor( |
std::unique_ptr<IndexedDBBackingStore::Cursor> cursor, |
@@ -28,13 +64,10 @@ IndexedDBCursor::IndexedDBCursor( |
cursor_type_(cursor_type), |
transaction_(transaction), |
cursor_(std::move(cursor)), |
- closed_(false) { |
- transaction_->RegisterOpenCursor(this); |
-} |
+ closed_(false), |
+ ptr_factory_(this) {} |
-IndexedDBCursor::~IndexedDBCursor() { |
- transaction_->UnregisterOpenCursor(this); |
-} |
+IndexedDBCursor::~IndexedDBCursor() {} |
void IndexedDBCursor::Continue(std::unique_ptr<IndexedDBKey> key, |
std::unique_ptr<IndexedDBKey> primary_key, |
@@ -42,19 +75,15 @@ void IndexedDBCursor::Continue(std::unique_ptr<IndexedDBKey> key, |
IDB_TRACE("IndexedDBCursor::Continue"); |
if (closed_) { |
- callbacks->OnError( |
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
- "The cursor has been closed.")); |
+ callbacks->OnError(CreateCursorClosedError()); |
return; |
} |
transaction_->ScheduleTask( |
task_type_, |
- base::Bind(&IndexedDBCursor::CursorIterationOperation, |
- this, |
- base::Passed(&key), |
- base::Passed(&primary_key), |
- callbacks)); |
+ BindWeakOperation(&IndexedDBCursor::CursorIterationOperation, |
+ ptr_factory_.GetWeakPtr(), base::Passed(&key), |
+ base::Passed(&primary_key), callbacks)); |
} |
void IndexedDBCursor::Advance(uint32_t count, |
@@ -62,16 +91,27 @@ void IndexedDBCursor::Advance(uint32_t count, |
IDB_TRACE("IndexedDBCursor::Advance"); |
if (closed_) { |
- callbacks->OnError( |
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
- "The cursor has been closed.")); |
+ callbacks->OnError(CreateCursorClosedError()); |
return; |
} |
transaction_->ScheduleTask( |
task_type_, |
- base::Bind( |
- &IndexedDBCursor::CursorAdvanceOperation, this, count, callbacks)); |
+ BindWeakOperation(&IndexedDBCursor::CursorAdvanceOperation, |
+ ptr_factory_.GetWeakPtr(), count, callbacks)); |
+} |
+ |
+void IndexedDBCursor::Close() { |
+ IDB_TRACE("IndexedDBCursor::Close"); |
+ closed_ = true; |
+ cursor_.reset(); |
+ saved_cursor_.reset(); |
+ transaction_ = nullptr; |
+} |
+ |
+void IndexedDBCursor::RemoveCursorFromTransaction() { |
+ if (transaction_) |
+ transaction_->UnregisterOpenCursor(this); |
} |
leveldb::Status IndexedDBCursor::CursorAdvanceOperation( |
@@ -131,18 +171,14 @@ void IndexedDBCursor::PrefetchContinue( |
IDB_TRACE("IndexedDBCursor::PrefetchContinue"); |
if (closed_) { |
- callbacks->OnError( |
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
- "The cursor has been closed.")); |
+ callbacks->OnError(CreateCursorClosedError()); |
return; |
} |
transaction_->ScheduleTask( |
task_type_, |
- base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation, |
- this, |
- number_to_fetch, |
- callbacks)); |
+ BindWeakOperation(&IndexedDBCursor::CursorPrefetchIterationOperation, |
+ ptr_factory_.GetWeakPtr(), number_to_fetch, callbacks)); |
} |
leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation( |
@@ -239,11 +275,4 @@ leveldb::Status IndexedDBCursor::PrefetchReset(int used_prefetches, |
return s; |
} |
-void IndexedDBCursor::Close() { |
cmumford
2016/12/01 19:14:51
Any reason to move Close()? git-blame works better
dmurph
2016/12/01 21:12:23
Just trying to put it in header order. Moved back.
|
- IDB_TRACE("IndexedDBCursor::Close"); |
- closed_ = true; |
- cursor_.reset(); |
- saved_cursor_.reset(); |
-} |
- |
} // namespace content |