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

Side by Side Diff: third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp

Issue 2314933005: Align IndexedDB metadata rollback on transaction abort to spec. (Closed)
Patch Set: Rebased. Created 4 years, 3 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 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 } 102 }
103 103
104 int64_t IDBDatabase::nextTransactionId() 104 int64_t IDBDatabase::nextTransactionId()
105 { 105 {
106 // Only keep a 32-bit counter to allow ports to use the other 32 106 // Only keep a 32-bit counter to allow ports to use the other 32
107 // bits of the id. 107 // bits of the id.
108 static int currentTransactionId = 0; 108 static int currentTransactionId = 0;
109 return atomicIncrement(&currentTransactionId); 109 return atomicIncrement(&currentTransactionId);
110 } 110 }
111 111
112 void IDBDatabase::indexCreated(int64_t objectStoreId, const IDBIndexMetadata& me tadata) 112 void IDBDatabase::setMetadata(const IDBDatabaseMetadata& metadata)
113 { 113 {
114 IDBDatabaseMetadata::ObjectStoreMap::iterator it = m_metadata.objectStores.f ind(objectStoreId); 114 m_metadata = metadata;
115 ASSERT_WITH_SECURITY_IMPLICATION(it != m_metadata.objectStores.end());
116 it->value.indexes.set(metadata.id, metadata);
117 } 115 }
118 116
119 void IDBDatabase::indexDeleted(int64_t objectStoreId, int64_t indexId) 117 void IDBDatabase::setOwnMetadata(const IDBDatabaseOwnMetadata& metadata)
120 { 118 {
121 IDBDatabaseMetadata::ObjectStoreMap::iterator it = m_metadata.objectStores.f ind(objectStoreId); 119 m_metadata.own = metadata;
122 ASSERT_WITH_SECURITY_IMPLICATION(it != m_metadata.objectStores.end());
123 it->value.indexes.remove(indexId);
124 }
125
126 void IDBDatabase::indexRenamed(int64_t objectStoreId, int64_t indexId, const Str ing& newName)
127 {
128 IDBDatabaseMetadata::ObjectStoreMap::iterator storeIterator = m_metadata.obj ectStores.find(objectStoreId);
129 SECURITY_DCHECK(storeIterator != m_metadata.objectStores.end());
130
131 IDBObjectStoreMetadata& storeMetadata = storeIterator->value;
132 IDBObjectStoreMetadata::IndexMap::iterator indexIterator = storeMetadata.ind exes.find(indexId);
133 DCHECK(indexIterator != storeMetadata.indexes.end());
134 indexIterator->value.name = newName;
135 } 120 }
136 121
137 void IDBDatabase::transactionCreated(IDBTransaction* transaction) 122 void IDBDatabase::transactionCreated(IDBTransaction* transaction)
138 { 123 {
139 ASSERT(transaction); 124 ASSERT(transaction);
140 ASSERT(!m_transactions.contains(transaction->id())); 125 ASSERT(!m_transactions.contains(transaction->id()));
141 m_transactions.add(transaction->id(), transaction); 126 m_transactions.add(transaction->id(), transaction);
142 127
143 if (transaction->isVersionChange()) { 128 if (transaction->isVersionChange()) {
144 ASSERT(!m_versionChangeTransaction); 129 ASSERT(!m_versionChangeTransaction);
(...skipping 26 matching lines...) Expand all
171 void IDBDatabase::onComplete(int64_t transactionId) 156 void IDBDatabase::onComplete(int64_t transactionId)
172 { 157 {
173 ASSERT(m_transactions.contains(transactionId)); 158 ASSERT(m_transactions.contains(transactionId));
174 m_transactions.get(transactionId)->onComplete(); 159 m_transactions.get(transactionId)->onComplete();
175 } 160 }
176 161
177 DOMStringList* IDBDatabase::objectStoreNames() const 162 DOMStringList* IDBDatabase::objectStoreNames() const
178 { 163 {
179 DOMStringList* objectStoreNames = DOMStringList::create(DOMStringList::Index edDB); 164 DOMStringList* objectStoreNames = DOMStringList::create(DOMStringList::Index edDB);
180 for (const auto& it : m_metadata.objectStores) 165 for (const auto& it : m_metadata.objectStores)
181 objectStoreNames->append(it.value.name); 166 objectStoreNames->append(it.value->own.name);
182 objectStoreNames->sort(); 167 objectStoreNames->sort();
183 return objectStoreNames; 168 return objectStoreNames;
184 } 169 }
185 170
186 const String& IDBDatabase::getObjectStoreName(int64_t objectStoreId) const 171 const String& IDBDatabase::getObjectStoreName(int64_t objectStoreId) const
187 { 172 {
188 const auto& it = m_metadata.objectStores.find(objectStoreId); 173 const auto& it = m_metadata.objectStores.find(objectStoreId);
189 DCHECK(it != m_metadata.objectStores.end()); 174 DCHECK(it != m_metadata.objectStores.end());
190 return it->value.name; 175 return it->value->own.name;
191 } 176 }
192 177
193 IDBObjectStore* IDBDatabase::createObjectStore(const String& name, const IDBKeyP ath& keyPath, bool autoIncrement, ExceptionState& exceptionState) 178 IDBObjectStore* IDBDatabase::createObjectStore(const String& name, const IDBKeyP ath& keyPath, bool autoIncrement, ExceptionState& exceptionState)
194 { 179 {
195 IDB_TRACE("IDBDatabase::createObjectStore"); 180 IDB_TRACE("IDBDatabase::createObjectStore");
196 recordApiCallsHistogram(IDBCreateObjectStoreCall); 181 recordApiCallsHistogram(IDBCreateObjectStoreCall);
197 182
198 if (!m_versionChangeTransaction) { 183 if (!m_versionChangeTransaction) {
199 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage); 184 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage);
200 return nullptr; 185 return nullptr;
(...skipping 20 matching lines...) Expand all
221 if (autoIncrement && ((keyPath.getType() == IDBKeyPath::StringType && keyPat h.string().isEmpty()) || keyPath.getType() == IDBKeyPath::ArrayType)) { 206 if (autoIncrement && ((keyPath.getType() == IDBKeyPath::StringType && keyPat h.string().isEmpty()) || keyPath.getType() == IDBKeyPath::ArrayType)) {
222 exceptionState.throwDOMException(InvalidAccessError, "The autoIncrement option was set but the keyPath option was empty or an array."); 207 exceptionState.throwDOMException(InvalidAccessError, "The autoIncrement option was set but the keyPath option was empty or an array.");
223 return nullptr; 208 return nullptr;
224 } 209 }
225 210
226 if (!m_backend) { 211 if (!m_backend) {
227 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 212 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
228 return nullptr; 213 return nullptr;
229 } 214 }
230 215
231 int64_t objectStoreId = m_metadata.maxObjectStoreId + 1; 216 int64_t objectStoreId = m_metadata.own.maxObjectStoreId + 1;
217 DCHECK(objectStoreId != IDBObjectStoreMetadata::InvalidId);
232 m_backend->createObjectStore(m_versionChangeTransaction->id(), objectStoreId , name, keyPath, autoIncrement); 218 m_backend->createObjectStore(m_versionChangeTransaction->id(), objectStoreId , name, keyPath, autoIncrement);
233 219
234 IDBObjectStoreMetadata metadata(name, objectStoreId, keyPath, autoIncrement, WebIDBDatabase::minimumIndexId); 220 RefPtr<IDBObjectStoreMetadata> storeMetadata = adoptRef(new IDBObjectStoreMe tadata(
235 IDBObjectStore* objectStore = IDBObjectStore::create(metadata, m_versionChan geTransaction.get()); 221 name, objectStoreId, keyPath, autoIncrement, WebIDBDatabase::minimumInde xId));
236 m_metadata.objectStores.set(metadata.id, metadata); 222 IDBObjectStore* objectStore = IDBObjectStore::create(storeMetadata, m_versio nChangeTransaction.get());
237 ++m_metadata.maxObjectStoreId; 223 m_versionChangeTransaction->objectStoreCreated(name, objectStore);
224 m_metadata.objectStores.set(objectStoreId, std::move(storeMetadata));
225 ++m_metadata.own.maxObjectStoreId;
238 226
239 m_versionChangeTransaction->objectStoreCreated(name, objectStore);
240 return objectStore; 227 return objectStore;
241 } 228 }
242 229
243 void IDBDatabase::deleteObjectStore(const String& name, ExceptionState& exceptio nState) 230 void IDBDatabase::deleteObjectStore(const String& name, ExceptionState& exceptio nState)
244 { 231 {
245 IDB_TRACE("IDBDatabase::deleteObjectStore"); 232 IDB_TRACE("IDBDatabase::deleteObjectStore");
246 recordApiCallsHistogram(IDBDeleteObjectStoreCall); 233 recordApiCallsHistogram(IDBDeleteObjectStoreCall);
247 if (!m_versionChangeTransaction) { 234 if (!m_versionChangeTransaction) {
248 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage); 235 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage);
249 return; 236 return;
(...skipping 12 matching lines...) Expand all
262 exceptionState.throwDOMException(NotFoundError, "The specified object st ore was not found."); 249 exceptionState.throwDOMException(NotFoundError, "The specified object st ore was not found.");
263 return; 250 return;
264 } 251 }
265 252
266 if (!m_backend) { 253 if (!m_backend) {
267 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 254 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
268 return; 255 return;
269 } 256 }
270 257
271 m_backend->deleteObjectStore(m_versionChangeTransaction->id(), objectStoreId ); 258 m_backend->deleteObjectStore(m_versionChangeTransaction->id(), objectStoreId );
272 m_versionChangeTransaction->objectStoreDeleted(name); 259 m_versionChangeTransaction->objectStoreDeleted(objectStoreId, name);
273 m_metadata.objectStores.remove(objectStoreId); 260 m_metadata.objectStores.remove(objectStoreId);
274 } 261 }
275 262
276 IDBTransaction* IDBDatabase::transaction(ScriptState* scriptState, const StringO rStringSequenceOrDOMStringList& storeNames, const String& modeString, ExceptionS tate& exceptionState) 263 IDBTransaction* IDBDatabase::transaction(ScriptState* scriptState, const StringO rStringSequenceOrDOMStringList& storeNames, const String& modeString, ExceptionS tate& exceptionState)
277 { 264 {
278 IDB_TRACE("IDBDatabase::transaction"); 265 IDB_TRACE("IDBDatabase::transaction");
279 recordApiCallsHistogram(IDBTransactionCall); 266 recordApiCallsHistogram(IDBTransactionCall);
280 267
281 HashSet<String> scope; 268 HashSet<String> scope;
282 if (storeNames.isString()) { 269 if (storeNames.isString()) {
(...skipping 17 matching lines...) Expand all
300 if (m_closePending) { 287 if (m_closePending) {
301 exceptionState.throwDOMException(InvalidStateError, "The database connec tion is closing."); 288 exceptionState.throwDOMException(InvalidStateError, "The database connec tion is closing.");
302 return nullptr; 289 return nullptr;
303 } 290 }
304 291
305 if (!m_backend) { 292 if (!m_backend) {
306 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 293 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
307 return nullptr; 294 return nullptr;
308 } 295 }
309 296
310
311 if (scope.isEmpty()) { 297 if (scope.isEmpty()) {
312 exceptionState.throwDOMException(InvalidAccessError, "The storeNames par ameter was empty."); 298 exceptionState.throwDOMException(InvalidAccessError, "The storeNames par ameter was empty.");
313 return nullptr; 299 return nullptr;
314 } 300 }
315 301
316 Vector<int64_t> objectStoreIds; 302 Vector<int64_t> objectStoreIds;
317 for (const String& name : scope) { 303 for (const String& name : scope) {
318 int64_t objectStoreId = findObjectStoreId(name); 304 int64_t objectStoreId = findObjectStoreId(name);
319 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) { 305 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) {
320 exceptionState.throwDOMException(NotFoundError, "One of the specifie d object stores was not found."); 306 exceptionState.throwDOMException(NotFoundError, "One of the specifie d object stores was not found.");
321 return nullptr; 307 return nullptr;
322 } 308 }
323 objectStoreIds.append(objectStoreId); 309 objectStoreIds.append(objectStoreId);
324 } 310 }
325 311
326 WebIDBTransactionMode mode = IDBTransaction::stringToMode(modeString); 312 WebIDBTransactionMode mode = IDBTransaction::stringToMode(modeString);
327 if (mode != WebIDBTransactionModeReadOnly && mode != WebIDBTransactionModeRe adWrite) { 313 if (mode != WebIDBTransactionModeReadOnly && mode != WebIDBTransactionModeRe adWrite) {
328 exceptionState.throwTypeError("The mode provided ('" + modeString + "') is not one of 'readonly' or 'readwrite'."); 314 exceptionState.throwTypeError("The mode provided ('" + modeString + "') is not one of 'readonly' or 'readwrite'.");
329 return nullptr; 315 return nullptr;
330 } 316 }
331 317
332 int64_t transactionId = nextTransactionId(); 318 int64_t transactionId = nextTransactionId();
333 m_backend->createTransaction(transactionId, WebIDBDatabaseCallbacksImpl::cre ate(m_databaseCallbacks).release(), objectStoreIds, mode); 319 m_backend->createTransaction(transactionId, WebIDBDatabaseCallbacksImpl::cre ate(m_databaseCallbacks).release(), objectStoreIds, mode);
334 320
335 return IDBTransaction::create(scriptState, transactionId, scope, mode, this) ; 321 return IDBTransaction::createNonVersionChange(scriptState, transactionId, sc ope, mode, this);
336 } 322 }
337 323
338 void IDBDatabase::forceClose() 324 void IDBDatabase::forceClose()
339 { 325 {
340 for (const auto& it : m_transactions) 326 for (const auto& it : m_transactions)
341 it.value->abort(IGNORE_EXCEPTION); 327 it.value->abort(IGNORE_EXCEPTION);
342 this->close(); 328 this->close();
343 enqueueEvent(Event::create(EventTypeNames::close)); 329 enqueueEvent(Event::create(EventTypeNames::close));
344 } 330 }
345 331
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 406
421 DispatchEventResult dispatchResult = EventTarget::dispatchEventInternal(even t); 407 DispatchEventResult dispatchResult = EventTarget::dispatchEventInternal(even t);
422 if (event->type() == EventTypeNames::versionchange && !m_closePending && m_b ackend) 408 if (event->type() == EventTypeNames::versionchange && !m_closePending && m_b ackend)
423 m_backend->versionChangeIgnored(); 409 m_backend->versionChangeIgnored();
424 return dispatchResult; 410 return dispatchResult;
425 } 411 }
426 412
427 int64_t IDBDatabase::findObjectStoreId(const String& name) const 413 int64_t IDBDatabase::findObjectStoreId(const String& name) const
428 { 414 {
429 for (const auto& it : m_metadata.objectStores) { 415 for (const auto& it : m_metadata.objectStores) {
430 if (it.value.name == name) { 416 if (it.value->own.name == name) {
431 ASSERT(it.key != IDBObjectStoreMetadata::InvalidId); 417 ASSERT(it.key != IDBObjectStoreMetadata::InvalidId);
432 return it.key; 418 return it.key;
433 } 419 }
434 } 420 }
435 return IDBObjectStoreMetadata::InvalidId; 421 return IDBObjectStoreMetadata::InvalidId;
436 } 422 }
437 423
438 void IDBDatabase::objectStoreRenamed(int64_t storeId, const String& newName) 424 void IDBDatabase::renameObjectStore(int64_t objectStoreId, const String& newName )
439 { 425 {
440 DCHECK(m_metadata.objectStores.contains(storeId)); 426 DCHECK(m_versionChangeTransaction) << "Object store renamed on database with out a versionchange transaction";
441 IDBDatabaseMetadata::ObjectStoreMap::iterator it = m_metadata.objectStores.f ind(storeId); 427 DCHECK(m_versionChangeTransaction->isActive()) << "Object store renamed when versionchange transaction is not active";
442 it->value.name = newName; 428 DCHECK(m_backend) << "Object store renamed after database connection closed" ;
429 DCHECK(m_metadata.objectStores.contains(objectStoreId));
430
431 m_backend->renameObjectStore(m_versionChangeTransaction->id(), objectStoreId , newName);
432
433 IDBDatabaseMetadata::ObjectStoreMap::iterator it = m_metadata.objectStores.f ind(objectStoreId);
434 IDBObjectStoreMetadata* objectStoreMetadata = it->value.get();
435 m_versionChangeTransaction->objectStoreRenamed(objectStoreMetadata->own.name , newName);
436 objectStoreMetadata->own.name = newName;
437 }
438
439 void IDBDatabase::revertObjectStoreCreation(int64_t objectStoreId)
440 {
441 DCHECK(m_versionChangeTransaction) << "Object store metadata reverted on dat abase without a versionchange transaction";
442 DCHECK(!m_versionChangeTransaction->isActive()) << "Object store metadata re verted when versionchange transaction is still active";
443 DCHECK(m_metadata.objectStores.contains(objectStoreId));
444 m_metadata.objectStores.remove(objectStoreId);
445 }
446
447 void IDBDatabase::revertObjectStoreMetadata(RefPtr<IDBObjectStoreMetadata> oldMe tadata)
448 {
449 DCHECK(m_versionChangeTransaction) << "Object store metadata reverted on dat abase without a versionchange transaction";
450 DCHECK(!m_versionChangeTransaction->isActive()) << "Object store metadata re verted when versionchange transaction is still active";
451 DCHECK(oldMetadata.get());
452 m_metadata.objectStores.set(oldMetadata->own.id, std::move(oldMetadata));
443 } 453 }
444 454
445 bool IDBDatabase::hasPendingActivity() const 455 bool IDBDatabase::hasPendingActivity() const
446 { 456 {
447 // The script wrapper must not be collected before the object is closed or 457 // The script wrapper must not be collected before the object is closed or
448 // we can't fire a "versionchange" event to let script manually close the co nnection. 458 // we can't fire a "versionchange" event to let script manually close the co nnection.
449 return !m_closePending && hasEventListeners() && !m_contextStopped; 459 return !m_closePending && hasEventListeners() && !m_contextStopped;
450 } 460 }
451 461
452 void IDBDatabase::stop() 462 void IDBDatabase::stop()
(...skipping 19 matching lines...) Expand all
472 return ActiveDOMObject::getExecutionContext(); 482 return ActiveDOMObject::getExecutionContext();
473 } 483 }
474 484
475 void IDBDatabase::recordApiCallsHistogram(IndexedDatabaseMethods method) 485 void IDBDatabase::recordApiCallsHistogram(IndexedDatabaseMethods method)
476 { 486 {
477 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, apiCallsHistogram, new EnumerationHistogram("WebCore.IndexedDB.FrontEndAPICalls", IDBMethodsMax)); 487 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, apiCallsHistogram, new EnumerationHistogram("WebCore.IndexedDB.FrontEndAPICalls", IDBMethodsMax));
478 apiCallsHistogram.count(method); 488 apiCallsHistogram.count(method);
479 } 489 }
480 490
481 } // namespace blink 491 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698