diff options
Diffstat (limited to 'WebCore/storage/DatabaseTracker.cpp')
| -rw-r--r-- | WebCore/storage/DatabaseTracker.cpp | 135 |
1 files changed, 79 insertions, 56 deletions
diff --git a/WebCore/storage/DatabaseTracker.cpp b/WebCore/storage/DatabaseTracker.cpp index e7c9485..76492c9 100644 --- a/WebCore/storage/DatabaseTracker.cpp +++ b/WebCore/storage/DatabaseTracker.cpp @@ -31,13 +31,15 @@ #if ENABLE(DATABASE) +#include "Chrome.h" #include "ChromeClient.h" #include "Database.h" +#include "DatabaseThread.h" #include "DatabaseTrackerClient.h" -#include "Document.h" #include "Logging.h" #include "OriginQuotaManager.h" #include "Page.h" +#include "ScriptExecutionContext.h" #include "SecurityOrigin.h" #include "SecurityOriginHash.h" #include "SQLiteFileSystem.h" @@ -118,7 +120,7 @@ void DatabaseTracker::openTrackerDatabase(bool createIfDoesNotExist) } } -bool DatabaseTracker::canEstablishDatabase(Document* document, const String& name, const String& displayName, unsigned long estimatedSize) +bool DatabaseTracker::canEstablishDatabase(ScriptExecutionContext* context, const String& name, const String& displayName, unsigned long estimatedSize) { ASSERT(currentThread() == m_thread); @@ -126,12 +128,12 @@ bool DatabaseTracker::canEstablishDatabase(Document* document, const String& nam // can run on the database thread later. populateOrigins(); - SecurityOrigin* origin = document->securityOrigin(); + SecurityOrigin* origin = context->securityOrigin(); - // Since we're imminently opening a database within this Document's origin, make sure this origin is being tracked by the QuotaTracker + // Since we're imminently opening a database within this context's origin, make sure this origin is being tracked by the QuotaTracker // by fetching it's current usage now unsigned long long usage = usageForOrigin(origin); - + // If a database already exists, ignore the passed-in estimated size and say it's OK. if (hasEntryForDatabase(origin, name)) return true; @@ -145,12 +147,9 @@ bool DatabaseTracker::canEstablishDatabase(Document* document, const String& nam // Give the chrome client a chance to increase the quota. // Temporarily make the details of the proposed database available, so the client can get at them. - Page* page = document->page(); - if (!page) - return false; pair<SecurityOrigin*, DatabaseDetails> details(origin, DatabaseDetails(name, displayName, estimatedSize, 0)); m_proposedDatabase = &details; - page->chrome()->client()->exceededDatabaseQuota(document->frame(), name); + context->databaseExceededQuota(name); m_proposedDatabase = 0; // If the database will fit now, allow its creation. @@ -182,6 +181,16 @@ bool DatabaseTracker::hasEntryForDatabase(SecurityOrigin* origin, const String& return statement.step() == SQLResultRow; } +unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database) +{ + ASSERT(currentThread() == database->scriptExecutionContext()->databaseThread()->getThreadID()); + // The maximum size for a database is the full quota for its origin, minus the current usage within the origin, + // plus the current usage of the given database + Locker<OriginQuotaManager> locker(originQuotaManager()); + SecurityOrigin* origin = database->securityOrigin(); + return quotaForOrigin(origin) - originQuotaManager().diskUsage(origin) + SQLiteFileSystem::getDatabaseFileSize(database->fileName()); +} + String DatabaseTracker::originPath(SecurityOrigin* origin) const { ASSERT(currentThread() == m_thread); @@ -197,11 +206,11 @@ String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String String originIdentifier = origin->databaseIdentifier(); String originPath = this->originPath(origin); - + // Make sure the path for this SecurityOrigin exists if (createIfNotExists && !SQLiteFileSystem::ensureDatabaseDirectoryExists(originPath)) return String(); - + // See if we have a path for this database yet openTrackerDatabase(false); if (!m_database.isOpen()) @@ -220,14 +229,14 @@ String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String return SQLiteFileSystem::appendDatabaseFileNameToPath(originPath, statement.getColumnText(0)); if (!createIfNotExists) return String(); - + if (result != SQLResultDone) { LOG_ERROR("Failed to retrieve filename from Database Tracker for origin %s, name %s", origin->databaseIdentifier().ascii().data(), name.ascii().data()); return String(); } statement.finalize(); - - String fileName = SQLiteFileSystem::getFileNameForNewDatabase(originPath, origin->databaseIdentifier(), name, &m_database); + + String fileName = SQLiteFileSystem::getFileNameForNewDatabase(originPath, name, origin->databaseIdentifier(), &m_database); if (!addDatabase(origin, name, fileName)) return String(); @@ -239,7 +248,7 @@ String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String if (originQuotaManager().tracksOrigin(origin)) originQuotaManager().addDatabase(origin, name, fullFilePath); } - + return fullFilePath; } @@ -321,19 +330,19 @@ DatabaseDetails DatabaseTracker::detailsForNameAndOrigin(const String& name, Sec SQLiteStatement statement(m_database, "SELECT displayName, estimatedSize FROM Databases WHERE origin=? AND name=?"); if (statement.prepare() != SQLResultOk) return DatabaseDetails(); - + statement.bindText(1, originIdentifier); statement.bindText(2, name); - + int result = statement.step(); if (result == SQLResultDone) return DatabaseDetails(); - + if (result != SQLResultRow) { LOG_ERROR("Error retrieving details for database %s in origin %s from tracker database", name.ascii().data(), originIdentifier.ascii().data()); return DatabaseDetails(); } - + return DatabaseDetails(name, statement.getColumnText(0), statement.getColumnInt64(1), usageForDatabase(name, origin)); } @@ -343,17 +352,17 @@ void DatabaseTracker::setDatabaseDetails(SecurityOrigin* origin, const String& n String originIdentifier = origin->databaseIdentifier(); int64_t guid = 0; - + openTrackerDatabase(true); if (!m_database.isOpen()) return; SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?"); if (statement.prepare() != SQLResultOk) return; - + statement.bindText(1, originIdentifier); statement.bindText(2, name); - + int result = statement.step(); if (result == SQLResultRow) guid = statement.getColumnInt64(0); @@ -371,20 +380,20 @@ void DatabaseTracker::setDatabaseDetails(SecurityOrigin* origin, const String& n } return; } - + SQLiteStatement updateStatement(m_database, "UPDATE Databases SET displayName=?, estimatedSize=? WHERE guid=?"); if (updateStatement.prepare() != SQLResultOk) return; - + updateStatement.bindText(1, displayName); updateStatement.bindInt64(2, estimatedSize); updateStatement.bindInt64(3, guid); - + if (updateStatement.step() != SQLResultDone) { LOG_ERROR("Failed to update details for database %s in origin %s", name.ascii().data(), originIdentifier.ascii().data()); - return; + return; } - + if (m_client) m_client->dispatchDidModifyDatabase(origin, name); } @@ -395,7 +404,7 @@ unsigned long long DatabaseTracker::usageForDatabase(const String& name, Securit String path = fullPathForDatabase(origin, name, false); if (path.isEmpty()) return 0; - + return SQLiteFileSystem::getDatabaseFileSize(path); } @@ -409,13 +418,11 @@ void DatabaseTracker::addOpenDatabase(Database* database) if (!m_openDatabaseMap) m_openDatabaseMap.set(new DatabaseOriginMap); - RefPtr<SecurityOrigin> origin(database->securityOriginCopy()); String name(database->stringIdentifier()); - - DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); + DatabaseNameMap* nameMap = m_openDatabaseMap->get(database->securityOrigin()); if (!nameMap) { nameMap = new DatabaseNameMap; - m_openDatabaseMap->set(origin, nameMap); + m_openDatabaseMap->set(database->securityOrigin(), nameMap); } DatabaseSet* databaseSet = nameMap->get(name); @@ -441,10 +448,8 @@ void DatabaseTracker::removeOpenDatabase(Database* database) return; } - RefPtr<SecurityOrigin> origin(database->securityOriginCopy()); String name(database->stringIdentifier()); - - DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); + DatabaseNameMap* nameMap = m_openDatabaseMap->get(database->securityOrigin()); if (!nameMap) { ASSERT_NOT_REACHED(); return; @@ -469,10 +474,28 @@ void DatabaseTracker::removeOpenDatabase(Database* database) if (!nameMap->isEmpty()) return; - m_openDatabaseMap->remove(origin); + m_openDatabaseMap->remove(database->securityOrigin()); delete nameMap; } +void DatabaseTracker::getOpenDatabases(SecurityOrigin* origin, const String& name, HashSet<RefPtr<Database> >* databases) +{ + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); + if (!m_openDatabaseMap) + return; + + DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); + if (!nameMap) + return; + + DatabaseSet* databaseSet = nameMap->get(name); + if (!databaseSet) + return; + + for (DatabaseSet::iterator it = databaseSet->begin(); it != databaseSet->end(); ++it) + databases->add(*it); +} + unsigned long long DatabaseTracker::usageForOrigin(SecurityOrigin* origin) { ASSERT(currentThread() == m_thread); @@ -481,16 +504,16 @@ unsigned long long DatabaseTracker::usageForOrigin(SecurityOrigin* origin) // Use the OriginQuotaManager mechanism to calculate the usage if (originQuotaManager().tracksOrigin(origin)) return originQuotaManager().diskUsage(origin); - + // If the OriginQuotaManager doesn't track this origin already, prime it to do so originQuotaManager().trackOrigin(origin); - + Vector<String> names; databaseNamesForOrigin(origin, names); for (unsigned i = 0; i < names.size(); ++i) originQuotaManager().addDatabase(origin, names[i], fullPathForDatabase(origin, names[i], false)); - + if (!originQuotaManager().tracksOrigin(origin)) return 0; return originQuotaManager().diskUsage(origin); @@ -529,7 +552,7 @@ void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota) LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data()); } } else { - SQLiteStatement statement(m_database, "UPDATE Origins SET quota=? WHERE origin=?"); + SQLiteStatement statement(m_database, "UPDATE Origins SET quota=? WHERE origin=?"); bool error = statement.prepare() != SQLResultOk; if (!error) { statement.bindInt64(1, quota); @@ -556,7 +579,7 @@ bool DatabaseTracker::addDatabase(SecurityOrigin* origin, const String& name, co openTrackerDatabase(true); if (!m_database.isOpen()) return false; - + // New database should never be added until the origin has been established ASSERT(hasEntryForOrigin(origin)); @@ -573,10 +596,10 @@ bool DatabaseTracker::addDatabase(SecurityOrigin* origin, const String& name, co LOG_ERROR("Failed to add database %s to origin %s: %s\n", name.ascii().data(), origin->databaseIdentifier().ascii().data(), m_database.lastErrorMsg()); return false; } - + if (m_client) m_client->dispatchDidModifyOrigin(origin); - + return true; } @@ -603,27 +626,27 @@ void DatabaseTracker::deleteOrigin(SecurityOrigin* origin) LOG_ERROR("Unable to retrieve list of database names for origin %s", origin->databaseIdentifier().ascii().data()); return; } - + for (unsigned i = 0; i < databaseNames.size(); ++i) { if (!deleteDatabaseFile(origin, databaseNames[i])) { + // Even if the file can't be deleted, we want to try and delete the rest, don't return early here. LOG_ERROR("Unable to delete file for database %s in origin %s", databaseNames[i].ascii().data(), origin->databaseIdentifier().ascii().data()); - return; } } - + SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=?"); if (statement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data()); return; } - + statement.bindText(1, origin->databaseIdentifier()); - + if (!statement.executeCommand()) { LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data()); return; } - + SQLiteStatement originStatement(m_database, "DELETE FROM Origins WHERE origin=?"); if (originStatement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of origin %s from tracker", origin->databaseIdentifier().ascii().data()); @@ -631,7 +654,7 @@ void DatabaseTracker::deleteOrigin(SecurityOrigin* origin) } originStatement.bindText(1, origin->databaseIdentifier()); - + if (!originStatement.executeCommand()) { LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data()); return; @@ -674,26 +697,26 @@ void DatabaseTracker::deleteDatabase(SecurityOrigin* origin, const String& name) LOG_ERROR("Unable to delete file for database %s in origin %s", name.ascii().data(), origin->databaseIdentifier().ascii().data()); return; } - + SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=? AND name=?"); if (statement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data()); return; } - + statement.bindText(1, origin->databaseIdentifier()); statement.bindText(2, name); - + if (!statement.executeCommand()) { LOG_ERROR("Unable to execute deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data()); return; } - + { Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager()); originQuotaManager().removeDatabase(origin, name); } - + if (m_client) { m_client->dispatchDidModifyOrigin(origin); m_client->dispatchDidModifyDatabase(origin, name); @@ -762,7 +785,7 @@ void DatabaseTracker::scheduleNotifyDatabaseChanged(SecurityOrigin* origin, cons { MutexLocker locker(notificationMutex()); - notificationQueue().append(pair<SecurityOrigin*, String>(origin, name.copy())); + notificationQueue().append(pair<SecurityOrigin*, String>(origin, name.crossThreadString())); scheduleForNotification(); } |
