indexed_db_database.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/stl_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/indexed_db/indexed_db_connection.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_cursor.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_factory.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_index_writer.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_transaction.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_path.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_range.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Int64ToString16;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebIDBKeyTypeNumber;
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingOpenCall has a scoped_refptr<IndexedDBDatabaseCallbacks> because it
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// isn't a connection yet.
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingOpenCall {
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingOpenCall(scoped_refptr<IndexedDBCallbacks> callbacks,
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  int64 transaction_id,
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  int64 version)
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks),
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_callbacks_(database_callbacks),
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        version_(version),
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction_id_(transaction_id) {}
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBDatabaseCallbacks> const database_callbacks() {
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return database_callbacks_;
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 transaction_id() const { return transaction_id_; }
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks_;
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingUpgradeCall has a scoped_ptr<IndexedDBConnection> because it owns the
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in-progress connection.
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingUpgradeCall {
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingUpgradeCall(scoped_refptr<IndexedDBCallbacks> callbacks,
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     scoped_ptr<IndexedDBConnection> connection,
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 transaction_id,
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callbacks_(callbacks),
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection_(connection.Pass()),
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        version_(version),
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transaction_id_(transaction_id) {}
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Takes ownership of the connection object.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> ReleaseConnection() WARN_UNUSED_RESULT {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return connection_.Pass();
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 transaction_id() const { return transaction_id_; }
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection_;
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingSuccessCall has a IndexedDBConnection* because the connection is now
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// owned elsewhere, but we need to cancel the success call if that connection
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// closes before it is sent.
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingSuccessCall {
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingSuccessCall(scoped_refptr<IndexedDBCallbacks> callbacks,
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     IndexedDBConnection* connection,
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : callbacks_(callbacks), connection_(connection), version_(version) {}
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IndexedDBConnection* connection() const { return connection_; }
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBConnection* connection_;
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingDeleteCall {
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacks> callbacks)
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks) {}
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBFactory* factory,
118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const Identifier& unique_identifier) {
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database =
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!database->OpenInternal())
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return database;
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const base::string16::value_type kNoStringVersion[] = {0};
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBBackingStore* backing_store,
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBFactory* factory,
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     const Identifier& unique_identifier)
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : backing_store_(backing_store),
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_(name,
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId,
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kNoStringVersion,
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION,
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId),
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      identifier_(unique_identifier),
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_(factory) {
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!metadata_.name.empty());
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddObjectStore(
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store,
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_max_object_store_id) {
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store.id) ==
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) {
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id);
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata_.max_object_store_id = new_max_object_store_id;
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store.id] = object_store;
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveObjectStore(int64 object_store_id) {
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.erase(object_store_id);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddIndex(int64 object_store_id,
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const IndexedDBIndexMetadata& index,
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int64 new_max_index_id) {
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end());
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes[index.id] = index;
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) {
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(object_store.max_index_id, new_max_index_id);
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    object_store.max_index_id = new_max_index_id;
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveIndex(int64 object_store_id, int64 index_id) {
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes.erase(index_id);
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::OpenInternal() {
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store_->GetIDBDatabaseMetaData(
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, &metadata_, &success);
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                  << " id = " << metadata_.id;
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (success)
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store_->GetObjectStores(metadata_.id,
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &metadata_.object_stores);
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_->CreateIDBDatabaseMetaData(
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::~IndexedDBDatabase() {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.empty());
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_open_calls_.empty());
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_delete_calls_.empty());
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochIndexedDBTransaction* IndexedDBDatabase::GetTransaction(
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 transaction_id) const {
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TransactionMap::const_iterator trans_iterator =
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transactions_.find(transaction_id);
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (trans_iterator == transactions_.end())
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return NULL;
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return trans_iterator->second;
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreId(int64 object_store_id) const {
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(metadata_.object_stores, object_store_id)) {
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndIndexId(int64 object_store_id,
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                        int64 index_id) const {
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(object_store_metadata.indexes, index_id)) {
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndOptionalIndexId(
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (index_id != IndexedDBIndexMetadata::kInvalidId &&
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !ContainsKey(object_store_metadata.indexes, index_id)) {
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId(
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(object_store_metadata.indexes, index_id)) {
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id,
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                          const base::string16& name,
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const IndexedDBKeyPath& key_path,
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          bool auto_increment) {
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateObjectStore");
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(metadata_.object_stores, object_store_id)) {
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata(
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name,
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_path,
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      auto_increment,
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBDatabase::kMinimumIndexId);
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreOperation,
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id));
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddObjectStore(object_store_metadata, object_store_id);
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreOperation(
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateObjectStore(
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->database()->id(),
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.id,
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.name,
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.key_path,
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.auto_increment)) {
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error creating object store '") +
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            object_store_metadata.name + ASCIIToUTF16("'.")));
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id) {
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteObjectStore");
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreOperation,
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata));
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveObjectStore(object_store_id);
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateIndex(int64 transaction_id,
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id,
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    const base::string16& name,
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const IndexedDBKeyPath& key_path,
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool unique,
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool multi_entry) {
356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateIndex");
3577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndNewIndexId(object_store_id, index_id))
3637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata(
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name, index_id, key_path, unique, multi_entry);
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexOperation,
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation,
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_id));
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, index_id);
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexOperation(
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexOperation");
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   transaction->database()->id(),
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.id,
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.name,
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.key_path,
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.unique,
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.multi_entry)) {
393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error creating index '") +
395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexAbortOperation(
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation");
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id) {
414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteIndex");
4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id))
4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBIndexMetadata& index_metadata =
4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores[object_store_id].indexes[index_id];
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexOperation,
4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation,
4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata));
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexOperation(
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation");
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        object_store_id,
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        index_metadata.id);
447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting index '") +
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexAbortOperation(
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation");
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Commit(int64 transaction_id) {
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend suggests that we commit, but we may have previously initiated
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // an abort, and so have disposed of the transaction. on_abort has already
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // been dispatched to the frontend, so it will find out about that
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // asynchronously.
4707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Commit();
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id) {
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort();
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id,
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const IndexedDBDatabaseError& error) {
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort(error);
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Get(int64 transaction_id,
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 object_store_id,
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 index_id,
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_ptr<IndexedDBKeyRange> key_range,
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            bool key_only,
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks) {
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Get");
4997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
5007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
5047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::GetOperation,
5083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      this,
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Passed(&key_range),
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::GetOperation(
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    indexed_db::CursorType cursor_type,
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::GetOperation");
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[object_store_id];
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKey* key;
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
5333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (key_range->IsOnlyKey()) {
5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = &key_range->lower();
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
5363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // ObjectStore Retrieval Operation
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Value Retrieval Operation
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Referenced Value Retrieval Operation
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!backing_store_cursor) {
5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &backing_store_cursor->key();
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key;
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok;
5753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Object Store Retrieval Operation
5777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string value;
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
5793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   id(),
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   *key,
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   &value);
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnError(
585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 "Internal error in GetRecord."));
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (value.empty()) {
5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (object_store_metadata.auto_increment &&
5963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        !object_store_metadata.key_path.IsNull()) {
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value);
602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // From here we are dealing only with indexes.
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ok = backing_store_->GetPrimaryKeyViaIndex(
607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
6083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      id(),
6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store_id,
6103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      index_id,
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *key,
612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &primary_key);
613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               "Internal error in GetPrimaryKeyViaIndex."));
617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!primary_key) {
6203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Index Value Retrieval Operation
6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(*primary_key);
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Index Referenced Value Retrieval Operation
6307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string value;
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
6323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
6333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 object_store_id,
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 *primary_key,
635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 &value);
636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
6373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               "Internal error in GetRecord."));
640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (value.empty()) {
6443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store_metadata.auto_increment &&
6483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !object_store_metadata.key_path.IsNull()) {
6493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(&value);
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static scoped_ptr<IndexedDBKey> GenerateKey(
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBTransaction* transaction,
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 max_generator_value =
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      9007199254740992LL;  // Maximum integer storable as ECMAScript number.
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 current_number;
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store->GetKeyGeneratorCurrentNumber(
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &current_number);
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "Failed to GetKeyGeneratorCurrentNumber";
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_number < 0 || current_number > max_generator_value)
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return make_scoped_ptr(new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static bool UpdateKeyGenerator(IndexedDBBackingStore* backing_store,
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               IndexedDBTransaction* transaction,
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               int64 database_id,
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               int64 object_store_id,
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const IndexedDBKey& key,
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               bool check_current) {
6843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(WebIDBKeyTypeNumber, key.type());
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
6893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<int64>(floor(key.number())) + 1,
690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_current);
691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::PutOperationParams {
6943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PutOperationParams() {}
6953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
6963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string value;
6973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
6983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::PutMode put_mode;
6993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
7003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<IndexKeys> index_keys;
7013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
7033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
7043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
7053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Put(int64 transaction_id,
707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
7087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                            std::string* value,
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_ptr<IndexedDBKey> key,
710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            PutMode put_mode,
711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks,
712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<IndexKeys>& index_keys) {
713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Put");
7147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
7157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
7207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
7233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<PutOperationParams> params(new PutOperationParams());
7243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
7253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->value.swap(*value);
7263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key = key.Pass();
7273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->put_mode = put_mode;
7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
7293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_keys = index_keys;
7303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::PutOperation, this, base::Passed(&params)));
7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBTransaction* transaction) {
7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::PutOperation");
737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool key_was_generated = false;
739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(params->object_store_id) !=
7413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
7423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store =
7433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[params->object_store_id];
7443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(object_store.auto_increment || params->key->IsValid());
7453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
7483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store.auto_increment && !params->key->IsValid()) {
7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        backing_store_.get(), transaction, id(), params->object_store_id);
751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key_was_generated = true;
752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!auto_inc_key->IsValid()) {
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
754f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Maximum key generator value reached."));
756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = auto_inc_key.Pass();
759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
7603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = params->key.Pass();
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key->IsValid());
764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
7663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool found = false;
768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool ok = backing_store_->KeyExistsInObjectStore(
769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
7703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
7713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->object_store_id,
7723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key,
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &record_identifier,
774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &found);
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
7763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
777f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error checking key existence."));
779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (found) {
7823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
783f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Key already exists in the object store."));
785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
7933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                backing_store_.get(),
7943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                id(),
7953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                object_store,
796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *key,
797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                key_was_generated,
7983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                params->index_keys,
799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
8033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
804f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
805868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
806868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
807868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
808868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
8093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
810f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Before this point, don't do any mutation. After this point, rollback the
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // transaction in case of error.
816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  backing_store_success =
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->PutRecord(transaction->BackingStoreTransaction(),
8183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                id(),
8193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->object_store_id,
8203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                *key,
8213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->value,
822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &record_identifier);
823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
8243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
825f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error performing put/add."));
827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
8333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 backing_store_.get(),
834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
8353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id);
837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store.auto_increment &&
8403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
841ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      key->type() == WebIDBKeyTypeNumber) {
8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool ok = UpdateKeyGenerator(backing_store_.get(),
843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction,
8443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id,
8463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 *key,
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 !key_was_generated);
848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
8493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
850f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
851868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error updating key generator."));
852868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
855868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(*key);
857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 object_store_id,
861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     scoped_ptr<IndexedDBKey> primary_key,
862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<IndexKeys>& index_keys) {
863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexKeys");
8647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
8657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(alecflett): This method could be asynchronous, but we need to
870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // evaluate if it's worth the extra complexity.
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
8731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool ok = backing_store_->KeyExistsInObjectStore(
8741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      transaction->BackingStoreTransaction(),
8751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      metadata_.id,
8761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      object_store_id,
8771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *primary_key,
8781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &record_identifier,
8791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &found);
880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
881868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(
882f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error setting index keys."));
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
887868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
888f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error setting index keys for object store."));
890868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
891868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
892868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
894a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
898868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
9011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                backing_store_,
902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                id(),
903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                object_store_metadata,
904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *primary_key,
905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                false,
906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                index_keys,
907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
912f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
918f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
921868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
922868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
924868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
9251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 backing_store_,
926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 id(),
928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id);
929868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
930868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        int64,
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        const std::vector<int64>& index_ids) {
935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexesReady");
9367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
9397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(
9423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      IndexedDBDatabase::PREEMPTIVE_TASK,
9433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
9443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
9453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_ids.size()));
946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReadyOperation(
9493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t index_count,
9503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
9513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::SetIndexesReadyOperation");
9523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < index_count; ++i)
953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->DidCompletePreemptiveEvent();
954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::OpenCursorOperationParams {
9573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  OpenCursorOperationParams() {}
9583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
9593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 index_id;
9603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKeyRange> key_range;
9613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorDirection direction;
9623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorType cursor_type;
9633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::TaskType task_type;
9643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
9653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
9673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
9683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
9693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
970868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenCursor(
971868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
975868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    indexed_db::CursorDirection direction,
976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
977868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskType task_type,
978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::OpenCursor");
9807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
9827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
9837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
9847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<OpenCursorOperationParams> params(new OpenCursorOperationParams());
9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_id = index_id;
9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key_range = key_range.Pass();
9913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->direction = direction;
9923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->cursor_type =
9933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
9943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->task_type = task_type;
9953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
9963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
9973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(&params)));
9983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
9993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::OpenCursorOperation(
10013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<OpenCursorOperationParams> params,
10023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
10033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::OpenCursorOperation");
1004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend has begun indexing, so this pauses the transaction
1006868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // until the indexing is complete. This can't happen any earlier
1007868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // because we don't want to switch to early mode in case multiple
1008868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // indexes are being created in a row, with Put()'s in between.
10093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
1010868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->AddPreemptiveEvent();
1011868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1012868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
10133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
1014424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1015424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
1016424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1017424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1018424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1019424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1020424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
1021424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->direction);
1022424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
1023424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1024424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1025424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1026424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1027424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->direction);
1029424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
10313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
10323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1033868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1034868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1040868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1041868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1048868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1051868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
10523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnSuccess(static_cast<std::string*>(NULL));
1053868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCursor> cursor =
10573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new IndexedDBCursor(backing_store_cursor.Pass(),
10583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->cursor_type,
10593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->task_type,
10603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          transaction);
10613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(
1062868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor, cursor->key(), cursor->primary_key(), cursor->Value());
1063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1064868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Count(int64 transaction_id,
1066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 index_id,
1068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_ptr<IndexedDBKeyRange> key_range,
1069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Count");
10717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
10727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
10737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1076868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation,
10793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
10803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
10813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       index_id,
10823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
10833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1084868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1085868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CountOperation(
10873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
10883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
10893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
10903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
10913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
10923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CountOperation");
1093868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 count = 0;
1094868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1095868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
1097868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
10993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        index_id,
11093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(count);
1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
1118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ++count;
11197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } while (backing_store_cursor->Continue());
1120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(count);
1122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteRange(
1125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteRange");
11307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
11347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation,
11393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
11403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
11413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
11423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteRangeOperation(
11463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
1151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->OpenObjectStoreCursor(
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
11543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
11553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
11563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (backing_store_cursor) {
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    do {
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!backing_store_->DeleteRecord(
1161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              transaction->BackingStoreTransaction(),
11623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              id(),
11633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              object_store_id,
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              backing_store_cursor->record_identifier())) {
11653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        callbacks->OnError(
1166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Internal error deleting data in range"));
1168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
1169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
11707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } while (backing_store_cursor->Continue());
1171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Clear(int64 transaction_id,
1177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Clear");
11807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
1182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
1184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
11867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
11893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks));
1190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::ClearOperation(
11933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::ObjectStoreClearOperation");
11973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->ClearObjectStore(
11983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          transaction->BackingStoreTransaction(), id(), object_store_id)) {
11993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
1200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error clearing object store"));
1202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreOperation(
12083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
12093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation");
1211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok =
1212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
12143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        object_store_metadata.id);
1215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
1216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
1217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting object store '") +
12183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_metadata.name + ASCIIToUTF16("'.");
1219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
1220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
1221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeOperation(
12253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 version,
12263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBConnection> connection,
1228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
12303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 old_version = metadata_.int_version;
12313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GT(version, old_version);
12323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = version;
12333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->UpdateIDBDatabaseIntVersion(
1234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
12353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
12363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          metadata_.int_version)) {
1237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseError error(
1238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
12397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ASCIIToUTF16(
12407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "Internal error writing data to stable storage when "
12417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "updating version."));
12423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(error);
1243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(error);
1244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_second_half_open_.reset(
1248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new PendingSuccessCall(callbacks, connection.get(), version));
12495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callbacks->OnUpgradeNeeded(old_version, connection.Pass(), metadata());
1250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
12535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool committed) {
1254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction->id()) != transactions_.end());
1255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transactions_[transaction->id()], transaction);
1256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transactions_.erase(transaction->id());
1257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (committed) {
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK_EQ(pending_second_half_open_->version(), metadata_.int_version);
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(metadata_.id != kInvalidId);
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Connection was already minted for OnUpgradeNeeded callback.
12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scoped_ptr<IndexedDBConnection> connection;
12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnSuccess(connection.Pass(),
12675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                          this->metadata());
12685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
12695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnError(
12705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
12715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "Version change transaction was aborted in "
12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "upgradeneeded event handler."));
12735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
12775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Connection queue is now unblocked.
1278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBDatabase::TransactionCommitFailed() {
12835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Factory may be null in unit tests.
12845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!factory_)
12855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
12861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  factory_->HandleBackingStoreFailure(backing_store_->origin_url());
12871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
12881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t IndexedDBDatabase::ConnectionCount() const {
1290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This does not include pending open calls, as those should not block version
1291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changes and deletes.
1292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return connections_.size();
1293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingOpenCount() const {
1296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_open_calls_.size();
1297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingUpgradeCount() const {
1300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_run_version_change_transaction_call_ ? 1 : 0;
1301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::RunningUpgradeCount() const {
1304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_second_half_open_ ? 1 : 0;
1305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingDeleteCount() const {
1308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_delete_calls_.size();
1309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::ProcessPendingCalls() {
1312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
13135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(pending_run_version_change_transaction_call_->version() >
1314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           metadata_.int_version);
1315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<PendingUpgradeCall> pending_call =
1316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_run_version_change_transaction_call_.Pass();
13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunVersionChangeTransactionFinal(pending_call->callbacks(),
13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->ReleaseConnection(),
13195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->transaction_id(),
13205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->version());
13215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(1u, ConnectionCount());
1322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through would be a no-op, since transaction must complete
1323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // asynchronously.
1324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsDeleteDatabaseBlocked());
1325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsOpenConnectionBlocked());
1326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDeleteDatabaseBlocked()) {
1330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingDeleteCallList pending_delete_calls;
1331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.swap(pending_delete_calls);
1332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_delete_calls.empty()) {
1333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Only the first delete call will delete the database, but each must fire
1334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // callbacks.
1335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingDeleteCall> pending_delete_call(
1336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pending_delete_calls.front());
1337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_delete_calls.pop_front();
13385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DeleteDatabaseFinal(pending_delete_call->callbacks());
1339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // delete_database_final should never re-queue calls.
1341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_delete_calls_.empty());
1342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsOpenConnectionBlocked()) {
1346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingOpenCallList pending_open_calls;
1347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.swap(pending_open_calls);
1348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_open_calls.empty()) {
1349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingOpenCall> pending_open_call(pending_open_calls.front());
1350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_open_calls.pop_front();
13515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      OpenConnection(pending_open_call->callbacks(),
13525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     pending_open_call->database_callbacks(),
13535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     pending_open_call->transaction_id(),
13545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     pending_open_call->version());
1355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateTransaction(
1360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexedDBConnection* connection,
1362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::vector<int64>& object_store_ids,
1363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint16 mode) {
1364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
13664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(transactions_.find(transaction_id) == transactions_.end());
13674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
13684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The transaction will add itself to this database's coordinator, which
13715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // manages the lifetime of the object.
13725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TransactionCreated(new IndexedDBTransaction(
13737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transaction_id,
13747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      connection->callbacks(),
13757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
13767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      static_cast<indexed_db::TransactionMode>(mode),
1377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      this,
13785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new IndexedDBBackingStore::Transaction(backing_store_)));
1379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) {
1382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transactions_[transaction->id()] = transaction;
1383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !pending_delete_calls_.empty() ||
13875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         transaction_coordinator_.IsRunningVersionChangeTransaction() ||
1388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         pending_run_version_change_transaction_call_;
1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenConnection(
1392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
1394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 version) {
1396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Should have a priority queue so that higher version
1399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // requests are processed first. http://crbug.com/225850
1400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsOpenConnectionBlocked()) {
1401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // The backing store only detects data loss when it is first opened. The
1402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // presence of existing connections means we didn't even check for data loss
1403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // so there'd better not be any.
14045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
1405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.push_back(new PendingOpenCall(
1406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks, database_callbacks, transaction_id, version));
1407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata_.id == kInvalidId) {
1411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The database was deleted then immediately re-opened; OpenInternal()
1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // recreates it in the backing store.
1413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (OpenInternal()) {
1414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
1415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                metadata_.int_version);
1416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 message;
14185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = ASCIIToUTF16(
1420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "Internal error opening database with no version specified.");
14215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
1422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message =
1423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16("Internal error opening database with version ") +
1424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(version);
14255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks->OnError(IndexedDBDatabaseError(
1427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          blink::WebIDBDatabaseExceptionUnknownError, message));
1428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We infer that the database didn't exist from its lack of either type of
1433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // version.
1434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_new_database =
1435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.version == kNoStringVersion &&
1436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
1437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection(
1439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new IndexedDBConnection(this, database_callbacks));
1440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
1442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // For unit tests only - skip upgrade steps. Calling from script with
1443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // DEFAULT_INT_VERSION throws exception.
1444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK that not in unit tests.
1445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(is_new_database);
1446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    connections_.insert(connection.get());
1447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    callbacks->OnSuccess(connection.Pass(), this->metadata());
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_new_database) {
1453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      connections_.insert(connection.get());
1454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callbacks->OnSuccess(connection.Pass(), this->metadata());
1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Spec says: If no version is specified and no database exists, set
1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database version to 1.
1459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    version = 1;
1460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version > metadata_.int_version) {
1463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    connections_.insert(connection.get());
14645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunVersionChangeTransaction(
14655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callbacks, connection.Pass(), transaction_id, version);
1466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version < metadata_.int_version) {
1469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(IndexedDBDatabaseError(
1470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionVersionError,
1471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("The requested version (") + Int64ToString16(version) +
1472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16(") is less than the existing version (") +
1473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(version, metadata_.int_version);
1477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.insert(connection.get());
1478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callbacks->OnSuccess(connection.Pass(), this->metadata());
1479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransaction(
1482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 requested_version) {
1486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(callbacks);
14888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection.get()));
1489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ConnectionCount() > 1) {
14905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
1491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Front end ensures the event is not fired at connections that have
1492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // close_pending set.
1493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (*it != connection.get()) {
14973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*it)->callbacks()->OnVersionChange(metadata_.int_version,
14983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            requested_version);
1499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
1500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Remove the call to OnBlocked and instead wait
1502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // until the frontend tells us that all the "versionchange" events
1503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // have been delivered.  http://crbug.com/100123
1504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!pending_run_version_change_transaction_call_);
1507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pending_run_version_change_transaction_call_.reset(new PendingUpgradeCall(
1508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        callbacks, connection.Pass(), transaction_id, requested_version));
1509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
15115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunVersionChangeTransactionFinal(
15125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callbacks, connection.Pass(), transaction_id, requested_version);
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<int64> object_store_ids;
1522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateTransaction(transaction_id,
1523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    connection.get(),
1524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    object_store_ids,
1525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    indexed_db::TRANSACTION_VERSION_CHANGE);
1526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  transactions_[transaction_id]
15285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ->ScheduleTask(base::Bind(&IndexedDBDatabase::VersionChangeOperation,
15295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
15305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                requested_version,
15315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                callbacks,
15325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                base::Passed(&connection)),
15335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
15345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
15355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.version,
15365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.int_version));
1537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabase(
1542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDeleteDatabaseBlocked()) {
1545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Front end ensures the event is not fired at connections that have
1549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // close_pending set.
1550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*it)->callbacks()->OnVersionChange(
1551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
1552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Only fire OnBlocked if there are open
1554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // connections after the VersionChangeEvents are received, not
1555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // just set up to fire.  http://crbug.com/100123
1556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
1558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteDatabaseFinal(callbacks);
1561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !!ConnectionCount();
1565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabaseFinal(
1568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!IsDeleteDatabaseBlocked());
1570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->DeleteDatabase(metadata_.name)) {
1572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(
1573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error deleting database."));
1575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.id = kInvalidId;
1579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.clear();
1581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks->OnSuccess();
15825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (factory_)
15835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    factory_->DatabaseDeleted(identifier_);
15845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::ForceClose() {
15875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IndexedDBConnection::ForceClose() may delete this database, so hold ref.
15885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> protect(this);
15895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConnectionSet::const_iterator it = connections_.begin();
15905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (it != connections_.end()) {
15915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBConnection* connection = *it++;
15925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection->ForceClose();
15935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
15945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(connections_.empty());
1595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
159758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
15988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
15998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->IsConnected());
16008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->database() == this);
1601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Abort outstanding transactions from the closing connection. This
1603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // can not happen if the close is requested by the connection itself
1604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // as the front-end defers the close until all transactions are
16058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // complete, but can occur on process termination or forced close.
1606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
1607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TransactionMap transactions(transactions_);
1608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (TransactionMap::const_iterator it = transactions.begin(),
1609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        end = transactions.end();
1610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != end;
1611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (it->second->connection() == connection->callbacks())
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        it->second->Abort(
1614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Connection is closing."));
1616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.erase(connection);
1620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_ &&
16215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pending_second_half_open_->connection() == connection) {
16225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_second_half_open_->callbacks()->OnError(
1623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
1624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "The connection was closed."));
1625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_.reset();
1626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessPendingCalls();
1629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ConnectionCount() && !pending_open_calls_.size() &&
1632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !pending_delete_calls_.size()) {
1633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(transactions_.empty());
1634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL origin_url = backing_store_->origin_url();
16361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store_ = NULL;
16371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // factory_ should only be null in unit tests.
1639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
164058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (factory_) {
16415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_->ReleaseDatabase(identifier_, forced);
164258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      factory_ = NULL;
164358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreAbortOperation(
16483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
1649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation");
1651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveObjectStore(object_store_id);
1653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
16563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
1657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation");
1659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddObjectStore(object_store_metadata,
16613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 IndexedDBObjectStoreMetadata::kInvalidId);
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeAbortOperation(
1665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& previous_version,
16663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 previous_int_version,
1667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.version = previous_version;
16713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = previous_int_version;
1672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
1675