Changeset 80028 in webkit
- Timestamp:
- Mar 1, 2011 12:42:17 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r80027 r80028 1 2011-02-18 Jeremy Orlow <jorlow@chromium.org> 2 3 Reviewed by Steve Block. 4 5 When an IDBTransaction is aborted, all requests that have not yet fired should fire an ABORT_ERR 6 https://bugs.webkit.org/show_bug.cgi?id=54785 7 8 * storage/indexeddb/transaction-abort.html: Added 9 * storage/indexeddb/transaction-abort-expected.txt: Added 10 1 11 2011-03-01 Tony Gentilcore <tonyg@chromium.org> 2 12 -
trunk/Source/WebCore/ChangeLog
r80025 r80028 1 2011-02-18 Jeremy Orlow <jorlow@chromium.org> 2 3 Reviewed by Steve Block. 4 5 When an IDBTransaction is aborted, all requests that have not yet fired should fire an ABORT_ERR 6 https://bugs.webkit.org/show_bug.cgi?id=54785 7 8 This patch adds in a lot of sanity checks/ASSERTs to make sure we're doing 9 the right thing and continue to do the right thing. It also modifies EventQueue 10 so that we can cancel an event. To do this efficiently, the vector is now a 11 ListHashSet. 12 13 Canelling the event is harder/messier, but the most deterministic thing to do. 14 To the user, the work isn't done until we fire the onsuccess/onerror handler. 15 So the event (which does fire that) needs to be cancelable. 16 17 transaction-abort.html tests this. 18 19 * dom/EventQueue.cpp: 20 (WebCore::EventQueue::enqueueEvent): 21 (WebCore::EventQueue::cancelEvent): 22 (WebCore::EventQueue::pendingEventTimerFired): 23 (WebCore::EventQueue::dispatchEvent): 24 * dom/EventQueue.h: 25 * dom/ExceptionCode.cpp: 26 * storage/IDBCursor.cpp: 27 (WebCore::IDBCursor::update): 28 (WebCore::IDBCursor::deleteFunction): 29 * storage/IDBDatabaseBackendImpl.cpp: 30 (WebCore::IDBDatabaseBackendImpl::close): 31 * storage/IDBDatabaseException.h: 32 * storage/IDBIndex.cpp: 33 (WebCore::IDBIndex::openCursor): 34 (WebCore::IDBIndex::openKeyCursor): 35 (WebCore::IDBIndex::get): 36 (WebCore::IDBIndex::getKey): 37 * storage/IDBObjectStore.cpp: 38 (WebCore::IDBObjectStore::get): 39 (WebCore::IDBObjectStore::add): 40 (WebCore::IDBObjectStore::put): 41 (WebCore::IDBObjectStore::deleteFunction): 42 (WebCore::IDBObjectStore::clear): 43 (WebCore::IDBObjectStore::openCursor): 44 * storage/IDBRequest.cpp: 45 (WebCore::IDBRequest::IDBRequest): 46 (WebCore::IDBRequest::~IDBRequest): 47 (WebCore::IDBRequest::readyState): 48 (WebCore::IDBRequest::markEarlyDeath): 49 (WebCore::IDBRequest::source): 50 (WebCore::IDBRequest::abort): 51 (WebCore::IDBRequest::onSuccess): 52 (WebCore::IDBRequest::dispatchEvent): 53 (WebCore::IDBRequest::enqueueEvent): 54 * storage/IDBRequest.h: 55 * storage/IDBTransaction.cpp: 56 (WebCore::IDBTransaction::registerRequest): 57 (WebCore::IDBTransaction::unregisterRequest): 58 (WebCore::IDBTransaction::onAbort): 59 * storage/IDBTransaction.h: 60 1 61 2011-02-28 Jeremy Orlow <jorlow@chromium.org> 2 62 -
trunk/Source/WebCore/dom/EventQueue.cpp
r77650 r80028 60 60 { 61 61 ASSERT(event->target()); 62 m_queuedEvents.append(event); 62 bool wasAdded = m_queuedEvents.add(event).second; 63 ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list. 63 64 64 65 if (!m_pendingEventTimer->isActive()) … … 78 79 } 79 80 81 bool EventQueue::cancelEvent(Event* event) 82 { 83 bool found = m_queuedEvents.contains(event); 84 m_queuedEvents.remove(event); 85 if (m_queuedEvents.isEmpty()) 86 m_pendingEventTimer->stop(); 87 return found; 88 } 89 80 90 void EventQueue::pendingEventTimerFired() 81 91 { 82 92 ASSERT(!m_pendingEventTimer->isActive()); 93 ASSERT(!m_queuedEvents.isEmpty()); 83 94 84 Vector<RefPtr<Event> > queuedEvents;85 queuedEvents.swap(m_queuedEvents);86 87 95 m_nodesWithQueuedScrollEvents.clear(); 88 96 89 for (size_t i = 0; i < queuedEvents.size(); i++) 90 dispatchEvent(queuedEvents[i].release()); 97 // Insert a marker for where we should stop. 98 ASSERT(!m_queuedEvents.contains(0)); 99 bool wasAdded = m_queuedEvents.add(0).second; 100 ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list. 101 102 while (!m_queuedEvents.isEmpty()) { 103 ListHashSet<RefPtr<Event> >::iterator iter = m_queuedEvents.begin(); 104 RefPtr<Event> event = *iter; 105 m_queuedEvents.remove(iter); 106 if (!event) 107 break; 108 dispatchEvent(event.get()); 109 } 91 110 } 92 111 … … 94 113 { 95 114 EventTarget* eventTarget = event->target(); 96 if (eventTarget->toNode()) 97 eventTarget->dispatchEvent(event); 98 else if (eventTarget->toDOMWindow()) 115 if (eventTarget->toDOMWindow()) 99 116 eventTarget->toDOMWindow()->dispatchEvent(event, 0); 100 117 else -
trunk/Source/WebCore/dom/EventQueue.h
r77355 r80028 29 29 30 30 #include <wtf/HashSet.h> 31 #include <wtf/ListHashSet.h> 31 32 #include <wtf/Noncopyable.h> 32 33 #include <wtf/OwnPtr.h> 33 34 #include <wtf/PassOwnPtr.h> 34 35 #include <wtf/RefPtr.h> 35 #include <wtf/Vector.h>36 36 37 37 namespace WebCore { … … 61 61 void enqueueEvent(PassRefPtr<Event>); 62 62 void enqueueScrollEvent(PassRefPtr<Node>, ScrollEventTargetType); 63 bool cancelEvent(Event*); 63 64 64 65 private: … … 69 70 70 71 OwnPtr<EventQueueTimer> m_pendingEventTimer; 71 Vector<RefPtr<Event> > m_queuedEvents;72 ListHashSet<RefPtr<Event> > m_queuedEvents; 72 73 HashSet<Node*> m_nodesWithQueuedScrollEvents; 73 74 -
trunk/Source/WebCore/dom/ExceptionCode.cpp
r75596 r80028 224 224 "TIMEOUT_ERR", 225 225 "DEADLOCK_ERR", 226 "READ_ONLY_ERR" 226 "READ_ONLY_ERR", 227 "ABORT_ERR" 227 228 }; 228 229 … … 239 240 "TIMEOUT_ERR", // This can't be thrown. 240 241 "DEADLOCK_ERR", // This can't be thrown. 241 "Write operations cannot be preformed on a read-only transaction." 242 "Write operations cannot be preformed on a read-only transaction.", 243 "The transaction was aborted, so the request cannot be fulfilled." 242 244 }; 243 245 #endif -
trunk/Source/WebCore/storage/IDBCursor.cpp
r77689 r80028 73 73 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 74 74 m_backend->update(value, request, ec); 75 if (ec) 75 if (ec) { 76 request->markEarlyDeath(); 76 77 return 0; 78 } 77 79 return request.release(); 78 80 } … … 92 94 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 93 95 m_backend->deleteFunction(request, ec); 94 if (ec) 96 if (ec) { 97 request->markEarlyDeath(); 95 98 return 0; 99 } 96 100 return request.release(); 97 101 } -
trunk/Source/WebCore/storage/IDBDatabaseException.h
r78525 r80028 56 56 TIMEOUT_ERR = IDBDatabaseExceptionOffset + 10, 57 57 DEADLOCK_ERR = IDBDatabaseExceptionOffset + 11, 58 READ_ONLY_ERR = IDBDatabaseExceptionOffset + 12 58 READ_ONLY_ERR = IDBDatabaseExceptionOffset + 12, 59 ABORT_ERR = IDBDatabaseExceptionOffset + 13 59 60 }; 60 61 -
trunk/Source/WebCore/storage/IDBDatabaseException.idl
r78525 r80028 53 53 const unsigned short DEADLOCK_ERR = 11; 54 54 const unsigned short READ_ONLY_ERR = 12; 55 const unsigned short ABORT_ERR = 13; 55 56 }; 56 57 -
trunk/Source/WebCore/storage/IDBIndex.cpp
r77689 r80028 63 63 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 64 64 m_backend->openCursor(keyRange, direction, request, m_transaction->backend(), ec); 65 if (ec) 65 if (ec) { 66 request->markEarlyDeath(); 66 67 return 0; 68 } 67 69 return request; 68 70 } … … 78 80 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 79 81 m_backend->openKeyCursor(keyRange, direction, request, m_transaction->backend(), ec); 80 if (ec) 82 if (ec) { 83 request->markEarlyDeath(); 81 84 return 0; 85 } 82 86 return request; 83 87 } … … 87 91 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 88 92 m_backend->get(key, request, m_transaction->backend(), ec); 89 if (ec) 93 if (ec) { 94 request->markEarlyDeath(); 90 95 return 0; 96 } 91 97 return request; 92 98 } … … 96 102 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 97 103 m_backend->getKey(key, request, m_transaction->backend(), ec); 98 if (ec) 104 if (ec) { 105 request->markEarlyDeath(); 99 106 return 0; 107 } 100 108 return request; 101 109 } -
trunk/Source/WebCore/storage/IDBObjectStore.cpp
r78416 r80028 72 72 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 73 73 m_objectStore->get(key, request, m_transaction->backend(), ec); 74 if (ec) 74 if (ec) { 75 request->markEarlyDeath(); 75 76 return 0; 77 } 76 78 return request.release(); 77 79 } … … 81 83 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 82 84 m_objectStore->put(value, key, IDBObjectStoreBackendInterface::AddOnly, request, m_transaction->backend(), ec); 83 if (ec) 85 if (ec) { 86 request->markEarlyDeath(); 84 87 return 0; 85 return request; 88 } 89 return request.release(); 86 90 } 87 91 … … 90 94 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 91 95 m_objectStore->put(value, key, IDBObjectStoreBackendInterface::AddOrUpdate, request, m_transaction->backend(), ec); 92 if (ec) 96 if (ec) { 97 request->markEarlyDeath(); 93 98 return 0; 94 return request; 99 } 100 return request.release(); 95 101 } 96 102 … … 99 105 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 100 106 m_objectStore->deleteFunction(key, request, m_transaction->backend(), ec); 101 if (ec) 107 if (ec) { 108 request->markEarlyDeath(); 102 109 return 0; 103 return request; 110 } 111 return request.release(); 104 112 } 105 113 … … 108 116 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 109 117 m_objectStore->clear(request, m_transaction->backend(), ec); 110 if (ec) 118 if (ec) { 119 request->markEarlyDeath(); 111 120 return 0; 112 return request; 121 } 122 return request.release(); 113 123 } 114 124 … … 149 159 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 150 160 m_objectStore->openCursor(range, direction, request, m_transaction->backend(), ec); 151 if (ec) 161 if (ec) { 162 request->markEarlyDeath(); 152 163 return 0; 164 } 153 165 return request.release(); 154 166 } -
trunk/Source/WebCore/storage/IDBRequest.cpp
r80025 r80028 43 43 #include "IDBObjectStore.h" 44 44 #include "IDBPendingTransactionMonitor.h" 45 #include "IDBTransaction.h" 45 46 46 47 namespace WebCore { … … 59 60 , m_finished(false) 60 61 { 62 if (m_transaction) { 63 m_transaction->registerRequest(this); 64 IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend()); 65 } 66 } 67 68 IDBRequest::~IDBRequest() 69 { 70 ASSERT(m_readyState == DONE || m_readyState == EarlyDeath); 61 71 if (m_transaction) 62 IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend()); 63 } 64 65 IDBRequest::~IDBRequest() 66 { 72 m_transaction->unregisterRequest(this); 67 73 } 68 74 … … 106 112 unsigned short IDBRequest::readyState() const 107 113 { 114 ASSERT(m_readyState == LOADING || m_readyState == DONE); 108 115 return m_readyState; 116 } 117 118 void IDBRequest::markEarlyDeath() 119 { 120 ASSERT(m_readyState == LOADING); 121 m_readyState = EarlyDeath; 109 122 } 110 123 … … 127 140 } 128 141 142 IDBAny* IDBRequest::source() 143 { 144 return m_source.get(); 145 } 146 147 void IDBRequest::abort() 148 { 149 if (m_readyState != LOADING) { 150 ASSERT(m_readyState == DONE); 151 return; 152 } 153 154 ASSERT(scriptExecutionContext()->isDocument()); 155 EventQueue* eventQueue = static_cast<Document*>(scriptExecutionContext())->eventQueue(); 156 for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { 157 bool removed = eventQueue->cancelEvent(m_enqueuedEvents[i].get()); 158 ASSERT_UNUSED(removed, removed); 159 } 160 m_enqueuedEvents.clear(); 161 162 m_errorCode = 0; 163 m_errorMessage = String(); 164 m_result.clear(); 165 onError(IDBDatabaseError::create(IDBDatabaseException::ABORT_ERR, "The transaction was aborted, so the request cannot be fulfilled.")); 166 } 167 129 168 void IDBRequest::onError(PassRefPtr<IDBDatabaseError> error) 130 169 { … … 219 258 { 220 259 ASSERT(!m_finished); 260 ASSERT(m_enqueuedEvents.size()); 221 261 ASSERT(scriptExecutionContext()); 222 262 ASSERT(event->target() == this); … … 224 264 if (event->type() != eventNames().blockedEvent) 225 265 m_readyState = DONE; 266 267 for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { 268 if (m_enqueuedEvents[i].get() == event.get()) 269 m_enqueuedEvents.remove(i); 270 } 226 271 227 272 Vector<RefPtr<EventTarget> > targets; … … 241 286 242 287 // If the result was of type IDBCursor, then we'll fire again. 243 // if (m_result && m_result->type() != IDBAny::IDBCursorType && event->type() != eventNames.blockedEvent)244 288 if (m_result && m_result->type() != IDBAny::IDBCursorType) 245 289 m_finished = true; … … 270 314 EventQueue* eventQueue = static_cast<Document*>(scriptExecutionContext())->eventQueue(); 271 315 event->setTarget(this); 272 eventQueue->enqueueEvent(event); 273 } 274 275 IDBAny* IDBRequest::source() 276 { 277 return m_source.get(); 316 eventQueue->enqueueEvent(event.get()); 317 m_enqueuedEvents.append(event); 278 318 } 279 319 -
trunk/Source/WebCore/storage/IDBRequest.h
r78908 r80028 59 59 enum ReadyState { 60 60 LOADING = 1, 61 DONE = 2 61 DONE = 2, 62 EarlyDeath = 3 62 63 }; 63 64 unsigned short readyState() const; … … 66 67 DEFINE_ATTRIBUTE_EVENT_LISTENER(error); 67 68 69 void markEarlyDeath(); 68 70 bool resetReadyState(IDBTransaction*); 69 71 IDBAny* source(); 72 void abort(); 70 73 71 74 // IDBCallbacks … … 112 115 ReadyState m_readyState; 113 116 bool m_finished; // Is it possible that we'll fire any more events? If not, we're finished. 117 Vector<RefPtr<Event> > m_enqueuedEvents; 114 118 115 119 EventTargetData m_eventTargetData; -
trunk/Source/WebCore/storage/IDBTransaction.cpp
r80025 r80028 104 104 } 105 105 106 void IDBTransaction::registerRequest(IDBRequest* request) 107 { 108 m_childRequests.add(request); 109 } 110 111 void IDBTransaction::unregisterRequest(IDBRequest* request) 112 { 113 // If we aborted the request, it will already have been removed. 114 m_childRequests.remove(request); 115 } 116 106 117 void IDBTransaction::onAbort() 107 118 { 119 while (!m_childRequests.isEmpty()) { 120 IDBRequest* request = *m_childRequests.begin(); 121 m_childRequests.remove(request); 122 request->abort(); 123 } 124 108 125 enqueueEvent(Event::create(eventNames().abortEvent, true, false)); 109 126 } -
trunk/Source/WebCore/storage/IDBTransaction.h
r78280 r80028 63 63 void abort(); 64 64 65 void registerRequest(IDBRequest*); 66 void unregisterRequest(IDBRequest*); 67 65 68 DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); 66 69 DEFINE_ATTRIBUTE_EVENT_LISTENER(complete); … … 101 104 bool m_finished; // Is it possible that we'll fire any more events or allow any new transactions? If not, we're finished. 102 105 106 ListHashSet<IDBRequest*> m_childRequests; 107 103 108 EventTargetData m_eventTargetData; 104 109 };
Note: See TracChangeset
for help on using the changeset viewer.