| 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 |