summaryrefslogtreecommitdiffstats
path: root/WebCore/storage/DatabaseTracker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/storage/DatabaseTracker.cpp')
-rw-r--r--WebCore/storage/DatabaseTracker.cpp135
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();
}