indexed_db_database.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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"
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "webkit/browser/blob/blob_data_handle.h"
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Int64ToString16;
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebIDBKeyTypeNumber;
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingUpgradeCall has a scoped_ptr<IndexedDBConnection> because it owns the
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in-progress connection.
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingUpgradeCall {
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingUpgradeCall(scoped_refptr<IndexedDBCallbacks> callbacks,
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     scoped_ptr<IndexedDBConnection> connection,
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 transaction_id,
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callbacks_(callbacks),
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection_(connection.Pass()),
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        version_(version),
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transaction_id_(transaction_id) {}
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Takes ownership of the connection object.
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> ReleaseConnection() WARN_UNUSED_RESULT {
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return connection_.Pass();
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 transaction_id() const { return transaction_id_; }
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection_;
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingSuccessCall has a IndexedDBConnection* because the connection is now
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// owned elsewhere, but we need to cancel the success call if that connection
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// closes before it is sent.
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingSuccessCall {
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingSuccessCall(scoped_refptr<IndexedDBCallbacks> callbacks,
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     IndexedDBConnection* connection,
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : callbacks_(callbacks), connection_(connection), version_(version) {}
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IndexedDBConnection* connection() const { return connection_; }
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBConnection* connection_;
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingDeleteCall {
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacks> callbacks)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks) {}
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBFactory* factory,
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const Identifier& unique_identifier,
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb::Status* s) {
100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database =
101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = database->OpenInternal();
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (s->ok())
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return database;
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const base::string16::value_type kNoStringVersion[] = {0};
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBBackingStore* backing_store,
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBFactory* factory,
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     const Identifier& unique_identifier)
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : backing_store_(backing_store),
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_(name,
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId,
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kNoStringVersion,
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION,
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId),
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      identifier_(unique_identifier),
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_(factory) {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddObjectStore(
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store,
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_max_object_store_id) {
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store.id) ==
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) {
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id);
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata_.max_object_store_id = new_max_object_store_id;
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store.id] = object_store;
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveObjectStore(int64 object_store_id) {
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.erase(object_store_id);
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddIndex(int64 object_store_id,
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const IndexedDBIndexMetadata& index,
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int64 new_max_index_id) {
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end());
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes[index.id] = index;
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) {
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(object_store.max_index_id, new_max_index_id);
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    object_store.max_index_id = new_max_index_id;
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveIndex(int64 object_store_id, int64 index_id) {
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes.erase(index_id);
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBDatabase::OpenInternal() {
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, &metadata_, &success);
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                  << " id = " << metadata_.id;
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (success)
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store_->GetObjectStores(metadata_.id,
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &metadata_.object_stores);
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_->CreateIDBDatabaseMetaData(
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::~IndexedDBDatabase() {
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.empty());
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_open_calls_.empty());
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_delete_calls_.empty());
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int child_process_id) {
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> connection(
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new IndexedDBConnection(this, database_callbacks));
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connections_.insert(connection.get());
2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  backing_store_->GrantChildProcessPermissions(child_process_id);
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return connection.Pass();
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochIndexedDBTransaction* IndexedDBDatabase::GetTransaction(
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 transaction_id) const {
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TransactionMap::const_iterator trans_iterator =
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transactions_.find(transaction_id);
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (trans_iterator == transactions_.end())
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return NULL;
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return trans_iterator->second;
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreId(int64 object_store_id) const {
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(metadata_.object_stores, object_store_id)) {
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndIndexId(int64 object_store_id,
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                        int64 index_id) const {
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(object_store_metadata.indexes, index_id)) {
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndOptionalIndexId(
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (index_id != IndexedDBIndexMetadata::kInvalidId &&
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !ContainsKey(object_store_metadata.indexes, index_id)) {
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId(
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(object_store_metadata.indexes, index_id)) {
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id,
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                          const base::string16& name,
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const IndexedDBKeyPath& key_path,
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          bool auto_increment) {
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateObjectStore");
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(metadata_.object_stores, object_store_id)) {
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata(
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name,
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_path,
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      auto_increment,
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBDatabase::kMinimumIndexId);
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreOperation,
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id));
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddObjectStore(object_store_metadata, object_store_id);
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreOperation(
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
302e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  leveldb::Status s =
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      backing_store_->CreateObjectStore(transaction->BackingStoreTransaction(),
304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        transaction->database()->id(),
305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.id,
306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.name,
307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.key_path,
308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.auto_increment);
309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!s.ok()) {
310e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error creating object store '") +
313e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            object_store_metadata.name + ASCIIToUTF16("'."));
314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
315e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
316e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
317e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id) {
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteObjectStore");
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreOperation,
3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata));
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveObjectStore(object_store_id);
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateIndex(int64 transaction_id,
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id,
349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    const base::string16& name,
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const IndexedDBKeyPath& key_path,
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool unique,
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool multi_entry) {
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateIndex");
3547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndNewIndexId(object_store_id, index_id))
3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata(
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name, index_id, key_path, unique, multi_entry);
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexOperation,
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation,
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_id));
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, index_id);
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexOperation(
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexOperation");
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   transaction->database()->id(),
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.id,
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.name,
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.key_path,
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.unique,
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   index_metadata.multi_entry).ok()) {
390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error creating index '") +
392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexAbortOperation(
4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation");
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id) {
411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteIndex");
4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id))
4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBIndexMetadata& index_metadata =
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores[object_store_id].indexes[index_id];
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
4233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexOperation,
4243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation,
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata));
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexOperation(
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation");
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  transaction->database()->id(),
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  index_metadata.id);
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting index '") +
448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
449e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
450e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 error_string);
451e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
452e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
453e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
454e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexAbortOperation(
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation");
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Commit(int64 transaction_id) {
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend suggests that we commit, but we may have previously initiated
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // an abort, and so have disposed of the transaction. on_abort has already
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // been dispatched to the frontend, so it will find out about that
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // asynchronously.
4727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Commit();
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id) {
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  IDB_TRACE("IndexedDBDatabase::Abort");
4817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort();
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id,
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const IndexedDBDatabaseError& error) {
4880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  IDB_TRACE("IndexedDBDatabase::Abort");
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort(error);
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Get(int64 transaction_id,
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 object_store_id,
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 index_id,
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_ptr<IndexedDBKeyRange> key_range,
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            bool key_only,
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks) {
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Get");
5037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
5047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
5087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::GetOperation,
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      this,
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Passed(&key_range),
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::GetOperation(
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    indexed_db::CursorType cursor_type,
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::GetOperation");
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[object_store_id];
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKey* key;
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
5383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (key_range->IsOnlyKey()) {
5393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = &key_range->lower();
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
5413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
5423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // ObjectStore Retrieval Operation
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
5490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          indexed_db::CURSOR_NEXT,
5500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
5513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Value Retrieval Operation
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
5590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          indexed_db::CURSOR_NEXT,
5600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Referenced Value Retrieval Operation
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
5690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          indexed_db::CURSOR_NEXT,
5700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
5710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
5720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok()) {
5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
5760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                   "Internal error deleting data in range");
5770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (s.IsCorruption()) {
5780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
5790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                               error);
5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!backing_store_cursor) {
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &backing_store_cursor->key();
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key;
5923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Object Store Retrieval Operation
59423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    IndexedDBValue value;
595a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
596a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  id(),
597a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
598a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  *key,
599a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  &value);
600a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
601e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
602e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error in GetRecord.");
603e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      callbacks->OnError(error);
604e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
605e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (s.IsCorruption())
606e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
607e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (value.empty()) {
6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (object_store_metadata.auto_increment &&
6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        !object_store_metadata.key_path.IsNull()) {
6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value);
623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // From here we are dealing only with indexes.
627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetPrimaryKeyViaIndex(
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      id(),
6303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store_id,
6313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      index_id,
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *key,
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &primary_key);
634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
635e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
636e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error in GetPrimaryKeyViaIndex.");
637e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    callbacks->OnError(error);
638e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
639e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
640e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!primary_key) {
6443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Index Value Retrieval Operation
6493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(*primary_key);
650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Index Referenced Value Retrieval Operation
65423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue value;
655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
656a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                id(),
657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                object_store_id,
658a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                *primary_key,
659a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                &value);
660a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
661e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
662e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error in GetRecord.");
663e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    callbacks->OnError(error);
664e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
665e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
666e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (value.empty()) {
6713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store_metadata.auto_increment &&
6753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !object_store_metadata.key_path.IsNull()) {
6763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(&value);
680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static scoped_ptr<IndexedDBKey> GenerateKey(
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBTransaction* transaction,
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 max_generator_value =
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      9007199254740992LL;  // Maximum integer storable as ECMAScript number.
689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 current_number;
690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store->GetKeyGeneratorCurrentNumber(
691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &current_number);
695a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "Failed to GetKeyGeneratorCurrentNumber";
697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_number < 0 || current_number > max_generator_value)
700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return make_scoped_ptr(new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
705a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status UpdateKeyGenerator(IndexedDBBackingStore* backing_store,
706a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          IndexedDBTransaction* transaction,
707a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 database_id,
708a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 object_store_id,
709a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          const IndexedDBKey& key,
710a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          bool check_current) {
7113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(WebIDBKeyTypeNumber, key.type());
712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
7163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<int64>(floor(key.number())) + 1,
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_current);
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::PutOperationParams {
7213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PutOperationParams() {}
7223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
72323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue value;
7240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ScopedVector<webkit_blob::BlobDataHandle> handles;
7253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::PutMode put_mode;
7273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<IndexKeys> index_keys;
7293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
7333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Put(int64 transaction_id,
735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
73623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                            IndexedDBValue* value,
7370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                            ScopedVector<webkit_blob::BlobDataHandle>* handles,
738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_ptr<IndexedDBKey> key,
739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            PutMode put_mode,
740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks,
741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<IndexKeys>& index_keys) {
742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Put");
7437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
7447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
7497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
7520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(value);
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<PutOperationParams> params(new PutOperationParams());
7543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
7553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->value.swap(*value);
7560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  params->handles.swap(*handles);
7573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key = key.Pass();
7583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->put_mode = put_mode;
7593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
7603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_keys = index_keys;
7613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
7623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::PutOperation, this, base::Passed(&params)));
7633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
7663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBTransaction* transaction) {
7673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::PutOperation");
768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool key_was_generated = false;
770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(params->object_store_id) !=
7723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
7733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store =
7743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[params->object_store_id];
7753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(object_store.auto_increment || params->key->IsValid());
7763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
7793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store.auto_increment && !params->key->IsValid()) {
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        backing_store_.get(), transaction, id(), params->object_store_id);
782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key_was_generated = true;
783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!auto_inc_key->IsValid()) {
7843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
785f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Maximum key generator value reached."));
787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = auto_inc_key.Pass();
790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
7913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = params->key.Pass();
792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key->IsValid());
795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
7973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool found = false;
799a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = backing_store_->KeyExistsInObjectStore(
800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
8013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
8023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->object_store_id,
8033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key,
804868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &record_identifier,
805868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &found);
806a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
807e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
808e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error checking key existence.");
809e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      params->callbacks->OnError(error);
810e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (s.IsCorruption())
811e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
812e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (found) {
8163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
817f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Key already exists in the object store."));
819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
8273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                backing_store_.get(),
8283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                id(),
8293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                object_store,
830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *key,
831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                key_was_generated,
8323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                params->index_keys,
833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
8373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
838f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
8433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
844f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
846868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Before this point, don't do any mutation. After this point, rollback the
849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // transaction in case of error.
850a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
851868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->PutRecord(transaction->BackingStoreTransaction(),
8523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                id(),
8533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->object_store_id,
8543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                *key,
8553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->value,
8560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                &params->handles,
857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &record_identifier);
858a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
859e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(
860f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
861e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        "Internal error: backing store error performing put/add.");
862e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->callbacks->OnError(error);
863e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
864e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
865e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
8723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 backing_store_.get(),
873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
8743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id);
876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store.auto_increment &&
8793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
880ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      key->type() == WebIDBKeyTypeNumber) {
881a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = UpdateKeyGenerator(backing_store_.get(),
882a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           transaction,
883a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           id(),
884a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           params->object_store_id,
885a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           *key,
886a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           !key_was_generated);
887a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
888e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
889e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error updating key generator.");
890e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      params->callbacks->OnError(error);
891e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (s.IsCorruption())
892e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
893e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(*key);
899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 object_store_id,
903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     scoped_ptr<IndexedDBKey> primary_key,
904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<IndexKeys>& index_keys) {
905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexKeys");
9067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(alecflett): This method could be asynchronous, but we need to
912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // evaluate if it's worth the extra complexity.
913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
915a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->KeyExistsInObjectStore(
9161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      transaction->BackingStoreTransaction(),
9171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      metadata_.id,
9181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      object_store_id,
9191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *primary_key,
9201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &record_identifier,
9211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &found);
922a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
923e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
924e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error setting index keys.");
925e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
926e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
927e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
928e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
929868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
930868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
933f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error setting index keys for object store."));
935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
939a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
944868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
9461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                backing_store_,
947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                id(),
948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                object_store_metadata,
949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *primary_key,
950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                false,
951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                index_keys,
952eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
963f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
966868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
969868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
9701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 backing_store_,
971868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 id(),
973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id);
974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
975868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
977868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
978868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        int64,
979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        const std::vector<int64>& index_ids) {
980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexesReady");
9817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
983868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
9847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(
9873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      IndexedDBDatabase::PREEMPTIVE_TASK,
9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_ids.size()));
991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReadyOperation(
9943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t index_count,
9953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
9963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::SetIndexesReadyOperation");
9973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < index_count; ++i)
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->DidCompletePreemptiveEvent();
999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::OpenCursorOperationParams {
10023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  OpenCursorOperationParams() {}
10033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
10043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 index_id;
10053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKeyRange> key_range;
10063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorDirection direction;
10073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorType cursor_type;
10083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::TaskType task_type;
10093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
10103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
10123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
10133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
10143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1015868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenCursor(
1016868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1018868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
1019868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    indexed_db::CursorDirection direction,
1021868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
1022868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskType task_type,
1023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::OpenCursor");
10257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
10267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
10277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1031868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<OpenCursorOperationParams> params(new OpenCursorOperationParams());
10333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
10343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_id = index_id;
10353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key_range = key_range.Pass();
10363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->direction = direction;
10373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->cursor_type =
10383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
10393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->task_type = task_type;
10403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
10413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
10423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(&params)));
10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::OpenCursorOperation(
10463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<OpenCursorOperationParams> params,
10473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
10483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::OpenCursorOperation");
1049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend has begun indexing, so this pauses the transaction
1051868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // until the indexing is complete. This can't happen any earlier
1052868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // because we don't want to switch to early mode in case multiple
1053868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // indexes are being created in a row, with Put()'s in between.
10543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->AddPreemptiveEvent();
1056868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
1058868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
10593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
1060424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1061424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
1062424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1063424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1064424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1065424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1066424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
1069424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
1070424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1071424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1072424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1073424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1074424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
1077424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1078868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
10793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
10803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1082868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
1089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
1091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params->direction,
10970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
10980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
10990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
11000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
11010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
11020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
11030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
11040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 "Internal error opening cursor operation");
11050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (s.IsCorruption()) {
11060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
11070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
1108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Why is Success being called?
111323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    params->callbacks->OnSuccess(static_cast<IndexedDBValue*>(NULL));
1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCursor> cursor =
11183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new IndexedDBCursor(backing_store_cursor.Pass(),
11193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->cursor_type,
11203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->task_type,
11213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          transaction);
11223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(
1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor, cursor->key(), cursor->primary_key(), cursor->Value());
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Count(int64 transaction_id,
1127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 index_id,
1129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_ptr<IndexedDBKeyRange> key_range,
1130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Count");
11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
11347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation,
11403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
11413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
11423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       index_id,
11433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
11443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CountOperation(
11483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
11503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CountOperation");
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 count = 0;
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
11583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
11640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        indexed_db::CURSOR_NEXT,
11650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        &s);
1166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        index_id,
11723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
11730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        indexed_db::CURSOR_NEXT,
11740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        &s);
11750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
11760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
11770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    DLOG(ERROR) << "Unable perform count operation: " << s.ToString();
11780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
11790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 "Internal error performing count operation");
11800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (s.IsCorruption()) {
11810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
11820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
11830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
1184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(count);
1187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
1191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ++count;
11920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } while (backing_store_cursor->Continue(&s));
11930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
11940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(cmumford): Check for database corruption.
1195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(count);
1197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteRange(
1200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteRange");
12057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
12067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
12077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
12087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
12097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
12107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
1211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation,
12143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
12153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
12163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
12173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteRangeOperation(
12213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
12223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
12233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
12260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
1227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->OpenObjectStoreCursor(
1229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
12303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
12313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
12323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
12330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          indexed_db::CURSOR_NEXT,
12340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &s);
12350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (backing_store_cursor && s.ok()) {
1236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    do {
1237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!backing_store_->DeleteRecord(
1238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               transaction->BackingStoreTransaction(),
1239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               id(),
1240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               object_store_id,
1241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               backing_store_cursor->record_identifier())
1242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               .ok()) {
12433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        callbacks->OnError(
1244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Internal error deleting data in range"));
1246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
1247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
12480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    } while (backing_store_cursor->Continue(&s));
12490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
12500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
12510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
12520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
12530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 ASCIIToUTF16("Internal error deleting range"));
12540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    transaction->Abort(error);
12550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (s.IsCorruption()) {
12560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
12570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
12580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
12590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
1260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Clear(int64 transaction_id,
1266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Clear");
12697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
12707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
1271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
1273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
12757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
12767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
12773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
12783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks));
1279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::ClearOperation(
12823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
12833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::ObjectStoreClearOperation");
12860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s = backing_store_->ClearObjectStore(
12870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      transaction->BackingStoreTransaction(), id(), object_store_id);
12880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
12890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
12900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 "Internal error clearing object store");
12910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    callbacks->OnError(error);
12920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (s.IsCorruption()) {
12930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
12940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             error);
12950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
1296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreOperation(
13023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
13033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
13043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation");
1305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
1306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
13083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        object_store_metadata.id);
1309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
1311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting object store '") +
13123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_metadata.name + ASCIIToUTF16("'.");
1313e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 error_string);
1315e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
1316e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
1317e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
1318e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
1319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeOperation(
13233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 version,
13243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
13253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBConnection> connection,
1326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
13273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
13283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 old_version = metadata_.int_version;
13293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GT(version, old_version);
13303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = version;
13313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->UpdateIDBDatabaseIntVersion(
1332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
13333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
13343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          metadata_.int_version)) {
1335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseError error(
1336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
13377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ASCIIToUTF16(
13387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "Internal error writing data to stable storage when "
13397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "updating version."));
13403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(error);
1341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(error);
1342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
13443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_second_half_open_.reset(
1346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new PendingSuccessCall(callbacks, connection.get(), version));
13475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callbacks->OnUpgradeNeeded(old_version, connection.Pass(), metadata());
1348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
13515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool committed) {
1352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction->id()) != transactions_.end());
1353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transactions_[transaction->id()], transaction);
1354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transactions_.erase(transaction->id());
1355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
13585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (committed) {
13595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK_EQ(pending_second_half_open_->version(), metadata_.int_version);
13605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(metadata_.id != kInvalidId);
13615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Connection was already minted for OnUpgradeNeeded callback.
13635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scoped_ptr<IndexedDBConnection> connection;
13645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnSuccess(connection.Pass(),
13655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                          this->metadata());
13665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
13675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnError(
13685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
13695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "Version change transaction was aborted in "
13705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "upgradeneeded event handler."));
13715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
13755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Connection queue is now unblocked.
1376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBDatabase::TransactionCommitFailed() {
13815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Factory may be null in unit tests.
13825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!factory_)
13835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
13841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  factory_->HandleBackingStoreFailure(backing_store_->origin_url());
13851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
13861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t IndexedDBDatabase::ConnectionCount() const {
1388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This does not include pending open calls, as those should not block version
1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changes and deletes.
1390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return connections_.size();
1391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1393ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingOpenCount() const {
1394ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_open_calls_.size();
1395ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1396ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1397ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingUpgradeCount() const {
1398ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_run_version_change_transaction_call_ ? 1 : 0;
1399ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1400ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1401ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::RunningUpgradeCount() const {
1402ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_second_half_open_ ? 1 : 0;
1403ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingDeleteCount() const {
1406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_delete_calls_.size();
1407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::ProcessPendingCalls() {
1410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
14115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(pending_run_version_change_transaction_call_->version() >
1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           metadata_.int_version);
1413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<PendingUpgradeCall> pending_call =
1414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_run_version_change_transaction_call_.Pass();
14155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunVersionChangeTransactionFinal(pending_call->callbacks(),
14165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->ReleaseConnection(),
14175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->transaction_id(),
14185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->version());
14195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(1u, ConnectionCount());
1420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through would be a no-op, since transaction must complete
1421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // asynchronously.
1422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsDeleteDatabaseBlocked());
1423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsOpenConnectionBlocked());
1424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDeleteDatabaseBlocked()) {
1428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingDeleteCallList pending_delete_calls;
1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.swap(pending_delete_calls);
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_delete_calls.empty()) {
1431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Only the first delete call will delete the database, but each must fire
1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // callbacks.
1433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingDeleteCall> pending_delete_call(
1434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pending_delete_calls.front());
1435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_delete_calls.pop_front();
14365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DeleteDatabaseFinal(pending_delete_call->callbacks());
1437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // delete_database_final should never re-queue calls.
1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_delete_calls_.empty());
1440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsOpenConnectionBlocked()) {
1444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingOpenCallList pending_open_calls;
1445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.swap(pending_open_calls);
1446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_open_calls.empty()) {
1447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OpenConnection(pending_open_calls.front());
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_open_calls.pop_front();
1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateTransaction(
1454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexedDBConnection* connection,
1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::vector<int64>& object_store_ids,
1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint16 mode) {
1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateTransaction");
14608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
14614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(transactions_.find(transaction_id) == transactions_.end());
14624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
14634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The transaction will add itself to this database's coordinator, which
14665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // manages the lifetime of the object.
14675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TransactionCreated(new IndexedDBTransaction(
14687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transaction_id,
14697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      connection->callbacks(),
14707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
14717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      static_cast<indexed_db::TransactionMode>(mode),
1472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      this,
14735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new IndexedDBBackingStore::Transaction(backing_store_)));
1474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) {
1477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transactions_[transaction->id()] = transaction;
1478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !pending_delete_calls_.empty() ||
14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         transaction_coordinator_.IsRunningVersionChangeTransaction() ||
1483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         pending_run_version_change_transaction_call_;
1484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenConnection(
1487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IndexedDBPendingConnection& connection) {
1488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Should have a priority queue so that higher version
1491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // requests are processed first. http://crbug.com/225850
1492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsOpenConnectionBlocked()) {
1493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // The backing store only detects data loss when it is first opened. The
1494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // presence of existing connections means we didn't even check for data loss
1495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // so there'd better not be any.
1496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss());
1497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    pending_open_calls_.push_back(connection);
1498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata_.id == kInvalidId) {
1502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The database was deleted then immediately re-opened; OpenInternal()
1503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // recreates it in the backing store.
1504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (OpenInternal().ok()) {
1505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
1506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                metadata_.int_version);
1507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 message;
1509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (connection.version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = ASCIIToUTF16(
1511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "Internal error opening database with no version specified.");
15125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message =
1514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16("Internal error opening database with version ") +
1515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(connection.version);
15165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1517a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnError(IndexedDBDatabaseError(
1518f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          blink::WebIDBDatabaseExceptionUnknownError, message));
1519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We infer that the database didn't exist from its lack of either type of
1524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // version.
1525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_new_database =
1526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.version == kNoStringVersion &&
1527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
1528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (connection.version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // For unit tests only - skip upgrade steps. Calling from script with
1531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // DEFAULT_INT_VERSION throws exception.
1532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK that not in unit tests.
1533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(is_new_database);
1534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnSuccess(
1535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        CreateConnection(connection.database_callbacks,
1536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         connection.child_process_id),
1537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        this->metadata());
1538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We may need to change the version.
1542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 local_version = connection.version;
1543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_new_database) {
1545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnSuccess(
1546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          CreateConnection(connection.database_callbacks,
1547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           connection.child_process_id),
1548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          this->metadata());
1549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Spec says: If no version is specified and no database exists, set
1552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database version to 1.
1553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    local_version = 1;
1554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version > metadata_.int_version) {
1557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    RunVersionChangeTransaction(connection.callbacks,
1558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                CreateConnection(connection.database_callbacks,
1559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                 connection.child_process_id),
1560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                connection.transaction_id,
1561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                local_version);
1562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version < metadata_.int_version) {
1565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnError(IndexedDBDatabaseError(
1566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionVersionError,
1567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ASCIIToUTF16("The requested version (") +
1568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(local_version) +
1569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16(") is less than the existing version (") +
1570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(local_version, metadata_.int_version);
1574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connection.callbacks->OnSuccess(
1575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateConnection(connection.database_callbacks,
1576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       connection.child_process_id),
1577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this->metadata());
1578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransaction(
1581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
15845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 requested_version) {
1585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(callbacks);
15878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection.get()));
1588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ConnectionCount() > 1) {
15895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
1590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Front end ensures the event is not fired at connections that have
1591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // close_pending set.
1592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (*it != connection.get()) {
15963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*it)->callbacks()->OnVersionChange(metadata_.int_version,
15973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            requested_version);
1598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
1599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Remove the call to OnBlocked and instead wait
1601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // until the frontend tells us that all the "versionchange" events
1602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // have been delivered.  http://crbug.com/100123
1603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!pending_run_version_change_transaction_call_);
1606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pending_run_version_change_transaction_call_.reset(new PendingUpgradeCall(
1607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        callbacks, connection.Pass(), transaction_id, requested_version));
1608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
16105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunVersionChangeTransactionFinal(
16115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callbacks, connection.Pass(), transaction_id, requested_version);
1612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<int64> object_store_ids;
1621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateTransaction(transaction_id,
1622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    connection.get(),
1623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    object_store_ids,
1624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    indexed_db::TRANSACTION_VERSION_CHANGE);
1625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  transactions_[transaction_id]
16275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ->ScheduleTask(base::Bind(&IndexedDBDatabase::VersionChangeOperation,
16285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
16295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                requested_version,
16305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                callbacks,
16315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                base::Passed(&connection)),
16325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
16335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
16345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.version,
16355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.int_version));
1636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabase(
1641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDeleteDatabaseBlocked()) {
1644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Front end ensures the event is not fired at connections that have
1648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // close_pending set.
1649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*it)->callbacks()->OnVersionChange(
1650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
1651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Only fire OnBlocked if there are open
1653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // connections after the VersionChangeEvents are received, not
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // just set up to fire.  http://crbug.com/100123
1655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
1657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteDatabaseFinal(callbacks);
1660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !!ConnectionCount();
1664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabaseFinal(
1667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!IsDeleteDatabaseBlocked());
1669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1670a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!backing_store_->DeleteDatabase(metadata_.name).ok()) {
1671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(
1672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error deleting database."));
1674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1676a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int64 old_version = metadata_.int_version;
1677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.id = kInvalidId;
1679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.clear();
1681a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  callbacks->OnSuccess(old_version);
16825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (factory_)
16835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    factory_->DatabaseDeleted(identifier_);
16845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::ForceClose() {
16875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IndexedDBConnection::ForceClose() may delete this database, so hold ref.
16885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> protect(this);
16895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConnectionSet::const_iterator it = connections_.begin();
16905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (it != connections_.end()) {
16915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBConnection* connection = *it++;
16925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection->ForceClose();
16935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
16945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(connections_.empty());
1695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
169758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
16988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
16998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->IsConnected());
17008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->database() == this);
1701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  IDB_TRACE("IndexedDBDatabase::Close");
17038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Abort outstanding transactions from the closing connection. This
1704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // can not happen if the close is requested by the connection itself
1705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // as the front-end defers the close until all transactions are
17068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // complete, but can occur on process termination or forced close.
1707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
1708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TransactionMap transactions(transactions_);
1709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (TransactionMap::const_iterator it = transactions.begin(),
1710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        end = transactions.end();
1711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != end;
1712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (it->second->connection() == connection->callbacks())
1714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        it->second->Abort(
1715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Connection is closing."));
1717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.erase(connection);
1721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_ &&
17225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pending_second_half_open_->connection() == connection) {
17235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_second_half_open_->callbacks()->OnError(
1724f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
1725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "The connection was closed."));
1726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_.reset();
1727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessPendingCalls();
1730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ConnectionCount() && !pending_open_calls_.size() &&
1733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !pending_delete_calls_.size()) {
1734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(transactions_.empty());
1735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL origin_url = backing_store_->origin_url();
17371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store_ = NULL;
17381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // factory_ should only be null in unit tests.
1740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
174158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (factory_) {
17425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_->ReleaseDatabase(identifier_, forced);
174358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      factory_ = NULL;
174458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreAbortOperation(
17493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
1750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
17513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation");
1752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
17533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveObjectStore(object_store_id);
1754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
17573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
1758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
17593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation");
1760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
17613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddObjectStore(object_store_metadata,
17623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 IndexedDBObjectStoreMetadata::kInvalidId);
1763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeAbortOperation(
1766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& previous_version,
17673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 previous_int_version,
1768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
17693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
17713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.version = previous_version;
17723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = previous_int_version;
1773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
1776