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