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 fe8d8b257a3a70f964e3ca86eba06986faf09ea7..6fbc77f87b99ee7583e67c1ebe95268c2a52d882 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" |
@@ -26,6 +27,7 @@ |
#include "content/browser/indexed_db/indexed_db_tracing.h" |
#include "content/browser/indexed_db/indexed_db_transaction.h" |
#include "content/browser/indexed_db/indexed_db_value.h" |
+#include "content/common/indexed_db/indexed_db_constants.h" |
#include "content/common/indexed_db/indexed_db_key_path.h" |
#include "content/common/indexed_db/indexed_db_key_range.h" |
#include "storage/browser/blob/blob_data_handle.h" |
@@ -531,6 +533,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 +737,98 @@ 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> cursor = |
+ backing_store_->OpenObjectStoreCursor( |
+ 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, |
+ "Internal error in GetAllOperation"); |
+ callbacks->OnError(error); |
+ if (s.IsCorruption()) { |
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(), |
+ error); |
+ } |
+ return; |
+ } |
+ |
+ std::vector<IndexedDBReturnValue> found_values; |
+ if (!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 = kMaxIDBMessageOverhead; |
+ do { |
+ bool cursor_valid; |
+ if (did_first_seek) { |
+ cursor_valid = cursor->Continue(&s); |
+ } else { |
+ cursor_valid = 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(*cursor->value()); |
+ |
+ size_t value_estimated_size = return_value.SizeEstimate(); |
+ |
+ if (generated_key) { |
+ return_value.primary_key = cursor->primary_key(); |
+ value_estimated_size += return_value.primary_key.size_estimate(); |
+ } |
+ |
+ if (response_size + value_estimated_size > |
+ IPC::Channel::kMaximumMessageSize) { |
+ // 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, |