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