88db3ae5ef1fd2957a7af9c698e9f6ffbae82f31
[WebKit-https.git] / WebCore / inspector / InspectorDatabaseAgent.cpp
1 /*
2  * Copyright (C) 2010 Google 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
31 #include "InspectorDatabaseAgent.h"
32
33 #if ENABLE(INSPECTOR) && ENABLE(DATABASE)
34
35 #include "Database.h"
36 #include "ExceptionCode.h"
37 #include "InspectorFrontend.h"
38 #include "InspectorController.h"
39 #include "InspectorDatabaseResource.h"
40 #include "InspectorValues.h"
41 #include "SQLError.h"
42 #include "SQLStatementCallback.h"
43 #include "SQLStatementErrorCallback.h"
44 #include "SQLResultSetRowList.h"
45 #include "SQLTransaction.h"
46 #include "SQLTransactionCallback.h"
47 #include "SQLTransactionErrorCallback.h"
48 #include "SQLValue.h"
49 #include "VoidCallback.h"
50
51 #include <wtf/Vector.h>
52
53 namespace WebCore {
54
55 namespace {
56
57 long lastTransactionId = 0;
58
59 void reportTransactionFailed(InspectorDatabaseAgent* agent, long transactionId, SQLError* error)
60 {
61     if (!agent->frontend())
62         return;
63     RefPtr<InspectorObject> errorObject = InspectorObject::create();
64     errorObject->setString("message", error->message());
65     errorObject->setNumber("code", error->code());
66     agent->frontend()->sqlTransactionFailed(transactionId, errorObject);
67 }
68
69 class StatementCallback : public SQLStatementCallback {
70 public:
71     static PassRefPtr<StatementCallback> create(long transactionId, PassRefPtr<InspectorDatabaseAgent> agent)
72     {
73         return adoptRef(new StatementCallback(transactionId, agent));
74     }
75
76     virtual ~StatementCallback() { }
77
78     virtual bool handleEvent(SQLTransaction*, SQLResultSet* resultSet)
79     {
80         if (!m_agent->frontend())
81             return true;
82
83         SQLResultSetRowList* rowList = resultSet->rows();
84
85         RefPtr<InspectorArray> columnNames = InspectorArray::create();
86         const Vector<String>& columns = rowList->columnNames();
87         for (size_t i = 0; i < columns.size(); ++i)
88             columnNames->pushString(columns[i]);
89
90         RefPtr<InspectorArray> values = InspectorArray::create();
91         const Vector<SQLValue>& data = rowList->values();
92         for (size_t i = 0; i < data.size(); ++i) {
93             const SQLValue& value = rowList->values()[i];
94             switch (value.type()) {
95                 case SQLValue::StringValue: values->pushString(value.string()); break;
96                 case SQLValue::NumberValue: values->pushNumber(value.number()); break;
97                 case SQLValue::NullValue: values->pushValue(InspectorValue::null()); break;
98             }
99         }
100         m_agent->frontend()->sqlTransactionSucceeded(m_transactionId, columnNames, values);
101         return true;
102     }
103
104 private:
105     StatementCallback(long transactionId, PassRefPtr<InspectorDatabaseAgent> agent)
106         : m_transactionId(transactionId)
107         , m_agent(agent) { }
108     long m_transactionId;
109     RefPtr<InspectorDatabaseAgent> m_agent;
110 };
111
112 class StatementErrorCallback : public SQLStatementErrorCallback {
113 public:
114     static PassRefPtr<StatementErrorCallback> create(long transactionId, PassRefPtr<InspectorDatabaseAgent> agent)
115     {
116         return adoptRef(new StatementErrorCallback(transactionId, agent));
117     }
118
119     virtual ~StatementErrorCallback() { }
120
121     virtual bool handleEvent(SQLTransaction*, SQLError* error)
122     {
123         reportTransactionFailed(m_agent.get(), m_transactionId, error);
124         return true;  
125     }
126
127 private:
128     StatementErrorCallback(long transactionId, RefPtr<InspectorDatabaseAgent> agent)
129         : m_transactionId(transactionId)
130         , m_agent(agent) { }
131     long m_transactionId;
132     RefPtr<InspectorDatabaseAgent> m_agent;
133 };
134
135 class TransactionCallback : public SQLTransactionCallback {
136 public:
137     static PassRefPtr<TransactionCallback> create(const String& sqlStatement, long transactionId, PassRefPtr<InspectorDatabaseAgent> agent)
138     {
139         return adoptRef(new TransactionCallback(sqlStatement, transactionId, agent));
140     }
141
142     virtual ~TransactionCallback() { }
143
144     virtual bool handleEvent(SQLTransaction* transaction)
145     {
146         if (!m_agent->frontend())
147             return true;
148
149         Vector<SQLValue> sqlValues;
150         RefPtr<SQLStatementCallback> callback(StatementCallback::create(m_transactionId, m_agent));
151         RefPtr<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::create(m_transactionId, m_agent));
152         ExceptionCode ec = 0;
153         transaction->executeSQL(m_sqlStatement, sqlValues, callback.release(), errorCallback.release(), ec);
154         return true;
155     }
156 private:
157     TransactionCallback(const String& sqlStatement, long transactionId, PassRefPtr<InspectorDatabaseAgent> agent)
158         : m_sqlStatement(sqlStatement)
159         , m_transactionId(transactionId)
160         , m_agent(agent) { }
161     String m_sqlStatement;
162     long m_transactionId;
163     RefPtr<InspectorDatabaseAgent> m_agent;
164 };
165
166 class TransactionErrorCallback : public SQLTransactionErrorCallback {
167 public:
168     static PassRefPtr<TransactionErrorCallback> create(long transactionId, PassRefPtr<InspectorDatabaseAgent> agent)
169     {
170         return adoptRef(new TransactionErrorCallback(transactionId, agent));
171     }
172
173     virtual ~TransactionErrorCallback() { }
174
175     virtual bool handleEvent(SQLError* error)
176     {
177         reportTransactionFailed(m_agent.get(), m_transactionId, error);
178         return true;
179     }
180 private:
181     TransactionErrorCallback(long transactionId, PassRefPtr<InspectorDatabaseAgent> agent)
182         : m_transactionId(transactionId)
183         , m_agent(agent) { }
184     long m_transactionId;
185     RefPtr<InspectorDatabaseAgent> m_agent;
186 };
187
188 class TransactionSuccessCallback : public VoidCallback {
189 public:
190     static PassRefPtr<TransactionSuccessCallback> create()
191     {
192         return adoptRef(new TransactionSuccessCallback());
193     }
194
195     virtual ~TransactionSuccessCallback() { }
196
197     virtual void handleEvent() { }
198
199 private:
200     TransactionSuccessCallback() { }
201 };
202
203 } // namespace
204
205 InspectorDatabaseAgent::~InspectorDatabaseAgent()
206 {
207 }
208
209 void InspectorDatabaseAgent::getDatabaseTableNames(long databaseId, RefPtr<InspectorArray>* names)
210 {
211     Database* database = databaseForId(databaseId);
212     if (database) {
213         Vector<String> tableNames = database->tableNames();
214         unsigned length = tableNames.size();
215         for (unsigned i = 0; i < length; ++i)
216             (*names)->pushString(tableNames[i]);
217     }
218 }
219
220 void InspectorDatabaseAgent::executeSQL(long databaseId, const String& query, bool* success, long* transactionId)
221 {
222     Database* database = databaseForId(databaseId);
223     if (!database) {
224         *success = false;
225         return;
226     }
227
228     *transactionId = ++lastTransactionId;
229     RefPtr<SQLTransactionCallback> callback(TransactionCallback::create(query, *transactionId, this));
230     RefPtr<SQLTransactionErrorCallback> errorCallback(TransactionErrorCallback::create(*transactionId, this));
231     RefPtr<VoidCallback> successCallback(TransactionSuccessCallback::create());
232     database->transaction(callback.release(), errorCallback.release(), successCallback.release());
233     *success = true;
234 }
235
236 Database* InspectorDatabaseAgent::databaseForId(long databaseId)
237 {
238     DatabaseResourcesMap::iterator it = m_databaseResources->find(databaseId);
239     if (it == m_databaseResources->end())
240         return 0;
241     return it->second->database();
242 }
243
244 void InspectorDatabaseAgent::selectDatabase(Database* database)
245 {
246     if (!m_frontend)
247         return;
248
249     for (DatabaseResourcesMap::iterator it = m_databaseResources->begin(); it != m_databaseResources->end(); ++it) {
250         if (it->second->database() == database) {
251             m_frontend->selectDatabase(it->first);
252             break;
253         }
254     }
255 }
256
257 void InspectorDatabaseAgent::clearFrontend()
258 {
259     m_frontend = 0;
260 }
261
262 InspectorDatabaseAgent::InspectorDatabaseAgent(DatabaseResourcesMap* databaseResources, InspectorFrontend* frontend)
263     : m_databaseResources(databaseResources)
264     , m_frontend(frontend)
265 {
266 }
267
268 } // namespace WebCore
269
270 #endif // ENABLE(INSPECTOR) && ENABLE(DATABASE)