Chromium Code Reviews| Index: content/browser/indexed_db/indexed_db_database.cc |
| diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc |
| index 860fc0c0043335df3c18b4d8780c70d5b7443334..d70782de162558348f45d620497f7b069600348f 100644 |
| --- a/content/browser/indexed_db/indexed_db_database.cc |
| +++ b/content/browser/indexed_db/indexed_db_database.cc |
| @@ -5,6 +5,7 @@ |
| #include "content/browser/indexed_db/indexed_db_database.h" |
| #include <math.h> |
| +#include <limits> |
| #include <set> |
| #include "base/auto_reset.h" |
| @@ -531,6 +532,24 @@ void IndexedDBDatabase::Abort(int64 transaction_id, |
| transaction->Abort(error); |
| } |
| +void IndexedDBDatabase::GetAll(int64 transaction_id, |
| + int64 object_store_id, |
| + scoped_ptr<IndexedDBKeyRange> key_range, |
| + int64 max_count, |
| + scoped_refptr<IndexedDBCallbacks> callbacks) { |
| + IDB_TRACE1("IndexedDBDatabase::GetAll", "txn.id", transaction_id); |
| + IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| + if (!transaction) |
| + return; |
| + |
| + if (!ValidateObjectStoreId(object_store_id)) |
| + return; |
| + |
| + transaction->ScheduleTask( |
| + base::Bind(&IndexedDBDatabase::GetAllOperation, this, object_store_id, |
| + Passed(&key_range), max_count, callbacks)); |
| +} |
| + |
| void IndexedDBDatabase::Get(int64 transaction_id, |
| int64 object_store_id, |
| int64 index_id, |
| @@ -717,6 +736,103 @@ void IndexedDBDatabase::GetOperation( |
| callbacks->OnSuccess(&value); |
| } |
| +void IndexedDBDatabase::GetAllOperation( |
| + int64 object_store_id, |
| + scoped_ptr<IndexedDBKeyRange> key_range, |
| + int64 max_count, |
| + scoped_refptr<IndexedDBCallbacks> callbacks, |
| + IndexedDBTransaction* transaction) { |
| + IDB_TRACE1("IndexedDBDatabase::GetAllOperation", "txn.id", transaction->id()); |
| + |
| + DCHECK_GE(max_count, 0); |
| + if (!max_count) |
| + max_count = std::numeric_limits<decltype(max_count)>::max(); |
| + |
| + DCHECK(metadata_.object_stores.find(object_store_id) != |
| + metadata_.object_stores.end()); |
| + const IndexedDBObjectStoreMetadata& object_store_metadata = |
| + metadata_.object_stores[object_store_id]; |
| + |
| + leveldb::Status s; |
| + |
| + scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; |
|
jsbell
2015/04/30 17:28:18
Could just call this `cursor` to reduce clutter. N
cmumford
2015/04/30 22:30:12
Done.
|
| + if (key_range->IsEmpty()) { |
| + backing_store_cursor = backing_store_->OpenObjectStoreCursor( |
| + transaction->BackingStoreTransaction(), id(), object_store_id, |
| + *key_range, blink::WebIDBCursorDirectionNext, &s); |
| + } else { |
| + backing_store_cursor = backing_store_->OpenObjectStoreCursor( |
|
jsbell
2015/04/30 17:28:18
The `else` block looks identical to the `if` block
cmumford
2015/04/30 22:30:12
True that! :$
|
| + transaction->BackingStoreTransaction(), id(), object_store_id, |
| + *key_range, blink::WebIDBCursorDirectionNext, &s); |
| + } |
| + |
| + if (!s.ok()) { |
| + DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString(); |
| + IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
|
jsbell
2015/04/30 17:28:18
Call callbacks->OnError() here?
|
| + "Internal error in GetAllOperation"); |
| + if (s.IsCorruption()) { |
| + factory_->HandleBackingStoreCorruption(backing_store_->origin_url(), |
| + error); |
| + } |
|
jsbell
2015/04/30 17:28:18
Should return at end of !s.ok() block?
cmumford
2015/04/30 22:30:12
Yes, you are correct (on both). Pointing this out
|
| + } |
| + |
| + std::vector<IndexedDBReturnValue> found_values; |
| + if (!backing_store_cursor) { |
| + callbacks->OnSuccessArray(&found_values, object_store_metadata.key_path); |
| + return; |
| + } |
| + |
| + bool did_first_seek = false; |
| + bool generated_key = object_store_metadata.auto_increment && |
| + !object_store_metadata.key_path.IsNull(); |
| + |
| + size_t response_size = 0; |
| + do { |
| + bool cursor_valid; |
| + if (did_first_seek) { |
| + cursor_valid = backing_store_cursor->Continue(&s); |
| + } else { |
| + cursor_valid = backing_store_cursor->FirstSeek(&s); |
| + did_first_seek = true; |
| + } |
| + if (!s.ok()) { |
| + IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| + "Internal error in GetAllOperation."); |
| + callbacks->OnError(error); |
| + |
| + if (s.IsCorruption()) |
| + factory_->HandleBackingStoreCorruption(backing_store_->origin_url(), |
| + error); |
| + return; |
| + } |
| + |
| + if (!cursor_valid) |
| + break; |
| + |
| + IndexedDBReturnValue return_value; |
| + return_value.swap(*backing_store_cursor->value()); |
| + |
| + size_t value_estimated_size = return_value.SizeEstimate(); |
| + |
| + if (generated_key) { |
| + return_value.primary_key = backing_store_cursor->primary_key(); |
| + value_estimated_size += return_value.primary_key.size_estimate(); |
| + } |
| + |
| + if (response_size + value_estimated_size > |
| + IPC::Channel::kMaximumMessageSize) { |
|
jsbell
2015/04/30 17:28:18
Since the estimate is approximate, can you add in
|
| + // TODO(cmumford): Reach this limit in more gracefully (crbug.com/478949) |
| + break; |
| + } |
| + |
| + found_values.push_back(return_value); |
| + response_size += value_estimated_size; |
| + |
| + } while (found_values.size() < static_cast<size_t>(max_count)); |
| + |
| + callbacks->OnSuccessArray(&found_values, object_store_metadata.key_path); |
| +} |
| + |
| static scoped_ptr<IndexedDBKey> GenerateKey( |
| IndexedDBBackingStore* backing_store, |
| IndexedDBTransaction* transaction, |