indexed_db_database.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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"
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "content/browser/indexed_db/indexed_db_context_impl.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_cursor.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_factory.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_index_writer.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_pending_connection.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_transaction.h"
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/browser/indexed_db/indexed_db_value.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_path.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_range.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Int64ToString16;
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebIDBKeyTypeNumber;
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingUpgradeCall has a scoped_ptr<IndexedDBConnection> because it owns the
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in-progress connection.
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingUpgradeCall {
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingUpgradeCall(scoped_refptr<IndexedDBCallbacks> callbacks,
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     scoped_ptr<IndexedDBConnection> connection,
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 transaction_id,
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callbacks_(callbacks),
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection_(connection.Pass()),
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        version_(version),
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transaction_id_(transaction_id) {}
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Takes ownership of the connection object.
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> ReleaseConnection() WARN_UNUSED_RESULT {
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return connection_.Pass();
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 transaction_id() const { return transaction_id_; }
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<IndexedDBConnection> connection_;
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 version_;
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 transaction_id_;
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PendingSuccessCall has a IndexedDBConnection* because the connection is now
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// owned elsewhere, but we need to cancel the success call if that connection
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// closes before it is sent.
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabase::PendingSuccessCall {
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PendingSuccessCall(scoped_refptr<IndexedDBCallbacks> callbacks,
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     IndexedDBConnection* connection,
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     int64 version)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : callbacks_(callbacks), connection_(connection), version_(version) {}
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IndexedDBConnection* connection() const { return connection_; }
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 version() const { return version_; }
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBConnection* connection_;
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingDeleteCall {
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacks> callbacks)
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks) {}
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBCallbacks> callbacks_;
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBFactory* factory,
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const Identifier& unique_identifier) {
96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database =
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!database->OpenInternal().ok())
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return database;
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const base::string16::value_type kNoStringVersion[] = {0};
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBBackingStore* backing_store,
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBFactory* factory,
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     const Identifier& unique_identifier)
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : backing_store_(backing_store),
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_(name,
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId,
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kNoStringVersion,
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION,
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId),
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      identifier_(unique_identifier),
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_(factory) {
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddObjectStore(
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store,
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_max_object_store_id) {
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store.id) ==
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) {
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id);
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata_.max_object_store_id = new_max_object_store_id;
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store.id] = object_store;
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveObjectStore(int64 object_store_id) {
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.erase(object_store_id);
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddIndex(int64 object_store_id,
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const IndexedDBIndexMetadata& index,
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int64 new_max_index_id) {
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end());
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes[index.id] = index;
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) {
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(object_store.max_index_id, new_max_index_id);
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    object_store.max_index_id = new_max_index_id;
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveIndex(int64 object_store_id, int64 index_id) {
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes.erase(index_id);
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBDatabase::OpenInternal() {
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->GetIDBDatabaseMetaData(
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, &metadata_, &success);
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                  << " id = " << metadata_.id;
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (success)
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store_->GetObjectStores(metadata_.id,
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &metadata_.object_stores);
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_->CreateIDBDatabaseMetaData(
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::~IndexedDBDatabase() {
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.empty());
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_open_calls_.empty());
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_delete_calls_.empty());
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int child_process_id) {
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<IndexedDBConnection> connection(
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new IndexedDBConnection(this, database_callbacks));
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connections_.insert(connection.get());
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  /* TODO(ericu):  Grant child process permissions here so that the connection
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   * can create Blobs.
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  */
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return connection.Pass();
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochIndexedDBTransaction* IndexedDBDatabase::GetTransaction(
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 transaction_id) const {
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TransactionMap::const_iterator trans_iterator =
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transactions_.find(transaction_id);
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (trans_iterator == transactions_.end())
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return NULL;
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return trans_iterator->second;
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreId(int64 object_store_id) const {
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(metadata_.object_stores, object_store_id)) {
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndIndexId(int64 object_store_id,
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                        int64 index_id) const {
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(object_store_metadata.indexes, index_id)) {
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndOptionalIndexId(
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (index_id != IndexedDBIndexMetadata::kInvalidId &&
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !ContainsKey(object_store_metadata.indexes, index_id)) {
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId(
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 object_store_id,
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 index_id) const {
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBObjectStoreMetadata& object_store_metadata =
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores.find(object_store_id)->second;
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(object_store_metadata.indexes, index_id)) {
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid index_id";
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id,
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                          const base::string16& name,
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const IndexedDBKeyPath& key_path,
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          bool auto_increment) {
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateObjectStore");
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(metadata_.object_stores, object_store_id)) {
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Invalid object_store_id";
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata(
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name,
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_path,
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      auto_increment,
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBDatabase::kMinimumIndexId);
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreOperation,
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateObjectStoreAbortOperation,
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id));
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddObjectStore(object_store_metadata, object_store_id);
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreOperation(
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  leveldb::Status s =
299e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      backing_store_->CreateObjectStore(transaction->BackingStoreTransaction(),
300e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        transaction->database()->id(),
301e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.id,
302e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.name,
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.key_path,
304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                        object_store_metadata.auto_increment);
305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!s.ok()) {
306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error creating object store '") +
309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            object_store_metadata.name + ASCIIToUTF16("'."));
310e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
311e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
312e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
313e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id) {
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteObjectStore");
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreOperation,
3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata),
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation,
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_metadata));
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveObjectStore(object_store_id);
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateIndex(int64 transaction_id,
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id,
345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    const base::string16& name,
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const IndexedDBKeyPath& key_path,
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool unique,
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool multi_entry) {
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::CreateIndex");
3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
3517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndNewIndexId(object_store_id, index_id))
3567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata(
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name, index_id, key_path, unique, multi_entry);
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexOperation,
3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation,
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_id));
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, index_id);
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexOperation(
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexOperation");
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   transaction->database()->id(),
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   object_store_id,
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.id,
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.name,
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.key_path,
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   index_metadata.unique,
385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   index_metadata.multi_entry).ok()) {
386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error creating index '") +
388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError, error_string));
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateIndexAbortOperation(
3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation");
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id) {
407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteIndex");
4087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id))
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const IndexedDBIndexMetadata& index_metadata =
4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      metadata_.object_stores[object_store_id].indexes[index_id];
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexOperation,
4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata),
4233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation,
4243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 object_store_id,
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_metadata));
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexOperation(
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation");
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  transaction->database()->id(),
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  index_metadata.id);
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting index '") +
444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        index_metadata.name + ASCIIToUTF16("'.");
445e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
446e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 error_string);
447e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
448e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
449e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
450e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteIndexAbortOperation(
4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBIndexMetadata& index_metadata,
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation");
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Commit(int64 transaction_id) {
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend suggests that we commit, but we may have previously initiated
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // an abort, and so have disposed of the transaction. on_abort has already
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // been dispatched to the frontend, so it will find out about that
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // asynchronously.
4687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Commit();
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id) {
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort();
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id,
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const IndexedDBDatabaseError& error) {
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
4857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (transaction)
4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    transaction->Abort(error);
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Get(int64 transaction_id,
491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 object_store_id,
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            int64 index_id,
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_ptr<IndexedDBKeyRange> key_range,
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            bool key_only,
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks) {
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Get");
4977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
4987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
5007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
5027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
5053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::GetOperation,
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      this,
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
5093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Passed(&key_range),
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::GetOperation(
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    indexed_db::CursorType cursor_type,
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::GetOperation");
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[object_store_id];
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKey* key;
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (key_range->IsOnlyKey()) {
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = &key_range->lower();
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // ObjectStore Retrieval Operation
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
5433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Value Retrieval Operation
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Referenced Value Retrieval Operation
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
5563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          index_id,
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!backing_store_cursor) {
5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &backing_store_cursor->key();
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key;
572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s;
5733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Object Store Retrieval Operation
57523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    IndexedDBValue value;
576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  id(),
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  object_store_id,
579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  *key,
580a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  &value);
581a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
582e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
583e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error in GetRecord.");
584e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      callbacks->OnError(error);
585e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
586e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (s.IsCorruption())
587e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
588e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (value.empty()) {
5933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess();
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (object_store_metadata.auto_increment &&
5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        !object_store_metadata.key_path.IsNull()) {
5993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value);
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // From here we are dealing only with indexes.
608a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetPrimaryKeyViaIndex(
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
6103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      id(),
6113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store_id,
6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      index_id,
613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *key,
614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &primary_key);
615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
616e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
617e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error in GetPrimaryKeyViaIndex.");
618e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    callbacks->OnError(error);
619e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
620e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
621e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!primary_key) {
6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Index Value Retrieval Operation
6303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(*primary_key);
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Index Referenced Value Retrieval Operation
63523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue value;
636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
637a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                id(),
638a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                object_store_id,
639a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                *primary_key,
640a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                &value);
641a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
642e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
643e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error in GetRecord.");
644e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    callbacks->OnError(error);
645e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
646e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
647e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (value.empty()) {
6523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess();
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store_metadata.auto_increment &&
6563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !object_store_metadata.key_path.IsNull()) {
6573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(&value);
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static scoped_ptr<IndexedDBKey> GenerateKey(
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBBackingStore* backing_store,
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBTransaction* transaction,
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 max_generator_value =
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      9007199254740992LL;  // Maximum integer storable as ECMAScript number.
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 current_number;
671a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store->GetKeyGeneratorCurrentNumber(
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &current_number);
676a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "Failed to GetKeyGeneratorCurrentNumber";
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_number < 0 || current_number > max_generator_value)
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return make_scoped_ptr(new IndexedDBKey(current_number, WebIDBKeyTypeNumber));
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
686a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status UpdateKeyGenerator(IndexedDBBackingStore* backing_store,
687a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          IndexedDBTransaction* transaction,
688a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 database_id,
689a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          int64 object_store_id,
690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          const IndexedDBKey& key,
691a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          bool check_current) {
6923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(WebIDBKeyTypeNumber, key.type());
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
6973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<int64>(floor(key.number())) + 1,
698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_current);
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::PutOperationParams {
7023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PutOperationParams() {}
7033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
70423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue value;
7053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::PutMode put_mode;
7073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
7083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<IndexKeys> index_keys;
7093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
7113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
7123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
7133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Put(int64 transaction_id,
715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
71623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                            IndexedDBValue* value,
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_ptr<IndexedDBKey> key,
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            PutMode put_mode,
719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            scoped_refptr<IndexedDBCallbacks> callbacks,
720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<IndexKeys>& index_keys) {
721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Put");
7227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
7237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
7287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<PutOperationParams> params(new PutOperationParams());
7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
7333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->value.swap(*value);
7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key = key.Pass();
7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->put_mode = put_mode;
7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_keys = index_keys;
7383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
7393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::PutOperation, this, base::Passed(&params)));
7403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
7433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     IndexedDBTransaction* transaction) {
7443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::PutOperation");
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool key_was_generated = false;
747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(params->object_store_id) !=
7493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         metadata_.object_stores.end());
7503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store =
7513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      metadata_.object_stores[params->object_store_id];
7523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(object_store.auto_increment || params->key->IsValid());
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
7553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
7563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      object_store.auto_increment && !params->key->IsValid()) {
7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        backing_store_.get(), transaction, id(), params->object_store_id);
759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key_was_generated = true;
760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!auto_inc_key->IsValid()) {
7613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
762f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Maximum key generator value reached."));
764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = auto_inc_key.Pass();
767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
7683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    key = params->key.Pass();
769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key->IsValid());
772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
7743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool found = false;
776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = backing_store_->KeyExistsInObjectStore(
777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
7783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
7793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->object_store_id,
7803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key,
781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &record_identifier,
782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &found);
783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
784e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
785e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error checking key existence.");
786e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      params->callbacks->OnError(error);
787e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (s.IsCorruption())
788e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
789e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (found) {
7933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->callbacks->OnError(
794f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Key already exists in the object store."));
796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
801a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
8043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                backing_store_.get(),
8053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                id(),
8063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                object_store,
807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *key,
808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                key_was_generated,
8093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                params->index_keys,
810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
8143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
815f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
8203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    params->callbacks->OnError(IndexedDBDatabaseError(
821f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Before this point, don't do any mutation. After this point, rollback the
826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // transaction in case of error.
827a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->PutRecord(transaction->BackingStoreTransaction(),
8293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                id(),
8303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->object_store_id,
8313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                *key,
8323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                params->value,
833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &record_identifier);
834a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
835e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(
836f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
837e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        "Internal error: backing store error performing put/add.");
838e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->callbacks->OnError(error);
839e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
840e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
841e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
8483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 backing_store_.get(),
849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
8503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 id(),
8513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 params->object_store_id);
852868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (object_store.auto_increment &&
8553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      key->type() == WebIDBKeyTypeNumber) {
857a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = UpdateKeyGenerator(backing_store_.get(),
858a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           transaction,
859a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           id(),
860a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           params->object_store_id,
861a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           *key,
862a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           !key_was_generated);
863a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok()) {
864e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
865e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   "Internal error updating key generator.");
866e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      params->callbacks->OnError(error);
867e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (s.IsCorruption())
868e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
869e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               error);
870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(*key);
875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 object_store_id,
879868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     scoped_ptr<IndexedDBKey> primary_key,
880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<IndexKeys>& index_keys) {
881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexKeys");
8827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
8837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(alecflett): This method could be asynchronous, but we need to
888868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // evaluate if it's worth the extra complexity.
889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
890868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
891a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = backing_store_->KeyExistsInObjectStore(
8921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      transaction->BackingStoreTransaction(),
8931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      metadata_.id,
8941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      object_store_id,
8951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *primary_key,
8961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &record_identifier,
8971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &found);
898a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
899e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
900e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 "Internal error setting index keys.");
901e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
902e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
903e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
904e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
909f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error setting index keys for object store."));
911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<IndexWriter> index_writers;
915a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 error_message;
916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
918868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool backing_store_success = MakeIndexWriters(transaction,
9221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                backing_store_,
923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                id(),
924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                object_store_metadata,
925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                *primary_key,
926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                false,
927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                index_keys,
928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &index_writers,
929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &error_message,
930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                &obeys_constraints);
931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
933f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
939f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionConstraintError, error_message));
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexWriter* index_writer = index_writers[i];
945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
9461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 backing_store_,
947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 id(),
949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id);
950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        int64,
955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        const std::vector<int64>& index_ids) {
956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::SetIndexesReady");
9577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
9587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
9607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(
9633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      IndexedDBDatabase::PREEMPTIVE_TASK,
9643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
9653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 this,
9663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 index_ids.size()));
967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReadyOperation(
9703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t index_count,
9713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
9723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::SetIndexesReadyOperation");
9733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < index_count; ++i)
974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->DidCompletePreemptiveEvent();
975868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct IndexedDBDatabase::OpenCursorOperationParams {
9783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  OpenCursorOperationParams() {}
9793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 object_store_id;
9803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 index_id;
9813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<IndexedDBKeyRange> key_range;
9823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorDirection direction;
9833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  indexed_db::CursorType cursor_type;
9843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IndexedDBDatabase::TaskType task_type;
9853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacks> callbacks;
9863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenCursorOperationParams);
9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenCursor(
992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
993868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
994868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
995868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    indexed_db::CursorDirection direction,
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskType task_type,
999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::OpenCursor");
10017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
10027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
10037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1006868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1007868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<OpenCursorOperationParams> params(new OpenCursorOperationParams());
10093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->object_store_id = object_store_id;
10103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->index_id = index_id;
10113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->key_range = key_range.Pass();
10123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->direction = direction;
10133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->cursor_type =
10143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
10153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->task_type = task_type;
10163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks = callbacks;
10173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
10183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(&params)));
10193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::OpenCursorOperation(
10223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<OpenCursorOperationParams> params,
10233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
10243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::OpenCursorOperation");
1025868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1026868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend has begun indexing, so this pauses the transaction
1027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // until the indexing is complete. This can't happen any earlier
1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // because we don't want to switch to early mode in case multiple
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // indexes are being created in a row, with Put()'s in between.
10303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
1031868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->AddPreemptiveEvent();
1032868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1033868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
10343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
1035424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1036424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
1037424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1038424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1039424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1040424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1041424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
1042424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->direction);
1043424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
1044424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1045424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1046424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          id(),
1047424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          params->object_store_id,
1048424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          *params->key_range,
10493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params->direction);
1050424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1051868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
10523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
10533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1061868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1062868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
1063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
10643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
10653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->object_store_id,
10663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->index_id,
10673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *params->key_range,
10683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          params->direction);
1069868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1070868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1071868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1072868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
107323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    params->callbacks->OnSuccess(static_cast<IndexedDBValue*>(NULL));
1074868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1075868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1076868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<IndexedDBCursor> cursor =
10783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new IndexedDBCursor(backing_store_cursor.Pass(),
10793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->cursor_type,
10803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params->task_type,
10813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          transaction);
10823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  params->callbacks->OnSuccess(
1083868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor, cursor->key(), cursor->primary_key(), cursor->Value());
1084868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1085868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Count(int64 transaction_id,
1087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 index_id,
1089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_ptr<IndexedDBKeyRange> key_range,
1090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Count");
10927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
10937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
10947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id))
1097868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation,
11003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
11013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
11023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       index_id,
11033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
11043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CountOperation(
11083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 index_id,
11103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CountOperation");
1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 count = 0;
1115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
1118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
11273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id(),
11283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_id,
11293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        index_id,
11303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *key_range,
1131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
11343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnSuccess(count);
1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ++count;
11407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } while (backing_store_cursor->Continue());
1141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess(count);
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteRange(
1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::DeleteRange");
11517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
11527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
11537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
11547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
11557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
11567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation,
11603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       this,
11613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       object_store_id,
11623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       base::Passed(&key_range),
11633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       callbacks));
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteRangeOperation(
11673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
11683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
11693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
11703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
11713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->OpenObjectStoreCursor(
1174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
11753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
11763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          object_store_id,
11773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *key_range,
1178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
1179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (backing_store_cursor) {
1180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    do {
1181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!backing_store_->DeleteRecord(
1182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               transaction->BackingStoreTransaction(),
1183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               id(),
1184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               object_store_id,
1185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               backing_store_cursor->record_identifier())
1186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               .ok()) {
11873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        callbacks->OnError(
1188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Internal error deleting data in range"));
1190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
1191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
11927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } while (backing_store_cursor->Continue());
1193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBDatabase::Clear(int64 transaction_id,
1199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 object_store_id,
1200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              scoped_refptr<IndexedDBCallbacks> callbacks) {
1201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBDatabase::Clear");
12027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  IndexedDBTransaction* transaction = GetTransaction(transaction_id);
12037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!transaction)
1204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
1206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ValidateObjectStoreId(object_store_id))
12087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
12097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
12103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  transaction->ScheduleTask(base::Bind(
12113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks));
1212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::ClearOperation(
12153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
12163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::ObjectStoreClearOperation");
1219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!backing_store_->ClearObjectStore(transaction->BackingStoreTransaction(),
1220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        id(),
1221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        object_store_id).ok()) {
12223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(
1223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error clearing object store"));
1225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callbacks->OnSuccess();
1228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreOperation(
12313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
12323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation");
1234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
1235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
12373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        object_store_metadata.id);
1238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 error_string =
1240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting object store '") +
12413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        object_store_metadata.name + ASCIIToUTF16("'.");
1242e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1243e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 error_string);
1244e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    transaction->Abort(error);
1245e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (s.IsCorruption())
1246e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
1247e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                             error);
1248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeOperation(
12523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 version,
12533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacks> callbacks,
12543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<IndexedDBConnection> connection,
1255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
12563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
12573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int64 old_version = metadata_.int_version;
12583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GT(version, old_version);
12593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = version;
12603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!backing_store_->UpdateIDBDatabaseIntVersion(
1261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
12623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          id(),
12633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          metadata_.int_version)) {
1264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseError error(
1265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
12667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ASCIIToUTF16(
12677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "Internal error writing data to stable storage when "
12687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            "updating version."));
12693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callbacks->OnError(error);
1270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(error);
1271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_second_half_open_.reset(
1275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new PendingSuccessCall(callbacks, connection.get(), version));
12765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callbacks->OnUpgradeNeeded(old_version, connection.Pass(), metadata());
1277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
12805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool committed) {
1281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction->id()) != transactions_.end());
1282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transactions_[transaction->id()], transaction);
1283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transactions_.erase(transaction->id());
1284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
12875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (committed) {
12885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK_EQ(pending_second_half_open_->version(), metadata_.int_version);
12895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(metadata_.id != kInvalidId);
12905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Connection was already minted for OnUpgradeNeeded callback.
12925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scoped_ptr<IndexedDBConnection> connection;
12935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnSuccess(connection.Pass(),
12945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                          this->metadata());
12955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
12965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_second_half_open_->callbacks()->OnError(
12975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
12985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "Version change transaction was aborted in "
12995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   "upgradeneeded event handler."));
13005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
13045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Connection queue is now unblocked.
1305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBDatabase::TransactionCommitFailed() {
13105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Factory may be null in unit tests.
13115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!factory_)
13125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
13131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  factory_->HandleBackingStoreFailure(backing_store_->origin_url());
13141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
13151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t IndexedDBDatabase::ConnectionCount() const {
1317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This does not include pending open calls, as those should not block version
1318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changes and deletes.
1319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return connections_.size();
1320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingOpenCount() const {
1323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_open_calls_.size();
1324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingUpgradeCount() const {
1327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_run_version_change_transaction_call_ ? 1 : 0;
1328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::RunningUpgradeCount() const {
1331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_second_half_open_ ? 1 : 0;
1332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochsize_t IndexedDBDatabase::PendingDeleteCount() const {
1335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return pending_delete_calls_.size();
1336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::ProcessPendingCalls() {
1339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
13405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(pending_run_version_change_transaction_call_->version() >
1341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           metadata_.int_version);
1342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<PendingUpgradeCall> pending_call =
1343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_run_version_change_transaction_call_.Pass();
13445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunVersionChangeTransactionFinal(pending_call->callbacks(),
13455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->ReleaseConnection(),
13465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->transaction_id(),
13475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     pending_call->version());
13485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(1u, ConnectionCount());
1349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through would be a no-op, since transaction must complete
1350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // asynchronously.
1351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsDeleteDatabaseBlocked());
1352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsOpenConnectionBlocked());
1353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDeleteDatabaseBlocked()) {
1357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingDeleteCallList pending_delete_calls;
1358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.swap(pending_delete_calls);
1359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_delete_calls.empty()) {
1360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Only the first delete call will delete the database, but each must fire
1361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // callbacks.
1362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingDeleteCall> pending_delete_call(
1363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pending_delete_calls.front());
1364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_delete_calls.pop_front();
13655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DeleteDatabaseFinal(pending_delete_call->callbacks());
1366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // delete_database_final should never re-queue calls.
1368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_delete_calls_.empty());
1369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsOpenConnectionBlocked()) {
1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingOpenCallList pending_open_calls;
1374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.swap(pending_open_calls);
1375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_open_calls.empty()) {
1376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OpenConnection(pending_open_calls.front());
1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_open_calls.pop_front();
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateTransaction(
1383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IndexedDBConnection* connection,
1385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::vector<int64>& object_store_ids,
1386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint16 mode) {
1387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
13894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(transactions_.find(transaction_id) == transactions_.end());
13904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
13914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The transaction will add itself to this database's coordinator, which
13945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // manages the lifetime of the object.
13955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TransactionCreated(new IndexedDBTransaction(
13967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transaction_id,
13977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      connection->callbacks(),
13987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
13997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      static_cast<indexed_db::TransactionMode>(mode),
1400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      this,
14015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new IndexedDBBackingStore::Transaction(backing_store_)));
1402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) {
1405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transactions_[transaction->id()] = transaction;
1406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !pending_delete_calls_.empty() ||
14105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         transaction_coordinator_.IsRunningVersionChangeTransaction() ||
1411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         pending_run_version_change_transaction_call_;
1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenConnection(
1415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IndexedDBPendingConnection& connection) {
1416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Should have a priority queue so that higher version
1419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // requests are processed first. http://crbug.com/225850
1420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsOpenConnectionBlocked()) {
1421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // The backing store only detects data loss when it is first opened. The
1422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // presence of existing connections means we didn't even check for data loss
1423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // so there'd better not be any.
1424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss());
1425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    pending_open_calls_.push_back(connection);
1426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata_.id == kInvalidId) {
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The database was deleted then immediately re-opened; OpenInternal()
1431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // recreates it in the backing store.
1432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (OpenInternal().ok()) {
1433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
1434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                metadata_.int_version);
1435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 message;
1437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (connection.version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = ASCIIToUTF16(
1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "Internal error opening database with no version specified.");
14405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
1441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message =
1442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16("Internal error opening database with version ") +
1443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(connection.version);
14445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnError(IndexedDBDatabaseError(
1446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          blink::WebIDBDatabaseExceptionUnknownError, message));
1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We infer that the database didn't exist from its lack of either type of
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // version.
1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_new_database =
1454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.version == kNoStringVersion &&
1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (connection.version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // For unit tests only - skip upgrade steps. Calling from script with
1459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // DEFAULT_INT_VERSION throws exception.
1460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK that not in unit tests.
1461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(is_new_database);
1462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnSuccess(
1463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        CreateConnection(connection.database_callbacks,
1464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         connection.child_process_id),
1465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        this->metadata());
1466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We may need to change the version.
1470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 local_version = connection.version;
1471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_new_database) {
1473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection.callbacks->OnSuccess(
1474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          CreateConnection(connection.database_callbacks,
1475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           connection.child_process_id),
1476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          this->metadata());
1477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Spec says: If no version is specified and no database exists, set
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database version to 1.
1481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    local_version = 1;
1482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version > metadata_.int_version) {
1485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    RunVersionChangeTransaction(connection.callbacks,
1486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                CreateConnection(connection.database_callbacks,
1487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                 connection.child_process_id),
1488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                connection.transaction_id,
1489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                local_version);
1490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (local_version < metadata_.int_version) {
1493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection.callbacks->OnError(IndexedDBDatabaseError(
1494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionVersionError,
1495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ASCIIToUTF16("The requested version (") +
1496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            Int64ToString16(local_version) +
1497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16(") is less than the existing version (") +
1498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(local_version, metadata_.int_version);
1502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connection.callbacks->OnSuccess(
1503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateConnection(connection.database_callbacks,
1504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       connection.child_process_id),
1505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this->metadata());
1506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransaction(
1509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
15125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 requested_version) {
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(callbacks);
15158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection.get()));
1516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ConnectionCount() > 1) {
15175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
1518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Front end ensures the event is not fired at connections that have
1519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // close_pending set.
1520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (*it != connection.get()) {
15243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*it)->callbacks()->OnVersionChange(metadata_.int_version,
15253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            requested_version);
1526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
1527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Remove the call to OnBlocked and instead wait
1529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // until the frontend tells us that all the "versionchange" events
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // have been delivered.  http://crbug.com/100123
1531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!pending_run_version_change_transaction_call_);
1534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pending_run_version_change_transaction_call_.reset(new PendingUpgradeCall(
1535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        callbacks, connection.Pass(), transaction_id, requested_version));
1536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
15385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunVersionChangeTransactionFinal(
15395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callbacks, connection.Pass(), transaction_id, requested_version);
1540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<IndexedDBConnection> connection,
1545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<int64> object_store_ids;
1549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateTransaction(transaction_id,
1550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    connection.get(),
1551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    object_store_ids,
1552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    indexed_db::TRANSACTION_VERSION_CHANGE);
1553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  transactions_[transaction_id]
15555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ->ScheduleTask(base::Bind(&IndexedDBDatabase::VersionChangeOperation,
15565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
15575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                requested_version,
15585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                callbacks,
15595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                base::Passed(&connection)),
15605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
15615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                this,
15625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.version,
15635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                metadata_.int_version));
1564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabase(
1569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDeleteDatabaseBlocked()) {
1572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (ConnectionSet::const_iterator it = connections_.begin();
1573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         it != connections_.end();
1574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Front end ensures the event is not fired at connections that have
1576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // close_pending set.
1577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*it)->callbacks()->OnVersionChange(
1578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
1579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): Only fire OnBlocked if there are open
1581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // connections after the VersionChangeEvents are received, not
1582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // just set up to fire.  http://crbug.com/100123
1583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
1585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteDatabaseFinal(callbacks);
1588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !!ConnectionCount();
1592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabaseFinal(
1595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks) {
1596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!IsDeleteDatabaseBlocked());
1597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(backing_store_);
1598a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!backing_store_->DeleteDatabase(metadata_.name).ok()) {
1599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(
1600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error deleting database."));
1602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1604a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int64 old_version = metadata_.int_version;
1605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.id = kInvalidId;
1607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.clear();
1609a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  callbacks->OnSuccess(old_version);
16105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (factory_)
16115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    factory_->DatabaseDeleted(identifier_);
16125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IndexedDBDatabase::ForceClose() {
16155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IndexedDBConnection::ForceClose() may delete this database, so hold ref.
16165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> protect(this);
16175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConnectionSet::const_iterator it = connections_.begin();
16185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (it != connections_.end()) {
16195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IndexedDBConnection* connection = *it++;
16205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection->ForceClose();
16215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
16225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(connections_.empty());
1623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
162558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
16268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connections_.count(connection));
16278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->IsConnected());
16288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(connection->database() == this);
1629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Abort outstanding transactions from the closing connection. This
1631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // can not happen if the close is requested by the connection itself
1632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // as the front-end defers the close until all transactions are
16338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // complete, but can occur on process termination or forced close.
1634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
1635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TransactionMap transactions(transactions_);
1636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (TransactionMap::const_iterator it = transactions.begin(),
1637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        end = transactions.end();
1638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != end;
1639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (it->second->connection() == connection->callbacks())
1641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        it->second->Abort(
1642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Connection is closing."));
1644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  connections_.erase(connection);
1648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_ &&
16495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pending_second_half_open_->connection() == connection) {
16505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_second_half_open_->callbacks()->OnError(
1651f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
1652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "The connection was closed."));
1653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_.reset();
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessPendingCalls();
1657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ConnectionCount() && !pending_open_calls_.size() &&
1660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !pending_delete_calls_.size()) {
1661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(transactions_.empty());
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL origin_url = backing_store_->origin_url();
16641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store_ = NULL;
16651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // factory_ should only be null in unit tests.
1667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
166858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (factory_) {
16695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory_->ReleaseDatabase(identifier_, forced);
167058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      factory_ = NULL;
167158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStoreAbortOperation(
16763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 object_store_id,
1677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation");
1679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RemoveObjectStore(object_store_id);
1681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
16843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store_metadata,
1685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation");
1687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AddObjectStore(object_store_metadata,
16893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 IndexedDBObjectStoreMetadata::kInvalidId);
1690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void IndexedDBDatabase::VersionChangeAbortOperation(
1693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& previous_version,
16943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 previous_int_version,
1695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
16963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
16983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.version = previous_version;
16993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  metadata_.int_version = previous_int_version;
1700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
1703