| 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,
|
|
|