2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
31 #include "InspectorDatabaseAgent.h"
33 #if ENABLE(INSPECTOR) && ENABLE(DATABASE)
36 #include "ExceptionCode.h"
37 #include "InspectorDatabaseResource.h"
38 #include "InspectorFrontend.h"
39 #include "InspectorState.h"
40 #include "InspectorValues.h"
41 #include "InstrumentingAgents.h"
43 #include "SQLStatementCallback.h"
44 #include "SQLStatementErrorCallback.h"
45 #include "SQLResultSetRowList.h"
46 #include "SQLTransaction.h"
47 #include "SQLTransactionCallback.h"
48 #include "SQLTransactionErrorCallback.h"
50 #include "VoidCallback.h"
52 #include <wtf/Vector.h>
56 namespace DatabaseAgentState {
57 static const char databaseAgentEnabled[] = "databaseAgentEnabled";
60 class InspectorDatabaseAgent::FrontendProvider : public RefCounted<InspectorDatabaseAgent::FrontendProvider> {
62 static PassRefPtr<FrontendProvider> create(InspectorFrontend* inspectorFrontend)
64 return adoptRef(new FrontendProvider(inspectorFrontend));
67 virtual ~FrontendProvider() { }
69 InspectorFrontend::Database* frontend() { return m_inspectorFrontend; }
70 void clearFrontend() { m_inspectorFrontend = 0; }
72 FrontendProvider(InspectorFrontend* inspectorFrontend) : m_inspectorFrontend(inspectorFrontend->database()) { }
73 InspectorFrontend::Database* m_inspectorFrontend;
78 int lastTransactionId = 0;
80 void reportTransactionFailed(InspectorFrontend::Database* frontend, int transactionId, SQLError* error)
84 RefPtr<InspectorObject> errorObject = InspectorObject::create();
85 errorObject->setString("message", error->message());
86 errorObject->setNumber("code", error->code());
87 frontend->sqlTransactionFailed(transactionId, errorObject);
90 class StatementCallback : public SQLStatementCallback {
92 static PassRefPtr<StatementCallback> create(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
94 return adoptRef(new StatementCallback(transactionId, frontendProvider));
97 virtual ~StatementCallback() { }
99 virtual bool handleEvent(SQLTransaction*, SQLResultSet* resultSet)
101 if (!m_frontendProvider->frontend())
104 SQLResultSetRowList* rowList = resultSet->rows();
106 RefPtr<InspectorArray> columnNames = InspectorArray::create();
107 const Vector<String>& columns = rowList->columnNames();
108 for (size_t i = 0; i < columns.size(); ++i)
109 columnNames->pushString(columns[i]);
111 RefPtr<InspectorArray> values = InspectorArray::create();
112 const Vector<SQLValue>& data = rowList->values();
113 for (size_t i = 0; i < data.size(); ++i) {
114 const SQLValue& value = rowList->values()[i];
115 switch (value.type()) {
116 case SQLValue::StringValue: values->pushString(value.string()); break;
117 case SQLValue::NumberValue: values->pushNumber(value.number()); break;
118 case SQLValue::NullValue: values->pushValue(InspectorValue::null()); break;
121 m_frontendProvider->frontend()->sqlTransactionSucceeded(m_transactionId, columnNames, values);
126 StatementCallback(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
127 : m_transactionId(transactionId)
128 , m_frontendProvider(frontendProvider) { }
130 RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider;
133 class StatementErrorCallback : public SQLStatementErrorCallback {
135 static PassRefPtr<StatementErrorCallback> create(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
137 return adoptRef(new StatementErrorCallback(transactionId, frontendProvider));
140 virtual ~StatementErrorCallback() { }
142 virtual bool handleEvent(SQLTransaction*, SQLError* error)
144 reportTransactionFailed(m_frontendProvider->frontend(), m_transactionId, error);
149 StatementErrorCallback(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
150 : m_transactionId(transactionId)
151 , m_frontendProvider(frontendProvider) { }
153 RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider;
156 class TransactionCallback : public SQLTransactionCallback {
158 static PassRefPtr<TransactionCallback> create(const String& sqlStatement, int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
160 return adoptRef(new TransactionCallback(sqlStatement, transactionId, frontendProvider));
163 virtual ~TransactionCallback() { }
165 virtual bool handleEvent(SQLTransaction* transaction)
167 if (!m_frontendProvider->frontend())
170 Vector<SQLValue> sqlValues;
171 RefPtr<SQLStatementCallback> callback(StatementCallback::create(m_transactionId, m_frontendProvider));
172 RefPtr<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::create(m_transactionId, m_frontendProvider));
173 ExceptionCode ec = 0;
174 transaction->executeSQL(m_sqlStatement, sqlValues, callback.release(), errorCallback.release(), ec);
178 TransactionCallback(const String& sqlStatement, int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
179 : m_sqlStatement(sqlStatement)
180 , m_transactionId(transactionId)
181 , m_frontendProvider(frontendProvider) { }
182 String m_sqlStatement;
184 RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider;
187 class TransactionErrorCallback : public SQLTransactionErrorCallback {
189 static PassRefPtr<TransactionErrorCallback> create(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
191 return adoptRef(new TransactionErrorCallback(transactionId, frontendProvider));
194 virtual ~TransactionErrorCallback() { }
196 virtual bool handleEvent(SQLError* error)
198 reportTransactionFailed(m_frontendProvider->frontend(), m_transactionId, error);
202 TransactionErrorCallback(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider)
203 : m_transactionId(transactionId)
204 , m_frontendProvider(frontendProvider) { }
206 RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider;
209 class TransactionSuccessCallback : public VoidCallback {
211 static PassRefPtr<TransactionSuccessCallback> create()
213 return adoptRef(new TransactionSuccessCallback());
216 virtual ~TransactionSuccessCallback() { }
218 virtual void handleEvent() { }
221 TransactionSuccessCallback() { }
226 void InspectorDatabaseAgent::didOpenDatabase(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
228 if (InspectorDatabaseResource* resource = findByFileName(database->fileName())) {
229 resource->setDatabase(database);
233 RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version);
234 m_resources.set(resource->id(), resource);
235 // Resources are only bound while visible.
236 if (m_frontendProvider && m_enabled)
237 resource->bind(m_frontendProvider->frontend());
240 void InspectorDatabaseAgent::clearResources()
245 InspectorDatabaseAgent::InspectorDatabaseAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state)
246 : m_instrumentingAgents(instrumentingAgents)
247 , m_inspectorState(state)
250 m_instrumentingAgents->setInspectorDatabaseAgent(this);
253 InspectorDatabaseAgent::~InspectorDatabaseAgent()
255 m_instrumentingAgents->setInspectorDatabaseAgent(0);
258 void InspectorDatabaseAgent::setFrontend(InspectorFrontend* frontend)
260 m_frontendProvider = FrontendProvider::create(frontend);
263 void InspectorDatabaseAgent::clearFrontend()
265 m_frontendProvider->clearFrontend();
266 m_frontendProvider.clear();
270 void InspectorDatabaseAgent::enable(ErrorString*)
275 m_inspectorState->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled);
277 DatabaseResourcesMap::iterator databasesEnd = m_resources.end();
278 for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != databasesEnd; ++it)
279 it->second->bind(m_frontendProvider->frontend());
282 void InspectorDatabaseAgent::disable(ErrorString*)
287 m_inspectorState->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled);
290 void InspectorDatabaseAgent::restore()
292 m_enabled = m_inspectorState->getBoolean(DatabaseAgentState::databaseAgentEnabled);
295 void InspectorDatabaseAgent::getDatabaseTableNames(ErrorString* error, int databaseId, RefPtr<InspectorArray>* names)
298 *error = "Database agent is not enabled";
302 Database* database = databaseForId(databaseId);
304 Vector<String> tableNames = database->tableNames();
305 unsigned length = tableNames.size();
306 for (unsigned i = 0; i < length; ++i)
307 (*names)->pushString(tableNames[i]);
311 void InspectorDatabaseAgent::executeSQL(ErrorString* error, int databaseId, const String& query, bool* success, int* transactionId)
314 *error = "Database agent is not enabled";
318 Database* database = databaseForId(databaseId);
324 *transactionId = ++lastTransactionId;
325 RefPtr<SQLTransactionCallback> callback(TransactionCallback::create(query, *transactionId, m_frontendProvider));
326 RefPtr<SQLTransactionErrorCallback> errorCallback(TransactionErrorCallback::create(*transactionId, m_frontendProvider));
327 RefPtr<VoidCallback> successCallback(TransactionSuccessCallback::create());
328 database->transaction(callback.release(), errorCallback.release(), successCallback.release());
332 int InspectorDatabaseAgent::databaseId(Database* database)
334 for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
335 if (it->second->database() == database)
341 InspectorDatabaseResource* InspectorDatabaseAgent::findByFileName(const String& fileName)
343 for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
344 if (it->second->database()->fileName() == fileName)
345 return it->second.get();
350 Database* InspectorDatabaseAgent::databaseForId(int databaseId)
352 DatabaseResourcesMap::iterator it = m_resources.find(databaseId);
353 if (it == m_resources.end())
355 return it->second->database();
358 } // namespace WebCore
360 #endif // ENABLE(INSPECTOR) && ENABLE(DATABASE)