e9f38a976dbe9f6f58756222b8ff4e06a9975570
[WebKit-https.git] / Source / WebCore / Modules / webdatabase / SQLTransaction.cpp
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "SQLTransaction.h"
31
32 #if ENABLE(SQL_DATABASE)
33
34 #include "Database.h"
35 #include "DatabaseAuthorizer.h"
36 #include "DatabaseContext.h"
37 #include "DatabaseThread.h"
38 #include "ExceptionCode.h"
39 #include "Logging.h"
40 #include "PlatformString.h"
41 #include "ScriptExecutionContext.h"
42 #include "SQLError.h"
43 #include "SQLiteTransaction.h"
44 #include "SQLStatement.h"
45 #include "SQLStatementCallback.h"
46 #include "SQLStatementErrorCallback.h"
47 #include "SQLTransactionCallback.h"
48 #include "SQLTransactionClient.h"
49 #include "SQLTransactionCoordinator.h"
50 #include "SQLTransactionErrorCallback.h"
51 #include "SQLValue.h"
52 #include "VoidCallback.h"
53 #include <wtf/OwnPtr.h>
54 #include <wtf/PassRefPtr.h>
55 #include <wtf/RefPtr.h>
56
57 // There's no way of knowing exactly how much more space will be required when a statement hits the quota limit.
58 // For now, we'll arbitrarily choose currentQuota + 1mb.
59 // In the future we decide to track if a size increase wasn't enough, and ask for larger-and-larger increases until its enough.
60 static const int DefaultQuotaSizeIncrease = 1048576;
61
62 namespace WebCore {
63
64 PassRefPtr<SQLTransaction> SQLTransaction::create(Database* db, PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback,
65                                                   PassRefPtr<VoidCallback> successCallback, PassRefPtr<SQLTransactionWrapper> wrapper, bool readOnly)
66 {
67     return adoptRef(new SQLTransaction(db, callback, errorCallback, successCallback, wrapper, readOnly));
68 }
69
70 SQLTransaction::SQLTransaction(Database* db, PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback,
71                                PassRefPtr<VoidCallback> successCallback, PassRefPtr<SQLTransactionWrapper> wrapper, bool readOnly)
72     : m_nextStep(&SQLTransaction::acquireLock)
73     , m_executeSqlAllowed(false)
74     , m_database(db)
75     , m_wrapper(wrapper)
76     , m_callbackWrapper(callback, db->scriptExecutionContext())
77     , m_successCallbackWrapper(successCallback, db->scriptExecutionContext())
78     , m_errorCallbackWrapper(errorCallback, db->scriptExecutionContext())
79     , m_shouldRetryCurrentStatement(false)
80     , m_modifiedDatabase(false)
81     , m_lockAcquired(false)
82     , m_readOnly(readOnly)
83     , m_hasVersionMismatch(false)
84 {
85     ASSERT(m_database);
86 }
87
88 SQLTransaction::~SQLTransaction()
89 {
90     ASSERT(!m_sqliteTransaction);
91 }
92
93 void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> callbackError, ExceptionCode& e)
94 {
95     if (!m_executeSqlAllowed || !m_database->opened()) {
96         e = INVALID_STATE_ERR;
97         return;
98     }
99
100     int permissions = DatabaseAuthorizer::ReadWriteMask;
101     if (!m_database->databaseContext()->allowDatabaseAccess())
102         permissions |= DatabaseAuthorizer::NoAccessMask;
103     else if (m_readOnly)
104         permissions |= DatabaseAuthorizer::ReadOnlyMask;
105
106     RefPtr<SQLStatement> statement = SQLStatement::create(m_database.get(), sqlStatement, arguments, callback, callbackError, permissions);
107
108     if (m_database->deleted())
109         statement->setDatabaseDeletedError(m_database.get());
110
111     enqueueStatement(statement);
112 }
113
114 void SQLTransaction::enqueueStatement(PassRefPtr<SQLStatement> statement)
115 {
116     MutexLocker locker(m_statementMutex);
117     m_statementQueue.append(statement);
118 }
119
120 #if !LOG_DISABLED
121 const char* SQLTransaction::debugStepName(SQLTransaction::TransactionStepMethod step)
122 {
123     if (step == &SQLTransaction::acquireLock)
124         return "acquireLock";
125     else if (step == &SQLTransaction::openTransactionAndPreflight)
126         return "openTransactionAndPreflight";
127     else if (step == &SQLTransaction::runStatements)
128         return "runStatements";
129     else if (step == &SQLTransaction::postflightAndCommit)
130         return "postflightAndCommit";
131     else if (step == &SQLTransaction::cleanupAfterTransactionErrorCallback)
132         return "cleanupAfterTransactionErrorCallback";
133     else if (step == &SQLTransaction::deliverTransactionCallback)
134         return "deliverTransactionCallback";
135     else if (step == &SQLTransaction::deliverTransactionErrorCallback)
136         return "deliverTransactionErrorCallback";
137     else if (step == &SQLTransaction::deliverStatementCallback)
138         return "deliverStatementCallback";
139     else if (step == &SQLTransaction::deliverQuotaIncreaseCallback)
140         return "deliverQuotaIncreaseCallback";
141     else if (step == &SQLTransaction::deliverSuccessCallback)
142         return "deliverSuccessCallback";
143     else if (step == &SQLTransaction::cleanupAfterSuccessCallback)
144         return "cleanupAfterSuccessCallback";
145     else
146         return "UNKNOWN";
147 }
148 #endif
149
150 void SQLTransaction::checkAndHandleClosedOrInterruptedDatabase()
151 {
152     if (m_database->opened() && !m_database->isInterrupted())
153         return;
154
155     // If the database was stopped, don't do anything and cancel queued work
156     LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction");
157     MutexLocker locker(m_statementMutex);
158     m_statementQueue.clear();
159     m_nextStep = 0;
160
161     // Release the unneeded callbacks, to break reference cycles.
162     m_callbackWrapper.clear();
163     m_successCallbackWrapper.clear();
164     m_errorCallbackWrapper.clear();
165
166     // The next steps should be executed only if we're on the DB thread.
167     if (currentThread() != database()->databaseContext()->databaseThread()->getThreadID())
168         return;
169
170     // The current SQLite transaction should be stopped, as well
171     if (m_sqliteTransaction) {
172         m_sqliteTransaction->stop();
173         m_sqliteTransaction.clear();
174     }
175
176     if (m_lockAcquired)
177         m_database->transactionCoordinator()->releaseLock(this);
178 }
179
180
181 bool SQLTransaction::performNextStep()
182 {
183     LOG(StorageAPI, "Step %s\n", debugStepName(m_nextStep));
184
185     ASSERT(m_nextStep == &SQLTransaction::acquireLock ||
186            m_nextStep == &SQLTransaction::openTransactionAndPreflight ||
187            m_nextStep == &SQLTransaction::runStatements ||
188            m_nextStep == &SQLTransaction::postflightAndCommit ||
189            m_nextStep == &SQLTransaction::cleanupAfterSuccessCallback ||
190            m_nextStep == &SQLTransaction::cleanupAfterTransactionErrorCallback);
191
192     checkAndHandleClosedOrInterruptedDatabase();
193
194     if (m_nextStep)
195         (this->*m_nextStep)();
196
197     // If there is no nextStep after performing the above step, the transaction is complete
198     return !m_nextStep;
199 }
200
201 void SQLTransaction::performPendingCallback()
202 {
203     LOG(StorageAPI, "Callback %s\n", debugStepName(m_nextStep));
204
205     ASSERT(m_nextStep == &SQLTransaction::deliverTransactionCallback ||
206            m_nextStep == &SQLTransaction::deliverTransactionErrorCallback ||
207            m_nextStep == &SQLTransaction::deliverStatementCallback ||
208            m_nextStep == &SQLTransaction::deliverQuotaIncreaseCallback ||
209            m_nextStep == &SQLTransaction::deliverSuccessCallback);
210
211     checkAndHandleClosedOrInterruptedDatabase();
212
213     if (m_nextStep)
214         (this->*m_nextStep)();
215 }
216
217 void SQLTransaction::notifyDatabaseThreadIsShuttingDown()
218 {
219     ASSERT(currentThread() == database()->databaseContext()->databaseThread()->getThreadID());
220
221     // If the transaction is in progress, we should roll it back here, since this is our last
222     // oportunity to do something related to this transaction on the DB thread.
223     // Clearing m_sqliteTransaction invokes SQLiteTransaction's destructor which does just that.
224     m_sqliteTransaction.clear();
225 }
226
227 void SQLTransaction::acquireLock()
228 {
229     m_database->transactionCoordinator()->acquireLock(this);
230 }
231
232 void SQLTransaction::lockAcquired()
233 {
234     m_lockAcquired = true;
235     m_nextStep = &SQLTransaction::openTransactionAndPreflight;
236     LOG(StorageAPI, "Scheduling openTransactionAndPreflight immediately for transaction %p\n", this);
237     m_database->scheduleTransactionStep(this, true);
238 }
239
240 void SQLTransaction::openTransactionAndPreflight()
241 {
242     ASSERT(!m_database->sqliteDatabase().transactionInProgress());
243     ASSERT(m_lockAcquired);
244
245     LOG(StorageAPI, "Opening and preflighting transaction %p", this);
246
247     // If the database was deleted, jump to the error callback
248     if (m_database->deleted()) {
249         m_database->reportStartTransactionResult(1, SQLError::UNKNOWN_ERR, 0);
250         m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unable to open a transaction, because the user deleted the database");
251         handleTransactionError(false);
252         return;
253     }
254
255     // Set the maximum usage for this transaction if this transactions is not read-only
256     if (!m_readOnly)
257         m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
258
259     ASSERT(!m_sqliteTransaction);
260     m_sqliteTransaction = adoptPtr(new SQLiteTransaction(m_database->sqliteDatabase(), m_readOnly));
261
262     m_database->resetDeletes();
263     m_database->disableAuthorizer();
264     m_sqliteTransaction->begin();
265     m_database->enableAuthorizer();
266
267     // Transaction Steps 1+2 - Open a transaction to the database, jumping to the error callback if that fails
268     if (!m_sqliteTransaction->inProgress()) {
269         ASSERT(!m_database->sqliteDatabase().transactionInProgress());
270         m_database->reportStartTransactionResult(2, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
271         m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to begin transaction",
272                                               m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
273         m_sqliteTransaction.clear();
274         handleTransactionError(false);
275         return;
276     }
277
278     // Note: We intentionally retrieve the actual version even with an empty expected version.
279     // In multi-process browsers, we take this opportinutiy to update the cached value for
280     // the actual version. In single-process browsers, this is just a map lookup.
281     String actualVersion;
282     if (!m_database->getActualVersionForTransaction(actualVersion)) {
283         m_database->reportStartTransactionResult(3, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
284         m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to read version",
285                                               m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
286         m_database->disableAuthorizer();
287         m_sqliteTransaction.clear();
288         m_database->enableAuthorizer();
289         handleTransactionError(false);
290         return;
291     }
292     m_hasVersionMismatch = !m_database->expectedVersion().isEmpty()
293                            && (m_database->expectedVersion() != actualVersion);
294
295     // Transaction Steps 3 - Peform preflight steps, jumping to the error callback if they fail
296     if (m_wrapper && !m_wrapper->performPreflight(this)) {
297         m_database->disableAuthorizer();
298         m_sqliteTransaction.clear();
299         m_database->enableAuthorizer();
300         m_transactionError = m_wrapper->sqlError();
301         if (!m_transactionError) {
302             m_database->reportStartTransactionResult(4, SQLError::UNKNOWN_ERR, 0);
303             m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight");
304         }
305         handleTransactionError(false);
306         return;
307     }
308
309     // Transaction Step 4 - Invoke the transaction callback with the new SQLTransaction object
310     m_nextStep = &SQLTransaction::deliverTransactionCallback;
311     LOG(StorageAPI, "Scheduling deliverTransactionCallback for transaction %p\n", this);
312     m_database->scheduleTransactionCallback(this);
313 }
314
315 void SQLTransaction::deliverTransactionCallback()
316 {
317     bool shouldDeliverErrorCallback = false;
318
319     RefPtr<SQLTransactionCallback> callback = m_callbackWrapper.unwrap();
320     if (callback) {
321         m_executeSqlAllowed = true;
322         shouldDeliverErrorCallback = !callback->handleEvent(this);
323         m_executeSqlAllowed = false;
324     }
325
326     // Transaction Step 5 - If the transaction callback was null or raised an exception, jump to the error callback
327     if (shouldDeliverErrorCallback) {
328         m_database->reportStartTransactionResult(5, SQLError::UNKNOWN_ERR, 0);
329         m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the SQLTransactionCallback was null or threw an exception");
330         deliverTransactionErrorCallback();
331     } else
332         scheduleToRunStatements();
333
334     m_database->reportStartTransactionResult(0, -1, 0); // OK
335 }
336
337 void SQLTransaction::scheduleToRunStatements()
338 {
339     m_nextStep = &SQLTransaction::runStatements;
340     LOG(StorageAPI, "Scheduling runStatements for transaction %p\n", this);
341     m_database->scheduleTransactionStep(this);
342 }
343
344 void SQLTransaction::runStatements()
345 {
346     ASSERT(m_lockAcquired);
347
348     // If there is a series of statements queued up that are all successful and have no associated
349     // SQLStatementCallback objects, then we can burn through the queue
350     do {
351         if (m_shouldRetryCurrentStatement && !m_sqliteTransaction->wasRolledBackBySqlite()) {
352             m_shouldRetryCurrentStatement = false;
353             // FIXME - Another place that needs fixing up after <rdar://problem/5628468> is addressed.
354             // See ::openTransactionAndPreflight() for discussion
355
356             // Reset the maximum size here, as it was increased to allow us to retry this statement.
357             // m_shouldRetryCurrentStatement is set to true only when a statement exceeds
358             // the quota, which can happen only in a read-write transaction. Therefore, there
359             // is no need to check here if the transaction is read-write.
360             m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
361         } else {
362             // If the current statement has already been run, failed due to quota constraints, and we're not retrying it,
363             // that means it ended in an error.  Handle it now
364             if (m_currentStatement && m_currentStatement->lastExecutionFailedDueToQuota()) {
365                 handleCurrentStatementError();
366                 break;
367             }
368
369             // Otherwise, advance to the next statement
370             getNextStatement();
371         }
372     } while (runCurrentStatement());
373
374     // If runCurrentStatement() returned false, that means either there was no current statement to run,
375     // or the current statement requires a callback to complete.  In the later case, it also scheduled
376     // the callback or performed any other additional work so we can return
377     if (!m_currentStatement)
378         postflightAndCommit();
379 }
380
381 void SQLTransaction::getNextStatement()
382 {
383     m_currentStatement = 0;
384
385     MutexLocker locker(m_statementMutex);
386     if (!m_statementQueue.isEmpty()) {
387         m_currentStatement = m_statementQueue.takeFirst();
388     }
389 }
390
391 bool SQLTransaction::runCurrentStatement()
392 {
393     if (!m_currentStatement)
394         return false;
395
396     m_database->resetAuthorizer();
397
398     if (m_hasVersionMismatch)
399         m_currentStatement->setVersionMismatchedError(m_database.get());
400
401     if (m_currentStatement->execute(m_database.get())) {
402         if (m_database->lastActionChangedDatabase()) {
403             // Flag this transaction as having changed the database for later delegate notification
404             m_modifiedDatabase = true;
405             // Also dirty the size of this database file for calculating quota usage
406             m_database->transactionClient()->didExecuteStatement(database());
407         }
408
409         if (m_currentStatement->hasStatementCallback()) {
410             m_nextStep = &SQLTransaction::deliverStatementCallback;
411             LOG(StorageAPI, "Scheduling deliverStatementCallback for transaction %p\n", this);
412             m_database->scheduleTransactionCallback(this);
413             return false;
414         }
415         return true;
416     }
417
418     if (m_currentStatement->lastExecutionFailedDueToQuota()) {
419         m_nextStep = &SQLTransaction::deliverQuotaIncreaseCallback;
420         LOG(StorageAPI, "Scheduling deliverQuotaIncreaseCallback for transaction %p\n", this);
421         m_database->scheduleTransactionCallback(this);
422         return false;
423     }
424
425     handleCurrentStatementError();
426
427     return false;
428 }
429
430 void SQLTransaction::handleCurrentStatementError()
431 {
432     // Transaction Steps 6.error - Call the statement's error callback, but if there was no error callback,
433     // or the transaction was rolled back, jump to the transaction error callback
434     if (m_currentStatement->hasStatementErrorCallback() && !m_sqliteTransaction->wasRolledBackBySqlite()) {
435         m_nextStep = &SQLTransaction::deliverStatementCallback;
436         LOG(StorageAPI, "Scheduling deliverStatementCallback for transaction %p\n", this);
437         m_database->scheduleTransactionCallback(this);
438     } else {
439         m_transactionError = m_currentStatement->sqlError();
440         if (!m_transactionError) {
441             m_database->reportCommitTransactionResult(1, SQLError::DATABASE_ERR, 0);
442             m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "the statement failed to execute");
443         }
444         handleTransactionError(false);
445     }
446 }
447
448 void SQLTransaction::deliverStatementCallback()
449 {
450     ASSERT(m_currentStatement);
451
452     // Transaction Step 6.6 and 6.3(error) - If the statement callback went wrong, jump to the transaction error callback
453     // Otherwise, continue to loop through the statement queue
454     m_executeSqlAllowed = true;
455     bool result = m_currentStatement->performCallback(this);
456     m_executeSqlAllowed = false;
457
458     if (result) {
459         m_database->reportCommitTransactionResult(2, SQLError::UNKNOWN_ERR, 0);
460         m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the statement callback raised an exception or statement error callback did not return false");
461         handleTransactionError(true);
462     } else
463         scheduleToRunStatements();
464 }
465
466 void SQLTransaction::deliverQuotaIncreaseCallback()
467 {
468     ASSERT(m_currentStatement);
469     ASSERT(!m_shouldRetryCurrentStatement);
470
471     m_shouldRetryCurrentStatement = m_database->transactionClient()->didExceedQuota(database());
472
473     m_nextStep = &SQLTransaction::runStatements;
474     LOG(StorageAPI, "Scheduling runStatements for transaction %p\n", this);
475     m_database->scheduleTransactionStep(this);
476 }
477
478 void SQLTransaction::postflightAndCommit()
479 {
480     ASSERT(m_lockAcquired);
481
482     // Transaction Step 7 - Peform postflight steps, jumping to the error callback if they fail
483     if (m_wrapper && !m_wrapper->performPostflight(this)) {
484         m_transactionError = m_wrapper->sqlError();
485         if (!m_transactionError) {
486             m_database->reportCommitTransactionResult(3, SQLError::UNKNOWN_ERR, 0);
487             m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight");
488         }
489         handleTransactionError(false);
490         return;
491     }
492
493     // Transacton Step 8+9 - Commit the transaction, jumping to the error callback if that fails
494     ASSERT(m_sqliteTransaction);
495
496     m_database->disableAuthorizer();
497     m_sqliteTransaction->commit();
498     m_database->enableAuthorizer();
499
500     // If the commit failed, the transaction will still be marked as "in progress"
501     if (m_sqliteTransaction->inProgress()) {
502         if (m_wrapper)
503             m_wrapper->handleCommitFailedAfterPostflight(this);
504         m_successCallbackWrapper.clear();
505         m_database->reportCommitTransactionResult(4, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
506         m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to commit transaction",
507                                               m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
508         handleTransactionError(false);
509         return;
510     }
511
512     m_database->reportCommitTransactionResult(0, -1, 0); // OK
513
514     // Vacuum the database if anything was deleted.
515     if (m_database->hadDeletes())
516         m_database->incrementalVacuumIfNeeded();
517
518     // The commit was successful. If the transaction modified this database, notify the delegates.
519     if (m_modifiedDatabase)
520         m_database->transactionClient()->didCommitWriteTransaction(database());
521
522     // Now release our unneeded callbacks, to break reference cycles.
523     m_errorCallbackWrapper.clear();
524
525     // Transaction Step 10 - Deliver success callback, if there is one
526     if (m_successCallbackWrapper.hasCallback()) {
527         m_nextStep = &SQLTransaction::deliverSuccessCallback;
528         LOG(StorageAPI, "Scheduling deliverSuccessCallback for transaction %p\n", this);
529         m_database->scheduleTransactionCallback(this);
530     } else
531         cleanupAfterSuccessCallback();
532 }
533
534 void SQLTransaction::deliverSuccessCallback()
535 {
536     // Transaction Step 10 - Deliver success callback
537     RefPtr<VoidCallback> successCallback = m_successCallbackWrapper.unwrap();
538     if (successCallback)
539         successCallback->handleEvent();
540
541     // Schedule a "post-success callback" step to return control to the database thread in case there
542     // are further transactions queued up for this Database
543     m_nextStep = &SQLTransaction::cleanupAfterSuccessCallback;
544     LOG(StorageAPI, "Scheduling cleanupAfterSuccessCallback for transaction %p\n", this);
545     m_database->scheduleTransactionStep(this);
546 }
547
548 void SQLTransaction::cleanupAfterSuccessCallback()
549 {
550     ASSERT(m_lockAcquired);
551
552     // Transaction Step 11 - End transaction steps
553     // There is no next step
554     LOG(StorageAPI, "Transaction %p is complete\n", this);
555     ASSERT(!m_database->sqliteDatabase().transactionInProgress());
556     m_sqliteTransaction.clear();
557     m_nextStep = 0;
558
559     // Release the lock on this database
560     m_database->transactionCoordinator()->releaseLock(this);
561 }
562
563 void SQLTransaction::handleTransactionError(bool inCallback)
564 {
565     if (m_errorCallbackWrapper.hasCallback()) {
566         if (inCallback)
567             deliverTransactionErrorCallback();
568         else {
569             m_nextStep = &SQLTransaction::deliverTransactionErrorCallback;
570             LOG(StorageAPI, "Scheduling deliverTransactionErrorCallback for transaction %p\n", this);
571             m_database->scheduleTransactionCallback(this);
572         }
573         return;
574     }
575
576     // No error callback, so fast-forward to:
577     // Transaction Step 12 - Rollback the transaction.
578     if (inCallback) {
579         m_nextStep = &SQLTransaction::cleanupAfterTransactionErrorCallback;
580         LOG(StorageAPI, "Scheduling cleanupAfterTransactionErrorCallback for transaction %p\n", this);
581         m_database->scheduleTransactionStep(this);
582     } else {
583         cleanupAfterTransactionErrorCallback();
584     }
585 }
586
587 void SQLTransaction::deliverTransactionErrorCallback()
588 {
589     ASSERT(m_transactionError);
590
591     // Transaction Step 12 - If exists, invoke error callback with the last
592     // error to have occurred in this transaction.
593     RefPtr<SQLTransactionErrorCallback> errorCallback = m_errorCallbackWrapper.unwrap();
594     if (errorCallback)
595         errorCallback->handleEvent(m_transactionError.get());
596
597     m_nextStep = &SQLTransaction::cleanupAfterTransactionErrorCallback;
598     LOG(StorageAPI, "Scheduling cleanupAfterTransactionErrorCallback for transaction %p\n", this);
599     m_database->scheduleTransactionStep(this);
600 }
601
602 void SQLTransaction::cleanupAfterTransactionErrorCallback()
603 {
604     ASSERT(m_lockAcquired);
605
606     m_database->disableAuthorizer();
607     if (m_sqliteTransaction) {
608         // Transaction Step 12 - Rollback the transaction.
609         m_sqliteTransaction->rollback();
610
611         ASSERT(!m_database->sqliteDatabase().transactionInProgress());
612         m_sqliteTransaction.clear();
613     }
614     m_database->enableAuthorizer();
615
616     // Transaction Step 12 - Any still-pending statements in the transaction are discarded.
617     {
618         MutexLocker locker(m_statementMutex);
619         m_statementQueue.clear();
620     }
621
622     // Transaction is complete!  There is no next step
623     LOG(StorageAPI, "Transaction %p is complete with an error\n", this);
624     ASSERT(!m_database->sqliteDatabase().transactionInProgress());
625     m_nextStep = 0;
626
627     // Now release the lock on this database
628     m_database->transactionCoordinator()->releaseLock(this);
629 }
630
631 } // namespace WebCore
632
633 #endif // ENABLE(SQL_DATABASE)