indexed_db_database.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/indexed_db/indexed_db_connection.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_cursor.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_factory.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_index_writer.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_transaction.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_path.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_range.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/browser_thread.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Int64ToString16;
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochusing WebKit::WebIDBKeyTypeNumber;
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingOpenCall has a scoped_refptr<IndexedDBDatabaseCallbacks> because it
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// isn't a connection yet.
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingOpenCall {
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingOpenCall(scoped_refptr<IndexedDBCallbacks> callbacks,
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  int64 transaction_id,
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  int64 version)
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks),
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_callbacks_(database_callbacks),
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        version_(version),
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction_id_(transaction_id) {}
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> Callbacks() { return callbacks_; }
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBDatabaseCallbacks> DatabaseCallbacks() {
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return database_callbacks_;
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 Version() { return version_; }
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 TransactionId() const { return transaction_id_; }
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks_;
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingUpgradeCall has a scoped_ptr<IndexedDBConnection> because it owns the
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in-progress connection.
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingUpgradeCall {
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingUpgradeCall(scoped_refptr<IndexedDBCallbacks> callbacks,
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     scoped_ptr<IndexedDBConnection> connection,
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 transaction_id,
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callbacks_(callbacks),
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection_(connection.Pass()),
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        version_(version),
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transaction_id_(transaction_id) {}
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> Callbacks() { return callbacks_; }
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> Connection() { return connection_.Pass(); }
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 Version() { return version_; }
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 TransactionId() const { return transaction_id_; }
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection_;
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingSuccessCall has a IndexedDBConnection* because the connection is now
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// owned elsewhere, but we need to cancel the success call if that connection
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// closes before it is sent.
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingSuccessCall {
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingSuccessCall(scoped_refptr<IndexedDBCallbacks> callbacks,
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     IndexedDBConnection* connection,
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 transaction_id,
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callbacks_(callbacks),
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection_(connection),
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        version_(version),
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transaction_id_(transaction_id) {}
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> Callbacks() { return callbacks_; }
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBConnection* Connection() { return connection_; }
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 Version() { return version_; }
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 TransactionId() const { return transaction_id_; }
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBConnection* connection_;
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 transaction_id_;
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingDeleteCall {
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacks> callbacks)
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks) {}
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> Callbacks() { return callbacks_; }
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const string16& name,
118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBFactory* factory,
120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const Identifier& unique_identifier) {
121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database =
122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!database->OpenInternal())
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return database;
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const base::string16::value_type kNoStringVersion[] = {0};
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochtemplate <typename T, typename U>
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool Contains(const T& container, const U& item) {
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return container.find(item) != container.end();
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)IndexedDBDatabase::IndexedDBDatabase(const string16& name,
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBBackingStore* backing_store,
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBFactory* factory,
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     const Identifier& unique_identifier)
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : backing_store_(backing_store),
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_(name,
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId,
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kNoStringVersion,
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION,
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId),
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      identifier_(unique_identifier),
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      factory_(factory),
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      running_version_change_transaction_(NULL) {
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!metadata_.name.empty());
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddObjectStore(
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store,
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_max_object_store_id) {
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store.id) ==
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) {
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id);
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata_.max_object_store_id = new_max_object_store_id;
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store.id] = object_store;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveObjectStore(int64 object_store_id) {
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.erase(object_store_id);
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddIndex(int64 object_store_id,
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const IndexedDBIndexMetadata& index,
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int64 new_max_index_id) {
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end());
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes[index.id] = index;
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) {
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(object_store.max_index_id, new_max_index_id);
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    object_store.max_index_id = new_max_index_id;
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveIndex(int64 object_store_id, int64 index_id) {
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes.erase(index_id);
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::OpenInternal() {
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store_->GetIDBDatabaseMetaData(
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, &metadata_, &success);
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                  << " id = " << metadata_.id;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok)
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (success)
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store_->GetObjectStores(metadata_.id,
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &metadata_.object_stores);
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_->CreateIDBDatabaseMetaData(
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::~IndexedDBDatabase() {
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.empty());
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_open_calls_.empty());
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_delete_calls_.empty());
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochIndexedDBTransaction* IndexedDBDatabase::GetTransaction(
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 transaction_id) const {
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TransactionMap::const_iterator trans_iterator =
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transactions_.find(transaction_id);
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (trans_iterator == transactions_.end())
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return NULL;
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return trans_iterator->second;
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreId(int64 object_store_id) const {
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!Contains(metadata_.object_stores, object_store_id)) {
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndIndexId(int64 object_store_id,
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                        int64 index_id) const {
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!Contains(object_store_metadata.indexes, index_id)) {
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndOptionalIndexId(
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (index_id != IndexedDBIndexMetadata::kInvalidId &&
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      !Contains(object_store_metadata.indexes, index_id)) {
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId(
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (Contains(object_store_metadata.indexes, index_id)) {
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id,
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const string16& name,
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const IndexedDBKeyPath& key_path,
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          bool auto_increment) {
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateObjectStore");
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (Contains(metadata_.object_stores, object_store_id)) {
2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata(
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name,
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_path,
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      auto_increment,
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBDatabase::kMinimumIndexId);
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreOperation,
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id));
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddObjectStore(object_store_metadata, object_store_id);
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreOperation(
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateObjectStore(
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->database()->id(),
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.id,
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.name,
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.key_path,
3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.auto_increment)) {
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error creating object store '") +
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            object_store_metadata.name + ASCIIToUTF16("'.")));
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id) {
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteObjectStore");
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreOperation,
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata));
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveObjectStore(object_store_id);
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateIndex(int64 transaction_id,
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id,
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const string16& name,
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const IndexedDBKeyPath& key_path,
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool unique,
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool multi_entry) {
364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateIndex");
3657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndNewIndexId(object_store_id, index_id))
3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata(
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name, index_id, key_path, unique, multi_entry);
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexOperation,
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation,
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_id));
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, index_id);
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexOperation(
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexOperation");
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   transaction->database()->id(),
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.id,
3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.name,
3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.key_path,
3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.unique,
4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.multi_entry)) {
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    string16 error_string = ASCIIToUTF16("Internal error creating index '") +
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            index_metadata.name + ASCIIToUTF16("'.");
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexAbortOperation(
4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation");
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id) {
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteIndex");
4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id))
4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBIndexMetadata& index_metadata =
4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores[object_store_id].indexes[index_id];
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexOperation,
4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation,
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata));
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexOperation(
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation");
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        object_store_id,
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        index_metadata.id);
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    string16 error_string = ASCIIToUTF16("Internal error deleting index '") +
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            index_metadata.name + ASCIIToUTF16("'.");
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexAbortOperation(
4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation");
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Commit(int64 transaction_id) {
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend suggests that we commit, but we may have previously initiated
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // an abort, and so have disposed of the transaction. on_abort has already
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // been dispatched to the frontend, so it will find out about that
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // asynchronously.
4767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Commit();
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id) {
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort();
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id,
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const IndexedDBDatabaseError& error) {
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort(error);
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Get(int64 transaction_id,
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 object_store_id,
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 index_id,
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_ptr<IndexedDBKeyRange> key_range,
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            bool key_only,
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks) {
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Get");
5057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::GetOperation,
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      this,
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Passed(&key_range),
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::GetOperation(
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    indexed_db::CursorType cursor_type,
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::GetOperation");
5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
5333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[object_store_id];
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKey* key;
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
5393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (key_range->IsOnlyKey()) {
5403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = &key_range->lower();
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
5423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
5433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // ObjectStore Retrieval Operation
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
5513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Value Retrieval Operation
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Referenced Value Retrieval Operation
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!backing_store_cursor) {
5723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &backing_store_cursor->key();
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key;
580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok;
5813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Object Store Retrieval Operation
5837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string value;
584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
5853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   id(),
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   *key,
588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   &value);
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnError(
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 "Internal error in GetRecord."));
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (value.empty()) {
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (object_store_metadata.auto_increment &&
6023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        !object_store_metadata.key_path.IsNull()) {
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value);
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // From here we are dealing only with indexes.
612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ok = backing_store_->GetPrimaryKeyViaIndex(
613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      id(),
6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store_id,
6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      index_id,
617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *key,
618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &primary_key);
619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
6203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               "Internal error in GetPrimaryKeyViaIndex."));
623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!primary_key) {
6263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Index Value Retrieval Operation
6313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(*primary_key);
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Index Referenced Value Retrieval Operation
6367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string value;
637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
6383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
6393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 object_store_id,
640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 *primary_key,
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 &value);
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
6433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               "Internal error in GetRecord."));
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (value.empty()) {
6503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store_metadata.auto_increment &&
6543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !object_store_metadata.key_path.IsNull()) {
6553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(&value);
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static scoped_ptr<IndexedDBKey> GenerateKey(
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBBackingStore> backing_store,
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBTransaction> transaction,
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 max_generator_value =
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      9007199254740992LL;  // Maximum integer storable as ECMAScript number.
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 current_number;
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store->GetKeyGeneratorCurrentNumber(
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &current_number);
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "Failed to GetKeyGeneratorCurrentNumber";
676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_number < 0 || current_number > max_generator_value)
679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return make_scoped_ptr(new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static bool UpdateKeyGenerator(
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBBackingStore> backing_store,
686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBTransaction> transaction,
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
6893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBKey& key,
690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool check_current) {
6913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(WebIDBKeyTypeNumber, key.type());
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
6963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<int64>(floor(key.number())) + 1,
697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_current);
698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::PutOperationParams {
7013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PutOperationParams() {}
7023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
7033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string value;
7043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::PutMode put_mode;
7063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
7073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<int64> index_ids;
7083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<IndexKeys> index_keys;
7093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
7113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
7123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Put(int64 transaction_id,
714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
7157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                            std::string* value,
716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_ptr<IndexedDBKey> key,
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            PutMode put_mode,
718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks,
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<int64>& index_ids,
720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<IndexKeys>& index_keys) {
721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Put");
7227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
7237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
7287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<PutOperationParams> params(new PutOperationParams());
7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
7333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->value.swap(*value);
7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key = key.Pass();
7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->put_mode = put_mode;
7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_ids = index_ids;
7383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_keys = index_keys;
7393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
7403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::PutOperation, this, base::Passed(&params)));
7413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
7443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBTransaction* transaction) {
7453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::PutOperation");
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
7473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(params->index_ids.size(), params->index_keys.size());
748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool key_was_generated = false;
749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(params->object_store_id) !=
7513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
7523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store =
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[params->object_store_id];
7543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(object_store.auto_increment || params->key->IsValid());
7553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
7583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store.auto_increment && !params->key->IsValid()) {
7593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKey> auto_inc_key =
7603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        GenerateKey(backing_store_, transaction, id(), params->object_store_id);
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key_was_generated = true;
762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!auto_inc_key->IsValid()) {
7633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Maximum key generator value reached."));
766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = auto_inc_key.Pass();
769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
7703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = params->key.Pass();
771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key->IsValid());
774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
7763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool found = false;
778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool ok = backing_store_->KeyExistsInObjectStore(
779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
7803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
7813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->object_store_id,
7823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key,
783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &record_identifier,
784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &found);
785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
7863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error checking key existence."));
789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (found) {
7923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Key already exists in the object store."));
795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  string16 error_message;
801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
8033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                backing_store_.get(),
8043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                id(),
8053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                object_store,
806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *key,
807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                key_was_generated,
8083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                params->index_ids,
8093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                params->index_keys,
810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
8143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
8203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionConstraintError, error_message));
822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Before this point, don't do any mutation. After this point, rollback the
826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // transaction in case of error.
827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  backing_store_success =
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->PutRecord(transaction->BackingStoreTransaction(),
8293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                id(),
8303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->object_store_id,
8313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                *key,
8323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->value,
833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &record_identifier);
834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
8353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error performing put/add."));
838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
8443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 backing_store_.get(),
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
8463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id);
848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store.auto_increment &&
8513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      key->type() == WebIDBKeyTypeNumber) {
853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool ok = UpdateKeyGenerator(backing_store_,
854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction,
8553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id,
8573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 *key,
858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 !key_was_generated);
859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
8603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error updating key generator."));
863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(*key);
868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 object_store_id,
872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     scoped_ptr<IndexedDBKey> primary_key,
873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<int64>& index_ids,
874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<IndexKeys>& index_keys) {
875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexKeys");
8767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
8777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
879868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(alecflett): This method could be asynchronous, but we need to
882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // evaluate if it's worth the extra complexity.
883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
8851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool ok = backing_store_->KeyExistsInObjectStore(
8861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      transaction->BackingStoreTransaction(),
8871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      metadata_.id,
8881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      object_store_id,
8891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *primary_key,
8901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &record_identifier,
8911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &found);
892868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(
894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error setting index keys."));
896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
898868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error setting index keys for object store."));
902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  string16 error_message;
907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
9131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                backing_store_,
914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                id(),
915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                object_store_metadata,
916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *primary_key,
917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                false,
918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                index_ids,
919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                index_keys,
920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
923868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
924868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
925868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
929868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
930868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionConstraintError, error_message));
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
9381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 backing_store_,
939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 id(),
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id);
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
944868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        int64,
947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        const std::vector<int64>& index_ids) {
948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexesReady");
9497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
9527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(
9553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      IndexedDBDatabase::PREEMPTIVE_TASK,
9563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
9573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
9583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_ids.size()));
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReadyOperation(
9623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t index_count,
9633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
9643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::SetIndexesReadyOperation");
9653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < index_count; ++i)
966868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->DidCompletePreemptiveEvent();
967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::OpenCursorOperationParams {
9703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  OpenCursorOperationParams() {}
9713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
9723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 index_id;
9733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKeyRange> key_range;
9743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorDirection direction;
9753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorType cursor_type;
9763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::TaskType task_type;
9773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
9783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
9803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
9813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
982868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenCursor(
983868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
984868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    indexed_db::CursorDirection direction,
988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
989868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskType task_type,
990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::OpenCursor");
9927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
9947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
9957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
9967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<OpenCursorOperationParams> params(new OpenCursorOperationParams());
10003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
10013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_id = index_id;
10023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key_range = key_range.Pass();
10033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->direction = direction;
10043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->cursor_type =
10053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
10063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->task_type = task_type;
10073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
10083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
10093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(&params)));
10103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::OpenCursorOperation(
10133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<OpenCursorOperationParams> params,
10143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
10153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::OpenCursorOperation");
1016868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend has begun indexing, so this pauses the transaction
1018868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // until the indexing is complete. This can't happen any earlier
1019868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // because we don't want to switch to early mode in case multiple
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // indexes are being created in a row, with Put()'s in between.
10213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
1022868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->AddPreemptiveEvent();
1023868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
10253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
1026424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1027424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
1028424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1029424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1030424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1031424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1032424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
1033424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->direction);
1034424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
1035424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1036424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1037424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1038424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1039424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->direction);
1041424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1045868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1052868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1053868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
1054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1060868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1061868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1062868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
10643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnSuccess(static_cast<std::string*>(NULL));
1065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1066868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCursor> cursor =
10693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new IndexedDBCursor(backing_store_cursor.Pass(),
10703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->cursor_type,
10713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->task_type,
10723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          transaction);
10733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(
1074868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor, cursor->key(), cursor->primary_key(), cursor->Value());
1075868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1076868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Count(int64 transaction_id,
1078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 index_id,
1080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_ptr<IndexedDBKeyRange> key_range,
1081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Count");
10837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
10847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
10857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation,
10913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
10923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
10933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       index_id,
10943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
10953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1096868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1097868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CountOperation(
10993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
11013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CountOperation");
1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 count = 0;
1106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
1109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        index_id,
11213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(count);
1126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
1130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ++count;
11317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } while (backing_store_cursor->Continue());
1132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(count);
1134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteRange(
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteRange");
11427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
11447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
11467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation,
11513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
11523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
11533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
11543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteRangeOperation(
11583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
1163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->OpenObjectStoreCursor(
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
11663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
11673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
11683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
1169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
1170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (backing_store_cursor) {
1171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    do {
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!backing_store_->DeleteRecord(
1173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              transaction->BackingStoreTransaction(),
11743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              id(),
11753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              object_store_id,
1176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              backing_store_cursor->record_identifier())) {
11773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        callbacks->OnError(
1178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Internal error deleting data in range"));
1180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
1181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
11827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } while (backing_store_cursor->Continue());
1183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Clear(int64 transaction_id,
1189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Clear");
11927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
1194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
1196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
11987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
12003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
12013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks));
1202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::ClearOperation(
12053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
12063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::ObjectStoreClearOperation");
12093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->ClearObjectStore(
12103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          transaction->BackingStoreTransaction(), id(), object_store_id)) {
12113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
1212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error clearing object store"));
1214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreOperation(
12203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
12213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation");
1223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok =
1224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
12263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        object_store_metadata.id);
1227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
1228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    string16 error_string =
1229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting object store '") +
12303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_metadata.name + ASCIIToUTF16("'.");
1231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
1232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
1233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeOperation(
12373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 version,
12383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBConnection> connection,
12403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    WebKit::WebIDBCallbacks::DataLoss data_loss,
1241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
12433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 old_version = metadata_.int_version;
12443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GT(version, old_version);
12453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = version;
12463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->UpdateIDBDatabaseIntVersion(
1247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
12483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
12493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          metadata_.int_version)) {
1250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseError error(
1251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
12527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ASCIIToUTF16(
12537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "Internal error writing data to stable storage when "
12547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "updating version."));
12553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(error);
1256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(error);
1257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
12603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  pending_second_half_open_.reset(new PendingSuccessCall(
12613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks, connection.get(), transaction->id(), version));
12623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnUpgradeNeeded(
12633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      old_version, connection.Pass(), metadata(), data_loss);
1264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionStarted(IndexedDBTransaction* transaction) {
1267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!running_version_change_transaction_);
1270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    running_version_change_transaction_ = transaction;
1271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction) {
1275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction->id()) != transactions_.end());
1277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transactions_[transaction->id()], transaction);
1278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transactions_.erase(transaction->id());
1279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(transaction, running_version_change_transaction_);
1281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    running_version_change_transaction_ = NULL;
1282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionFinishedAndAbortFired(
1286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
1289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_->Callbacks()->OnError(
1290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionAbortError,
1291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Version change transaction was aborted in "
1292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "upgradeneeded event handler."));
1293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionFinishedAndCompleteFired(
1300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_second_half_open_);
1303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
1304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK_EQ(pending_second_half_open_->Version(), metadata_.int_version);
1305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK(metadata_.id != kInvalidId);
1306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // Connection was already minted for OnUpgradeNeeded callback.
1308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      scoped_ptr<IndexedDBConnection> connection;
1309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
13103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      pending_second_half_open_->Callbacks()->OnSuccess(connection.Pass(),
13113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        this->metadata());
1312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBDatabase::TransactionCommitFailed() {
13191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  factory_->HandleBackingStoreFailure(backing_store_->origin_url());
13201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
13211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t IndexedDBDatabase::ConnectionCount() const {
1323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This does not include pending open calls, as those should not block version
1324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changes and deletes.
1325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return connections_.size();
1326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingOpenCount() const {
1329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_open_calls_.size();
1330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingUpgradeCount() const {
1333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_run_version_change_transaction_call_ ? 1 : 0;
1334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::RunningUpgradeCount() const {
1337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_second_half_open_ ? 1 : 0;
1338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingDeleteCount() const {
1341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_delete_calls_.size();
1342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::ProcessPendingCalls() {
1345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
1346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_run_version_change_transaction_call_->Version() >
1347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           metadata_.int_version);
1348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<PendingUpgradeCall> pending_call =
1349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_run_version_change_transaction_call_.Pass();
1350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RunVersionChangeTransactionFinal(pending_call->Callbacks(),
1351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     pending_call->Connection(),
1352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     pending_call->TransactionId(),
1353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     pending_call->Version());
1354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(static_cast<size_t>(1), ConnectionCount());
1355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through would be a no-op, since transaction must complete
1356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // asynchronously.
1357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsDeleteDatabaseBlocked());
1358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsOpenConnectionBlocked());
1359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDeleteDatabaseBlocked()) {
1363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingDeleteCallList pending_delete_calls;
1364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.swap(pending_delete_calls);
1365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_delete_calls.empty()) {
1366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Only the first delete call will delete the database, but each must fire
1367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // callbacks.
1368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingDeleteCall> pending_delete_call(
1369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pending_delete_calls.front());
1370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_delete_calls.pop_front();
1371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DeleteDatabaseFinal(pending_delete_call->Callbacks());
1372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // delete_database_final should never re-queue calls.
1374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_delete_calls_.empty());
1375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsOpenConnectionBlocked()) {
1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingOpenCallList pending_open_calls;
1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.swap(pending_open_calls);
1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_open_calls.empty()) {
1382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingOpenCall> pending_open_call(pending_open_calls.front());
1383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_open_calls.pop_front();
1384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      OpenConnection(pending_open_call->Callbacks(),
1385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pending_open_call->DatabaseCallbacks(),
1386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pending_open_call->TransactionId(),
1387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pending_open_call->Version());
1388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateTransaction(
1393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexedDBConnection* connection,
1395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::vector<int64>& object_store_ids,
1396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint16 mode) {
1397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
13994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(transactions_.find(transaction_id) == transactions_.end());
14004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
14014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
14047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transaction_id,
14057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      connection->callbacks(),
14067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
14077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      static_cast<indexed_db::TransactionMode>(mode),
14087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      this);
1409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  transactions_[transaction_id] = transaction;
1410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !pending_delete_calls_.empty() ||
1414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         running_version_change_transaction_ ||
1415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         pending_run_version_change_transaction_call_;
1416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenConnection(
1419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
1421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 version) {
1423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const WebKit::WebIDBCallbacks::DataLoss kDataLoss =
1424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      WebKit::WebIDBCallbacks::DataLossNone;
1425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OpenConnection(
1426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callbacks, database_callbacks, transaction_id, version, kDataLoss);
1427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::OpenConnection(
1430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
1432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 transaction_id,
1433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 version,
1434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    WebKit::WebIDBCallbacks::DataLoss data_loss) {
1435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Should have a priority queue so that higher version
1438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // requests are processed first. http://crbug.com/225850
1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsOpenConnectionBlocked()) {
1440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // The backing store only detects data loss when it is first opened. The
1441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // presence of existing connections means we didn't even check for data loss
1442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // so there'd better not be any.
1443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK_NE(WebKit::WebIDBCallbacks::DataLossTotal, data_loss);
1444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.push_back(new PendingOpenCall(
1445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks, database_callbacks, transaction_id, version));
1446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata_.id == kInvalidId) {
1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The database was deleted then immediately re-opened; OpenInternal()
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // recreates it in the backing store.
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (OpenInternal()) {
1453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
1454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                metadata_.int_version);
1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      string16 message;
1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = ASCIIToUTF16(
1459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "Internal error opening database with no version specified.");
1460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      else
1461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message =
1462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16("Internal error opening database with version ") +
1463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(version);
1464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks->OnError(IndexedDBDatabaseError(
1465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          WebKit::WebIDBDatabaseExceptionUnknownError, message));
1466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We infer that the database didn't exist from its lack of either type of
1471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // version.
1472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_new_database =
1473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.version == kNoStringVersion &&
1474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
1475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection(
1477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new IndexedDBConnection(this, database_callbacks));
1478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // For unit tests only - skip upgrade steps. Calling from script with
1481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // DEFAULT_INT_VERSION throws exception.
1482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK that not in unit tests.
1483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(is_new_database);
1484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    connections_.insert(connection.get());
1485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    callbacks->OnSuccess(connection.Pass(), this->metadata());
1486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_new_database) {
1491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      connections_.insert(connection.get());
1492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callbacks->OnSuccess(connection.Pass(), this->metadata());
1493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Spec says: If no version is specified and no database exists, set
1496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database version to 1.
1497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    version = 1;
1498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version > metadata_.int_version) {
1501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    connections_.insert(connection.get());
1502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RunVersionChangeTransaction(
1503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        callbacks, connection.Pass(), transaction_id, version, data_loss);
1504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version < metadata_.int_version) {
1507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(IndexedDBDatabaseError(
1508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionVersionError,
1509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("The requested version (") + Int64ToString16(version) +
1510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16(") is less than the existing version (") +
1511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(version, metadata_.int_version);
1515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.insert(connection.get());
1516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callbacks->OnSuccess(connection.Pass(), this->metadata());
1517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransaction(
1520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 requested_version,
1524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    WebKit::WebIDBCallbacks::DataLoss data_loss) {
1525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(callbacks);
15278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection.get()));
1528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ConnectionCount() > 1) {
1529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK_NE(WebKit::WebIDBCallbacks::DataLossTotal, data_loss);
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Front end ensures the event is not fired at connections that have
1531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // close_pending set.
1532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (*it != connection.get()) {
15363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*it)->callbacks()->OnVersionChange(metadata_.int_version,
15373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            requested_version);
1538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
1539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Remove the call to OnBlocked and instead wait
1541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // until the frontend tells us that all the "versionchange" events
1542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // have been delivered.  http://crbug.com/100123
1543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!pending_run_version_change_transaction_call_);
1546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pending_run_version_change_transaction_call_.reset(new PendingUpgradeCall(
1547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        callbacks, connection.Pass(), transaction_id, requested_version));
1548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunVersionChangeTransactionFinal(callbacks,
1551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   connection.Pass(),
1552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   transaction_id,
1553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   requested_version,
1554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   data_loss);
1555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const WebKit::WebIDBCallbacks::DataLoss kDataLoss =
1563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      WebKit::WebIDBCallbacks::DataLossNone;
1564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunVersionChangeTransactionFinal(callbacks,
1565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   connection.Pass(),
1566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   transaction_id,
1567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   requested_version,
1568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   kDataLoss);
1569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::RunVersionChangeTransactionFinal(
1572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 transaction_id,
1575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 requested_version,
1576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    WebKit::WebIDBCallbacks::DataLoss data_loss) {
1577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<int64> object_store_ids;
1579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateTransaction(transaction_id,
1580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    connection.get(),
1581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    object_store_ids,
1582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    indexed_db::TRANSACTION_VERSION_CHANGE);
1583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBTransaction> transaction =
1584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_[transaction_id];
1585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
15873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::VersionChangeOperation,
15883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
15893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 requested_version,
15903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 callbacks,
15913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 base::Passed(&connection),
15923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 data_loss),
15933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
15943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
15953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 metadata_.version,
15963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 metadata_.int_version));
1597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabase(
1602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDeleteDatabaseBlocked()) {
1605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Front end ensures the event is not fired at connections that have
1609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // close_pending set.
1610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*it)->callbacks()->OnVersionChange(
1611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
1612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Only fire OnBlocked if there are open
1614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // connections after the VersionChangeEvents are received, not
1615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // just set up to fire.  http://crbug.com/100123
1616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteDatabaseFinal(callbacks);
1621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !!ConnectionCount();
1625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabaseFinal(
1628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!IsDeleteDatabaseBlocked());
1630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->DeleteDatabase(metadata_.name)) {
1632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(
1633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error deleting database."));
1635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.id = kInvalidId;
1639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.clear();
1641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks->OnSuccess();
1642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
164458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
16458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
16468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->IsConnected());
16478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->database() == this);
1648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Abort outstanding transactions from the closing connection. This
1650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // can not happen if the close is requested by the connection itself
1651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // as the front-end defers the close until all transactions are
16528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // complete, but can occur on process termination or forced close.
1653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TransactionMap transactions(transactions_);
1655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (TransactionMap::const_iterator it = transactions.begin(),
1656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        end = transactions.end();
1657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != end;
1658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (it->second->connection() == connection->callbacks())
1660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        it->second->Abort(
1661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Connection is closing."));
1663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.erase(connection);
1667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_ &&
1668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pending_second_half_open_->Connection() == connection) {
1669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_->Callbacks()->OnError(
1670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionAbortError,
1671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "The connection was closed."));
1672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_.reset();
1673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessPendingCalls();
1676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ConnectionCount() && !pending_open_calls_.size() &&
1679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !pending_delete_calls_.size()) {
1680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(transactions_.empty());
1681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL origin_url = backing_store_->origin_url();
16831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store_ = NULL;
16841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // factory_ should only be null in unit tests.
1686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
168758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (factory_) {
16881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      factory_->ReleaseDatabase(identifier_, origin_url, forced);
168958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      factory_ = NULL;
169058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreAbortOperation(
16953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
1696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation");
1698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveObjectStore(object_store_id);
1700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
17033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
1704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
17053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation");
1706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
17073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddObjectStore(object_store_metadata,
17083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 IndexedDBObjectStoreMetadata::kInvalidId);
1709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeAbortOperation(
17123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const string16& previous_version,
17133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 previous_int_version,
1714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
17153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
17173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.version = previous_version;
17183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = previous_int_version;
1719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
1722