Home | History | Annotate | Download | only in webdatabase
      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