#include "base/auto_reset.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_index_writer.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
+#include "webkit/browser/blob/blob_data_handle.h"
using base::ASCIIToUTF16;
using base::Int64ToString16;
const base::string16& name,
IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
- const Identifier& unique_identifier) {
+ const Identifier& unique_identifier,
+ leveldb::Status* s) {
scoped_refptr<IndexedDBDatabase> database =
new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
- if (!database->OpenInternal().ok())
- return 0;
- return database;
+ *s = database->OpenInternal();
+ if (s->ok())
+ return database;
+ else
+ return NULL;
}
namespace {
scoped_ptr<IndexedDBConnection> connection(
new IndexedDBConnection(this, database_callbacks));
connections_.insert(connection.get());
- /* TODO(ericu): Grant child process permissions here so that the connection
- * can create Blobs.
- */
+ backing_store_->GrantChildProcessPermissions(child_process_id);
return connection.Pass();
}
const IndexedDBObjectStoreMetadata& object_store_metadata,
IndexedDBTransaction* transaction) {
IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
- if (!backing_store_->CreateObjectStore(
- transaction->BackingStoreTransaction(),
- transaction->database()->id(),
- object_store_metadata.id,
- object_store_metadata.name,
- object_store_metadata.key_path,
- object_store_metadata.auto_increment).ok()) {
- transaction->Abort(IndexedDBDatabaseError(
+ leveldb::Status s =
+ backing_store_->CreateObjectStore(transaction->BackingStoreTransaction(),
+ transaction->database()->id(),
+ object_store_metadata.id,
+ object_store_metadata.name,
+ object_store_metadata.key_path,
+ object_store_metadata.auto_increment);
+ if (!s.ok()) {
+ IndexedDBDatabaseError error(
blink::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16("Internal error creating object store '") +
- object_store_metadata.name + ASCIIToUTF16("'.")));
+ object_store_metadata.name + ASCIIToUTF16("'."));
+ transaction->Abort(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
}
base::string16 error_string =
ASCIIToUTF16("Internal error deleting index '") +
index_metadata.name + ASCIIToUTF16("'.");
- transaction->Abort(IndexedDBDatabaseError(
- blink::WebIDBDatabaseExceptionUnknownError, error_string));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ error_string);
+ transaction->Abort(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
}
}
void IndexedDBDatabase::Abort(int64 transaction_id) {
// If the transaction is unknown, then it has already been aborted by the
// backend before this call so it is safe to ignore it.
+ IDB_TRACE("IndexedDBDatabase::Abort");
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (transaction)
transaction->Abort();
void IndexedDBDatabase::Abort(int64 transaction_id,
const IndexedDBDatabaseError& error) {
+ IDB_TRACE("IndexedDBDatabase::Abort");
// If the transaction is unknown, then it has already been aborted by the
// backend before this call so it is safe to ignore it.
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
const IndexedDBKey* key;
+ leveldb::Status s;
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
if (key_range->IsOnlyKey()) {
key = &key_range->lower();
id(),
object_store_id,
*key_range,
- indexed_db::CURSOR_NEXT);
+ indexed_db::CURSOR_NEXT,
+ &s);
} else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
// Index Value Retrieval Operation
backing_store_cursor = backing_store_->OpenIndexKeyCursor(
object_store_id,
index_id,
*key_range,
- indexed_db::CURSOR_NEXT);
+ indexed_db::CURSOR_NEXT,
+ &s);
} else {
// Index Referenced Value Retrieval Operation
backing_store_cursor = backing_store_->OpenIndexCursor(
object_store_id,
index_id,
*key_range,
- indexed_db::CURSOR_NEXT);
+ indexed_db::CURSOR_NEXT,
+ &s);
+ }
+
+ if (!s.ok()) {
+ DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error deleting data in range");
+ if (s.IsCorruption()) {
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
+ }
}
if (!backing_store_cursor) {
}
scoped_ptr<IndexedDBKey> primary_key;
- leveldb::Status s;
if (index_id == IndexedDBIndexMetadata::kInvalidId) {
// Object Store Retrieval Operation
IndexedDBValue value;
*key,
&value);
if (!s.ok()) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error in GetRecord."));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error in GetRecord.");
+ callbacks->OnError(error);
+
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
*key,
&primary_key);
if (!s.ok()) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error in GetPrimaryKeyViaIndex."));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error in GetPrimaryKeyViaIndex.");
+ callbacks->OnError(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
if (!primary_key) {
*primary_key,
&value);
if (!s.ok()) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error in GetRecord."));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error in GetRecord.");
+ callbacks->OnError(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
PutOperationParams() {}
int64 object_store_id;
IndexedDBValue value;
+ ScopedVector<webkit_blob::BlobDataHandle> handles;
scoped_ptr<IndexedDBKey> key;
IndexedDBDatabase::PutMode put_mode;
scoped_refptr<IndexedDBCallbacks> callbacks;
void IndexedDBDatabase::Put(int64 transaction_id,
int64 object_store_id,
IndexedDBValue* value,
+ ScopedVector<webkit_blob::BlobDataHandle>* handles,
scoped_ptr<IndexedDBKey> key,
PutMode put_mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
return;
DCHECK(key);
+ DCHECK(value);
scoped_ptr<PutOperationParams> params(new PutOperationParams());
params->object_store_id = object_store_id;
params->value.swap(*value);
+ params->handles.swap(*handles);
params->key = key.Pass();
params->put_mode = put_mode;
params->callbacks = callbacks;
&record_identifier,
&found);
if (!s.ok()) {
- params->callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error checking key existence."));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error checking key existence.");
+ params->callbacks->OnError(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
if (found) {
params->object_store_id,
*key,
params->value,
+ ¶ms->handles,
&record_identifier);
if (!s.ok()) {
- params->callbacks->OnError(IndexedDBDatabaseError(
+ IndexedDBDatabaseError error(
blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error: backing store error performing put/add."));
+ "Internal error: backing store error performing put/add.");
+ params->callbacks->OnError(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
*key,
!key_was_generated);
if (!s.ok()) {
- params->callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error updating key generator."));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error updating key generator.");
+ params->callbacks->OnError(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
}
&record_identifier,
&found);
if (!s.ok()) {
- transaction->Abort(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error setting index keys."));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error setting index keys.");
+ transaction->Abort(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
return;
}
if (!found) {
if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
transaction->AddPreemptiveEvent();
+ leveldb::Status s;
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
id(),
params->object_store_id,
*params->key_range,
- params->direction);
+ params->direction,
+ &s);
} else {
backing_store_cursor = backing_store_->OpenObjectStoreCursor(
transaction->BackingStoreTransaction(),
id(),
params->object_store_id,
*params->key_range,
- params->direction);
+ params->direction,
+ &s);
}
} else {
DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
params->object_store_id,
params->index_id,
*params->key_range,
- params->direction);
+ params->direction,
+ &s);
} else {
backing_store_cursor = backing_store_->OpenIndexCursor(
transaction->BackingStoreTransaction(),
params->object_store_id,
params->index_id,
*params->key_range,
- params->direction);
+ params->direction,
+ &s);
+ }
+ }
+
+ if (!s.ok()) {
+ DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error opening cursor operation");
+ if (s.IsCorruption()) {
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
}
}
if (!backing_store_cursor) {
+ // Why is Success being called?
params->callbacks->OnSuccess(static_cast<IndexedDBValue*>(NULL));
return;
}
uint32 count = 0;
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
+ leveldb::Status s;
if (index_id == IndexedDBIndexMetadata::kInvalidId) {
backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
transaction->BackingStoreTransaction(),
id(),
object_store_id,
*key_range,
- indexed_db::CURSOR_NEXT);
+ indexed_db::CURSOR_NEXT,
+ &s);
} else {
backing_store_cursor = backing_store_->OpenIndexKeyCursor(
transaction->BackingStoreTransaction(),
object_store_id,
index_id,
*key_range,
- indexed_db::CURSOR_NEXT);
+ indexed_db::CURSOR_NEXT,
+ &s);
+ }
+ if (!s.ok()) {
+ DLOG(ERROR) << "Unable perform count operation: " << s.ToString();
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error performing count operation");
+ if (s.IsCorruption()) {
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
+ }
}
if (!backing_store_cursor) {
callbacks->OnSuccess(count);
do {
++count;
- } while (backing_store_cursor->Continue());
+ } while (backing_store_cursor->Continue(&s));
+
+ // TODO(cmumford): Check for database corruption.
callbacks->OnSuccess(count);
}
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction) {
IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
+ leveldb::Status s;
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
backing_store_->OpenObjectStoreCursor(
transaction->BackingStoreTransaction(),
id(),
object_store_id,
*key_range,
- indexed_db::CURSOR_NEXT);
- if (backing_store_cursor) {
+ indexed_db::CURSOR_NEXT,
+ &s);
+ if (backing_store_cursor && s.ok()) {
do {
if (!backing_store_->DeleteRecord(
transaction->BackingStoreTransaction(),
"Internal error deleting data in range"));
return;
}
- } while (backing_store_cursor->Continue());
+ } while (backing_store_cursor->Continue(&s));
+ }
+
+ if (!s.ok()) {
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16("Internal error deleting range"));
+ transaction->Abort(error);
+ if (s.IsCorruption()) {
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
+ }
+ return;
}
callbacks->OnSuccess();
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction) {
IDB_TRACE("IndexedDBDatabase::ObjectStoreClearOperation");
- if (!backing_store_->ClearObjectStore(transaction->BackingStoreTransaction(),
- id(),
- object_store_id).ok()) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error clearing object store"));
+ leveldb::Status s = backing_store_->ClearObjectStore(
+ transaction->BackingStoreTransaction(), id(), object_store_id);
+ if (!s.ok()) {
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error clearing object store");
+ callbacks->OnError(error);
+ if (s.IsCorruption()) {
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
+ }
return;
}
callbacks->OnSuccess();
base::string16 error_string =
ASCIIToUTF16("Internal error deleting object store '") +
object_store_metadata.name + ASCIIToUTF16("'.");
- transaction->Abort(IndexedDBDatabaseError(
- blink::WebIDBDatabaseExceptionUnknownError, error_string));
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ error_string);
+ transaction->Abort(error);
+ if (s.IsCorruption())
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
+ error);
}
}
const std::vector<int64>& object_store_ids,
uint16 mode) {
+ IDB_TRACE("IndexedDBDatabase::CreateTransaction");
DCHECK(connections_.count(connection));
DCHECK(transactions_.find(transaction_id) == transactions_.end());
if (transactions_.find(transaction_id) != transactions_.end())
"Internal error deleting database."));
return;
}
+ int64 old_version = metadata_.int_version;
metadata_.version = kNoStringVersion;
metadata_.id = kInvalidId;
metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
metadata_.object_stores.clear();
- callbacks->OnSuccess();
+ callbacks->OnSuccess(old_version);
if (factory_)
factory_->DatabaseDeleted(identifier_);
}
DCHECK(connection->IsConnected());
DCHECK(connection->database() == this);
+ IDB_TRACE("IndexedDBDatabase::Close");
// Abort outstanding transactions from the closing connection. This
// can not happen if the close is requested by the connection itself
// as the front-end defers the close until all transactions are