Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (C) 2009 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "DatabaseTracker.h"
     33 
     34 #include "CString.h"
     35 #include "Database.h"
     36 #include "DatabaseObserver.h"
     37 #include "DatabaseThread.h"
     38 #include "QuotaTracker.h"
     39 #include "ScriptExecutionContext.h"
     40 #include "SecurityOrigin.h"
     41 #include "SecurityOriginHash.h"
     42 #include "SQLiteFileSystem.h"
     43 #include <wtf/HashSet.h>
     44 #include <wtf/MainThread.h>
     45 #include <wtf/StdLibExtras.h>
     46 
     47 namespace WebCore {
     48 
     49 DatabaseTracker& DatabaseTracker::tracker()
     50 {
     51     DEFINE_STATIC_LOCAL(DatabaseTracker, tracker, ());
     52     return tracker;
     53 }
     54 
     55 DatabaseTracker::DatabaseTracker()
     56 {
     57     SQLiteFileSystem::registerSQLiteVFS();
     58 }
     59 
     60 bool DatabaseTracker::canEstablishDatabase(ScriptExecutionContext*, const String&, const String&, unsigned long)
     61 {
     62     // In Chromium, a database can always be established (even though we might not
     63     // be able to write anything to it if the quota for this origin was exceeded)
     64     return true;
     65 }
     66 
     67 void DatabaseTracker::setDatabaseDetails(SecurityOrigin*, const String&, const String&, unsigned long)
     68 {
     69     // Chromium sets the database details when the database is opened
     70 }
     71 
     72 String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String& name, bool)
     73 {
     74     return origin->databaseIdentifier() + "/" + name + "#";
     75 }
     76 
     77 void DatabaseTracker::addOpenDatabase(Database* database)
     78 {
     79     ASSERT(database->scriptExecutionContext()->isContextThread());
     80     MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
     81     if (!m_openDatabaseMap)
     82         m_openDatabaseMap.set(new DatabaseOriginMap());
     83 
     84     DatabaseNameMap* nameMap = m_openDatabaseMap->get(database->securityOrigin());
     85     if (!nameMap) {
     86         nameMap = new DatabaseNameMap();
     87         m_openDatabaseMap->set(database->securityOrigin(), nameMap);
     88     }
     89 
     90     String name(database->stringIdentifier());
     91     DatabaseSet* databaseSet = nameMap->get(name);
     92     if (!databaseSet) {
     93         databaseSet = new DatabaseSet();
     94         nameMap->set(name, databaseSet);
     95     }
     96 
     97     databaseSet->add(database);
     98 
     99     DatabaseObserver::databaseOpened(database);
    100 }
    101 
    102 class TrackerRemoveOpenDatabaseTask : public ScriptExecutionContext::Task {
    103 public:
    104     static PassOwnPtr<TrackerRemoveOpenDatabaseTask> create(PassRefPtr<Database> database)
    105     {
    106         return new TrackerRemoveOpenDatabaseTask(database);
    107     }
    108 
    109     virtual void performTask(ScriptExecutionContext* context)
    110     {
    111         DatabaseTracker::tracker().removeOpenDatabase(m_database.get());
    112     }
    113 
    114 private:
    115     TrackerRemoveOpenDatabaseTask(PassRefPtr<Database> database)
    116         : m_database(database)
    117     {
    118     }
    119 
    120     RefPtr<Database> m_database;
    121 };
    122 
    123 void DatabaseTracker::removeOpenDatabase(Database* database)
    124 {
    125     if (!database->scriptExecutionContext()->isContextThread()) {
    126         database->scriptExecutionContext()->postTask(TrackerRemoveOpenDatabaseTask::create(database));
    127         return;
    128     }
    129 
    130     MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
    131     ASSERT(m_openDatabaseMap);
    132     DatabaseNameMap* nameMap = m_openDatabaseMap->get(database->securityOrigin());
    133     ASSERT(nameMap);
    134     String name(database->stringIdentifier());
    135     DatabaseSet* databaseSet = nameMap->get(name);
    136     ASSERT(databaseSet);
    137     databaseSet->remove(database);
    138 
    139     if (databaseSet->isEmpty()) {
    140         nameMap->remove(name);
    141         delete databaseSet;
    142         if (nameMap->isEmpty()) {
    143             m_openDatabaseMap->remove(database->securityOrigin());
    144             delete nameMap;
    145         }
    146     }
    147 
    148     DatabaseObserver::databaseClosed(database);
    149 }
    150 
    151 
    152 void DatabaseTracker::getOpenDatabases(SecurityOrigin* origin, const String& name, HashSet<RefPtr<Database> >* databases)
    153 {
    154     MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
    155     if (!m_openDatabaseMap)
    156         return;
    157 
    158     DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin);
    159     if (!nameMap)
    160         return;
    161 
    162     DatabaseSet* databaseSet = nameMap->get(name);
    163     if (!databaseSet)
    164         return;
    165 
    166     for (DatabaseSet::iterator it = databaseSet->begin(); it != databaseSet->end(); ++it)
    167         databases->add(*it);
    168 }
    169 
    170 unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database)
    171 {
    172     ASSERT(currentThread() == database->scriptExecutionContext()->databaseThread()->getThreadID());
    173     unsigned long long spaceAvailable = 0;
    174     unsigned long long databaseSize = 0;
    175     QuotaTracker::instance().getDatabaseSizeAndSpaceAvailableToOrigin(
    176         database->securityOrigin()->databaseIdentifier(),
    177         database->stringIdentifier(), &databaseSize, &spaceAvailable);
    178     return databaseSize + spaceAvailable;
    179 }
    180 
    181 }
    182