| OLD | NEW |
| 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_cursor.h" | 5 #include "content/browser/indexed_db/indexed_db_cursor.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "content/browser/indexed_db/indexed_db_callbacks.h" | 13 #include "content/browser/indexed_db/indexed_db_callbacks.h" |
| 14 #include "content/browser/indexed_db/indexed_db_database_error.h" | 14 #include "content/browser/indexed_db/indexed_db_database_error.h" |
| 15 #include "content/browser/indexed_db/indexed_db_tracing.h" | 15 #include "content/browser/indexed_db/indexed_db_tracing.h" |
| 16 #include "content/browser/indexed_db/indexed_db_transaction.h" | 16 #include "content/browser/indexed_db/indexed_db_transaction.h" |
| 17 #include "content/browser/indexed_db/indexed_db_value.h" | 17 #include "content/browser/indexed_db/indexed_db_value.h" |
| 18 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" | 18 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" |
| 19 | 19 |
| 20 namespace content { | 20 namespace content { |
| 21 namespace { |
| 22 // This should never be script visible: the cursor should either be closed when |
| 23 // it hits the end of the range (and script throws an error before the call |
| 24 // could be made), if the transaction has finished (ditto), or if there's an |
| 25 // incoming request from the front end but the transaction has aborted on the |
| 26 // back end; in that case the tx will already have sent an abort to the request |
| 27 // so this would be ignored. |
| 28 IndexedDBDatabaseError CreateCursorClosedError() { |
| 29 return IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
| 30 "The cursor has been closed."); |
| 31 } |
| 32 |
| 33 leveldb::Status InvokeOrSucceed(base::WeakPtr<IndexedDBCursor> weak_cursor, |
| 34 IndexedDBTransaction::Operation operation, |
| 35 IndexedDBTransaction* transaction) { |
| 36 if (weak_cursor) |
| 37 return operation.Run(transaction); |
| 38 return leveldb::Status::OK(); |
| 39 } |
| 40 |
| 41 // This allows us to bind a function with a return value to a weak ptr, and if |
| 42 // the weak pointer is invalidated then we just return a default (success). |
| 43 template <typename Functor, typename... Args> |
| 44 IndexedDBTransaction::Operation BindWeakOperation( |
| 45 Functor&& functor, |
| 46 base::WeakPtr<IndexedDBCursor> weak_cursor, |
| 47 Args&&... args) { |
| 48 DCHECK(weak_cursor); |
| 49 IndexedDBCursor* cursor_ptr = weak_cursor.get(); |
| 50 return base::Bind( |
| 51 &InvokeOrSucceed, std::move(weak_cursor), |
| 52 base::Bind(std::forward<Functor>(functor), base::Unretained(cursor_ptr), |
| 53 std::forward<Args>(args)...)); |
| 54 } |
| 55 |
| 56 } // namespace |
| 21 | 57 |
| 22 IndexedDBCursor::IndexedDBCursor( | 58 IndexedDBCursor::IndexedDBCursor( |
| 23 std::unique_ptr<IndexedDBBackingStore::Cursor> cursor, | 59 std::unique_ptr<IndexedDBBackingStore::Cursor> cursor, |
| 24 indexed_db::CursorType cursor_type, | 60 indexed_db::CursorType cursor_type, |
| 25 blink::WebIDBTaskType task_type, | 61 blink::WebIDBTaskType task_type, |
| 26 IndexedDBTransaction* transaction) | 62 IndexedDBTransaction* transaction) |
| 27 : task_type_(task_type), | 63 : task_type_(task_type), |
| 28 cursor_type_(cursor_type), | 64 cursor_type_(cursor_type), |
| 29 transaction_(transaction), | 65 transaction_(transaction), |
| 30 cursor_(std::move(cursor)), | 66 cursor_(std::move(cursor)), |
| 31 closed_(false) { | 67 closed_(false), |
| 32 transaction_->RegisterOpenCursor(this); | 68 ptr_factory_(this) {} |
| 33 } | |
| 34 | 69 |
| 35 IndexedDBCursor::~IndexedDBCursor() { | 70 IndexedDBCursor::~IndexedDBCursor() {} |
| 36 transaction_->UnregisterOpenCursor(this); | |
| 37 } | |
| 38 | 71 |
| 39 void IndexedDBCursor::Continue(std::unique_ptr<IndexedDBKey> key, | 72 void IndexedDBCursor::Continue(std::unique_ptr<IndexedDBKey> key, |
| 40 std::unique_ptr<IndexedDBKey> primary_key, | 73 std::unique_ptr<IndexedDBKey> primary_key, |
| 41 scoped_refptr<IndexedDBCallbacks> callbacks) { | 74 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 42 IDB_TRACE("IndexedDBCursor::Continue"); | 75 IDB_TRACE("IndexedDBCursor::Continue"); |
| 43 | 76 |
| 44 if (closed_) { | 77 if (closed_) { |
| 45 callbacks->OnError( | 78 callbacks->OnError(CreateCursorClosedError()); |
| 46 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | |
| 47 "The cursor has been closed.")); | |
| 48 return; | 79 return; |
| 49 } | 80 } |
| 50 | 81 |
| 51 transaction_->ScheduleTask( | 82 transaction_->ScheduleTask( |
| 52 task_type_, | 83 task_type_, |
| 53 base::Bind(&IndexedDBCursor::CursorIterationOperation, | 84 BindWeakOperation(&IndexedDBCursor::CursorIterationOperation, |
| 54 this, | 85 ptr_factory_.GetWeakPtr(), base::Passed(&key), |
| 55 base::Passed(&key), | 86 base::Passed(&primary_key), callbacks)); |
| 56 base::Passed(&primary_key), | |
| 57 callbacks)); | |
| 58 } | 87 } |
| 59 | 88 |
| 60 void IndexedDBCursor::Advance(uint32_t count, | 89 void IndexedDBCursor::Advance(uint32_t count, |
| 61 scoped_refptr<IndexedDBCallbacks> callbacks) { | 90 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 62 IDB_TRACE("IndexedDBCursor::Advance"); | 91 IDB_TRACE("IndexedDBCursor::Advance"); |
| 63 | 92 |
| 64 if (closed_) { | 93 if (closed_) { |
| 65 callbacks->OnError( | 94 callbacks->OnError(CreateCursorClosedError()); |
| 66 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | |
| 67 "The cursor has been closed.")); | |
| 68 return; | 95 return; |
| 69 } | 96 } |
| 70 | 97 |
| 71 transaction_->ScheduleTask( | 98 transaction_->ScheduleTask( |
| 72 task_type_, | 99 task_type_, |
| 73 base::Bind( | 100 BindWeakOperation(&IndexedDBCursor::CursorAdvanceOperation, |
| 74 &IndexedDBCursor::CursorAdvanceOperation, this, count, callbacks)); | 101 ptr_factory_.GetWeakPtr(), count, callbacks)); |
| 102 } |
| 103 |
| 104 void IndexedDBCursor::RemoveCursorFromTransaction() { |
| 105 if (transaction_) |
| 106 transaction_->UnregisterOpenCursor(this); |
| 75 } | 107 } |
| 76 | 108 |
| 77 leveldb::Status IndexedDBCursor::CursorAdvanceOperation( | 109 leveldb::Status IndexedDBCursor::CursorAdvanceOperation( |
| 78 uint32_t count, | 110 uint32_t count, |
| 79 scoped_refptr<IndexedDBCallbacks> callbacks, | 111 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 80 IndexedDBTransaction* /*transaction*/) { | 112 IndexedDBTransaction* /*transaction*/) { |
| 81 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation"); | 113 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation"); |
| 82 leveldb::Status s = leveldb::Status::OK(); | 114 leveldb::Status s = leveldb::Status::OK(); |
| 83 | 115 |
| 84 if (!cursor_ || !cursor_->Advance(count, &s)) { | 116 if (!cursor_ || !cursor_->Advance(count, &s)) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 callbacks->OnSuccess(this->key(), this->primary_key(), Value()); | 156 callbacks->OnSuccess(this->key(), this->primary_key(), Value()); |
| 125 return s; | 157 return s; |
| 126 } | 158 } |
| 127 | 159 |
| 128 void IndexedDBCursor::PrefetchContinue( | 160 void IndexedDBCursor::PrefetchContinue( |
| 129 int number_to_fetch, | 161 int number_to_fetch, |
| 130 scoped_refptr<IndexedDBCallbacks> callbacks) { | 162 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 131 IDB_TRACE("IndexedDBCursor::PrefetchContinue"); | 163 IDB_TRACE("IndexedDBCursor::PrefetchContinue"); |
| 132 | 164 |
| 133 if (closed_) { | 165 if (closed_) { |
| 134 callbacks->OnError( | 166 callbacks->OnError(CreateCursorClosedError()); |
| 135 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | |
| 136 "The cursor has been closed.")); | |
| 137 return; | 167 return; |
| 138 } | 168 } |
| 139 | 169 |
| 140 transaction_->ScheduleTask( | 170 transaction_->ScheduleTask( |
| 141 task_type_, | 171 task_type_, |
| 142 base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation, | 172 BindWeakOperation(&IndexedDBCursor::CursorPrefetchIterationOperation, |
| 143 this, | 173 ptr_factory_.GetWeakPtr(), number_to_fetch, callbacks)); |
| 144 number_to_fetch, | |
| 145 callbacks)); | |
| 146 } | 174 } |
| 147 | 175 |
| 148 leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation( | 176 leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation( |
| 149 int number_to_fetch, | 177 int number_to_fetch, |
| 150 scoped_refptr<IndexedDBCallbacks> callbacks, | 178 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 151 IndexedDBTransaction* /*transaction*/) { | 179 IndexedDBTransaction* /*transaction*/) { |
| 152 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation"); | 180 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation"); |
| 153 leveldb::Status s = leveldb::Status::OK(); | 181 leveldb::Status s = leveldb::Status::OK(); |
| 154 | 182 |
| 155 std::vector<IndexedDBKey> found_keys; | 183 std::vector<IndexedDBKey> found_keys; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 } | 265 } |
| 238 | 266 |
| 239 return s; | 267 return s; |
| 240 } | 268 } |
| 241 | 269 |
| 242 void IndexedDBCursor::Close() { | 270 void IndexedDBCursor::Close() { |
| 243 IDB_TRACE("IndexedDBCursor::Close"); | 271 IDB_TRACE("IndexedDBCursor::Close"); |
| 244 closed_ = true; | 272 closed_ = true; |
| 245 cursor_.reset(); | 273 cursor_.reset(); |
| 246 saved_cursor_.reset(); | 274 saved_cursor_.reset(); |
| 275 transaction_ = nullptr; |
| 247 } | 276 } |
| 248 | 277 |
| 249 } // namespace content | 278 } // namespace content |
| OLD | NEW |