indexed_db_database.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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>
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <vector>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/auto_reset.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_backing_store.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_cursor.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_factory.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_index_writer.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_transaction.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_path.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_range.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Int64ToString16;
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using WebKit::WebIDBKey;
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CreateObjectStoreOperation : public IndexedDBTransaction::Operation {
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateObjectStoreOperation(
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBBackingStore> backing_store,
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const IndexedDBObjectStoreMetadata& object_store_metadata)
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_metadata_(object_store_metadata) {}
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata object_store_metadata_;
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class DeleteObjectStoreOperation : public IndexedDBTransaction::Operation {
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteObjectStoreOperation(
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBBackingStore> backing_store,
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const IndexedDBObjectStoreMetadata& object_store_metadata)
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_metadata_(object_store_metadata) {}
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata object_store_metadata_;
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::VersionChangeOperation
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : public IndexedDBTransaction::Operation {
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  VersionChangeOperation(
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBDatabase> database,
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int64 transaction_id,
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int64 version,
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks)
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : database_(database),
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction_id_(transaction_id),
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        version_(version),
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_(callbacks),
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_callbacks_(database_callbacks) {}
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database_;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 transaction_id_;
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks_;
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CreateObjectStoreAbortOperation : public IndexedDBTransaction::Operation {
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateObjectStoreAbortOperation(scoped_refptr<IndexedDBDatabase> database,
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  int64 object_store_id)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : database_(database), object_store_id_(object_store_id) {}
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBDatabase> database_;
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class DeleteObjectStoreAbortOperation : public IndexedDBTransaction::Operation {
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteObjectStoreAbortOperation(
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBDatabase> database,
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const IndexedDBObjectStoreMetadata& object_store_metadata)
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : database_(database), object_store_metadata_(object_store_metadata) {}
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database_;
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata_;
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::VersionChangeAbortOperation
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : public IndexedDBTransaction::Operation {
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  VersionChangeAbortOperation(scoped_refptr<IndexedDBDatabase> database,
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const string16& previous_version,
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              int64 previous_int_version)
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : database_(database),
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        previous_version_(previous_version),
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        previous_int_version_(previous_int_version) {}
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database_;
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  string16 previous_version_;
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 previous_int_version_;
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CreateIndexOperation : public IndexedDBTransaction::Operation {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateIndexOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       int64 object_store_id,
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const IndexedDBIndexMetadata& index_metadata)
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_metadata_(index_metadata) {}
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata_;
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class DeleteIndexOperation : public IndexedDBTransaction::Operation {
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteIndexOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       int64 object_store_id,
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const IndexedDBIndexMetadata& index_metadata)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_metadata_(index_metadata) {}
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata_;
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CreateIndexAbortOperation : public IndexedDBTransaction::Operation {
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateIndexAbortOperation(scoped_refptr<IndexedDBDatabase> database,
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 index_id)
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : database_(database),
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_id_(index_id) {}
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBDatabase> database_;
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 index_id_;
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class DeleteIndexAbortOperation : public IndexedDBTransaction::Operation {
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteIndexAbortOperation(scoped_refptr<IndexedDBDatabase> database,
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const IndexedDBIndexMetadata& index_metadata)
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : database_(database),
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_metadata_(index_metadata) {}
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBDatabase> database_;
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata_;
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class GetOperation : public IndexedDBTransaction::Operation {
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GetOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               int64 database_id,
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               int64 object_store_id,
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               int64 index_id,
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               const IndexedDBKeyPath& key_path,
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               const bool auto_increment,
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               scoped_ptr<IndexedDBKeyRange> key_range,
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               indexed_db::CursorType cursor_type,
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               scoped_refptr<IndexedDBCallbacksWrapper> callbacks)
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        database_id_(database_id),
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_id_(index_id),
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        key_path_(key_path),
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        auto_increment_(auto_increment),
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        key_range_(key_range.Pass()),
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cursor_type_(cursor_type),
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_(callbacks) {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 database_id_;
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 index_id_;
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKeyPath key_path_;
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const bool auto_increment_;
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_ptr<IndexedDBKeyRange> key_range_;
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const indexed_db::CursorType cursor_type_;
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class PutOperation : public IndexedDBTransaction::Operation {
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PutOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               int64 database_id,
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               const IndexedDBObjectStoreMetadata& object_store,
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               std::vector<char>* value,
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               scoped_ptr<IndexedDBKey> key,
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               IndexedDBDatabase::PutMode put_mode,
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               const std::vector<int64>& index_ids,
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               const std::vector<IndexedDBDatabase::IndexKeys>& index_keys)
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_(database_id),
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_(object_store),
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        key_(key.Pass()),
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        put_mode_(put_mode),
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_(callbacks),
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_ids_(index_ids),
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_keys_(index_keys) {
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    value_.swap(*value);
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 database_id_;
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata object_store_;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<char> value_;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key_;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBDatabase::PutMode put_mode_;
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::vector<int64> index_ids_;
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::vector<IndexedDBDatabase::IndexKeys> index_keys_;
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class SetIndexesReadyOperation : public IndexedDBTransaction::Operation {
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit SetIndexesReadyOperation(size_t index_count)
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : index_count_(index_count) {}
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const size_t index_count_;
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class OpenCursorOperation : public IndexedDBTransaction::Operation {
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OpenCursorOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      int64 database_id,
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      int64 object_store_id,
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      int64 index_id,
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      scoped_ptr<IndexedDBKeyRange> key_range,
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      indexed_db::CursorDirection direction,
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      indexed_db::CursorType cursor_type,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      IndexedDBDatabase::TaskType task_type,
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      scoped_refptr<IndexedDBCallbacksWrapper> callbacks)
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_(database_id),
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_id_(index_id),
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        key_range_(key_range.Pass()),
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        direction_(direction),
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cursor_type_(cursor_type),
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        task_type_(task_type),
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_(callbacks) {}
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 database_id_;
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 index_id_;
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_ptr<IndexedDBKeyRange> key_range_;
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const indexed_db::CursorDirection direction_;
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const indexed_db::CursorType cursor_type_;
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBDatabase::TaskType task_type_;
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CountOperation : public IndexedDBTransaction::Operation {
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CountOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 int64 database_id,
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 int64 object_store_id,
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 int64 index_id,
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 scoped_ptr<IndexedDBKeyRange> key_range,
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 scoped_refptr<IndexedDBCallbacksWrapper> callbacks)
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_(database_id),
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_id_(index_id),
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        key_range_(key_range.Pass()),
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_(callbacks) {}
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 database_id_;
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 index_id_;
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_ptr<IndexedDBKeyRange> key_range_;
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class DeleteRangeOperation : public IndexedDBTransaction::Operation {
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteRangeOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       int64 database_id,
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       int64 object_store_id,
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       scoped_ptr<IndexedDBKeyRange> key_range,
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       scoped_refptr<IndexedDBCallbacksWrapper> callbacks)
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_(database_id),
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        key_range_(key_range.Pass()),
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_(callbacks) {}
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 database_id_;
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_ptr<IndexedDBKeyRange> key_range_;
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ClearOperation : public IndexedDBTransaction::Operation {
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ClearOperation(scoped_refptr<IndexedDBBackingStore> backing_store,
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 int64 database_id,
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 int64 object_store_id,
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 scoped_refptr<IndexedDBCallbacksWrapper> callbacks)
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : backing_store_(backing_store),
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_(database_id),
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_(object_store_id),
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_(callbacks) {}
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBBackingStore> backing_store_;
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 database_id_;
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 object_store_id_;
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingOpenCall {
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PendingOpenCall(
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int64 transaction_id,
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int64 version)
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks),
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_callbacks_(database_callbacks),
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        version_(version),
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction_id_(transaction_id) {}
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacksWrapper> Callbacks() { return callbacks_; }
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabaseCallbacksWrapper> DatabaseCallbacks() {
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return database_callbacks_;
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 Version() { return version_; }
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 TransactionId() const { return transaction_id_; }
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks_;
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version_;
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 transaction_id_;
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBDatabase::PendingDeleteCall {
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacksWrapper> callbacks)
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : callbacks_(callbacks) {}
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacksWrapper> Callbacks() { return callbacks_; }
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const string16& name,
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore* database,
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBFactory* factory,
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const string16& unique_identifier) {
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> backend =
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new IndexedDBDatabase(name, database, factory, unique_identifier);
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backend->OpenInternal())
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backend;
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const base::string16::value_type kNoStringVersion[] = {0};
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::IndexedDBDatabase(const string16& name,
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     IndexedDBBackingStore* backing_store,
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     IndexedDBFactory* factory,
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const string16& unique_identifier)
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : backing_store_(backing_store),
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_(name,
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId,
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kNoStringVersion,
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION,
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                kInvalidId),
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      identifier_(unique_identifier),
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      factory_(factory),
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      running_version_change_transaction_(NULL),
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      closing_connection_(false) {
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!metadata_.name.empty());
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddObjectStore(
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBObjectStoreMetadata& object_store,
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_max_object_store_id) {
439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store.id) ==
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) {
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id);
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata_.max_object_store_id = new_max_object_store_id;
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store.id] = object_store;
446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveObjectStore(int64 object_store_id) {
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.erase(object_store_id);
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::AddIndex(int64 object_store_id,
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const IndexedDBIndexMetadata& index,
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int64 new_max_index_id) {
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end());
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes[index.id] = index;
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) {
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LT(object_store.max_index_id, new_max_index_id);
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    object_store.max_index_id = new_max_index_id;
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RemoveIndex(int64 object_store_id, int64 index_id) {
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  object_store.indexes.erase(index_id);
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores[object_store_id] = object_store;
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::OpenInternal() {
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store_->GetIDBDatabaseMetaData(
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, &metadata_, &success);
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  << " id_ = " << metadata_.id;
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok)
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (success)
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store_->GetObjectStores(metadata_.id,
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &metadata_.object_stores);
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_->CreateIDBDatabaseMetaData(
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBDatabase::~IndexedDBDatabase() {
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.empty());
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_open_calls_.empty());
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(pending_delete_calls_.empty());
502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBBackingStore> IndexedDBDatabase::BackingStore() const {
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store_;
506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id,
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const string16& name,
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const IndexedDBKeyPath& key_path,
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          bool auto_increment) {
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::create_object_store");
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) ==
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store_metadata(
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name,
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_path,
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      auto_increment,
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBDatabase::kMinimumIndexId);
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new CreateObjectStoreOperation(backing_store_, object_store_metadata),
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new CreateObjectStoreAbortOperation(this, object_store_id));
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddObjectStore(object_store_metadata, object_store_id);
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CreateObjectStoreOperation::Perform(IndexedDBTransaction* transaction) {
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("CreateObjectStoreOperation");
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateObjectStore(
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->database()->id(),
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_metadata_.id,
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_metadata_.name,
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_metadata_.key_path,
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_metadata_.auto_increment)) {
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error creating object store '") +
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            object_store_metadata_.name + ASCIIToUTF16("'.")));
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int64 object_store_id) {
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::delete_object_store");
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new DeleteObjectStoreOperation(backing_store_, object_store_metadata),
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new DeleteObjectStoreAbortOperation(this, object_store_metadata));
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveObjectStore(object_store_id);
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateIndex(int64 transaction_id,
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id,
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const string16& name,
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    const IndexedDBKeyPath& key_path,
580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool unique,
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bool multi_entry) {
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::create_index");
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata object_store =
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) == object_store.indexes.end());
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata index_metadata(
597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      name, index_id, key_path, unique, multi_entry);
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new CreateIndexOperation(backing_store_, object_store_id, index_metadata),
601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new CreateIndexAbortOperation(this, object_store_id, index_id));
602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddIndex(object_store_id, index_metadata, index_id);
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CreateIndexOperation::Perform(IndexedDBTransaction* transaction) {
607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("CreateIndexOperation");
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(),
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   transaction->database()->id(),
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   object_store_id_,
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   index_metadata_.id,
612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   index_metadata_.name,
613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   index_metadata_.key_path,
614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   index_metadata_.unique,
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   index_metadata_.multi_entry)) {
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    string16 error_string = ASCIIToUTF16("Internal error creating index '") +
617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            index_metadata_.name + ASCIIToUTF16("'.");
618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CreateIndexAbortOperation::Perform(IndexedDBTransaction* transaction) {
625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("CreateIndexAbortOperation");
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->RemoveIndex(object_store_id_, index_id_);
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 object_store_id,
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int64 index_id) {
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::delete_index");
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBObjectStoreMetadata object_store =
644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end());
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBIndexMetadata& index_metadata = object_store.indexes[index_id];
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new DeleteIndexOperation(backing_store_, object_store_id, index_metadata),
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new DeleteIndexAbortOperation(this, object_store_id, index_metadata));
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveIndex(object_store_id, index_id);
654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DeleteIndexOperation::Perform(IndexedDBTransaction* transaction) {
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("DeleteIndexOperation");
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        object_store_id_,
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        index_metadata_.id);
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    string16 error_string = ASCIIToUTF16("Internal error deleting index '") +
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            index_metadata_.name + ASCIIToUTF16("'.");
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DeleteIndexAbortOperation::Perform(IndexedDBTransaction* transaction) {
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("DeleteIndexAbortOperation");
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->AddIndex(
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id_, index_metadata_, IndexedDBIndexMetadata::kInvalidId);
675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Commit(int64 transaction_id) {
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend suggests that we commit, but we may have previously initiated
679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // an abort, and so have disposed of the transaction. on_abort has already
680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // been dispatched to the frontend, so it will find out about that
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // asynchronously.
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transactions_[transaction_id]->Commit();
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id) {
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transactions_[transaction_id]->Abort();
691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Abort(int64 transaction_id,
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const IndexedDBDatabaseError& error) {
695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If the transaction is unknown, then it has already been aborted by the
696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend before this call so it is safe to ignore it.
697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transactions_.find(transaction_id) != transactions_.end())
698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transactions_[transaction_id]->Abort(error);
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Get(
702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::get");
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
7137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  IndexedDBDatabaseMetadata::ObjectStoreMap::const_iterator store_iterator =
7147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      metadata_.object_stores.find(object_store_id);
7157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (store_iterator == metadata_.object_stores.end())
7167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(new GetOperation(
720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_,
7217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      metadata_.id,
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
7247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      store_iterator->second.key_path,
7257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      store_iterator->second.auto_increment,
726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_range.Pass(),
727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void GetOperation::Perform(IndexedDBTransaction* transaction) {
732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("GetOperation");
733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBKey* key;
735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (key_range_->IsOnlyKey()) {
738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &key_range_->lower();
739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK_NE(cursor_type_, indexed_db::CURSOR_KEY_ONLY);
742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // ObjectStore Retrieval Operation
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenObjectStoreCursor(
744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id_,
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id_,
747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          *key_range_,
748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) {
750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Value Retrieval Operation
751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id_,
754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id_,
755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          index_id_,
756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          *key_range_,
757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Index Referenced Value Retrieval Operation
760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id_,
763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id_,
764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          index_id_,
765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          *key_range_,
766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!backing_store_cursor) {
770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnSuccess();
771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = &backing_store_cursor->key();
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
776868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key;
778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok;
779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Object Store Retrieval Operation
781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::vector<char> value;
782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   database_id_,
784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   object_store_id_,
785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   *key,
786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   &value);
787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnError(
789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error in get_record."));
791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (value.empty()) {
795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnSuccess();
796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (auto_increment_ && !key_path_.IsNull()) {
800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnSuccess(&value, *key, key_path_);
801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
803868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
804868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnSuccess(&value);
805868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
806868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
807868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
808868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // From here we are dealing only with indexes.
809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ok = backing_store_->GetPrimaryKeyViaIndex(
810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id_,
812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id_,
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id_,
814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *key,
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &primary_key);
816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnError(
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error in get_primary_key_via_index."));
820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!primary_key) {
823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnSuccess();
824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) {
827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Index Value Retrieval Operation
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnSuccess(*primary_key);
829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
831868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Index Referenced Value Retrieval Operation
833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<char> value;
834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 database_id_,
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id_,
837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 *primary_key,
838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 &value);
839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnError(
841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error in get_record."));
843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
846868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (value.empty()) {
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnSuccess();
848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
850868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (auto_increment_ && !key_path_.IsNull()) {
851868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnSuccess(&value, *primary_key, key_path_);
852868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks_->OnSuccess(&value);
855868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
856868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static scoped_ptr<IndexedDBKey> GenerateKey(
858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBBackingStore> backing_store,
859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBTransaction> transaction,
860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 max_generator_value =
863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      9007199254740992LL;  // Maximum integer storable as ECMAScript number.
864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 current_number;
865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok = backing_store->GetKeyGeneratorCurrentNumber(
866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &current_number);
870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LOG(ERROR) << "Failed to get_key_generator_current_number";
872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_number < 0 || current_number > max_generator_value)
875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return make_scoped_ptr(new IndexedDBKey());
876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return make_scoped_ptr(
878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new IndexedDBKey(current_number, WebIDBKey::NumberType));
879868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
881868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static bool UpdateKeyGenerator(
882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBBackingStore> backing_store,
883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBTransaction> transaction,
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey* key,
887868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool check_current) {
888868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(WebIDBKey::NumberType, key->type());
890868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store->MaybeUpdateKeyGeneratorCurrentNumber(
891868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction->BackingStoreTransaction(),
892868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id,
893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      static_cast<int64>(floor(key->number())) + 1,
895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_current);
896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
898868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Put(int64 transaction_id,
899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int64 object_store_id,
900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            std::vector<char>* value,
901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_ptr<IndexedDBKey> key,
902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            PutMode put_mode,
903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<int64>& index_ids,
905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::vector<IndexKeys>& index_keys) {
906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::put");
907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata object_store_metadata =
915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key);
918868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_store_metadata.auto_increment || key->IsValid());
919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(new PutOperation(backing_store_,
920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             id(),
921868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             object_store_metadata,
922868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             value,
923868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             key.Pass(),
924868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             put_mode,
925868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             callbacks,
926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             index_ids,
927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             index_keys));
928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
929868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
930868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PutOperation::Perform(IndexedDBTransaction* transaction) {
931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("PutOperation");
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(index_ids_.size(), index_keys_.size());
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool key_was_generated = false;
935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> key;
937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (put_mode_ != IndexedDBDatabase::CURSOR_UPDATE &&
938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_.auto_increment && !key_->IsValid()) {
939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        backing_store_, transaction, database_id_, object_store_.id);
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key_was_generated = true;
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!auto_inc_key->IsValid()) {
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnError(
944868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Maximum key generator value reached."));
946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = auto_inc_key.Pass();
949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    key = key_.Pass();
951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key->IsValid());
954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (put_mode_ == IndexedDBDatabase::ADD_ONLY) {
957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool found = false;
958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool ok = backing_store_->KeyExistsInObjectStore(
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_,
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_.id,
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        *key.get(),
963868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &record_identifier,
964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &found);
965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
966868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnError(
967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error checking key existence."));
969868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
970868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
971868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (found) {
972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnError(
973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Key already exists in the object store."));
975868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
977868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
978868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ScopedVector<IndexedDBObjectStoreImpl::IndexWriter> index_writers;
980868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  string16 error_message;
981868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
982868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool backing_store_success =
983868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBObjectStoreImpl::MakeIndexWriters(transaction,
984868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 backing_store_.get(),
985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 database_id_,
986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 object_store_,
987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 *key,
988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 key_was_generated,
989868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 index_ids_,
990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 index_keys_,
991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 &index_writers,
992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 &error_message,
993868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 &obeys_constraints);
994868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
995868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnError(IndexedDBDatabaseError(
996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
1001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnError(IndexedDBDatabaseError(
1002868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionConstraintError, error_message));
1003868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1006868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Before this point, don't do any mutation. After this point, rollback the
1007868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // transaction in case of error.
1008868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  backing_store_success =
1009868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->PutRecord(transaction->BackingStoreTransaction(),
1010868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                database_id_,
1011868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                object_store_.id,
1012868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                *key.get(),
1013868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                value_,
1014868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &record_identifier);
1015868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
1016868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnError(IndexedDBDatabaseError(
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
1018868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error performing put/add."));
1019868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1021868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1022868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
1023868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBObjectStoreImpl::IndexWriter* index_writer = index_writers[i];
1024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
10257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                 backing_store_.get(),
1026868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
1027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 database_id_,
1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_.id);
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1031868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (object_store_.auto_increment &&
1032868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      put_mode_ != IndexedDBDatabase::CURSOR_UPDATE &&
1033868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key->type() == WebIDBKey::NumberType) {
1034868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool ok = UpdateKeyGenerator(backing_store_,
1035868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction,
1036868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 database_id_,
1037868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_.id,
1038868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 key.get(),
1039868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 !key_was_generated);
1040868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!ok) {
1041868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_->OnError(
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1043868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Internal error updating key generator."));
1044868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1045868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1047868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1048868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks_->OnSuccess(*key);
1049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1051868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
1052868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 object_store_id,
1053868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     scoped_ptr<IndexedDBKey> primary_key,
1054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<int64>& index_ids,
1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     const std::vector<IndexKeys>& index_keys) {
1056868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::set_index_keys");
1057868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
1058868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
1059868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
1060868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1061868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
1062868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
1063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1064868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBBackingStore> store = BackingStore();
1065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): This method could be asynchronous, but we need to
1066868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // evaluate if it's worth the extra complexity.
1067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::RecordIdentifier record_identifier;
1068868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
1069868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok =
1070868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      store->KeyExistsInObjectStore(transaction->BackingStoreTransaction(),
1071868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    metadata_.id,
1072868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    object_store_id,
1073868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    *primary_key,
1074868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    &record_identifier,
1075868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    &found);
1076868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
1077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(
1078868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1079868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error setting index keys."));
1080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1082868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
1083868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
1084868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
1085868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error setting index keys for object store."));
1086868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1087868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ScopedVector<IndexedDBObjectStoreImpl::IndexWriter> index_writers;
1090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  string16 error_message;
1091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool obeys_constraints = false;
1092868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
1093868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
1094868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const IndexedDBObjectStoreMetadata& object_store_metadata =
1095868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.object_stores[object_store_id];
1096868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool backing_store_success =
1097868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBObjectStoreImpl::MakeIndexWriters(transaction,
1098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 store.get(),
1099868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 id(),
1100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 object_store_metadata,
1101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 *primary_key,
1102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 false,
1103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 index_ids,
1104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 index_keys,
1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 &index_writers,
1106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 &error_message,
1107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 &obeys_constraints);
1108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_success) {
1109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
1111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "Internal error: backing store error updating index keys."));
1112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!obeys_constraints) {
1115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
1116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionConstraintError, error_message));
1117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_writers.size(); ++i) {
1121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBObjectStoreImpl::IndexWriter* index_writer = index_writers[i];
1122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    index_writer->WriteIndexKeys(record_identifier,
1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 store.get(),
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction->BackingStoreTransaction(),
1125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 id(),
1126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 object_store_id);
1127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
1131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        int64,
1132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        const std::vector<int64>& index_ids) {
1133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBObjectStoreImpl::set_indexes_ready");
1134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
1140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(IndexedDBDatabase::PREEMPTIVE_TASK,
1142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            new SetIndexesReadyOperation(index_ids.size()));
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SetIndexesReadyOperation::Perform(IndexedDBTransaction* transaction) {
1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("SetIndexesReadyOperation");
1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < index_count_; ++i)
1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->DidCompletePreemptiveEvent();
1149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenCursor(
1152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    indexed_db::CursorDirection direction,
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool key_only,
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskType task_type,
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::open_cursor");
1161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
1162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
1163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
1166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(new OpenCursorOperation(
1168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_,
1169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      id(),
1170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      object_store_id,
1171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      index_id,
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_range.Pass(),
1173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      direction,
1174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
1175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      task_type,
1176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks));
1177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void OpenCursorOperation::Perform(IndexedDBTransaction* transaction) {
1180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("OpenCursorOperation");
1181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The frontend has begun indexing, so this pauses the transaction
1183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // until the indexing is complete. This can't happen any earlier
1184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // because we don't want to switch to early mode in case multiple
1185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // indexes are being created in a row, with Put()'s in between.
1186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (task_type_ == IndexedDBDatabase::PREEMPTIVE_TASK)
1187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->AddPreemptiveEvent();
1188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
1191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_NE(cursor_type_, indexed_db::CURSOR_KEY_ONLY);
1192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
1194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_,
1195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_,
1196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        *key_range_,
1197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        direction_);
1198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(task_type_, IndexedDBDatabase::NORMAL_TASK);
1200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) {
1201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id_,
1204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id_,
1205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          index_id_,
1206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          *key_range_,
1207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          direction_);
1208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor = backing_store_->OpenIndexCursor(
1210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id_,
1212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id_,
1213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          index_id_,
1214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          *key_range_,
1215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          direction_);
1216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
1220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnSuccess(static_cast<std::vector<char>*>(NULL));
1221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBDatabase::TaskType task_type(
1225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      static_cast<IndexedDBDatabase::TaskType>(task_type_));
1226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBCursor> cursor = IndexedDBCursor::Create(
1227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_cursor.Pass(), cursor_type_, task_type, transaction);
1228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks_->OnSuccess(
1229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor, cursor->key(), cursor->primary_key(), cursor->Value());
1230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Count(
1233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
1236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
1238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::count");
1239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
1240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
1241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
1242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
1244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(metadata_.object_stores.find(object_store_id) !=
1246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         metadata_.object_stores.end());
1247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(new CountOperation(backing_store_,
1248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               id(),
1249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               object_store_id,
1250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               index_id,
1251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               key_range.Pass(),
1252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               callbacks));
1253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CountOperation::Perform(IndexedDBTransaction* transaction) {
1256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("CountOperation");
1257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 count = 0;
1258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (index_id_ == IndexedDBIndexMetadata::kInvalidId) {
1261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
1263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_,
1264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_,
1265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        *key_range_,
1266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction->BackingStoreTransaction(),
1270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id_,
1271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_id_,
1272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_id_,
1273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        *key_range_,
1274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        indexed_db::CURSOR_NEXT);
1275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_cursor) {
1277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnSuccess(count);
1278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
1282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ++count;
1283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (backing_store_cursor->ContinueFunction(0));
1284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks_->OnSuccess(count);
1286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteRange(
1289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKeyRange> key_range,
1292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
1293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::delete_range");
1294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
1295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
1296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
1297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
1299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(new DeleteRangeOperation(
1301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_, id(), object_store_id, key_range.Pass(), callbacks));
1302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DeleteRangeOperation::Perform(IndexedDBTransaction* transaction) {
1305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("DeleteRangeOperation");
1306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->OpenObjectStoreCursor(
1308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id_,
1310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id_,
1311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          *key_range_,
1312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          indexed_db::CURSOR_NEXT);
1313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (backing_store_cursor) {
1314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    do {
1315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!backing_store_->DeleteRecord(
1316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              transaction->BackingStoreTransaction(),
1317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              database_id_,
1318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              object_store_id_,
1319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              backing_store_cursor->record_identifier())) {
1320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks_->OnError(
1321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Internal error deleting data in range"));
1323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
1324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } while (backing_store_cursor->ContinueFunction(0));
1326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks_->OnSuccess();
1329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Clear(
1332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
1335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("IndexedDBDatabase::clear");
1336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionMap::const_iterator trans_iterator =
1337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_.find(transaction_id);
1338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (trans_iterator == transactions_.end())
1339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBTransaction* transaction = trans_iterator->second;
1341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
1342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
1344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new ClearOperation(backing_store_, id(), object_store_id, callbacks));
1345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ClearOperation::Perform(IndexedDBTransaction* transaction) {
1348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("ObjectStoreClearOperation");
1349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->ClearObjectStore(transaction->BackingStoreTransaction(),
1350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        database_id_,
1351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        object_store_id_)) {
1352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnError(
1353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error clearing object store"));
1355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks_->OnSuccess();
1358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DeleteObjectStoreOperation::Perform(IndexedDBTransaction* transaction) {
1361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("DeleteObjectStoreOperation");
1362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ok =
1363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        transaction->database()->id(),
1365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        object_store_metadata_.id);
1366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ok) {
1367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    string16 error_string =
1368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error deleting object store '") +
1369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        object_store_metadata_.name + ASCIIToUTF16("'.");
1370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(IndexedDBDatabaseError(
1371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
1372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::VersionChangeOperation::Perform(
1376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("VersionChangeOperation");
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 database_id = database_->id();
1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 old_version = database_->metadata_.int_version;
1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GT(version_, old_version);
1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->metadata_.int_version = version_;
1382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!database_->backing_store_->UpdateIDBDatabaseIntVersion(
1383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction->BackingStoreTransaction(),
1384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id,
1385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_->metadata_.int_version)) {
1386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseError error(
1387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionUnknownError,
1388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("Internal error writing data to stable storage when "
1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     "updating version."));
1390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks_->OnError(error);
1391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Abort(error);
1392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!database_->pending_second_half_open_);
1395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->pending_second_half_open_.reset(new PendingOpenCall(
1396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks_, database_callbacks_, transaction_id_, version_));
1397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks_->OnUpgradeNeeded(old_version, database_, database_->metadata());
1398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionStarted(IndexedDBTransaction* transaction) {
1401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!running_version_change_transaction_);
1404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    running_version_change_transaction_ = transaction;
1405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction) {
1409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction->id()) != transactions_.end());
1411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(transactions_[transaction->id()], transaction);
1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transactions_.erase(transaction->id());
1413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(transaction, running_version_change_transaction_);
1415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    running_version_change_transaction_ = NULL;
1416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionFinishedAndAbortFired(
1420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
1423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_->Callbacks()->OnError(
1424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionAbortError,
1425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "Version change transaction was aborted in "
1426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "upgradeneeded event handler."));
1427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::TransactionFinishedAndCompleteFired(
1434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_second_half_open_);
1437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pending_second_half_open_) {
1438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK_EQ(pending_second_half_open_->Version(), metadata_.int_version);
1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK(metadata_.id != kInvalidId);
1440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_->Callbacks()->OnSuccess(this, this->metadata());
1441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_second_half_open_.reset();
1442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessPendingCalls();
1444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t IndexedDBDatabase::ConnectionCount() const {
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This does not include pending open calls, as those should not block version
1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changes and deletes.
1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return database_callbacks_set_.size();
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::ProcessPendingCalls() {
1454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_) {
1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(pending_second_half_open_->Version(), metadata_.int_version);
1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(metadata_.id != kInvalidId);
1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<PendingOpenCall> pending_call = pending_second_half_open_.Pass();
1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_call->Callbacks()->OnSuccess(this, this->metadata());
1459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
1463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_run_version_change_transaction_call_->Version() >
1464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           metadata_.int_version);
1465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<PendingOpenCall> pending_call =
1466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_run_version_change_transaction_call_.Pass();
1467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RunVersionChangeTransactionFinal(pending_call->Callbacks(),
1468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     pending_call->DatabaseCallbacks(),
1469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     pending_call->TransactionId(),
1470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     pending_call->Version());
1471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(static_cast<size_t>(1), ConnectionCount());
1472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through would be a no-op, since transaction must complete
1473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // asynchronously.
1474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsDeleteDatabaseBlocked());
1475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(IsOpenConnectionBlocked());
1476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDeleteDatabaseBlocked()) {
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingDeleteCallList pending_delete_calls;
1481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.swap(pending_delete_calls);
1482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_delete_calls.empty()) {
1483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Only the first delete call will delete the database, but each must fire
1484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // callbacks.
1485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingDeleteCall> pending_delete_call(
1486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pending_delete_calls.front());
1487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_delete_calls.pop_front();
1488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DeleteDatabaseFinal(pending_delete_call->Callbacks());
1489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // delete_database_final should never re-queue calls.
1491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(pending_delete_calls_.empty());
1492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Fall through when complete, as pending opens may be unblocked.
1493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsOpenConnectionBlocked()) {
1496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PendingOpenCallList pending_open_calls;
1497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.swap(pending_open_calls);
1498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while (!pending_open_calls.empty()) {
1499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<PendingOpenCall> pending_open_call(pending_open_calls.front());
1500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_open_calls.pop_front();
1501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      OpenConnection(pending_open_call->Callbacks(),
1502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pending_open_call->DatabaseCallbacks(),
1503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pending_open_call->TransactionId(),
1504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pending_open_call->Version());
1505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::CreateTransaction(
1510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacksWrapper> callbacks,
1512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::vector<int64>& object_store_ids,
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint16 mode) {
1514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(database_callbacks_set_.has(callbacks));
1516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBTransaction> transaction =
1518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexedDBTransaction::Create(
1519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          transaction_id,
1520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          callbacks,
1521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_ids,
1522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          static_cast<indexed_db::TransactionMode>(mode),
1523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          this);
1524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transactions_.find(transaction_id) == transactions_.end());
15257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  transactions_[transaction_id] = transaction.get();
1526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !pending_delete_calls_.empty() ||
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         running_version_change_transaction_ ||
1531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         pending_run_version_change_transaction_call_;
1532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::OpenConnection(
1535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
1536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
1537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 version) {
1539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(backing_store_.get());
1540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Should have a priority queue so that higher version
1542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // requests are processed first. http://crbug.com/225850
1543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsOpenConnectionBlocked()) {
1544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_open_calls_.push_back(new PendingOpenCall(
1545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks, database_callbacks, transaction_id, version));
1546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata_.id == kInvalidId) {
1550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The database was deleted then immediately re-opened; OpenInternal()
1551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // recreates it in the backing store.
1552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (OpenInternal()) {
1553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK_EQ(metadata_.int_version,
1554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                IndexedDBDatabaseMetadata::NO_INT_VERSION);
1555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
1556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      string16 message;
1557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
1558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = ASCIIToUTF16(
1559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "Internal error opening database with no version specified.");
1560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      else
1561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message =
1562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16("Internal error opening database with version ") +
1563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(version);
1564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks->OnError(IndexedDBDatabaseError(
1565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          WebKit::WebIDBDatabaseExceptionUnknownError, message));
1566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We infer that the database didn't exist from its lack of either type of
1571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // version.
1572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_new_database =
1573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.version == kNoStringVersion &&
1574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
1575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
1577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // For unit tests only - skip upgrade steps. Calling from script with
1578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // DEFAULT_INT_VERSION throws exception.
1579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(jsbell): Assert that we're executing a unit test.
1580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(is_new_database);
1581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    database_callbacks_set_.insert(database_callbacks);
1582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnSuccess(this, this->metadata());
1583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
1587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_new_database) {
1588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_callbacks_set_.insert(database_callbacks);
1589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks->OnSuccess(this, this->metadata());
1590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
1591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Spec says: If no version is specified and no database exists, set
1593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database version to 1.
1594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    version = 1;
1595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version > metadata_.int_version) {
1598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    database_callbacks_set_.insert(database_callbacks);
1599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RunVersionChangeTransaction(
1600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks, database_callbacks, transaction_id, version);
1601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (version < metadata_.int_version) {
1604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(IndexedDBDatabaseError(
1605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebKit::WebIDBDatabaseExceptionVersionError,
1606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ASCIIToUTF16("The requested version (") + Int64ToString16(version) +
1607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ASCIIToUTF16(") is less than the existing version (") +
1608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(version, metadata_.int_version);
1612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_callbacks_set_.insert(database_callbacks);
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks->OnSuccess(this, this->metadata());
1614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransaction(
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
1619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(callbacks.get());
1623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(database_callbacks_set_.has(database_callbacks));
1624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ConnectionCount() > 1) {
1625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Front end ensures the event is not fired at connections that have
1626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // close_pending set.
1627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (DatabaseCallbacksSet::const_iterator it =
1628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)             database_callbacks_set_.begin();
1629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != database_callbacks_set_.end();
1630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
16317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (it->get() != database_callbacks.get())
1632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        (*it)->OnVersionChange(metadata_.int_version, requested_version);
1633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(jsbell): Remove the call to on_blocked and instead wait
1635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // until the frontend tells us that all the "versionchange" events
1636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // have been delivered.  http://crbug.com/100123
1637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(!pending_run_version_change_transaction_call_);
1640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_run_version_change_transaction_call_.reset(new PendingOpenCall(
1641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callbacks, database_callbacks, transaction_id, requested_version));
1642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RunVersionChangeTransactionFinal(
1645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks, database_callbacks, transaction_id, requested_version);
1646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
1650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
1651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
1652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 requested_version) {
1653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<int64> object_store_ids;
1655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateTransaction(transaction_id,
1656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    database_callbacks,
1657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    object_store_ids,
1658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    indexed_db::TRANSACTION_VERSION_CHANGE);
1659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBTransaction> transaction =
1660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transactions_[transaction_id];
1661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->ScheduleTask(
1663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new VersionChangeOperation(this,
1664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 transaction_id,
1665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 requested_version,
1666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 callbacks,
1667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 database_callbacks),
1668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new VersionChangeAbortOperation(
1669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          this, metadata_.version, metadata_.int_version));
1670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!pending_second_half_open_);
1672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabase(
1675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
1676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDeleteDatabaseBlocked()) {
1678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (DatabaseCallbacksSet::const_iterator it =
1679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)             database_callbacks_set_.begin();
1680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != database_callbacks_set_.end();
1681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
1682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Front end ensures the event is not fired at connections that have
1683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // close_pending set.
1684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      (*it)->OnVersionChange(metadata_.int_version,
1685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             IndexedDBDatabaseMetadata::NO_INT_VERSION);
1686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(jsbell): Only fire on_blocked if there are open
1688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // connections after the VersionChangeEvents are received, not
1689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // just set up to fire.  http://crbug.com/100123
1690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnBlocked(metadata_.int_version);
1691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
1692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeleteDatabaseFinal(callbacks);
1695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !!ConnectionCount();
1699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::DeleteDatabaseFinal(
1702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
1703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!IsDeleteDatabaseBlocked());
17047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(backing_store_.get());
1705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!backing_store_->DeleteDatabase(metadata_.name)) {
1706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(
1707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error deleting database."));
1709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.version = kNoStringVersion;
1712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.id = kInvalidId;
1713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  metadata_.object_stores.clear();
1715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks->OnSuccess();
1716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::Close(
1719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<IndexedDBDatabaseCallbacksWrapper> callbacks) {
17207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(callbacks.get());
1721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(database_callbacks_set_.has(callbacks));
1722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Close outstanding transactions from the closing connection. This
1724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // can not happen if the close is requested by the connection itself
1725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // as the front-end defers the close until all transactions are
1726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // complete, so something unusual has happened e.g. unexpected
1727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // process termination.
1728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
1729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TransactionMap transactions(transactions_);
1730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (TransactionMap::const_iterator it = transactions.begin(),
1731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        end = transactions.end();
1732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it != end;
1733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         ++it) {
17347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (it->second->connection() == callbacks.get())
1735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        it->second->Abort(
1736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
1737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   "Connection is closing."));
1738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_callbacks_set_.erase(callbacks);
1742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_second_half_open_ &&
17437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pending_second_half_open_->DatabaseCallbacks().get() == callbacks.get()) {
1744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_->Callbacks()->OnError(
1745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionAbortError,
1746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "The connection was closed."));
1747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_second_half_open_.reset();
1748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // process_pending_calls allows the inspector to process a pending open call
1751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // and call close, reentering IndexedDBDatabase::close. Then the
1752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // backend would be removed both by the inspector closing its connection, and
1753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // by the connection that first called close.
1754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // To avoid that situation, don't proceed in case of reentrancy.
1755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (closing_connection_)
1756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::AutoReset<bool> ClosingConnection(&closing_connection_, true);
1758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessPendingCalls();
1759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ConnectionCount() && !pending_open_calls_.size() &&
1762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !pending_delete_calls_.size()) {
1763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(transactions_.empty());
1764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    backing_store_ = NULL;
1766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // This check should only be false in unit tests.
1768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(jsbell): Assert factory_ || we're executing a unit test.
17697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (factory_.get())
1770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      factory_->RemoveIDBDatabaseBackend(identifier_);
1771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CreateObjectStoreAbortOperation::Perform(
1775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1776868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("CreateObjectStoreAbortOperation");
1777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
1778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->RemoveObjectStore(object_store_id_);
1779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DeleteObjectStoreAbortOperation::Perform(
1782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("DeleteObjectStoreAbortOperation");
1784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
1785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->AddObjectStore(object_store_metadata_,
1786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            IndexedDBObjectStoreMetadata::kInvalidId);
1787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBDatabase::VersionChangeAbortOperation::Perform(
1790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBTransaction* transaction) {
1791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IDB_TRACE("VersionChangeAbortOperation");
1792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!transaction);
1793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->metadata_.version = previous_version_;
1794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  database_->metadata_.int_version = previous_int_version_;
1795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
1798