OLD | NEW |
| (Empty) |
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 #include "core/inspector/InspectorDatabaseAgent.h" | |
31 | |
32 #include "bindings/v8/ExceptionStatePlaceholder.h" | |
33 #include "core/inspector/InspectorDatabaseResource.h" | |
34 #include "core/inspector/InspectorState.h" | |
35 #include "core/inspector/InstrumentingAgents.h" | |
36 #include "core/loader/DocumentLoader.h" | |
37 #include "core/frame/Frame.h" | |
38 #include "core/html/VoidCallback.h" | |
39 #include "core/page/Page.h" | |
40 #include "modules/webdatabase/Database.h" | |
41 #include "modules/webdatabase/SQLError.h" | |
42 #include "modules/webdatabase/SQLResultSet.h" | |
43 #include "modules/webdatabase/SQLResultSetRowList.h" | |
44 #include "modules/webdatabase/SQLStatementCallback.h" | |
45 #include "modules/webdatabase/SQLStatementErrorCallback.h" | |
46 #include "modules/webdatabase/SQLTransaction.h" | |
47 #include "modules/webdatabase/SQLTransactionCallback.h" | |
48 #include "modules/webdatabase/SQLTransactionErrorCallback.h" | |
49 #include "modules/webdatabase/sqlite/SQLValue.h" | |
50 #include "platform/JSONValues.h" | |
51 #include "wtf/Vector.h" | |
52 | |
53 typedef WebCore::InspectorBackendDispatcher::DatabaseCommandHandler::ExecuteSQLC
allback ExecuteSQLCallback; | |
54 | |
55 namespace WebCore { | |
56 | |
57 namespace DatabaseAgentState { | |
58 static const char databaseAgentEnabled[] = "databaseAgentEnabled"; | |
59 }; | |
60 | |
61 namespace { | |
62 | |
63 void reportTransactionFailed(ExecuteSQLCallback* requestCallback, SQLError* erro
r) | |
64 { | |
65 RefPtr<TypeBuilder::Database::Error> errorObject = TypeBuilder::Database::Er
ror::create() | |
66 .setMessage(error->message()) | |
67 .setCode(error->code()); | |
68 requestCallback->sendSuccess(0, 0, errorObject.release()); | |
69 } | |
70 | |
71 class StatementCallback FINAL : public SQLStatementCallback { | |
72 public: | |
73 static PassOwnPtr<StatementCallback> create(PassRefPtr<ExecuteSQLCallback> r
equestCallback) | |
74 { | |
75 return adoptPtr(new StatementCallback(requestCallback)); | |
76 } | |
77 | |
78 virtual ~StatementCallback() { } | |
79 | |
80 virtual bool handleEvent(SQLTransaction*, SQLResultSet* resultSet) OVERRIDE | |
81 { | |
82 SQLResultSetRowList* rowList = resultSet->rows(); | |
83 | |
84 RefPtr<TypeBuilder::Array<String> > columnNames = TypeBuilder::Array<Str
ing>::create(); | |
85 const Vector<String>& columns = rowList->columnNames(); | |
86 for (size_t i = 0; i < columns.size(); ++i) | |
87 columnNames->addItem(columns[i]); | |
88 | |
89 RefPtr<TypeBuilder::Array<JSONValue> > values = TypeBuilder::Array<JSONV
alue>::create(); | |
90 const Vector<SQLValue>& data = rowList->values(); | |
91 for (size_t i = 0; i < data.size(); ++i) { | |
92 const SQLValue& value = rowList->values()[i]; | |
93 switch (value.type()) { | |
94 case SQLValue::StringValue: values->addItem(JSONString::create(value
.string())); break; | |
95 case SQLValue::NumberValue: values->addItem(JSONBasicValue::create(v
alue.number())); break; | |
96 case SQLValue::NullValue: values->addItem(JSONValue::null()); break; | |
97 } | |
98 } | |
99 m_requestCallback->sendSuccess(columnNames.release(), values.release(),
0); | |
100 return true; | |
101 } | |
102 | |
103 private: | |
104 StatementCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) | |
105 : m_requestCallback(requestCallback) { } | |
106 RefPtr<ExecuteSQLCallback> m_requestCallback; | |
107 }; | |
108 | |
109 class StatementErrorCallback FINAL : public SQLStatementErrorCallback { | |
110 public: | |
111 static PassOwnPtr<StatementErrorCallback> create(PassRefPtr<ExecuteSQLCallba
ck> requestCallback) | |
112 { | |
113 return adoptPtr(new StatementErrorCallback(requestCallback)); | |
114 } | |
115 | |
116 virtual ~StatementErrorCallback() { } | |
117 | |
118 virtual bool handleEvent(SQLTransaction*, SQLError* error) OVERRIDE | |
119 { | |
120 reportTransactionFailed(m_requestCallback.get(), error); | |
121 return true; | |
122 } | |
123 | |
124 private: | |
125 StatementErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) | |
126 : m_requestCallback(requestCallback) { } | |
127 RefPtr<ExecuteSQLCallback> m_requestCallback; | |
128 }; | |
129 | |
130 class TransactionCallback FINAL : public SQLTransactionCallback { | |
131 public: | |
132 static PassOwnPtr<TransactionCallback> create(const String& sqlStatement, Pa
ssRefPtr<ExecuteSQLCallback> requestCallback) | |
133 { | |
134 return adoptPtr(new TransactionCallback(sqlStatement, requestCallback)); | |
135 } | |
136 | |
137 virtual ~TransactionCallback() { } | |
138 | |
139 virtual bool handleEvent(SQLTransaction* transaction) OVERRIDE | |
140 { | |
141 if (!m_requestCallback->isActive()) | |
142 return true; | |
143 | |
144 Vector<SQLValue> sqlValues; | |
145 OwnPtr<SQLStatementCallback> callback(StatementCallback::create(m_reques
tCallback.get())); | |
146 OwnPtr<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::
create(m_requestCallback.get())); | |
147 transaction->executeSQL(m_sqlStatement, sqlValues, callback.release(), e
rrorCallback.release(), IGNORE_EXCEPTION); | |
148 return true; | |
149 } | |
150 private: | |
151 TransactionCallback(const String& sqlStatement, PassRefPtr<ExecuteSQLCallbac
k> requestCallback) | |
152 : m_sqlStatement(sqlStatement) | |
153 , m_requestCallback(requestCallback) { } | |
154 String m_sqlStatement; | |
155 RefPtr<ExecuteSQLCallback> m_requestCallback; | |
156 }; | |
157 | |
158 class TransactionErrorCallback FINAL : public SQLTransactionErrorCallback { | |
159 public: | |
160 static PassOwnPtr<TransactionErrorCallback> create(PassRefPtr<ExecuteSQLCall
back> requestCallback) | |
161 { | |
162 return adoptPtr(new TransactionErrorCallback(requestCallback)); | |
163 } | |
164 | |
165 virtual ~TransactionErrorCallback() { } | |
166 | |
167 virtual bool handleEvent(SQLError* error) OVERRIDE | |
168 { | |
169 reportTransactionFailed(m_requestCallback.get(), error); | |
170 return true; | |
171 } | |
172 private: | |
173 TransactionErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) | |
174 : m_requestCallback(requestCallback) { } | |
175 RefPtr<ExecuteSQLCallback> m_requestCallback; | |
176 }; | |
177 | |
178 class TransactionSuccessCallback FINAL : public VoidCallback { | |
179 public: | |
180 static PassOwnPtr<TransactionSuccessCallback> create() | |
181 { | |
182 return adoptPtr(new TransactionSuccessCallback()); | |
183 } | |
184 | |
185 virtual ~TransactionSuccessCallback() { } | |
186 | |
187 virtual void handleEvent() OVERRIDE { } | |
188 | |
189 private: | |
190 TransactionSuccessCallback() { } | |
191 }; | |
192 | |
193 } // namespace | |
194 | |
195 void InspectorDatabaseAgent::didOpenDatabase(PassRefPtr<Database> database, cons
t String& domain, const String& name, const String& version) | |
196 { | |
197 if (InspectorDatabaseResource* resource = findByFileName(database->fileName(
))) { | |
198 resource->setDatabase(database); | |
199 return; | |
200 } | |
201 | |
202 RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::crea
te(database, domain, name, version); | |
203 m_resources.set(resource->id(), resource); | |
204 // Resources are only bound while visible. | |
205 if (m_frontend && m_enabled) | |
206 resource->bind(m_frontend); | |
207 } | |
208 | |
209 void InspectorDatabaseAgent::didCommitLoad(Frame* frame, DocumentLoader* loader) | |
210 { | |
211 // FIXME: If "frame" is always guarenteed to be in the same Page as loader->
frame() | |
212 // then all we need to check here is loader->frame()->isMainFrame() | |
213 // and we don't need "frame" at all. | |
214 if (loader->frame() != frame->page()->mainFrame()) | |
215 return; | |
216 | |
217 m_resources.clear(); | |
218 } | |
219 | |
220 InspectorDatabaseAgent::InspectorDatabaseAgent() | |
221 : InspectorBaseAgent<InspectorDatabaseAgent>("Database") | |
222 , m_frontend(0) | |
223 , m_enabled(false) | |
224 { | |
225 } | |
226 | |
227 void InspectorDatabaseAgent::init() | |
228 { | |
229 m_instrumentingAgents->setInspectorDatabaseAgent(this); | |
230 } | |
231 | |
232 InspectorDatabaseAgent::~InspectorDatabaseAgent() | |
233 { | |
234 m_instrumentingAgents->setInspectorDatabaseAgent(0); | |
235 } | |
236 | |
237 void InspectorDatabaseAgent::setFrontend(InspectorFrontend* frontend) | |
238 { | |
239 m_frontend = frontend->database(); | |
240 } | |
241 | |
242 void InspectorDatabaseAgent::clearFrontend() | |
243 { | |
244 m_frontend = 0; | |
245 disable(0); | |
246 } | |
247 | |
248 void InspectorDatabaseAgent::enable(ErrorString*) | |
249 { | |
250 if (m_enabled) | |
251 return; | |
252 m_enabled = true; | |
253 m_state->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled); | |
254 | |
255 DatabaseResourcesMap::iterator databasesEnd = m_resources.end(); | |
256 for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != database
sEnd; ++it) | |
257 it->value->bind(m_frontend); | |
258 } | |
259 | |
260 void InspectorDatabaseAgent::disable(ErrorString*) | |
261 { | |
262 if (!m_enabled) | |
263 return; | |
264 m_enabled = false; | |
265 m_state->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled); | |
266 } | |
267 | |
268 void InspectorDatabaseAgent::restore() | |
269 { | |
270 m_enabled = m_state->getBoolean(DatabaseAgentState::databaseAgentEnabled); | |
271 } | |
272 | |
273 void InspectorDatabaseAgent::getDatabaseTableNames(ErrorString* error, const Str
ing& databaseId, RefPtr<TypeBuilder::Array<String> >& names) | |
274 { | |
275 if (!m_enabled) { | |
276 *error = "Database agent is not enabled"; | |
277 return; | |
278 } | |
279 | |
280 names = TypeBuilder::Array<String>::create(); | |
281 | |
282 Database* database = databaseForId(databaseId); | |
283 if (database) { | |
284 Vector<String> tableNames = database->tableNames(); | |
285 unsigned length = tableNames.size(); | |
286 for (unsigned i = 0; i < length; ++i) | |
287 names->addItem(tableNames[i]); | |
288 } | |
289 } | |
290 | |
291 void InspectorDatabaseAgent::executeSQL(ErrorString*, const String& databaseId,
const String& query, PassRefPtr<ExecuteSQLCallback> prpRequestCallback) | |
292 { | |
293 RefPtr<ExecuteSQLCallback> requestCallback = prpRequestCallback; | |
294 | |
295 if (!m_enabled) { | |
296 requestCallback->sendFailure("Database agent is not enabled"); | |
297 return; | |
298 } | |
299 | |
300 Database* database = databaseForId(databaseId); | |
301 if (!database) { | |
302 requestCallback->sendFailure("Database not found"); | |
303 return; | |
304 } | |
305 | |
306 OwnPtr<SQLTransactionCallback> callback(TransactionCallback::create(query, r
equestCallback.get())); | |
307 OwnPtr<SQLTransactionErrorCallback> errorCallback(TransactionErrorCallback::
create(requestCallback.get())); | |
308 OwnPtr<VoidCallback> successCallback(TransactionSuccessCallback::create()); | |
309 database->transaction(callback.release(), errorCallback.release(), successCa
llback.release()); | |
310 } | |
311 | |
312 InspectorDatabaseResource* InspectorDatabaseAgent::findByFileName(const String&
fileName) | |
313 { | |
314 for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != m_resour
ces.end(); ++it) { | |
315 if (it->value->database()->fileName() == fileName) | |
316 return it->value.get(); | |
317 } | |
318 return 0; | |
319 } | |
320 | |
321 Database* InspectorDatabaseAgent::databaseForId(const String& databaseId) | |
322 { | |
323 DatabaseResourcesMap::iterator it = m_resources.find(databaseId); | |
324 if (it == m_resources.end()) | |
325 return 0; | |
326 return it->value->database(); | |
327 } | |
328 | |
329 } // namespace WebCore | |
OLD | NEW |