indexed_db_database.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_database.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <math.h>
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <set>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/auto_reset.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/memory/scoped_vector.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/stl_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/indexed_db/indexed_db_blob_info.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/indexed_db/indexed_db_connection.h"
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "content/browser/indexed_db/indexed_db_context_impl.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_cursor.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_factory.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_index_writer.h"
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_pending_connection.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_transaction.h"
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/browser/indexed_db/indexed_db_value.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_path.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_range.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "third_party/leveldatabase/env_chromium.h"
310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "webkit/browser/blob/blob_data_handle.h"
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Int64ToString16;
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebIDBKeyTypeNumber;
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingUpgradeCall has a scoped_ptr<IndexedDBConnection> because it owns the
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in-progress connection.
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingUpgradeCall {
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingUpgradeCall(scoped_refptr<IndexedDBCallbacks> callbacks,
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     scoped_ptr<IndexedDBConnection> connection,
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 transaction_id,
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callbacks_(callbacks),
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection_(connection.Pass()),
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        version_(version),
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transaction_id_(transaction_id) {}
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Takes ownership of the connection object.
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> ReleaseConnection() WARN_UNUSED_RESULT {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return connection_.Pass();
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 transaction_id() const { return transaction_id_; }
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection_;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingSuccessCall has a IndexedDBConnection* because the connection is now
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// owned elsewhere, but we need to cancel the success call if that connection
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// closes before it is sent.
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingSuccessCall {
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingSuccessCall(scoped_refptr<IndexedDBCallbacks> callbacks,
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     IndexedDBConnection* connection,
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : callbacks_(callbacks), connection_(connection), version_(version) {}
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IndexedDBConnection* connection() const { return connection_; }
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBConnection* connection_;
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingDeleteCall {
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacks> callbacks)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks) {}
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBFactory* factory,
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const Identifier& unique_identifier,
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb::Status* s) {
101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database =
102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = database->OpenInternal();
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (s->ok())
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return database;
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const base::string16::value_type kNoStringVersion[] = {0};
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBBackingStore* backing_store,
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBFactory* factory,
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     const Identifier& unique_identifier)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : backing_store_(backing_store),
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_(name,
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId,
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kNoStringVersion,
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION,
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId),
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      identifier_(unique_identifier),
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_(factory) {
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddObjectStore(
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store,
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_max_object_store_id) {
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store.id) ==
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) {
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id);
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata_.max_object_store_id = new_max_object_store_id;
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store.id] = object_store;
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveObjectStore(int64 object_store_id) {
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.erase(object_store_id);
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddIndex(int64 object_store_id,
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const IndexedDBIndexMetadata& index,
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int64 new_max_index_id) {
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end());
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes[index.id] = index;
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) {
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(object_store.max_index_id, new_max_index_id);
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    object_store.max_index_id = new_max_index_id;
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveIndex(int64 object_store_id, int64 index_id) {
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes.erase(index_id);
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBDatabase::OpenInternal() {
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, &metadata_, &success);
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                  << " id = " << metadata_.id;
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (success)
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store_->GetObjectStores(metadata_.id,
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &metadata_.object_stores);
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_->CreateIDBDatabaseMetaData(
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::~IndexedDBDatabase() {
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.empty());
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_open_calls_.empty());
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_delete_calls_.empty());
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int child_process_id) {
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> connection(
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new IndexedDBConnection(this, database_callbacks));
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connections_.insert(connection.get());
2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  backing_store_->GrantChildProcessPermissions(child_process_id);
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return connection.Pass();
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochIndexedDBTransaction* IndexedDBDatabase::GetTransaction(
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 transaction_id) const {
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TransactionMap::const_iterator trans_iterator =
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transactions_.find(transaction_id);
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (trans_iterator == transactions_.end())
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return NULL;
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return trans_iterator->second;
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreId(int64 object_store_id) const {
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(metadata_.object_stores, object_store_id)) {
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndIndexId(int64 object_store_id,
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                        int64 index_id) const {
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(object_store_metadata.indexes, index_id)) {
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndOptionalIndexId(
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (index_id != IndexedDBIndexMetadata::kInvalidId &&
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !ContainsKey(object_store_metadata.indexes, index_id)) {
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId(
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(object_store_metadata.indexes, index_id)) {
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id,
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                          const base::string16& name,
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const IndexedDBKeyPath& key_path,
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          bool auto_increment) {
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::CreateObjectStore", "txn.id", transaction_id);
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(metadata_.object_stores, object_store_id)) {
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Store creation is done synchronously, as it may be followed by
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // index creation (also sync) since preemptive OpenCursor/SetIndexKeys
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // may follow.
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata(
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name,
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_path,
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      auto_increment,
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBDatabase::kMinimumIndexId);
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
291e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  leveldb::Status s =
292e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      backing_store_->CreateObjectStore(transaction->BackingStoreTransaction(),
293e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        transaction->database()->id(),
294e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.id,
295e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.name,
296e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.key_path,
297e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.auto_increment);
298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!s.ok()) {
299e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error creating object store '") +
302e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            object_store_metadata.name + ASCIIToUTF16("'."));
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s))
305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AddObjectStore(object_store_metadata, object_store_id);
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transaction->ScheduleAbortTask(
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 this,
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 object_store_id));
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id) {
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::DeleteObjectStore", "txn.id", transaction_id);
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreOperation,
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 object_store_id));
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateIndex(int64 transaction_id,
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id,
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    const base::string16& name,
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const IndexedDBKeyPath& key_path,
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool unique,
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool multi_entry) {
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::CreateIndex", "txn.id", transaction_id);
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndNewIndexId(object_store_id, index_id))
3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Index creation is done synchronously since preemptive
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // OpenCursor/SetIndexKeys may follow.
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata(
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name, index_id, key_path, unique, multi_entry);
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   transaction->database()->id(),
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.id,
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.name,
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.key_path,
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.unique,
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   index_metadata.multi_entry).ok()) {
363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error creating index '") +
365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, index_id);
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transaction->ScheduleAbortTask(
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation,
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 this,
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 object_store_id,
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 index_id));
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexAbortOperation(
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::CreateIndexAbortOperation",
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             "txn.id",
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             transaction->id());
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id) {
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::DeleteIndex", "txn.id", transaction_id);
3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id))
4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexOperation,
4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 index_id));
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexOperation(
4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 index_id,
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1(
414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "IndexedDBDatabase::DeleteIndexOperation", "txn.id", transaction->id());
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata =
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      metadata_.object_stores[object_store_id].indexes[index_id];
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  transaction->database()->id(),
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  index_id);
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting index '") +
427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
428e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
429e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 error_string);
430e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s))
432e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
433e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transaction->ScheduleAbortTask(
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation,
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 this,
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 object_store_id,
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 index_metadata));
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexAbortOperation(
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::DeleteIndexAbortOperation",
451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             "txn.id",
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             transaction->id());
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Commit(int64 transaction_id) {
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend suggests that we commit, but we may have previously initiated
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // an abort, and so have disposed of the transaction. on_abort has already
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // been dispatched to the frontend, so it will find out about that
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // asynchronously.
4617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (transaction) {
463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_refptr<IndexedDBFactory> factory = factory_;
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    leveldb::Status s = transaction->Commit();
465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (s.IsCorruption()) {
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                   "Internal error committing transaction.");
468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      factory->HandleBackingStoreCorruption(identifier_.first, error);
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id) {
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::Abort", "txn.id", transaction_id);
4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort();
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id,
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const IndexedDBDatabaseError& error) {
484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::Abort(error)", "txn.id", transaction_id);
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort(error);
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Get(int64 transaction_id,
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 object_store_id,
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 index_id,
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_ptr<IndexedDBKeyRange> key_range,
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            bool key_only,
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks) {
498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::Get", "txn.id", transaction_id);
4997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
5007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
5047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::GetOperation,
5083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      this,
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Passed(&key_range),
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::GetOperation(
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    indexed_db::CursorType cursor_type,
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::GetOperation", "txn.id", transaction->id());
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[object_store_id];
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKey* key;
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (key_range->IsOnlyKey()) {
5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = &key_range->lower();
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
5383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // ObjectStore Retrieval Operation
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
545116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          blink::WebIDBCursorDirectionNext,
5460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Value Retrieval Operation
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          blink::WebIDBCursorDirectionNext,
5560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Referenced Value Retrieval Operation
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          blink::WebIDBCursorDirectionNext,
5660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
5670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
5680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok()) {
5700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
5710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
5720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                   "Internal error deleting data in range");
57346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (leveldb_env::IsCorruption(s)) {
5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                               error);
5760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!backing_store_cursor) {
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &backing_store_cursor->key();
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key;
5883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Object Store Retrieval Operation
59023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    IndexedDBValue value;
591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
592a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  id(),
593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  *key,
595a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  &value);
596a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
597e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
598e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error in GetRecord.");
599e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      callbacks->OnError(error);
600e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (leveldb_env::IsCorruption(s))
602e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
603e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (value.empty()) {
6083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (object_store_metadata.auto_increment &&
6133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        !object_store_metadata.key_path.IsNull()) {
6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value);
619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // From here we are dealing only with indexes.
623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetPrimaryKeyViaIndex(
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      id(),
6263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store_id,
6273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      index_id,
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *key,
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &primary_key);
630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
631e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
632e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error in GetPrimaryKeyViaIndex.");
633e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    callbacks->OnError(error);
63446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s))
635e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
636e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!primary_key) {
6403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Index Value Retrieval Operation
6453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(*primary_key);
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Index Referenced Value Retrieval Operation
65023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue value;
651a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
652a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                id(),
653a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                object_store_id,
654a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                *primary_key,
655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                &value);
656a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
657e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
658e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error in GetRecord.");
659e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    callbacks->OnError(error);
66046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s))
661e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
662e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (value.empty()) {
6673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store_metadata.auto_increment &&
6713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !object_store_metadata.key_path.IsNull()) {
6723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(&value);
676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static scoped_ptr<IndexedDBKey> GenerateKey(
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBTransaction* transaction,
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 max_generator_value =
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      9007199254740992LL;  // Maximum integer storable as ECMAScript number.
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 current_number;
686a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store->GetKeyGeneratorCurrentNumber(
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &current_number);
691a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "Failed to GetKeyGeneratorCurrentNumber";
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_number < 0 || current_number > max_generator_value)
696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return make_scoped_ptr(new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
701a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status UpdateKeyGenerator(IndexedDBBackingStore* backing_store,
702a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          IndexedDBTransaction* transaction,
703a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 database_id,
704a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 object_store_id,
705a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          const IndexedDBKey& key,
706a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          bool check_current) {
7073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(WebIDBKeyTypeNumber, key.type());
708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
7123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<int64>(floor(key.number())) + 1,
713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_current);
714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::PutOperationParams {
7173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PutOperationParams() {}
7183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
71923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue value;
7200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ScopedVector<webkit_blob::BlobDataHandle> handles;
7213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
722116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blink::WebIDBPutMode put_mode;
7233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
7243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<IndexKeys> index_keys;
7253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
7273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
7293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Put(int64 transaction_id,
731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
73223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                            IndexedDBValue* value,
7330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                            ScopedVector<webkit_blob::BlobDataHandle>* handles,
734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_ptr<IndexedDBKey> key,
735116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            blink::WebIDBPutMode put_mode,
736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks,
737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<IndexKeys>& index_keys) {
738f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::Put", "txn.id", transaction_id);
7397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
7407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
742116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
7457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
7480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(value);
7493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<PutOperationParams> params(new PutOperationParams());
7503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
7513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->value.swap(*value);
7520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  params->handles.swap(*handles);
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key = key.Pass();
7543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->put_mode = put_mode;
7553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
7563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_keys = index_keys;
7573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
7583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::PutOperation, this, base::Passed(&params)));
7593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
7623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBTransaction* transaction) {
763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::PutOperation", "txn.id", transaction->id());
764116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool key_was_generated = false;
766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(params->object_store_id) !=
7683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
7693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store =
7703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[params->object_store_id];
7713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(object_store.auto_increment || params->key->IsValid());
7723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (params->put_mode != blink::WebIDBPutModeCursorUpdate &&
7753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store.auto_increment && !params->key->IsValid()) {
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        backing_store_.get(), transaction, id(), params->object_store_id);
778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key_was_generated = true;
779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!auto_inc_key->IsValid()) {
7803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
781f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Maximum key generator value reached."));
783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = auto_inc_key.Pass();
786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
7873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = params->key.Pass();
788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key->IsValid());
791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
793116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (params->put_mode == blink::WebIDBPutModeAddOnly) {
794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool found = false;
795a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = backing_store_->KeyExistsInObjectStore(
796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
7973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
7983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->object_store_id,
7993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key,
800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &record_identifier,
801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &found);
802a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
803e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
804e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error checking key existence.");
805e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      params->callbacks->OnError(error);
80646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (leveldb_env::IsCorruption(s))
807e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
808e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (found) {
8123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
813f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Key already exists in the object store."));
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
820a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
8233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                backing_store_.get(),
8243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                id(),
8253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                object_store,
826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *key,
827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                key_was_generated,
8283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                params->index_keys,
829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
8333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
834f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
8393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
840f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Before this point, don't do any mutation. After this point, rollback the
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // transaction in case of error.
846a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->PutRecord(transaction->BackingStoreTransaction(),
8483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                id(),
8493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->object_store_id,
8503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                *key,
8513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->value,
8520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                &params->handles,
853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &record_identifier);
854a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
855e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(
856f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
857e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        "Internal error: backing store error performing put/add.");
858e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->callbacks->OnError(error);
85946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s))
860e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
861e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
8683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 backing_store_.get(),
869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
8703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id);
872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store.auto_increment &&
875116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      params->put_mode != blink::WebIDBPutModeCursorUpdate &&
876ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      key->type() == WebIDBKeyTypeNumber) {
877a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = UpdateKeyGenerator(backing_store_.get(),
878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           transaction,
879a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           id(),
880a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           params->object_store_id,
881a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           *key,
882a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           !key_was_generated);
883a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
884e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
885e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error updating key generator.");
886e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      params->callbacks->OnError(error);
88746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (leveldb_env::IsCorruption(s))
888e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
889e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
890868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
891868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
892868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(*key);
895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
898868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 object_store_id,
899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     scoped_ptr<IndexedDBKey> primary_key,
900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<IndexKeys>& index_keys) {
901f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::SetIndexKeys", "txn.id", transaction_id);
9027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(alecflett): This method could be asynchronous, but we need to
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // evaluate if it's worth the extra complexity.
909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
911a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->KeyExistsInObjectStore(
9121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      transaction->BackingStoreTransaction(),
9131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      metadata_.id,
9141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      object_store_id,
9151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *primary_key,
9161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &record_identifier,
9171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &found);
918a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
919e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
920e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error setting index keys.");
921e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
92246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s))
923e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
924e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
925868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
929f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
930868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error setting index keys for object store."));
931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
935a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
9421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                backing_store_,
943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                id(),
944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                object_store_metadata,
945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *primary_key,
946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                false,
947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                index_keys,
948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
953f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
959f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
963868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
9661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 backing_store_,
967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 id(),
969868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id);
970868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
971868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        int64,
975868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        const std::vector<int64>& index_ids) {
976f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::SetIndexesReady", "txn.id", transaction_id);
9777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
980116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
981868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(
983116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      blink::WebIDBTaskTypePreemptive,
9843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
9853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
9863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_ids.size()));
987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReadyOperation(
9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t index_count,
9913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
992f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::SetIndexesReadyOperation",
993f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             "txn.id",
994f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             transaction->id());
9953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < index_count; ++i)
996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->DidCompletePreemptiveEvent();
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::OpenCursorOperationParams {
10003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  OpenCursorOperationParams() {}
10013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
10023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 index_id;
10033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKeyRange> key_range;
1004116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blink::WebIDBCursorDirection direction;
10053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorType cursor_type;
1006116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blink::WebIDBTaskType task_type;
10073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
10083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
10103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
10113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
10123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1013868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenCursor(
1014868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1015868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1016868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1018116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBCursorDirection direction,
1019868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
1020116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBTaskType task_type,
1021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1022f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::OpenCursor", "txn.id", transaction_id);
10237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
10247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
10257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<OpenCursorOperationParams> params(new OpenCursorOperationParams());
10313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
10323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_id = index_id;
10333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key_range = key_range.Pass();
10343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->direction = direction;
10353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->cursor_type =
10363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
10373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->task_type = task_type;
10383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
10393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
10403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(&params)));
10413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::OpenCursorOperation(
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<OpenCursorOperationParams> params,
10453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1046f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1(
1047f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "IndexedDBDatabase::OpenCursorOperation", "txn.id", transaction->id());
1048868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend has begun indexing, so this pauses the transaction
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // until the indexing is complete. This can't happen any earlier
1051868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // because we don't want to switch to early mode in case multiple
1052868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // indexes are being created in a row, with Put()'s in between.
1053116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (params->task_type == blink::WebIDBTaskTypePreemptive)
1054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->AddPreemptiveEvent();
1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
1057868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
10583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
1059424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1060116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DCHECK_EQ(params->task_type, blink::WebIDBTaskTypeNormal);
1061424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1062424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1063424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1064424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1065424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
1068424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
1069424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1070424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1071424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1072424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1073424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
1076424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1078116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK_EQ(params->task_type, blink::WebIDBTaskTypeNormal);
10793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
1088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
1090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
10970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
10980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
10990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
11000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
11010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
11020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
11030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 "Internal error opening cursor operation");
110446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s)) {
11050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
11060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
1107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Why is Success being called?
111223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    params->callbacks->OnSuccess(static_cast<IndexedDBValue*>(NULL));
1113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCursor> cursor =
11173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new IndexedDBCursor(backing_store_cursor.Pass(),
11183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->cursor_type,
11193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->task_type,
11203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          transaction);
11213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(
1122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor, cursor->key(), cursor->primary_key(), cursor->Value());
1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Count(int64 transaction_id,
1126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 index_id,
1128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_ptr<IndexedDBKeyRange> key_range,
1129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::Count", "txn.id", transaction_id);
11317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation,
11393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
11403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
11413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       index_id,
11423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
11433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CountOperation(
11473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
11493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::CountOperation", "txn.id", transaction->id());
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 count = 0;
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
11573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        blink::WebIDBCursorDirectionNext,
11640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        &s);
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        index_id,
11713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        blink::WebIDBCursorDirectionNext,
11730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        &s);
11740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
11750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
11760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    DLOG(ERROR) << "Unable perform count operation: " << s.ToString();
11770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
11780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 "Internal error performing count operation");
117946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s)) {
11800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
11810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
11820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
1183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(count);
1186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
1190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ++count;
11910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } while (backing_store_cursor->Continue(&s));
11920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
11930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(cmumford): Check for database corruption.
1194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(count);
1196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteRange(
1199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::DeleteRange", "txn.id", transaction_id);
12047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
12057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
12067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
1207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
12087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
12097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
1210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation,
12133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
12143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
12153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
12163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteRangeOperation(
12203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
12213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
12223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1(
1225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "IndexedDBDatabase::DeleteRangeOperation", "txn.id", transaction->id());
122646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  leveldb::Status s =
122746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      backing_store_->DeleteRange(transaction->BackingStoreTransaction(),
122846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  id(),
122946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  object_store_id,
123046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  *key_range);
12310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
123246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::string16 error_string =
123346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        ASCIIToUTF16("Internal error deleting data in range");
12340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
123546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 error_string);
12360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    transaction->Abort(error);
123746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s)) {
12380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
12390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
12400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
12410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
1242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Clear(int64 transaction_id,
1247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::Clear", "txn.id", transaction_id);
12507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
12517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
1252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
1254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
12567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
12577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
12583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
12593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks));
1260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::ClearOperation(
12633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
12643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::ClearOperation", "txn.id", transaction->id());
12670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s = backing_store_->ClearObjectStore(
12680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      transaction->BackingStoreTransaction(), id(), object_store_id);
12690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
12700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
12710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 "Internal error clearing object store");
12720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    callbacks->OnError(error);
127346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s)) {
12740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
12750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
12760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
1277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreOperation(
1283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 object_store_id,
12843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::DeleteObjectStoreOperation",
1286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             "txn.id",
1287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             transaction->id());
1288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const IndexedDBObjectStoreMetadata object_store_metadata =
1290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      metadata_.object_stores[object_store_id];
1291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
1292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
1294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        object_store_id);
1295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
1297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting object store '") +
12983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_metadata.name + ASCIIToUTF16("'.");
1299e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1300e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 error_string);
1301e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
130246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (leveldb_env::IsCorruption(s))
1303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
1304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
1305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
1306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RemoveObjectStore(object_store_id);
1309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transaction->ScheduleAbortTask(
1310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
1311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 this,
1312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 object_store_metadata));
1313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeOperation(
13163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 version,
13173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
13183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBConnection> connection,
1319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1(
1321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "IndexedDBDatabase::VersionChangeOperation", "txn.id", transaction->id());
13223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 old_version = metadata_.int_version;
13233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GT(version, old_version);
1324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
13253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->UpdateIDBDatabaseIntVersion(
1326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          transaction->BackingStoreTransaction(), id(), version)) {
1327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseError error(
1328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
13297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ASCIIToUTF16(
13307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "Internal error writing data to stable storage when "
13317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "updating version."));
13323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(error);
1333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(error);
1334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transaction->ScheduleAbortTask(
1338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
1339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 this,
1340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 metadata_.version,
1341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 metadata_.int_version));
1342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metadata_.int_version = version;
1343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
13453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_second_half_open_.reset(
1347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new PendingSuccessCall(callbacks, connection.get(), version));
13485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callbacks->OnUpgradeNeeded(old_version, connection.Pass(), metadata());
1349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
13525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool committed) {
1353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction->id()) != transactions_.end());
1354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transactions_[transaction->id()], transaction);
1355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transactions_.erase(transaction->id());
1356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (transaction->mode() == blink::WebIDBTransactionModeVersionChange) {
1358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
13595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (committed) {
13605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK_EQ(pending_second_half_open_->version(), metadata_.int_version);
13615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(metadata_.id != kInvalidId);
13625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Connection was already minted for OnUpgradeNeeded callback.
13645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scoped_ptr<IndexedDBConnection> connection;
13655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnSuccess(connection.Pass(),
13665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                          this->metadata());
13675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
13685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnError(
13695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
13705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "Version change transaction was aborted in "
13715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "upgradeneeded event handler."));
13725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
13765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Connection queue is now unblocked.
1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1381116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid IndexedDBDatabase::TransactionCommitFailed(const leveldb::Status& status) {
13825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Factory may be null in unit tests.
13835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!factory_)
13845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (status.IsCorruption()) {
1386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 "Error committing transaction");
1388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    factory_->HandleBackingStoreCorruption(backing_store_->origin_url(), error);
1389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
1390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    factory_->HandleBackingStoreFailure(backing_store_->origin_url());
1391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
13921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
13931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t IndexedDBDatabase::ConnectionCount() const {
1395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This does not include pending open calls, as those should not block version
1396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changes and deletes.
1397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return connections_.size();
1398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1400ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingOpenCount() const {
1401ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_open_calls_.size();
1402ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1403ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingUpgradeCount() const {
1405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_run_version_change_transaction_call_ ? 1 : 0;
1406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::RunningUpgradeCount() const {
1409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_second_half_open_ ? 1 : 0;
1410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1411ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingDeleteCount() const {
1413ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_delete_calls_.size();
1414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::ProcessPendingCalls() {
1417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
14185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(pending_run_version_change_transaction_call_->version() >
1419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           metadata_.int_version);
1420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<PendingUpgradeCall> pending_call =
1421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_run_version_change_transaction_call_.Pass();
14225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunVersionChangeTransactionFinal(pending_call->callbacks(),
14235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->ReleaseConnection(),
14245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->transaction_id(),
14255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->version());
14265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(1u, ConnectionCount());
1427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through would be a no-op, since transaction must complete
1428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // asynchronously.
1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsDeleteDatabaseBlocked());
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsOpenConnectionBlocked());
1431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDeleteDatabaseBlocked()) {
1435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingDeleteCallList pending_delete_calls;
1436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.swap(pending_delete_calls);
1437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_delete_calls.empty()) {
1438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Only the first delete call will delete the database, but each must fire
1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // callbacks.
1440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingDeleteCall> pending_delete_call(
1441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pending_delete_calls.front());
1442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_delete_calls.pop_front();
14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DeleteDatabaseFinal(pending_delete_call->callbacks());
1444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // delete_database_final should never re-queue calls.
1446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_delete_calls_.empty());
1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsOpenConnectionBlocked()) {
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingOpenCallList pending_open_calls;
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.swap(pending_open_calls);
1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_open_calls.empty()) {
1454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OpenConnection(pending_open_calls.front());
1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_open_calls.pop_front();
1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateTransaction(
1461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexedDBConnection* connection,
1463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::vector<int64>& object_store_ids,
1464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBTransactionMode mode) {
1465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::CreateTransaction", "txn.id", transaction_id);
14668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
14674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(transactions_.find(transaction_id) == transactions_.end());
14684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
14694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The transaction will add itself to this database's coordinator, which
14725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // manages the lifetime of the object.
14735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TransactionCreated(new IndexedDBTransaction(
14747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transaction_id,
14757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      connection->callbacks(),
14767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
1477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      mode,
1478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      this,
14795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new IndexedDBBackingStore::Transaction(backing_store_)));
1480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) {
1483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transactions_[transaction->id()] = transaction;
1484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !pending_delete_calls_.empty() ||
14885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         transaction_coordinator_.IsRunningVersionChangeTransaction() ||
1489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         pending_run_version_change_transaction_call_;
1490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenConnection(
1493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IndexedDBPendingConnection& connection) {
1494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Should have a priority queue so that higher version
1497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // requests are processed first. http://crbug.com/225850
1498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsOpenConnectionBlocked()) {
1499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // The backing store only detects data loss when it is first opened. The
1500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // presence of existing connections means we didn't even check for data loss
1501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // so there'd better not be any.
1502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss());
1503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    pending_open_calls_.push_back(connection);
1504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata_.id == kInvalidId) {
1508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The database was deleted then immediately re-opened; OpenInternal()
1509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // recreates it in the backing store.
1510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (OpenInternal().ok()) {
1511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
1512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                metadata_.int_version);
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 message;
1515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (connection.version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = ASCIIToUTF16(
1517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "Internal error opening database with no version specified.");
15185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
1519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message =
1520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16("Internal error opening database with version ") +
1521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(connection.version);
15225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnError(IndexedDBDatabaseError(
1524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          blink::WebIDBDatabaseExceptionUnknownError, message));
1525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We infer that the database didn't exist from its lack of either type of
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // version.
1531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_new_database =
1532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.version == kNoStringVersion &&
1533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
1534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (connection.version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
1536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // For unit tests only - skip upgrade steps. Calling from script with
1537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // DEFAULT_INT_VERSION throws exception.
1538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK that not in unit tests.
1539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(is_new_database);
1540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnSuccess(
1541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        CreateConnection(connection.database_callbacks,
1542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         connection.child_process_id),
1543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        this->metadata());
1544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We may need to change the version.
1548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 local_version = connection.version;
1549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_new_database) {
1551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnSuccess(
1552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          CreateConnection(connection.database_callbacks,
1553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           connection.child_process_id),
1554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          this->metadata());
1555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Spec says: If no version is specified and no database exists, set
1558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database version to 1.
1559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    local_version = 1;
1560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version > metadata_.int_version) {
1563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    RunVersionChangeTransaction(connection.callbacks,
1564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                CreateConnection(connection.database_callbacks,
1565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                 connection.child_process_id),
1566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                connection.transaction_id,
1567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                local_version);
1568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version < metadata_.int_version) {
1571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnError(IndexedDBDatabaseError(
1572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionVersionError,
1573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ASCIIToUTF16("The requested version (") +
1574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(local_version) +
1575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16(") is less than the existing version (") +
1576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(local_version, metadata_.int_version);
1580a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connection.callbacks->OnSuccess(
1581a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateConnection(connection.database_callbacks,
1582a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       connection.child_process_id),
1583a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this->metadata());
1584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransaction(
1587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
15905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 requested_version) {
1591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(callbacks);
15938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection.get()));
1594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ConnectionCount() > 1) {
15955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
1596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Front end ensures the event is not fired at connections that have
1597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // close_pending set.
1598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (*it != connection.get()) {
16023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*it)->callbacks()->OnVersionChange(metadata_.int_version,
16033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            requested_version);
1604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
1605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1606116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // OnBlocked will be fired at the request when one of the other
1607116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // connections acks that the OnVersionChange was ignored.
1608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!pending_run_version_change_transaction_call_);
1610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pending_run_version_change_transaction_call_.reset(new PendingUpgradeCall(
1611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        callbacks, connection.Pass(), transaction_id, requested_version));
1612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
16145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunVersionChangeTransactionFinal(
16155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callbacks, connection.Pass(), transaction_id, requested_version);
1616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<int64> object_store_ids;
1625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateTransaction(transaction_id,
1626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    connection.get(),
1627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    object_store_ids,
1628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    blink::WebIDBTransactionModeVersionChange);
1629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transactions_[transaction_id]->ScheduleTask(
1631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::VersionChangeOperation,
1632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 this,
1633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 requested_version,
1634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 callbacks,
1635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Passed(&connection)));
1636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabase(
1640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDeleteDatabaseBlocked()) {
1643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Front end ensures the event is not fired at connections that have
1647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // close_pending set.
1648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*it)->callbacks()->OnVersionChange(
1649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
1650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1651116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // OnBlocked will be fired at the request when one of the other
1652116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // connections acks that the OnVersionChange was ignored.
1653116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
1655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteDatabaseFinal(callbacks);
1658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !!ConnectionCount();
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabaseFinal(
1665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!IsDeleteDatabaseBlocked());
1667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1668116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name);
1669116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!s.ok()) {
1670116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1671116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 "Internal error deleting database.");
1672116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callbacks->OnError(error);
1673116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (s.IsCorruption()) {
1674116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GURL origin_url = backing_store_->origin_url();
1675116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      backing_store_ = NULL;
1676116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      factory_->HandleBackingStoreCorruption(origin_url, error);
1677116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
1678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1680a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int64 old_version = metadata_.int_version;
1681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.id = kInvalidId;
1683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.clear();
1685a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  callbacks->OnSuccess(old_version);
16865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (factory_)
16875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    factory_->DatabaseDeleted(identifier_);
16885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::ForceClose() {
16915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IndexedDBConnection::ForceClose() may delete this database, so hold ref.
16925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> protect(this);
16935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConnectionSet::const_iterator it = connections_.begin();
16945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (it != connections_.end()) {
16955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBConnection* connection = *it++;
16965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection->ForceClose();
16975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
16985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(connections_.empty());
1699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1701116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid IndexedDBDatabase::VersionChangeIgnored() {
1702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (pending_run_version_change_transaction_call_)
1703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    pending_run_version_change_transaction_call_->callbacks()->OnBlocked(
1704116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        metadata_.int_version);
1705116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1706116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (PendingDeleteCallList::iterator it = pending_delete_calls_.begin();
1707116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       it != pending_delete_calls_.end();
1708116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       ++it) {
1709116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    (*it)->callbacks()->OnBlocked(metadata_.int_version);
1710116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1711116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
1712116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1713116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
171458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
17158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
17168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->IsConnected());
17178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->database() == this);
1718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  IDB_TRACE("IndexedDBDatabase::Close");
17208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Abort outstanding transactions from the closing connection. This
1721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // can not happen if the close is requested by the connection itself
1722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // as the front-end defers the close until all transactions are
17238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // complete, but can occur on process termination or forced close.
1724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
1725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TransactionMap transactions(transactions_);
1726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (TransactionMap::const_iterator it = transactions.begin(),
1727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        end = transactions.end();
1728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != end;
1729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (it->second->connection() == connection->callbacks())
1731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        it->second->Abort(
1732f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Connection is closing."));
1734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.erase(connection);
1738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_ &&
17395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pending_second_half_open_->connection() == connection) {
17405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_second_half_open_->callbacks()->OnError(
1741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
1742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "The connection was closed."));
1743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_.reset();
1744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessPendingCalls();
1747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ConnectionCount() && !pending_open_calls_.size() &&
1750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !pending_delete_calls_.size()) {
1751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(transactions_.empty());
1752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL origin_url = backing_store_->origin_url();
17541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store_ = NULL;
17551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // factory_ should only be null in unit tests.
1757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
175858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (factory_) {
17595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_->ReleaseDatabase(identifier_, forced);
176058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      factory_ = NULL;
176158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreAbortOperation(
17663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
1767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
1769f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::CreateObjectStoreAbortOperation",
1770f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             "txn.id",
1771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             transaction->id());
17723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveObjectStore(object_store_id);
1773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
17763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
1777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
1779f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::DeleteObjectStoreAbortOperation",
1780f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             "txn.id",
1781f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             transaction->id());
17823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddObjectStore(object_store_metadata,
17833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 IndexedDBObjectStoreMetadata::kInvalidId);
1784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeAbortOperation(
1787a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& previous_version,
17883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 previous_int_version,
1789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
1791f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IDB_TRACE1("IndexedDBDatabase::VersionChangeAbortOperation",
1792f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             "txn.id",
1793f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             transaction->id());
17943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.version = previous_version;
17953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = previous_int_version;
1796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
1799