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

Side by Side Diff: third_party/WebKit/Source/modules/indexeddb/IDBTransaction.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 28 matching lines...) Expand all
39 #include "modules/indexeddb/IDBObjectStore.h" 39 #include "modules/indexeddb/IDBObjectStore.h"
40 #include "modules/indexeddb/IDBOpenDBRequest.h" 40 #include "modules/indexeddb/IDBOpenDBRequest.h"
41 #include "modules/indexeddb/IDBTracing.h" 41 #include "modules/indexeddb/IDBTracing.h"
42 #include "wtf/PtrUtil.h" 42 #include "wtf/PtrUtil.h"
43 #include <memory> 43 #include <memory>
44 44
45 using blink::WebIDBDatabase; 45 using blink::WebIDBDatabase;
46 46
47 namespace blink { 47 namespace blink {
48 48
49 IDBTransaction* IDBTransaction::create(ScriptState* scriptState, int64_t id, con st HashSet<String>& objectStoreNames, WebIDBTransactionMode mode, IDBDatabase* d b) 49 IDBTransaction* IDBTransaction::createNonVersionChange(ScriptState* scriptState, int64_t id, const HashSet<String>& objectStoreNames, WebIDBTransactionMode mode , IDBDatabase* db)
50 { 50 {
51 DCHECK_NE(mode, WebIDBTransactionModeVersionChange);
52 DCHECK(!objectStoreNames.isEmpty()) << "Non-version transactions should oper ate on a well-defined set of stores";
51 IDBOpenDBRequest* openDBRequest = nullptr; 53 IDBOpenDBRequest* openDBRequest = nullptr;
52 IDBTransaction* transaction = new IDBTransaction(scriptState, id, objectStor eNames, mode, db, openDBRequest, IDBDatabaseMetadata()); 54 IDBTransaction* transaction = new IDBTransaction(scriptState, id, objectStor eNames, mode, db, openDBRequest, IDBDatabaseOwnMetadata());
53 transaction->suspendIfNeeded(); 55 transaction->suspendIfNeeded();
54 return transaction; 56 return transaction;
55 } 57 }
56 58
57 IDBTransaction* IDBTransaction::create(ScriptState* scriptState, int64_t id, IDB Database* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previo usMetadata) 59 IDBTransaction* IDBTransaction::createVersionChange(ScriptState* scriptState, in t64_t id, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseOwn Metadata& oldMetadata)
58 { 60 {
59 IDBTransaction* transaction = new IDBTransaction(scriptState, id, HashSet<St ring>(), WebIDBTransactionModeVersionChange, db, openDBRequest, previousMetadata ); 61 IDBTransaction* transaction = new IDBTransaction(scriptState, id, HashSet<St ring>(), WebIDBTransactionModeVersionChange, db, openDBRequest, oldMetadata);
60 transaction->suspendIfNeeded(); 62 transaction->suspendIfNeeded();
61 return transaction; 63 return transaction;
62 } 64 }
63 65
64 namespace { 66 namespace {
65 67
66 class DeactivateTransactionTask : public V8PerIsolateData::EndOfScopeTask { 68 class DeactivateTransactionTask : public V8PerIsolateData::EndOfScopeTask {
67 public: 69 public:
68 static std::unique_ptr<DeactivateTransactionTask> create(IDBTransaction* tra nsaction) 70 static std::unique_ptr<DeactivateTransactionTask> create(IDBTransaction* tra nsaction)
69 { 71 {
70 return wrapUnique(new DeactivateTransactionTask(transaction)); 72 return wrapUnique(new DeactivateTransactionTask(transaction));
71 } 73 }
72 74
73 void run() override 75 void run() override
74 { 76 {
75 m_transaction->setActive(false); 77 m_transaction->setActive(false);
76 m_transaction.clear(); 78 m_transaction.clear();
77 } 79 }
78 80
79 private: 81 private:
80 explicit DeactivateTransactionTask(IDBTransaction* transaction) 82 explicit DeactivateTransactionTask(IDBTransaction* transaction)
81 : m_transaction(transaction) { } 83 : m_transaction(transaction) { }
82 84
83 Persistent<IDBTransaction> m_transaction; 85 Persistent<IDBTransaction> m_transaction;
84 }; 86 };
85 87
86 } // namespace 88 } // namespace
87 89
88 IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const HashS et<String>& objectStoreNames, WebIDBTransactionMode mode, IDBDatabase* db, IDBOp enDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata) 90 IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const HashS et<String>& objectStoreNames, WebIDBTransactionMode mode, IDBDatabase* db, IDBOp enDBRequest* openDBRequest, const IDBDatabaseOwnMetadata& oldMetadata)
89 : ActiveScriptWrappable(this) 91 : ActiveScriptWrappable(this)
90 , ActiveDOMObject(scriptState->getExecutionContext()) 92 , ActiveDOMObject(scriptState->getExecutionContext())
91 , m_id(id) 93 , m_id(id)
92 , m_database(db) 94 , m_database(db)
93 , m_objectStoreNames(objectStoreNames) 95 , m_scope(objectStoreNames)
94 , m_openDBRequest(openDBRequest) 96 , m_openDBRequest(openDBRequest)
95 , m_mode(mode) 97 , m_mode(mode)
96 , m_previousMetadata(previousMetadata) 98 , m_oldDatabaseMetadata(oldMetadata)
97 { 99 {
98 if (mode == WebIDBTransactionModeVersionChange) { 100 if (isVersionChange()) {
101 DCHECK(objectStoreNames.isEmpty());
102
99 // Not active until the callback. 103 // Not active until the callback.
100 m_state = Inactive; 104 m_state = Inactive;
105 } else {
106 DCHECK(!objectStoreNames.isEmpty()) << "Non-versionchange transactions m ust operate on a well-defined set of stores";
101 } 107 }
102 108
103 if (m_state == Active) 109 if (m_state == Active)
104 V8PerIsolateData::from(scriptState->isolate())->addEndOfScopeTask(Deacti vateTransactionTask::create(this)); 110 V8PerIsolateData::from(scriptState->isolate())->addEndOfScopeTask(Deacti vateTransactionTask::create(this));
105 m_database->transactionCreated(this); 111 m_database->transactionCreated(this);
106 } 112 }
107 113
108 IDBTransaction::~IDBTransaction() 114 IDBTransaction::~IDBTransaction()
109 { 115 {
110 ASSERT(m_state == Finished || m_contextStopped); 116 ASSERT(m_state == Finished || m_contextStopped);
111 ASSERT(m_requestList.isEmpty() || m_contextStopped); 117 ASSERT(m_requestList.isEmpty() || m_contextStopped);
112 } 118 }
113 119
114 DEFINE_TRACE(IDBTransaction) 120 DEFINE_TRACE(IDBTransaction)
115 { 121 {
116 visitor->trace(m_database); 122 visitor->trace(m_database);
117 visitor->trace(m_openDBRequest); 123 visitor->trace(m_openDBRequest);
118 visitor->trace(m_error); 124 visitor->trace(m_error);
119 visitor->trace(m_requestList); 125 visitor->trace(m_requestList);
120 visitor->trace(m_objectStoreMap); 126 visitor->trace(m_objectStoreMap);
121 visitor->trace(m_createdObjectStores); 127 visitor->trace(m_oldStoreMetadata);
122 visitor->trace(m_deletedObjectStores); 128 visitor->trace(m_deletedIndexes);
123 visitor->trace(m_objectStoreCleanupMap);
124 EventTargetWithInlineData::trace(visitor); 129 EventTargetWithInlineData::trace(visitor);
125 ActiveDOMObject::trace(visitor); 130 ActiveDOMObject::trace(visitor);
126 } 131 }
127 132
128 void IDBTransaction::setError(DOMException* error) 133 void IDBTransaction::setError(DOMException* error)
129 { 134 {
130 ASSERT(m_state != Finished); 135 DCHECK_NE(m_state, Finished);
131 ASSERT(error); 136 DCHECK(error);
132 137
133 // The first error to be set is the true cause of the 138 // The first error to be set is the true cause of the
134 // transaction abort. 139 // transaction abort.
135 if (!m_error) { 140 if (!m_error)
136 m_error = error; 141 m_error = error;
137 }
138 } 142 }
139 143
140 IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState) 144 IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState)
141 { 145 {
142 if (m_state == Finished) { 146 if (isFinished()) {
143 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage); 147 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage);
144 return nullptr; 148 return nullptr;
145 } 149 }
146 150
147 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); 151 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
148 if (it != m_objectStoreMap.end()) 152 if (it != m_objectStoreMap.end())
149 return it->value; 153 return it->value;
150 154
151 if (!isVersionChange() && !m_objectStoreNames.contains(name)) { 155 if (!isVersionChange() && !m_scope.contains(name)) {
152 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage); 156 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage);
153 return nullptr; 157 return nullptr;
154 } 158 }
155 159
156 int64_t objectStoreId = m_database->findObjectStoreId(name); 160 int64_t objectStoreId = m_database->findObjectStoreId(name);
157 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) { 161 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) {
158 ASSERT(isVersionChange()); 162 ASSERT(isVersionChange());
159 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage); 163 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage);
160 return nullptr; 164 return nullptr;
161 } 165 }
162 166
163 const IDBDatabaseMetadata& metadata = m_database->metadata(); 167 const IDBDatabaseMetadata& metadata = m_database->metadata();
164 168
165 IDBObjectStore* objectStore = IDBObjectStore::create(metadata.objectStores.g et(objectStoreId), this); 169 RefPtr<IDBObjectStoreMetadata> objectStoreMetadata = metadata.objectStores.g et(objectStoreId);
170 DCHECK(objectStoreMetadata.get());
171 IDBObjectStore* objectStore = IDBObjectStore::create(std::move(objectStoreMe tadata), this);
172 DCHECK(!m_objectStoreMap.contains(name));
166 m_objectStoreMap.set(name, objectStore); 173 m_objectStoreMap.set(name, objectStore);
167 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata()); 174
175 if (isVersionChange()) {
176 RefPtr<IDBObjectStoreMetadata> backupMetadata = objectStore->metadata(). createCopy();
177 m_oldStoreMetadata.set(objectStore, std::move(backupMetadata));
178 }
168 return objectStore; 179 return objectStore;
169 } 180 }
170 181
171 void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* obje ctStore) 182 void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* obje ctStore)
172 { 183 {
173 ASSERT(m_state != Finished); 184 DCHECK_NE(m_state, Finished) << "A finished transaction created an object st ore";
174 ASSERT(isVersionChange()); 185 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction created an object store";
186 DCHECK(!m_objectStoreMap.contains(name)) << "An object store was created wit h the name of an existing store";
175 m_objectStoreMap.set(name, objectStore); 187 m_objectStoreMap.set(name, objectStore);
176 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
177 m_createdObjectStores.add(objectStore);
178 } 188 }
179 189
180 void IDBTransaction::objectStoreDeleted(const String& name) 190 void IDBTransaction::objectStoreDeleted(const int64_t objectStoreId, const Strin g& name)
181 { 191 {
182 ASSERT(m_state != Finished); 192 DCHECK_NE(m_state, Finished) << "A finished transaction deleted an object st ore";
183 ASSERT(isVersionChange()); 193 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction deleted an object store";
184 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); 194 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
185 if (it != m_objectStoreMap.end()) { 195 if (it == m_objectStoreMap.end()) {
196 DCHECK(m_database->metadata().objectStores.contains(objectStoreId));
197 RefPtr<IDBObjectStoreMetadata> metadata = m_database->metadata().objectS tores.get(objectStoreId);
198 DCHECK(metadata.get());
199 DCHECK(metadata->own.name == name);
200 m_deletedObjectStores.append(std::move(metadata));
201 } else {
186 IDBObjectStore* objectStore = it->value; 202 IDBObjectStore* objectStore = it->value;
187 m_objectStoreMap.remove(name); 203 m_objectStoreMap.remove(name);
188 objectStore->markDeleted(); 204 objectStore->markDeleted();
189 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
190 m_deletedObjectStores.add(objectStore);
191 } 205 }
192 } 206 }
193 207
194 void IDBTransaction::objectStoreRenamed(const String& oldName, const String& new Name) 208 void IDBTransaction::objectStoreRenamed(const String& oldName, const String& new Name)
195 { 209 {
196 DCHECK(m_state != Finished); 210 DCHECK_NE(m_state, Finished) << "A finished transaction renamed an object st ore";
197 DCHECK(isVersionChange()); 211 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction renamed an object store";
198 212
199 DCHECK(!m_objectStoreMap.contains(newName)); 213 DCHECK(!m_objectStoreMap.contains(newName));
200 DCHECK(m_objectStoreMap.contains(oldName)) << "The object store had to be ac cessed in order to be renamed."; 214 DCHECK(m_objectStoreMap.contains(oldName)) << "The object store had to be ac cessed in order to be renamed.";
215 IDBObjectStore* objectStore = m_objectStoreMap.take(oldName);
216 m_objectStoreMap.set(newName, objectStore);
217 }
201 218
202 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(oldName); 219 void IDBTransaction::indexDeleted(IDBIndex* index)
203 m_objectStoreMap.set(newName, it->value); 220 {
204 m_objectStoreMap.remove(oldName); 221 DCHECK(index);
222 DCHECK(!index->isDeleted()) << "indexDeleted called twice for the same index ";
223
224 IDBObjectStore* objectStore = index->objectStore();
225 DCHECK(objectStore->transaction() == this);
226 DCHECK(m_objectStoreMap.contains(objectStore->name())) << "An index was dele ted without accessing its object store";
227
228 const auto& objectStoreIterator = m_oldStoreMetadata.find(objectStore);
229 if (objectStoreIterator == m_oldStoreMetadata.end())
230 return;
231
232 const IDBObjectStoreMetadata* oldStoreMetadata = objectStoreIterator->value. get();
233 DCHECK(oldStoreMetadata);
234 if (!oldStoreMetadata->indexes.contains(index->id()))
235 return;
236
237 m_deletedIndexes.append(index);
205 } 238 }
206 239
207 void IDBTransaction::setActive(bool active) 240 void IDBTransaction::setActive(bool active)
208 { 241 {
209 DCHECK_NE(m_state, Finished) << "A finished transaction tried to setActive(" << (active ? "true" : "false") << ")"; 242 DCHECK_NE(m_state, Finished) << "A finished transaction tried to setActive(" << (active ? "true" : "false") << ")";
210 if (m_state == Finishing) 243 if (m_state == Finishing)
211 return; 244 return;
212 ASSERT(active != (m_state == Active)); 245 ASSERT(active != (m_state == Active));
213 m_state = active ? Active : Inactive; 246 m_state = active ? Active : Inactive;
214 247
215 if (!active && m_requestList.isEmpty() && backendDB()) 248 if (!active && m_requestList.isEmpty() && backendDB())
216 backendDB()->commit(m_id); 249 backendDB()->commit(m_id);
217 } 250 }
218 251
219 void IDBTransaction::abort(ExceptionState& exceptionState) 252 void IDBTransaction::abort(ExceptionState& exceptionState)
220 { 253 {
221 if (m_state == Finishing || m_state == Finished) { 254 if (m_state == Finishing || m_state == Finished) {
222 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage); 255 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage);
223 return; 256 return;
224 } 257 }
225 258
226 m_state = Finishing; 259 m_state = Finishing;
227 260
228 if (m_contextStopped) 261 if (m_contextStopped)
229 return; 262 return;
230 263
231 for (IDBRequest* request : m_requestList) 264 abortOutstandingRequests();
232 request->abort(); 265 revertDatabaseMetadata();
233 m_requestList.clear();
234
235 for (IDBObjectStore* store : m_createdObjectStores) {
236 store->abort();
237 store->markDeleted();
238 }
239 266
240 if (backendDB()) 267 if (backendDB())
241 backendDB()->abort(m_id); 268 backendDB()->abort(m_id);
242 } 269 }
243 270
244 void IDBTransaction::registerRequest(IDBRequest* request) 271 void IDBTransaction::registerRequest(IDBRequest* request)
245 { 272 {
246 ASSERT(request); 273 ASSERT(request);
247 ASSERT(m_state == Active); 274 ASSERT(m_state == Active);
248 m_requestList.add(request); 275 m_requestList.add(request);
249 } 276 }
250 277
251 void IDBTransaction::unregisterRequest(IDBRequest* request) 278 void IDBTransaction::unregisterRequest(IDBRequest* request)
252 { 279 {
253 ASSERT(request); 280 ASSERT(request);
254 // If we aborted the request, it will already have been removed. 281 // If we aborted the request, it will already have been removed.
255 m_requestList.remove(request); 282 m_requestList.remove(request);
256 } 283 }
257 284
258 void IDBTransaction::onAbort(DOMException* error) 285 void IDBTransaction::onAbort(DOMException* error)
259 { 286 {
260 IDB_TRACE("IDBTransaction::onAbort"); 287 IDB_TRACE("IDBTransaction::onAbort");
261 if (m_contextStopped) { 288 if (m_contextStopped) {
262 m_database->transactionFinished(this); 289 finish();
263 return; 290 return;
264 } 291 }
265 292
266 ASSERT(m_state != Finished); 293 ASSERT(m_state != Finished);
267 if (m_state != Finishing) { 294 if (m_state != Finishing) {
268 // Abort was not triggered by front-end. 295 // Abort was not triggered by front-end.
269 ASSERT(error); 296 ASSERT(error);
270 setError(error); 297 setError(error);
271 298
272 // Outstanding requests must be aborted. 299 abortOutstandingRequests();
273 for (IDBRequest* request : m_requestList) 300 revertDatabaseMetadata();
274 request->abort();
275 m_requestList.clear();
276
277 // Newly created stores must be marked as deleted.
278 for (IDBObjectStore* store : m_createdObjectStores)
279 store->markDeleted();
280
281 // Used stores may need to mark indexes as deleted.
282 for (auto& it : m_objectStoreCleanupMap)
283 it.key->abort();
284 301
285 m_state = Finishing; 302 m_state = Finishing;
286 } 303 }
287 304
288 if (isVersionChange()) { 305 if (isVersionChange())
289 for (auto& it : m_objectStoreCleanupMap)
290 it.key->setMetadata(it.value);
291 m_database->setMetadata(m_previousMetadata);
292 m_database->close(); 306 m_database->close();
293 }
294 m_objectStoreCleanupMap.clear();
295 307
296 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters. 308 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters.
297 enqueueEvent(Event::createBubble(EventTypeNames::abort)); 309 enqueueEvent(Event::createBubble(EventTypeNames::abort));
298 310 finish();
299 m_database->transactionFinished(this);
300 } 311 }
301 312
302 void IDBTransaction::onComplete() 313 void IDBTransaction::onComplete()
303 { 314 {
304 IDB_TRACE("IDBTransaction::onComplete"); 315 IDB_TRACE("IDBTransaction::onComplete");
305 if (m_contextStopped) { 316 if (m_contextStopped) {
306 m_database->transactionFinished(this); 317 finish();
307 return; 318 return;
308 } 319 }
309 320
310 ASSERT(m_state != Finished); 321 ASSERT(m_state != Finished);
311 m_state = Finishing; 322 m_state = Finishing;
312 m_objectStoreCleanupMap.clear();
313 323
314 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters. 324 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters.
315 enqueueEvent(Event::create(EventTypeNames::complete)); 325 enqueueEvent(Event::create(EventTypeNames::complete));
316 326 finish();
317 m_database->transactionFinished(this);
318 } 327 }
319 328
320 bool IDBTransaction::hasPendingActivity() const 329 bool IDBTransaction::hasPendingActivity() const
321 { 330 {
322 // FIXME: In an ideal world, we should return true as long as anyone has a o r can 331 // FIXME: In an ideal world, we should return true as long as anyone has a o r can
323 // get a handle to us or any child request object and any of those ha ve 332 // get a handle to us or any child request object and any of those ha ve
324 // event listeners. This is in order to handle user generated events properly. 333 // event listeners. This is in order to handle user generated events properly.
325 return m_hasPendingActivity && !m_contextStopped; 334 return m_hasPendingActivity && !m_contextStopped;
326 } 335 }
327 336
328 WebIDBTransactionMode IDBTransaction::stringToMode(const String& modeString) 337 WebIDBTransactionMode IDBTransaction::stringToMode(const String& modeString)
329 { 338 {
330 if (modeString == IndexedDBNames::readonly) 339 if (modeString == IndexedDBNames::readonly)
331 return WebIDBTransactionModeReadOnly; 340 return WebIDBTransactionModeReadOnly;
332 if (modeString == IndexedDBNames::readwrite) 341 if (modeString == IndexedDBNames::readwrite)
333 return WebIDBTransactionModeReadWrite; 342 return WebIDBTransactionModeReadWrite;
334 if (modeString == IndexedDBNames::versionchange) 343 if (modeString == IndexedDBNames::versionchange)
335 return WebIDBTransactionModeVersionChange; 344 return WebIDBTransactionModeVersionChange;
336 ASSERT_NOT_REACHED(); 345 ASSERT_NOT_REACHED();
337 return WebIDBTransactionModeReadOnly; 346 return WebIDBTransactionModeReadOnly;
338 } 347 }
339 348
349 WebIDBDatabase* IDBTransaction::backendDB() const
350 {
351 return m_database->backend();
352 }
353
340 const String& IDBTransaction::mode() const 354 const String& IDBTransaction::mode() const
341 { 355 {
342 switch (m_mode) { 356 switch (m_mode) {
343 case WebIDBTransactionModeReadOnly: 357 case WebIDBTransactionModeReadOnly:
344 return IndexedDBNames::readonly; 358 return IndexedDBNames::readonly;
345 359
346 case WebIDBTransactionModeReadWrite: 360 case WebIDBTransactionModeReadWrite:
347 return IndexedDBNames::readwrite; 361 return IndexedDBNames::readwrite;
348 362
349 case WebIDBTransactionModeVersionChange: 363 case WebIDBTransactionModeVersionChange:
350 return IndexedDBNames::versionchange; 364 return IndexedDBNames::versionchange;
351 } 365 }
352 366
353 ASSERT_NOT_REACHED(); 367 ASSERT_NOT_REACHED();
354 return IndexedDBNames::readonly; 368 return IndexedDBNames::readonly;
355 } 369 }
356 370
357 DOMStringList* IDBTransaction::objectStoreNames() const 371 DOMStringList* IDBTransaction::objectStoreNames() const
358 { 372 {
359 if (m_mode == WebIDBTransactionModeVersionChange) 373 if (isVersionChange())
360 return m_database->objectStoreNames(); 374 return m_database->objectStoreNames();
361 375
362 DOMStringList* objectStoreNames = DOMStringList::create(DOMStringList::Index edDB); 376 DOMStringList* objectStoreNames = DOMStringList::create(DOMStringList::Index edDB);
363 for (const String& name : m_objectStoreNames) 377 for (const String& objectStoreName : m_scope)
364 objectStoreNames->append(name); 378 objectStoreNames->append(objectStoreName);
365 objectStoreNames->sort(); 379 objectStoreNames->sort();
366 return objectStoreNames; 380 return objectStoreNames;
367 } 381 }
368 382
369 const AtomicString& IDBTransaction::interfaceName() const 383 const AtomicString& IDBTransaction::interfaceName() const
370 { 384 {
371 return EventTargetNames::IDBTransaction; 385 return EventTargetNames::IDBTransaction;
372 } 386 }
373 387
374 ExecutionContext* IDBTransaction::getExecutionContext() const 388 ExecutionContext* IDBTransaction::getExecutionContext() const
375 { 389 {
376 return ActiveDOMObject::getExecutionContext(); 390 return ActiveDOMObject::getExecutionContext();
377 } 391 }
378 392
379 DispatchEventResult IDBTransaction::dispatchEventInternal(Event* event) 393 DispatchEventResult IDBTransaction::dispatchEventInternal(Event* event)
380 { 394 {
381 IDB_TRACE("IDBTransaction::dispatchEvent"); 395 IDB_TRACE("IDBTransaction::dispatchEvent");
382 if (m_contextStopped || !getExecutionContext()) { 396 if (m_contextStopped || !getExecutionContext()) {
383 m_state = Finished; 397 m_state = Finished;
384 return DispatchEventResult::CanceledBeforeDispatch; 398 return DispatchEventResult::CanceledBeforeDispatch;
385 } 399 }
386 ASSERT(m_state != Finished); 400 ASSERT(m_state != Finished);
387 ASSERT(m_hasPendingActivity); 401 ASSERT(m_hasPendingActivity);
388 ASSERT(getExecutionContext()); 402 ASSERT(getExecutionContext());
389 ASSERT(event->target() == this); 403 ASSERT(event->target() == this);
390 m_state = Finished; 404 m_state = Finished;
391 405
392 // Break reference cycles.
393 // TODO(jsbell): This can be removed c/o Oilpan.
394 for (auto& it : m_objectStoreMap)
395 it.value->transactionFinished();
396 m_objectStoreMap.clear();
397 for (auto& it : m_deletedObjectStores)
398 it->transactionFinished();
399 m_createdObjectStores.clear();
400 m_deletedObjectStores.clear();
401
402 HeapVector<Member<EventTarget>> targets; 406 HeapVector<Member<EventTarget>> targets;
403 targets.append(this); 407 targets.append(this);
404 targets.append(db()); 408 targets.append(db());
405 409
406 // FIXME: When we allow custom event dispatching, this will probably need to change. 410 // FIXME: When we allow custom event dispatching, this will probably need to change.
407 ASSERT(event->type() == EventTypeNames::complete || event->type() == EventTy peNames::abort); 411 ASSERT(event->type() == EventTypeNames::complete || event->type() == EventTy peNames::abort);
408 DispatchEventResult dispatchResult = IDBEventDispatcher::dispatch(event, tar gets); 412 DispatchEventResult dispatchResult = IDBEventDispatcher::dispatch(event, tar gets);
409 // FIXME: Try to construct a test where |this| outlives openDBRequest and we 413 // FIXME: Try to construct a test where |this| outlives openDBRequest and we
410 // get a crash. 414 // get a crash.
411 if (m_openDBRequest) { 415 if (m_openDBRequest) {
(...skipping 18 matching lines...) Expand all
430 { 434 {
431 DCHECK_NE(m_state, Finished) << "A finished transaction tried to enqueue an event of type " << event->type() << "."; 435 DCHECK_NE(m_state, Finished) << "A finished transaction tried to enqueue an event of type " << event->type() << ".";
432 if (m_contextStopped || !getExecutionContext()) 436 if (m_contextStopped || !getExecutionContext())
433 return; 437 return;
434 438
435 EventQueue* eventQueue = getExecutionContext()->getEventQueue(); 439 EventQueue* eventQueue = getExecutionContext()->getEventQueue();
436 event->setTarget(this); 440 event->setTarget(this);
437 eventQueue->enqueueEvent(event); 441 eventQueue->enqueueEvent(event);
438 } 442 }
439 443
440 WebIDBDatabase* IDBTransaction::backendDB() const 444 void IDBTransaction::abortOutstandingRequests()
441 { 445 {
442 return m_database->backend(); 446 for (IDBRequest* request : m_requestList)
447 request->abort();
448 m_requestList.clear();
449 }
450
451 void IDBTransaction::revertDatabaseMetadata()
452 {
453 DCHECK_NE(m_state, Active);
454 if (!isVersionChange())
455 return;
456
457 // Mark stores created by this transaction as deleted.
458 // Object store IDs are allocated sequentially, so we can tell if an object
459 // store was created in this transaction by comparing its ID against the
460 // database's maximum object store ID at the time when the transaction was
461 // started.
462 const int64_t oldMaxObjectStoreId = m_oldDatabaseMetadata.maxObjectStoreId;
463 for (auto& it : m_objectStoreMap) {
464 IDBObjectStore* objectStore = it.value;
465 const int64_t objectStoreId = objectStore->id();
466 if (objectStoreId < oldMaxObjectStoreId)
467 continue;
468
469 m_database->revertObjectStoreCreation(objectStoreId);
470 objectStore->markDeleted();
471 }
472
473 for (auto& it : m_oldStoreMetadata) {
474 IDBObjectStore* objectStore = it.key;
475 RefPtr<IDBObjectStoreMetadata> oldMetadata = it.value;
476
477 m_database->revertObjectStoreMetadata(oldMetadata);
478 objectStore->revertMetadata(oldMetadata);
479 }
480 for (auto& it : m_deletedIndexes) {
481 IDBIndex* index = static_cast<IDBIndex*>(it);
482 index->objectStore()->revertDeletedIndexMetadata(*index);
483 }
484 for (auto& it: m_deletedObjectStores) {
485 RefPtr<IDBObjectStoreMetadata> oldMedata = static_cast<RefPtr<IDBObjectS toreMetadata>>(it);
486 m_database->revertObjectStoreMetadata(std::move(it));
487 }
488 m_database->setOwnMetadata(m_oldDatabaseMetadata);
489 }
490
491 void IDBTransaction::finish()
492 {
493 m_database->transactionFinished(this);
494
495 // Remove references to the IDBObjectStore and IDBIndex instances held by
496 // this transaction, so OilPan can garbage-collect the instances that aren't
497 // used by JavaScript.
498 m_objectStoreMap.clear();
499 m_oldStoreMetadata.clear();
500 m_deletedIndexes.clear();
501 m_deletedObjectStores.clear();
443 } 502 }
444 503
445 } // namespace blink 504 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698