OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/indexed_db/indexed_db_database.h" | 5 #include "content/browser/indexed_db/indexed_db_database.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 #include <memory> | 10 #include <memory> |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 scoped_refptr<IndexedDBDatabase> db_; | 110 scoped_refptr<IndexedDBDatabase> db_; |
111 | 111 |
112 private: | 112 private: |
113 DISALLOW_COPY_AND_ASSIGN(OpenOrDeleteRequest); | 113 DISALLOW_COPY_AND_ASSIGN(OpenOrDeleteRequest); |
114 }; | 114 }; |
115 | 115 |
116 class IndexedDBDatabase::OpenRequest | 116 class IndexedDBDatabase::OpenRequest |
117 : public IndexedDBDatabase::OpenOrDeleteRequest { | 117 : public IndexedDBDatabase::OpenOrDeleteRequest { |
118 public: | 118 public: |
119 OpenRequest(scoped_refptr<IndexedDBDatabase> db, | 119 OpenRequest(scoped_refptr<IndexedDBDatabase> db, |
120 const IndexedDBPendingConnection& pending_connection) | 120 std::unique_ptr<IndexedDBPendingConnection> pending_connection) |
121 : OpenOrDeleteRequest(db), pending_(pending_connection) {} | 121 : OpenOrDeleteRequest(db), pending_(std::move(pending_connection)) {} |
122 | 122 |
123 void Perform() override { | 123 void Perform() override { |
124 if (db_->metadata_.id == kInvalidId) { | 124 if (db_->metadata_.id == kInvalidId) { |
125 // The database was deleted then immediately re-opened; OpenInternal() | 125 // The database was deleted then immediately re-opened; OpenInternal() |
126 // recreates it in the backing store. | 126 // recreates it in the backing store. |
127 if (!db_->OpenInternal().ok()) { | 127 if (!db_->OpenInternal().ok()) { |
128 // TODO(jsbell): Consider including sanitized leveldb status message. | 128 // TODO(jsbell): Consider including sanitized leveldb status message. |
129 base::string16 message; | 129 base::string16 message; |
130 if (pending_.version == IndexedDBDatabaseMetadata::NO_VERSION) { | 130 if (pending_->version == IndexedDBDatabaseMetadata::NO_VERSION) { |
131 message = ASCIIToUTF16( | 131 message = ASCIIToUTF16( |
132 "Internal error opening database with no version specified."); | 132 "Internal error opening database with no version specified."); |
133 } else { | 133 } else { |
134 message = | 134 message = |
135 ASCIIToUTF16("Internal error opening database with version ") + | 135 ASCIIToUTF16("Internal error opening database with version ") + |
136 Int64ToString16(pending_.version); | 136 Int64ToString16(pending_->version); |
137 } | 137 } |
138 pending_.callbacks->OnError(IndexedDBDatabaseError( | 138 pending_->callbacks->OnError(IndexedDBDatabaseError( |
139 blink::WebIDBDatabaseExceptionUnknownError, message)); | 139 blink::WebIDBDatabaseExceptionUnknownError, message)); |
140 db_->RequestComplete(this); | 140 db_->RequestComplete(this); |
141 return; | 141 return; |
142 } | 142 } |
143 | 143 |
144 DCHECK_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata_.version); | 144 DCHECK_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata_.version); |
145 } | 145 } |
146 | 146 |
147 const int64_t old_version = db_->metadata_.version; | 147 const int64_t old_version = db_->metadata_.version; |
148 int64_t& new_version = pending_.version; | 148 int64_t& new_version = pending_->version; |
149 | 149 |
150 bool is_new_database = old_version == IndexedDBDatabaseMetadata::NO_VERSION; | 150 bool is_new_database = old_version == IndexedDBDatabaseMetadata::NO_VERSION; |
151 | 151 |
152 if (new_version == IndexedDBDatabaseMetadata::DEFAULT_VERSION) { | 152 if (new_version == IndexedDBDatabaseMetadata::DEFAULT_VERSION) { |
153 // For unit tests only - skip upgrade steps. (Calling from script with | 153 // For unit tests only - skip upgrade steps. (Calling from script with |
154 // DEFAULT_VERSION throws exception.) | 154 // DEFAULT_VERSION throws exception.) |
155 DCHECK(is_new_database); | 155 DCHECK(is_new_database); |
156 pending_.callbacks->OnSuccess( | 156 pending_->callbacks->OnSuccess( |
157 db_->CreateConnection(pending_.database_callbacks, | 157 db_->CreateConnection(pending_->database_callbacks, |
158 pending_.child_process_id), | 158 pending_->child_process_id), |
159 db_->metadata_); | 159 db_->metadata_); |
160 db_->RequestComplete(this); | 160 db_->RequestComplete(this); |
161 return; | 161 return; |
162 } | 162 } |
163 | 163 |
164 if (!is_new_database && | 164 if (!is_new_database && |
165 (new_version == old_version || | 165 (new_version == old_version || |
166 new_version == IndexedDBDatabaseMetadata::NO_VERSION)) { | 166 new_version == IndexedDBDatabaseMetadata::NO_VERSION)) { |
167 pending_.callbacks->OnSuccess( | 167 pending_->callbacks->OnSuccess( |
168 db_->CreateConnection(pending_.database_callbacks, | 168 db_->CreateConnection(pending_->database_callbacks, |
169 pending_.child_process_id), | 169 pending_->child_process_id), |
170 db_->metadata_); | 170 db_->metadata_); |
171 db_->RequestComplete(this); | 171 db_->RequestComplete(this); |
172 return; | 172 return; |
173 } | 173 } |
174 | 174 |
175 if (new_version == IndexedDBDatabaseMetadata::NO_VERSION) { | 175 if (new_version == IndexedDBDatabaseMetadata::NO_VERSION) { |
176 // If no version is specified and no database exists, upgrade the | 176 // If no version is specified and no database exists, upgrade the |
177 // database version to 1. | 177 // database version to 1. |
178 DCHECK(is_new_database); | 178 DCHECK(is_new_database); |
179 new_version = 1; | 179 new_version = 1; |
180 } else if (new_version < old_version) { | 180 } else if (new_version < old_version) { |
181 // Requested version is lower than current version - fail the request. | 181 // Requested version is lower than current version - fail the request. |
182 DCHECK(!is_new_database); | 182 DCHECK(!is_new_database); |
183 pending_.callbacks->OnError(IndexedDBDatabaseError( | 183 pending_->callbacks->OnError(IndexedDBDatabaseError( |
184 blink::WebIDBDatabaseExceptionVersionError, | 184 blink::WebIDBDatabaseExceptionVersionError, |
185 ASCIIToUTF16("The requested version (") + | 185 ASCIIToUTF16("The requested version (") + |
186 Int64ToString16(pending_.version) + | 186 Int64ToString16(pending_->version) + |
187 ASCIIToUTF16(") is less than the existing version (") + | 187 ASCIIToUTF16(") is less than the existing version (") + |
188 Int64ToString16(db_->metadata_.version) + ASCIIToUTF16(")."))); | 188 Int64ToString16(db_->metadata_.version) + ASCIIToUTF16(")."))); |
189 db_->RequestComplete(this); | 189 db_->RequestComplete(this); |
190 return; | 190 return; |
191 } | 191 } |
192 | 192 |
193 // Requested version is higher than current version - upgrade needed. | 193 // Requested version is higher than current version - upgrade needed. |
194 DCHECK_GT(new_version, old_version); | 194 DCHECK_GT(new_version, old_version); |
195 | 195 |
196 if (db_->connections_.empty()) { | 196 if (db_->connections_.empty()) { |
197 StartUpgrade(); | 197 StartUpgrade(); |
198 return; | 198 return; |
199 } | 199 } |
200 | 200 |
201 // There are outstanding connections - fire "versionchange" events and | 201 // There are outstanding connections - fire "versionchange" events and |
202 // wait for the connections to close. Front end ensures the event is not | 202 // wait for the connections to close. Front end ensures the event is not |
203 // fired at connections that have close_pending set. A "blocked" event | 203 // fired at connections that have close_pending set. A "blocked" event |
204 // will be fired at the request when one of the connections acks that the | 204 // will be fired at the request when one of the connections acks that the |
205 // "versionchange" event was ignored. | 205 // "versionchange" event was ignored. |
206 DCHECK_NE(pending_.callbacks->data_loss_info().status, | 206 DCHECK_NE(pending_->data_loss_info.status, blink::WebIDBDataLossTotal); |
207 blink::WebIDBDataLossTotal); | |
208 for (const auto* connection : db_->connections_) | 207 for (const auto* connection : db_->connections_) |
209 connection->callbacks()->OnVersionChange(old_version, new_version); | 208 connection->callbacks()->OnVersionChange(old_version, new_version); |
210 | 209 |
211 // When all connections have closed the upgrade can proceed. | 210 // When all connections have closed the upgrade can proceed. |
212 } | 211 } |
213 | 212 |
214 void OnVersionChangeIgnored() const override { | 213 void OnVersionChangeIgnored() const override { |
215 pending_.callbacks->OnBlocked(db_->metadata_.version); | 214 pending_->callbacks->OnBlocked(db_->metadata_.version); |
216 } | 215 } |
217 | 216 |
218 void OnConnectionClosed(IndexedDBConnection* connection) override { | 217 void OnConnectionClosed(IndexedDBConnection* connection) override { |
219 // This connection closed prematurely; signal an error and complete. | 218 // This connection closed prematurely; signal an error and complete. |
220 if (connection && connection->callbacks() == pending_.database_callbacks) { | 219 if (connection && connection->callbacks() == pending_->database_callbacks) { |
221 pending_.callbacks->OnError( | 220 pending_->callbacks->OnError( |
222 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, | 221 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, |
223 "The connection was closed.")); | 222 "The connection was closed.")); |
224 db_->RequestComplete(this); | 223 db_->RequestComplete(this); |
225 return; | 224 return; |
226 } | 225 } |
227 | 226 |
228 if (!db_->connections_.empty()) | 227 if (!db_->connections_.empty()) |
229 return; | 228 return; |
230 | 229 |
231 StartUpgrade(); | 230 StartUpgrade(); |
232 } | 231 } |
233 | 232 |
234 // Initiate the upgrade. The bulk of the work actually happens in | 233 // Initiate the upgrade. The bulk of the work actually happens in |
235 // IndexedDBDatabase::VersionChangeOperation in order to kick the | 234 // IndexedDBDatabase::VersionChangeOperation in order to kick the |
236 // transaction into the correct state. | 235 // transaction into the correct state. |
237 void StartUpgrade() { | 236 void StartUpgrade() { |
238 connection_ = db_->CreateConnection(pending_.database_callbacks, | 237 connection_ = db_->CreateConnection(pending_->database_callbacks, |
239 pending_.child_process_id); | 238 pending_->child_process_id); |
240 DCHECK_EQ(db_->connections_.count(connection_.get()), 1UL); | 239 DCHECK_EQ(db_->connections_.count(connection_.get()), 1UL); |
241 | 240 |
242 std::vector<int64_t> object_store_ids; | 241 std::vector<int64_t> object_store_ids; |
243 IndexedDBTransaction* transaction = db_->CreateTransaction( | 242 IndexedDBTransaction* transaction = db_->CreateTransaction( |
244 pending_.transaction_id, connection_.get(), object_store_ids, | 243 pending_->transaction_id, connection_.get(), object_store_ids, |
245 blink::WebIDBTransactionModeVersionChange); | 244 blink::WebIDBTransactionModeVersionChange); |
246 | 245 |
247 DCHECK(db_->transaction_coordinator_.IsRunningVersionChangeTransaction()); | 246 DCHECK(db_->transaction_coordinator_.IsRunningVersionChangeTransaction()); |
248 transaction->ScheduleTask( | 247 transaction->ScheduleTask( |
249 base::Bind(&IndexedDBDatabase::VersionChangeOperation, db_, | 248 base::Bind(&IndexedDBDatabase::VersionChangeOperation, db_, |
250 pending_.version, pending_.callbacks)); | 249 pending_->version, pending_->callbacks)); |
251 } | 250 } |
252 | 251 |
253 // Called when the upgrade transaction has started executing. | 252 // Called when the upgrade transaction has started executing. |
254 void UpgradeTransactionStarted(int64_t old_version) override { | 253 void UpgradeTransactionStarted(int64_t old_version) override { |
255 DCHECK(connection_); | 254 DCHECK(connection_); |
256 pending_.callbacks->OnUpgradeNeeded(old_version, std::move(connection_), | 255 pending_->callbacks->OnUpgradeNeeded(old_version, std::move(connection_), |
257 db_->metadata_); | 256 db_->metadata_, |
| 257 pending_->data_loss_info); |
258 } | 258 } |
259 | 259 |
260 void UpgradeTransactionFinished(bool committed) override { | 260 void UpgradeTransactionFinished(bool committed) override { |
261 // Ownership of connection was already passed along in OnUpgradeNeeded. | 261 // Ownership of connection was already passed along in OnUpgradeNeeded. |
262 DCHECK(!connection_); | 262 DCHECK(!connection_); |
263 | 263 |
264 if (committed) { | 264 if (committed) { |
265 DCHECK_EQ(pending_.version, db_->metadata_.version); | 265 DCHECK_EQ(pending_->version, db_->metadata_.version); |
266 pending_.callbacks->OnSuccess(std::unique_ptr<IndexedDBConnection>(), | 266 pending_->callbacks->OnSuccess(std::unique_ptr<IndexedDBConnection>(), |
267 db_->metadata()); | 267 db_->metadata()); |
268 } else { | 268 } else { |
269 DCHECK_NE(pending_.version, db_->metadata_.version); | 269 DCHECK_NE(pending_->version, db_->metadata_.version); |
270 pending_.callbacks->OnError( | 270 pending_->callbacks->OnError( |
271 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, | 271 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, |
272 "Version change transaction was aborted in " | 272 "Version change transaction was aborted in " |
273 "upgradeneeded event handler.")); | 273 "upgradeneeded event handler.")); |
274 } | 274 } |
275 db_->RequestComplete(this); | 275 db_->RequestComplete(this); |
276 } | 276 } |
277 | 277 |
278 private: | 278 private: |
279 IndexedDBPendingConnection pending_; | 279 std::unique_ptr<IndexedDBPendingConnection> pending_; |
280 | 280 |
281 // If an upgrade is needed, holds the pending connection until ownership is | 281 // If an upgrade is needed, holds the pending connection until ownership is |
282 // transferred to the IndexedDBDispatcherHost via OnUpgradeNeeded. | 282 // transferred to the IndexedDBDispatcherHost via OnUpgradeNeeded. |
283 std::unique_ptr<IndexedDBConnection> connection_; | 283 std::unique_ptr<IndexedDBConnection> connection_; |
284 | 284 |
285 DISALLOW_COPY_AND_ASSIGN(OpenRequest); | 285 DISALLOW_COPY_AND_ASSIGN(OpenRequest); |
286 }; | 286 }; |
287 | 287 |
288 class IndexedDBDatabase::DeleteRequest | 288 class IndexedDBDatabase::DeleteRequest |
289 : public IndexedDBDatabase::OpenOrDeleteRequest { | 289 : public IndexedDBDatabase::OpenOrDeleteRequest { |
290 public: | 290 public: |
291 DeleteRequest(scoped_refptr<IndexedDBDatabase> db, | 291 DeleteRequest(scoped_refptr<IndexedDBDatabase> db, |
292 scoped_refptr<IndexedDBCallbacks> callbacks) | 292 scoped_refptr<IndexedDBCallbacks> callbacks) |
293 : OpenOrDeleteRequest(db), callbacks_(callbacks) {} | 293 : OpenOrDeleteRequest(db), callbacks_(callbacks) {} |
294 | 294 |
295 void Perform() override { | 295 void Perform() override { |
296 if (db_->connections_.empty()) { | 296 if (db_->connections_.empty()) { |
297 // No connections, so delete immediately. | 297 // No connections, so delete immediately. |
298 DoDelete(); | 298 DoDelete(); |
299 return; | 299 return; |
300 } | 300 } |
301 | 301 |
302 // Front end ensures the event is not fired at connections that have | 302 // Front end ensures the event is not fired at connections that have |
303 // close_pending set. | 303 // close_pending set. |
304 const int64_t old_version = db_->metadata_.version; | 304 const int64_t old_version = db_->metadata_.version; |
305 const int64_t new_version = IndexedDBDatabaseMetadata::NO_VERSION; | 305 const int64_t new_version = IndexedDBDatabaseMetadata::NO_VERSION; |
306 DCHECK_NE(callbacks_->data_loss_info().status, blink::WebIDBDataLossTotal); | |
307 for (const auto* connection : db_->connections_) | 306 for (const auto* connection : db_->connections_) |
308 connection->callbacks()->OnVersionChange(old_version, new_version); | 307 connection->callbacks()->OnVersionChange(old_version, new_version); |
309 } | 308 } |
310 | 309 |
311 void OnVersionChangeIgnored() const override { | 310 void OnVersionChangeIgnored() const override { |
312 callbacks_->OnBlocked(db_->metadata_.version); | 311 callbacks_->OnBlocked(db_->metadata_.version); |
313 } | 312 } |
314 | 313 |
315 void OnConnectionClosed(IndexedDBConnection* connection) override { | 314 void OnConnectionClosed(IndexedDBConnection* connection) override { |
316 if (!db_->connections_.empty()) | 315 if (!db_->connections_.empty()) |
(...skipping 1595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1912 mode, new IndexedDBBackingStore::Transaction(backing_store_.get())); | 1911 mode, new IndexedDBBackingStore::Transaction(backing_store_.get())); |
1913 TransactionCreated(transaction); | 1912 TransactionCreated(transaction); |
1914 return transaction; | 1913 return transaction; |
1915 } | 1914 } |
1916 | 1915 |
1917 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { | 1916 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { |
1918 transactions_[transaction->id()] = transaction; | 1917 transactions_[transaction->id()] = transaction; |
1919 } | 1918 } |
1920 | 1919 |
1921 void IndexedDBDatabase::OpenConnection( | 1920 void IndexedDBDatabase::OpenConnection( |
1922 const IndexedDBPendingConnection& connection) { | 1921 std::unique_ptr<IndexedDBPendingConnection> connection) { |
1923 AppendRequest(base::MakeUnique<OpenRequest>(this, connection)); | 1922 AppendRequest(base::MakeUnique<OpenRequest>(this, std::move(connection))); |
1924 } | 1923 } |
1925 | 1924 |
1926 void IndexedDBDatabase::DeleteDatabase( | 1925 void IndexedDBDatabase::DeleteDatabase( |
1927 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1926 scoped_refptr<IndexedDBCallbacks> callbacks) { |
1928 AppendRequest(base::MakeUnique<DeleteRequest>(this, callbacks)); | 1927 AppendRequest(base::MakeUnique<DeleteRequest>(this, callbacks)); |
1929 } | 1928 } |
1930 | 1929 |
1931 void IndexedDBDatabase::ForceClose() { | 1930 void IndexedDBDatabase::ForceClose() { |
1932 // IndexedDBConnection::ForceClose() may delete this database, so hold ref. | 1931 // IndexedDBConnection::ForceClose() may delete this database, so hold ref. |
1933 scoped_refptr<IndexedDBDatabase> protect(this); | 1932 scoped_refptr<IndexedDBDatabase> protect(this); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2005 | 2004 |
2006 void IndexedDBDatabase::VersionChangeAbortOperation( | 2005 void IndexedDBDatabase::VersionChangeAbortOperation( |
2007 int64_t previous_version, | 2006 int64_t previous_version, |
2008 IndexedDBTransaction* transaction) { | 2007 IndexedDBTransaction* transaction) { |
2009 DCHECK(!transaction); | 2008 DCHECK(!transaction); |
2010 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); | 2009 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); |
2011 metadata_.version = previous_version; | 2010 metadata_.version = previous_version; |
2012 } | 2011 } |
2013 | 2012 |
2014 } // namespace content | 2013 } // namespace content |
OLD | NEW |