Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / webdatabase / SQLTransaction.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2013 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 "modules/webdatabase/SQLTransaction.h"
31
32 #include "bindings/core/v8/ExceptionState.h"
33 #include "core/dom/ExceptionCode.h"
34 #include "core/html/VoidCallback.h"
35 #include "core/inspector/InspectorInstrumentation.h"
36 #include "modules/webdatabase/Database.h"
37 #include "modules/webdatabase/DatabaseAuthorizer.h"
38 #include "modules/webdatabase/DatabaseContext.h"
39 #include "modules/webdatabase/SQLError.h"
40 #include "modules/webdatabase/SQLStatementCallback.h"
41 #include "modules/webdatabase/SQLStatementErrorCallback.h"
42 #include "modules/webdatabase/SQLTransactionBackend.h"
43 #include "modules/webdatabase/SQLTransactionCallback.h"
44 #include "modules/webdatabase/SQLTransactionClient.h" // FIXME: Should be used in the backend only.
45 #include "modules/webdatabase/SQLTransactionErrorCallback.h"
46 #include "platform/Logging.h"
47 #include "wtf/StdLibExtras.h"
48 #include "wtf/Vector.h"
49
50 namespace blink {
51
52 SQLTransaction* SQLTransaction::create(Database* db, SQLTransactionCallback* callback,
53     VoidCallback* successCallback, SQLTransactionErrorCallback* errorCallback, bool readOnly)
54 {
55     return new SQLTransaction(db, callback, successCallback, errorCallback, readOnly);
56 }
57
58 SQLTransaction::SQLTransaction(Database* db, SQLTransactionCallback* callback,
59     VoidCallback* successCallback, SQLTransactionErrorCallback* errorCallback,
60     bool readOnly)
61     : m_database(db)
62     , m_callback(callback)
63     , m_successCallback(successCallback)
64     , m_errorCallback(errorCallback)
65     , m_executeSqlAllowed(false)
66     , m_readOnly(readOnly)
67 {
68     ASSERT(m_database);
69     m_asyncOperationId = InspectorInstrumentation::traceAsyncOperationStarting(db->executionContext(), "SQLTransaction");
70 }
71
72 SQLTransaction::~SQLTransaction()
73 {
74 }
75
76 void SQLTransaction::trace(Visitor* visitor)
77 {
78     visitor->trace(m_database);
79     visitor->trace(m_backend);
80     visitor->trace(m_callback);
81     visitor->trace(m_successCallback);
82     visitor->trace(m_errorCallback);
83 }
84
85 bool SQLTransaction::hasCallback() const
86 {
87     return m_callback;
88 }
89
90 bool SQLTransaction::hasSuccessCallback() const
91 {
92     return m_successCallback;
93 }
94
95 bool SQLTransaction::hasErrorCallback() const
96 {
97     return m_errorCallback;
98 }
99
100 void SQLTransaction::setBackend(SQLTransactionBackend* backend)
101 {
102     ASSERT(!m_backend);
103     m_backend = backend;
104 }
105
106 SQLTransaction::StateFunction SQLTransaction::stateFunctionFor(SQLTransactionState state)
107 {
108     static const StateFunction stateFunctions[] = {
109         &SQLTransaction::unreachableState,                // 0. illegal
110         &SQLTransaction::unreachableState,                // 1. idle
111         &SQLTransaction::unreachableState,                // 2. acquireLock
112         &SQLTransaction::unreachableState,                // 3. openTransactionAndPreflight
113         &SQLTransaction::sendToBackendState,              // 4. runStatements
114         &SQLTransaction::unreachableState,                // 5. postflightAndCommit
115         &SQLTransaction::sendToBackendState,              // 6. cleanupAndTerminate
116         &SQLTransaction::sendToBackendState,              // 7. cleanupAfterTransactionErrorCallback
117         &SQLTransaction::deliverTransactionCallback,      // 8.
118         &SQLTransaction::deliverTransactionErrorCallback, // 9.
119         &SQLTransaction::deliverStatementCallback,        // 10.
120         &SQLTransaction::deliverQuotaIncreaseCallback,    // 11.
121         &SQLTransaction::deliverSuccessCallback           // 12.
122     };
123
124     ASSERT(WTF_ARRAY_LENGTH(stateFunctions) == static_cast<int>(SQLTransactionState::NumberOfStates));
125     ASSERT(state < SQLTransactionState::NumberOfStates);
126
127     return stateFunctions[static_cast<int>(state)];
128 }
129
130 // requestTransitToState() can be called from the backend. Hence, it should
131 // NOT be modifying SQLTransactionBackend in general. The only safe field to
132 // modify is m_requestedState which is meant for this purpose.
133 void SQLTransaction::requestTransitToState(SQLTransactionState nextState)
134 {
135     WTF_LOG(StorageAPI, "Scheduling %s for transaction %p\n", nameForSQLTransactionState(nextState), this);
136     m_requestedState = nextState;
137     m_database->scheduleTransactionCallback(this);
138 }
139
140 SQLTransactionState SQLTransaction::nextStateForTransactionError()
141 {
142     ASSERT(m_transactionError);
143     if (hasErrorCallback())
144         return SQLTransactionState::DeliverTransactionErrorCallback;
145
146     // No error callback, so fast-forward to:
147     // Transaction Step 11 - Rollback the transaction.
148     return SQLTransactionState::CleanupAfterTransactionErrorCallback;
149 }
150
151 SQLTransactionState SQLTransaction::deliverTransactionCallback()
152 {
153     bool shouldDeliverErrorCallback = false;
154
155     // Spec 4.3.2 4: Invoke the transaction callback with the new SQLTransaction object
156     if (SQLTransactionCallback* callback = m_callback.release()) {
157         m_executeSqlAllowed = true;
158         InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncCallbackStarting(m_database->executionContext(), m_asyncOperationId);
159         shouldDeliverErrorCallback = !callback->handleEvent(this);
160         InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
161         m_executeSqlAllowed = false;
162     }
163
164     // Spec 4.3.2 5: If the transaction callback was null or raised an exception, jump to the error callback
165     SQLTransactionState nextState = SQLTransactionState::RunStatements;
166     if (shouldDeliverErrorCallback) {
167         m_database->reportStartTransactionResult(5, SQLError::UNKNOWN_ERR, 0);
168         m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "the SQLTransactionCallback was null or threw an exception");
169         nextState = SQLTransactionState::DeliverTransactionErrorCallback;
170     }
171     m_database->reportStartTransactionResult(0, -1, 0); // OK
172     return nextState;
173 }
174
175 SQLTransactionState SQLTransaction::deliverTransactionErrorCallback()
176 {
177     InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncOperationCompletedCallbackStarting(m_database->executionContext(), m_asyncOperationId);
178
179     // Spec 4.3.2.10: If exists, invoke error callback with the last
180     // error to have occurred in this transaction.
181     if (SQLTransactionErrorCallback* errorCallback = m_errorCallback.release()) {
182         // If we get here with an empty m_transactionError, then the backend
183         // must be waiting in the idle state waiting for this state to finish.
184         // Hence, it's thread safe to fetch the backend transactionError without
185         // a lock.
186         if (!m_transactionError) {
187             ASSERT(m_backend->transactionError());
188             m_transactionError = SQLErrorData::create(*m_backend->transactionError());
189         }
190         ASSERT(m_transactionError);
191         errorCallback->handleEvent(SQLError::create(*m_transactionError));
192
193         m_transactionError = nullptr;
194     }
195
196     InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
197     clearCallbacks();
198
199     // Spec 4.3.2.10: Rollback the transaction.
200     return SQLTransactionState::CleanupAfterTransactionErrorCallback;
201 }
202
203 SQLTransactionState SQLTransaction::deliverStatementCallback()
204 {
205     // Spec 4.3.2.6.6 and 4.3.2.6.3: If the statement callback went wrong, jump to the transaction error callback
206     // Otherwise, continue to loop through the statement queue
207     m_executeSqlAllowed = true;
208
209     SQLStatement* currentStatement = m_backend->currentStatement();
210     ASSERT(currentStatement);
211
212     bool result = currentStatement->performCallback(this);
213
214     m_executeSqlAllowed = false;
215
216     if (result) {
217         m_database->reportCommitTransactionResult(2, SQLError::UNKNOWN_ERR, 0);
218         m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "the statement callback raised an exception or statement error callback did not return false");
219         return nextStateForTransactionError();
220     }
221     return SQLTransactionState::RunStatements;
222 }
223
224 SQLTransactionState SQLTransaction::deliverQuotaIncreaseCallback()
225 {
226     ASSERT(m_backend->currentStatement());
227
228     bool shouldRetryCurrentStatement = m_database->transactionClient()->didExceedQuota(database());
229     m_backend->setShouldRetryCurrentStatement(shouldRetryCurrentStatement);
230
231     return SQLTransactionState::RunStatements;
232 }
233
234 SQLTransactionState SQLTransaction::deliverSuccessCallback()
235 {
236     InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncOperationCompletedCallbackStarting(m_database->executionContext(), m_asyncOperationId);
237
238     // Spec 4.3.2.8: Deliver success callback.
239     if (VoidCallback* successCallback = m_successCallback.release())
240         successCallback->handleEvent();
241
242     InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
243     clearCallbacks();
244
245     // Schedule a "post-success callback" step to return control to the database thread in case there
246     // are further transactions queued up for this Database
247     return SQLTransactionState::CleanupAndTerminate;
248 }
249
250 // This state function is used as a stub function to plug unimplemented states
251 // in the state dispatch table. They are unimplemented because they should
252 // never be reached in the course of correct execution.
253 SQLTransactionState SQLTransaction::unreachableState()
254 {
255     ASSERT_NOT_REACHED();
256     return SQLTransactionState::End;
257 }
258
259 SQLTransactionState SQLTransaction::sendToBackendState()
260 {
261     ASSERT(m_nextState != SQLTransactionState::Idle);
262     m_backend->requestTransitToState(m_nextState);
263     return SQLTransactionState::Idle;
264 }
265
266 void SQLTransaction::performPendingCallback()
267 {
268     computeNextStateAndCleanupIfNeeded();
269     runStateMachine();
270 }
271
272 void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, SQLStatementCallback* callback, SQLStatementErrorCallback* callbackError, ExceptionState& exceptionState)
273 {
274     if (!m_executeSqlAllowed) {
275         exceptionState.throwDOMException(InvalidStateError, "SQL execution is disallowed.");
276         return;
277     }
278
279     if (!m_database->opened()) {
280         exceptionState.throwDOMException(InvalidStateError, "The database has not been opened.");
281         return;
282     }
283
284     int permissions = DatabaseAuthorizer::ReadWriteMask;
285     if (!m_database->databaseContext()->allowDatabaseAccess())
286         permissions |= DatabaseAuthorizer::NoAccessMask;
287     else if (m_readOnly)
288         permissions |= DatabaseAuthorizer::ReadOnlyMask;
289
290     SQLStatement* statement = SQLStatement::create(m_database.get(), callback, callbackError);
291     m_backend->executeSQL(statement, sqlStatement, arguments, permissions);
292 }
293
294 bool SQLTransaction::computeNextStateAndCleanupIfNeeded()
295 {
296     // Only honor the requested state transition if we're not supposed to be
297     // cleaning up and shutting down:
298     if (m_database->opened()) {
299         setStateToRequestedState();
300         ASSERT(m_nextState == SQLTransactionState::End
301             || m_nextState == SQLTransactionState::DeliverTransactionCallback
302             || m_nextState == SQLTransactionState::DeliverTransactionErrorCallback
303             || m_nextState == SQLTransactionState::DeliverStatementCallback
304             || m_nextState == SQLTransactionState::DeliverQuotaIncreaseCallback
305             || m_nextState == SQLTransactionState::DeliverSuccessCallback);
306
307         WTF_LOG(StorageAPI, "Callback %s\n", nameForSQLTransactionState(m_nextState));
308         return false;
309     }
310
311     clearCallbacks();
312     m_nextState = SQLTransactionState::CleanupAndTerminate;
313
314     return true;
315 }
316
317 void SQLTransaction::clearCallbacks()
318 {
319     m_callback.clear();
320     m_successCallback.clear();
321     m_errorCallback.clear();
322 }
323
324 SQLTransactionErrorCallback* SQLTransaction::releaseErrorCallback()
325 {
326     return m_errorCallback.release();
327 }
328
329 } // namespace blink