indexed_db_database.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_database.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <math.h>
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <set>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/auto_reset.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/stl_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/indexed_db/indexed_db_connection.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_cursor.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_factory.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_index_writer.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_pending_connection.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_transaction.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_path.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_range.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Int64ToString16;
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebIDBKeyTypeNumber;
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingUpgradeCall has a scoped_ptr<IndexedDBConnection> because it owns the
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in-progress connection.
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingUpgradeCall {
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingUpgradeCall(scoped_refptr<IndexedDBCallbacks> callbacks,
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     scoped_ptr<IndexedDBConnection> connection,
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 transaction_id,
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callbacks_(callbacks),
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection_(connection.Pass()),
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        version_(version),
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transaction_id_(transaction_id) {}
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Takes ownership of the connection object.
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> ReleaseConnection() WARN_UNUSED_RESULT {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return connection_.Pass();
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 transaction_id() const { return transaction_id_; }
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection_;
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingSuccessCall has a IndexedDBConnection* because the connection is now
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// owned elsewhere, but we need to cancel the success call if that connection
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// closes before it is sent.
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingSuccessCall {
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingSuccessCall(scoped_refptr<IndexedDBCallbacks> callbacks,
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     IndexedDBConnection* connection,
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : callbacks_(callbacks), connection_(connection), version_(version) {}
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IndexedDBConnection* connection() const { return connection_; }
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBConnection* connection_;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingDeleteCall {
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacks> callbacks)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks) {}
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBFactory* factory,
93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const Identifier& unique_identifier) {
94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database =
95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!database->OpenInternal().ok())
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return database;
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const base::string16::value_type kNoStringVersion[] = {0};
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBBackingStore* backing_store,
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBFactory* factory,
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     const Identifier& unique_identifier)
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : backing_store_(backing_store),
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_(name,
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId,
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kNoStringVersion,
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION,
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId),
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      identifier_(unique_identifier),
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_(factory) {
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddObjectStore(
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store,
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_max_object_store_id) {
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store.id) ==
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id);
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata_.max_object_store_id = new_max_object_store_id;
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store.id] = object_store;
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveObjectStore(int64 object_store_id) {
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.erase(object_store_id);
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddIndex(int64 object_store_id,
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const IndexedDBIndexMetadata& index,
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int64 new_max_index_id) {
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end());
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes[index.id] = index;
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) {
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(object_store.max_index_id, new_max_index_id);
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    object_store.max_index_id = new_max_index_id;
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveIndex(int64 object_store_id, int64 index_id) {
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes.erase(index_id);
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBDatabase::OpenInternal() {
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, &metadata_, &success);
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                  << " id = " << metadata_.id;
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (success)
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store_->GetObjectStores(metadata_.id,
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &metadata_.object_stores);
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_->CreateIDBDatabaseMetaData(
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::~IndexedDBDatabase() {
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.empty());
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_open_calls_.empty());
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_delete_calls_.empty());
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int child_process_id) {
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> connection(
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new IndexedDBConnection(this, database_callbacks));
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connections_.insert(connection.get());
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  /* TODO(ericu):  Grant child process permissions here so that the connection
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   * can create Blobs.
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  */
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return connection.Pass();
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochIndexedDBTransaction* IndexedDBDatabase::GetTransaction(
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 transaction_id) const {
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TransactionMap::const_iterator trans_iterator =
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transactions_.find(transaction_id);
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (trans_iterator == transactions_.end())
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return NULL;
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return trans_iterator->second;
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreId(int64 object_store_id) const {
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(metadata_.object_stores, object_store_id)) {
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndIndexId(int64 object_store_id,
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                        int64 index_id) const {
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(object_store_metadata.indexes, index_id)) {
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndOptionalIndexId(
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (index_id != IndexedDBIndexMetadata::kInvalidId &&
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !ContainsKey(object_store_metadata.indexes, index_id)) {
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId(
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(object_store_metadata.indexes, index_id)) {
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id,
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                          const base::string16& name,
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const IndexedDBKeyPath& key_path,
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          bool auto_increment) {
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateObjectStore");
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(metadata_.object_stores, object_store_id)) {
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata(
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name,
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_path,
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      auto_increment,
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBDatabase::kMinimumIndexId);
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreOperation,
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id));
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddObjectStore(object_store_metadata, object_store_id);
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreOperation(
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateObjectStore(
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->database()->id(),
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.id,
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.name,
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_metadata.key_path,
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          object_store_metadata.auto_increment).ok()) {
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error creating object store '") +
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            object_store_metadata.name + ASCIIToUTF16("'.")));
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id) {
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteObjectStore");
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreOperation,
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata));
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveObjectStore(object_store_id);
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateIndex(int64 transaction_id,
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id,
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    const base::string16& name,
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const IndexedDBKeyPath& key_path,
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool unique,
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool multi_entry) {
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateIndex");
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndNewIndexId(object_store_id, index_id))
3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata(
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name, index_id, key_path, unique, multi_entry);
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexOperation,
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation,
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_id));
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, index_id);
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexOperation(
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexOperation");
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   transaction->database()->id(),
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.id,
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.name,
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.key_path,
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.unique,
378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   index_metadata.multi_entry).ok()) {
379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error creating index '") +
381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexAbortOperation(
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation");
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
3943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id) {
400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteIndex");
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id))
4077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
4087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBIndexMetadata& index_metadata =
4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores[object_store_id].indexes[index_id];
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexOperation,
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation,
4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata));
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexOperation(
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation");
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  transaction->database()->id(),
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  index_metadata.id);
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting index '") +
437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexAbortOperation(
4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation");
448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Commit(int64 transaction_id) {
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend suggests that we commit, but we may have previously initiated
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // an abort, and so have disposed of the transaction. on_abort has already
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // been dispatched to the frontend, so it will find out about that
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // asynchronously.
4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Commit();
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id) {
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort();
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id,
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const IndexedDBDatabaseError& error) {
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort(error);
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Get(int64 transaction_id,
480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 object_store_id,
481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 index_id,
482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_ptr<IndexedDBKeyRange> key_range,
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            bool key_only,
484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks) {
485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Get");
4867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
4917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
4943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::GetOperation,
4953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      this,
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
4983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Passed(&key_range),
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::GetOperation(
5043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
5053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    indexed_db::CursorType cursor_type,
5083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
5093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::GetOperation");
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[object_store_id];
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKey* key;
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (key_range->IsOnlyKey()) {
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = &key_range->lower();
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // ObjectStore Retrieval Operation
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Value Retrieval Operation
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Referenced Value Retrieval Operation
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!backing_store_cursor) {
5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &backing_store_cursor->key();
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key;
561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s;
5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Object Store Retrieval Operation
5647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string value;
565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  id(),
567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  *key,
569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  &value);
570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
5713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnError(
572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 "Internal error in GetRecord."));
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (value.empty()) {
5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (object_store_metadata.auto_increment &&
5833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        !object_store_metadata.key_path.IsNull()) {
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value);
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // From here we are dealing only with indexes.
593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetPrimaryKeyViaIndex(
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
5953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      id(),
5963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store_id,
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      index_id,
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *key,
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &primary_key);
600a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
6013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               "Internal error in GetPrimaryKeyViaIndex."));
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!primary_key) {
6073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Index Value Retrieval Operation
6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(*primary_key);
613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Index Referenced Value Retrieval Operation
6177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string value;
618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                id(),
620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                object_store_id,
621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                *primary_key,
622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                &value);
623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
6243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               "Internal error in GetRecord."));
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (value.empty()) {
6313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store_metadata.auto_increment &&
6353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !object_store_metadata.key_path.IsNull()) {
6363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(&value);
640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static scoped_ptr<IndexedDBKey> GenerateKey(
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBTransaction* transaction,
645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 max_generator_value =
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      9007199254740992LL;  // Maximum integer storable as ECMAScript number.
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 current_number;
650a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store->GetKeyGeneratorCurrentNumber(
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &current_number);
655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "Failed to GetKeyGeneratorCurrentNumber";
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_number < 0 || current_number > max_generator_value)
660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return make_scoped_ptr(new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
665a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status UpdateKeyGenerator(IndexedDBBackingStore* backing_store,
666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          IndexedDBTransaction* transaction,
667a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 database_id,
668a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 object_store_id,
669a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          const IndexedDBKey& key,
670a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          bool check_current) {
6713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(WebIDBKeyTypeNumber, key.type());
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
6763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<int64>(floor(key.number())) + 1,
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_current);
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::PutOperationParams {
6813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PutOperationParams() {}
6823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
6833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string value;
6843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
6853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::PutMode put_mode;
6863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
6873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<IndexKeys> index_keys;
6883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
6903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
6913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
6923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Put(int64 transaction_id,
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
6957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                            std::string* value,
696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_ptr<IndexedDBKey> key,
697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            PutMode put_mode,
698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks,
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<IndexKeys>& index_keys) {
700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Put");
7017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
7027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
7077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
7103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<PutOperationParams> params(new PutOperationParams());
7113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
7123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->value.swap(*value);
7133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key = key.Pass();
7143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->put_mode = put_mode;
7153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
7163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_keys = index_keys;
7173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
7183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::PutOperation, this, base::Passed(&params)));
7193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
7223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBTransaction* transaction) {
7233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::PutOperation");
724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool key_was_generated = false;
726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(params->object_store_id) !=
7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
7293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store =
7303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[params->object_store_id];
7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(object_store.auto_increment || params->key->IsValid());
7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store.auto_increment && !params->key->IsValid()) {
7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        backing_store_.get(), transaction, id(), params->object_store_id);
738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key_was_generated = true;
739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!auto_inc_key->IsValid()) {
7403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Maximum key generator value reached."));
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = auto_inc_key.Pass();
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
7473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = params->key.Pass();
748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key->IsValid());
751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool found = false;
755a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = backing_store_->KeyExistsInObjectStore(
756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
7573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
7583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->object_store_id,
7593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key,
760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &record_identifier,
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &found);
762a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
7633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
764f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error checking key existence."));
766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (found) {
7693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Key already exists in the object store."));
772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
777a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
7803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                backing_store_.get(),
7813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                id(),
7823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                object_store,
783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *key,
784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                key_was_generated,
7853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                params->index_keys,
786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
7903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
791f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
7963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
797f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Before this point, don't do any mutation. After this point, rollback the
802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // transaction in case of error.
803a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
804868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->PutRecord(transaction->BackingStoreTransaction(),
8053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                id(),
8063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->object_store_id,
8073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                *key,
8083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->value,
809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &record_identifier);
810a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
8113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
812f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error performing put/add."));
814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
8203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 backing_store_.get(),
821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
8223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id);
824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store.auto_increment &&
8273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      key->type() == WebIDBKeyTypeNumber) {
829a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = UpdateKeyGenerator(backing_store_.get(),
830a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           transaction,
831a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           id(),
832a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           params->object_store_id,
833a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           *key,
834a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           !key_was_generated);
835a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
8363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
837f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error updating key generator."));
839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(*key);
844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
846868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 object_store_id,
848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     scoped_ptr<IndexedDBKey> primary_key,
849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<IndexKeys>& index_keys) {
850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexKeys");
8517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
8527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
855868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(alecflett): This method could be asynchronous, but we need to
857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // evaluate if it's worth the extra complexity.
858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
860a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->KeyExistsInObjectStore(
8611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      transaction->BackingStoreTransaction(),
8621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      metadata_.id,
8631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      object_store_id,
8641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *primary_key,
8651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &record_identifier,
8661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &found);
867a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(
869f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error setting index keys."));
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error setting index keys for object store."));
877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
879868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
881a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
8881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                backing_store_,
889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                id(),
890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                object_store_metadata,
891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *primary_key,
892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                false,
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                index_keys,
894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
898868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
905f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
9121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 backing_store_,
913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 id(),
915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id);
916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
918868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        int64,
921868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        const std::vector<int64>& index_ids) {
922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexesReady");
9237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
925868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
9267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(
9293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      IndexedDBDatabase::PREEMPTIVE_TASK,
9303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
9313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
9323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_ids.size()));
933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReadyOperation(
9363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t index_count,
9373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
9383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::SetIndexesReadyOperation");
9393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < index_count; ++i)
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->DidCompletePreemptiveEvent();
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::OpenCursorOperationParams {
9443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  OpenCursorOperationParams() {}
9453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
9463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 index_id;
9473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKeyRange> key_range;
9483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorDirection direction;
9493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorType cursor_type;
9503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::TaskType task_type;
9513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
9523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
9543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
9553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
9563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenCursor(
958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    indexed_db::CursorDirection direction,
963868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskType task_type,
965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::OpenCursor");
9677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
9697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
9707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
9717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<OpenCursorOperationParams> params(new OpenCursorOperationParams());
9753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
9763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_id = index_id;
9773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key_range = key_range.Pass();
9783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->direction = direction;
9793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->cursor_type =
9803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
9813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->task_type = task_type;
9823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
9833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
9843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(&params)));
9853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
9863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::OpenCursorOperation(
9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<OpenCursorOperationParams> params,
9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::OpenCursorOperation");
991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend has begun indexing, so this pauses the transaction
993868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // until the indexing is complete. This can't happen any earlier
994868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // because we don't want to switch to early mode in case multiple
995868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // indexes are being created in a row, with Put()'s in between.
9963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->AddPreemptiveEvent();
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
10003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
1001424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1002424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
1003424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1004424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1005424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1006424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1007424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
1008424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->direction);
1009424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
1010424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1011424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1012424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1013424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1014424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->direction);
1016424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
10183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
10193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1021868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1035868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1036868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1037868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1038868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
10393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnSuccess(static_cast<std::string*>(NULL));
1040868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1041868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCursor> cursor =
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new IndexedDBCursor(backing_store_cursor.Pass(),
10453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->cursor_type,
10463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->task_type,
10473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          transaction);
10483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(
1049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor, cursor->key(), cursor->primary_key(), cursor->Value());
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1051868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Count(int64 transaction_id,
1053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 index_id,
1055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_ptr<IndexedDBKeyRange> key_range,
1056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Count");
10587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
10597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
10607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1064868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation,
10663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
10673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
10683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       index_id,
10693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
10703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1071868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1072868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CountOperation(
10743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
10753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
10763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
10773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
10783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
10793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CountOperation");
1080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 count = 0;
1081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1082868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
1084868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1085868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
10863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
10873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
10883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1092868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
10933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
10943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
10953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        index_id,
10963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1097868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1099868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(count);
1101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ++count;
11067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } while (backing_store_cursor->Continue());
1107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(count);
1109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteRange(
1112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteRange");
11177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
11197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
11217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation,
11263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
11273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
11283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
11293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteRangeOperation(
11333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->OpenObjectStoreCursor(
1140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
11413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
11423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
11433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (backing_store_cursor) {
1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    do {
1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!backing_store_->DeleteRecord(
1148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               transaction->BackingStoreTransaction(),
1149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               id(),
1150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               object_store_id,
1151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               backing_store_cursor->record_identifier())
1152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               .ok()) {
11533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        callbacks->OnError(
1154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Internal error deleting data in range"));
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
11587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } while (backing_store_cursor->Continue());
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Clear(int64 transaction_id,
1165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Clear");
11687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
1170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
11747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
11773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks));
1178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::ClearOperation(
11813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::ObjectStoreClearOperation");
1185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!backing_store_->ClearObjectStore(transaction->BackingStoreTransaction(),
1186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        id(),
1187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        object_store_id).ok()) {
11883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
1189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error clearing object store"));
1191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
11933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreOperation(
11973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
11983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation");
1200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
1201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
12033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        object_store_metadata.id);
1204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
1206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting object store '") +
12073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_metadata.name + ASCIIToUTF16("'.");
1208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
1209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
1210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeOperation(
12143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 version,
12153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBConnection> connection,
1217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
12193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 old_version = metadata_.int_version;
12203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GT(version, old_version);
12213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = version;
12223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->UpdateIDBDatabaseIntVersion(
1223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
12243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
12253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          metadata_.int_version)) {
1226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseError error(
1227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
12287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ASCIIToUTF16(
12297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "Internal error writing data to stable storage when "
12307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "updating version."));
12313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(error);
1232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(error);
1233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_second_half_open_.reset(
1237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new PendingSuccessCall(callbacks, connection.get(), version));
12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callbacks->OnUpgradeNeeded(old_version, connection.Pass(), metadata());
1239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool committed) {
1243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction->id()) != transactions_.end());
1244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transactions_[transaction->id()], transaction);
1245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transactions_.erase(transaction->id());
1246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
12495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (committed) {
12505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK_EQ(pending_second_half_open_->version(), metadata_.int_version);
12515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(metadata_.id != kInvalidId);
12525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Connection was already minted for OnUpgradeNeeded callback.
12545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scoped_ptr<IndexedDBConnection> connection;
12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnSuccess(connection.Pass(),
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                          this->metadata());
12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnError(
12595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "Version change transaction was aborted in "
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "upgradeneeded event handler."));
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Connection queue is now unblocked.
1267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBDatabase::TransactionCommitFailed() {
12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Factory may be null in unit tests.
12735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!factory_)
12745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
12751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  factory_->HandleBackingStoreFailure(backing_store_->origin_url());
12761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
12771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t IndexedDBDatabase::ConnectionCount() const {
1279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This does not include pending open calls, as those should not block version
1280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changes and deletes.
1281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return connections_.size();
1282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingOpenCount() const {
1285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_open_calls_.size();
1286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingUpgradeCount() const {
1289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_run_version_change_transaction_call_ ? 1 : 0;
1290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::RunningUpgradeCount() const {
1293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_second_half_open_ ? 1 : 0;
1294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingDeleteCount() const {
1297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_delete_calls_.size();
1298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::ProcessPendingCalls() {
1301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
13025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(pending_run_version_change_transaction_call_->version() >
1303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           metadata_.int_version);
1304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<PendingUpgradeCall> pending_call =
1305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_run_version_change_transaction_call_.Pass();
13065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunVersionChangeTransactionFinal(pending_call->callbacks(),
13075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->ReleaseConnection(),
13085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->transaction_id(),
13095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->version());
13105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(1u, ConnectionCount());
1311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through would be a no-op, since transaction must complete
1312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // asynchronously.
1313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsDeleteDatabaseBlocked());
1314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsOpenConnectionBlocked());
1315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDeleteDatabaseBlocked()) {
1319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingDeleteCallList pending_delete_calls;
1320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.swap(pending_delete_calls);
1321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_delete_calls.empty()) {
1322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Only the first delete call will delete the database, but each must fire
1323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // callbacks.
1324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingDeleteCall> pending_delete_call(
1325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pending_delete_calls.front());
1326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_delete_calls.pop_front();
13275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DeleteDatabaseFinal(pending_delete_call->callbacks());
1328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // delete_database_final should never re-queue calls.
1330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_delete_calls_.empty());
1331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsOpenConnectionBlocked()) {
1335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingOpenCallList pending_open_calls;
1336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.swap(pending_open_calls);
1337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_open_calls.empty()) {
1338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OpenConnection(pending_open_calls.front());
1339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_open_calls.pop_front();
1340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateTransaction(
1345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexedDBConnection* connection,
1347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::vector<int64>& object_store_ids,
1348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint16 mode) {
1349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
13514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(transactions_.find(transaction_id) == transactions_.end());
13524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
13534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The transaction will add itself to this database's coordinator, which
13565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // manages the lifetime of the object.
13575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TransactionCreated(new IndexedDBTransaction(
13587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transaction_id,
13597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      connection->callbacks(),
13607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
13617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      static_cast<indexed_db::TransactionMode>(mode),
1362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      this,
13635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new IndexedDBBackingStore::Transaction(backing_store_)));
1364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) {
1367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transactions_[transaction->id()] = transaction;
1368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !pending_delete_calls_.empty() ||
13725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         transaction_coordinator_.IsRunningVersionChangeTransaction() ||
1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         pending_run_version_change_transaction_call_;
1374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenConnection(
1377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IndexedDBPendingConnection& connection) {
1378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Should have a priority queue so that higher version
1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // requests are processed first. http://crbug.com/225850
1382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsOpenConnectionBlocked()) {
1383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // The backing store only detects data loss when it is first opened. The
1384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // presence of existing connections means we didn't even check for data loss
1385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // so there'd better not be any.
1386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss());
1387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    pending_open_calls_.push_back(connection);
1388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata_.id == kInvalidId) {
1392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The database was deleted then immediately re-opened; OpenInternal()
1393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // recreates it in the backing store.
1394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (OpenInternal().ok()) {
1395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
1396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                metadata_.int_version);
1397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 message;
1399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (connection.version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = ASCIIToUTF16(
1401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "Internal error opening database with no version specified.");
14025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
1403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message =
1404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16("Internal error opening database with version ") +
1405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(connection.version);
14065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnError(IndexedDBDatabaseError(
1408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          blink::WebIDBDatabaseExceptionUnknownError, message));
1409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We infer that the database didn't exist from its lack of either type of
1414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // version.
1415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_new_database =
1416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.version == kNoStringVersion &&
1417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
1418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (connection.version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
1420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // For unit tests only - skip upgrade steps. Calling from script with
1421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // DEFAULT_INT_VERSION throws exception.
1422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK that not in unit tests.
1423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(is_new_database);
1424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnSuccess(
1425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        CreateConnection(connection.database_callbacks,
1426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         connection.child_process_id),
1427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        this->metadata());
1428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We may need to change the version.
1432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 local_version = connection.version;
1433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_new_database) {
1435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnSuccess(
1436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          CreateConnection(connection.database_callbacks,
1437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           connection.child_process_id),
1438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          this->metadata());
1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Spec says: If no version is specified and no database exists, set
1442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database version to 1.
1443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    local_version = 1;
1444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version > metadata_.int_version) {
1447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    RunVersionChangeTransaction(connection.callbacks,
1448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                CreateConnection(connection.database_callbacks,
1449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                 connection.child_process_id),
1450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                connection.transaction_id,
1451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                local_version);
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version < metadata_.int_version) {
1455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnError(IndexedDBDatabaseError(
1456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionVersionError,
1457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ASCIIToUTF16("The requested version (") +
1458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(local_version) +
1459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16(") is less than the existing version (") +
1460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(local_version, metadata_.int_version);
1464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connection.callbacks->OnSuccess(
1465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateConnection(connection.database_callbacks,
1466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       connection.child_process_id),
1467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this->metadata());
1468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransaction(
1471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
14745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 requested_version) {
1475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(callbacks);
14778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection.get()));
1478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ConnectionCount() > 1) {
14795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Front end ensures the event is not fired at connections that have
1481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // close_pending set.
1482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (*it != connection.get()) {
14863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*it)->callbacks()->OnVersionChange(metadata_.int_version,
14873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            requested_version);
1488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
1489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Remove the call to OnBlocked and instead wait
1491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // until the frontend tells us that all the "versionchange" events
1492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // have been delivered.  http://crbug.com/100123
1493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!pending_run_version_change_transaction_call_);
1496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pending_run_version_change_transaction_call_.reset(new PendingUpgradeCall(
1497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        callbacks, connection.Pass(), transaction_id, requested_version));
1498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
15005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunVersionChangeTransactionFinal(
15015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callbacks, connection.Pass(), transaction_id, requested_version);
1502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<int64> object_store_ids;
1511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateTransaction(transaction_id,
1512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    connection.get(),
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    object_store_ids,
1514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    indexed_db::TRANSACTION_VERSION_CHANGE);
1515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  transactions_[transaction_id]
15175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ->ScheduleTask(base::Bind(&IndexedDBDatabase::VersionChangeOperation,
15185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
15195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                requested_version,
15205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                callbacks,
15215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                base::Passed(&connection)),
15225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
15235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
15245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.version,
15255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.int_version));
1526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabase(
1531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDeleteDatabaseBlocked()) {
1534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Front end ensures the event is not fired at connections that have
1538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // close_pending set.
1539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*it)->callbacks()->OnVersionChange(
1540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
1541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Only fire OnBlocked if there are open
1543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // connections after the VersionChangeEvents are received, not
1544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // just set up to fire.  http://crbug.com/100123
1545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
1547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteDatabaseFinal(callbacks);
1550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !!ConnectionCount();
1554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabaseFinal(
1557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!IsDeleteDatabaseBlocked());
1559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!backing_store_->DeleteDatabase(metadata_.name).ok()) {
1561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(
1562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error deleting database."));
1564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.id = kInvalidId;
1568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.clear();
1570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks->OnSuccess();
15715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (factory_)
15725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    factory_->DatabaseDeleted(identifier_);
15735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::ForceClose() {
15765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IndexedDBConnection::ForceClose() may delete this database, so hold ref.
15775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> protect(this);
15785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConnectionSet::const_iterator it = connections_.begin();
15795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (it != connections_.end()) {
15805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBConnection* connection = *it++;
15815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection->ForceClose();
15825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
15835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(connections_.empty());
1584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
158658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
15878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
15888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->IsConnected());
15898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->database() == this);
1590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Abort outstanding transactions from the closing connection. This
1592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // can not happen if the close is requested by the connection itself
1593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // as the front-end defers the close until all transactions are
15948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // complete, but can occur on process termination or forced close.
1595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
1596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TransactionMap transactions(transactions_);
1597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (TransactionMap::const_iterator it = transactions.begin(),
1598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        end = transactions.end();
1599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != end;
1600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (it->second->connection() == connection->callbacks())
1602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        it->second->Abort(
1603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Connection is closing."));
1605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.erase(connection);
1609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_ &&
16105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pending_second_half_open_->connection() == connection) {
16115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_second_half_open_->callbacks()->OnError(
1612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "The connection was closed."));
1614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_.reset();
1615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessPendingCalls();
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ConnectionCount() && !pending_open_calls_.size() &&
1621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !pending_delete_calls_.size()) {
1622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(transactions_.empty());
1623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL origin_url = backing_store_->origin_url();
16251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store_ = NULL;
16261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // factory_ should only be null in unit tests.
1628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
162958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (factory_) {
16305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_->ReleaseDatabase(identifier_, forced);
163158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      factory_ = NULL;
163258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreAbortOperation(
16373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
1638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation");
1640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveObjectStore(object_store_id);
1642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
16453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
1646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation");
1648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddObjectStore(object_store_metadata,
16503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 IndexedDBObjectStoreMetadata::kInvalidId);
1651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeAbortOperation(
1654a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& previous_version,
16553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 previous_int_version,
1656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.version = previous_version;
16603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = previous_int_version;
1661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
1664