Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: content/browser/indexed_db/indexed_db_database.cc

Issue 2140193002: IndexedDB: Saving data loss status in IndexedDBPendingConnection. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@idb-data-loss
Patch Set: Deleted commented out code. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_database.h ('k') | content/browser/indexed_db/indexed_db_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698