void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota)
{
    LockHolder lockDatabase(m_databaseGuard);

    if (quotaForOriginNoLock(origin) == quota)
        return;

    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return;
    
#if PLATFORM(IOS)
    bool insertedNewOrigin = false;
#endif

    bool originEntryExists = hasEntryForOriginNoLock(origin);
    if (!originEntryExists) {
        SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
        if (statement.prepare() != SQLITE_OK) {
            LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data());
        } else {
            statement.bindText(1, origin->databaseIdentifier());
            statement.bindInt64(2, quota);

            if (statement.step() != SQLITE_DONE)
                LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data());
#if PLATFORM(IOS)
            else
                insertedNewOrigin = true;
#endif
        }
    } else {
        SQLiteStatement statement(m_database, "UPDATE Origins SET quota=? WHERE origin=?");
        bool error = statement.prepare() != SQLITE_OK;
        if (!error) {
            statement.bindInt64(1, quota);
            statement.bindText(2, origin->databaseIdentifier());

            error = !statement.executeCommand();
        }

        if (error)
            LOG_ERROR("Failed to set quota %llu in tracker database for origin %s", quota, origin->databaseIdentifier().ascii().data());
    }

    if (m_client) {
#if PLATFORM(IOS)
        if (insertedNewOrigin)
            m_client->dispatchDidAddNewOrigin(origin);
#endif
        m_client->dispatchDidModifyOrigin(origin);
    }
}
bool DatabaseTracker::hasAdequateQuotaForOrigin(SecurityOrigin* origin, unsigned long estimatedSize, DatabaseError& err)
{
    ASSERT(!m_databaseGuard.tryLock());
    unsigned long long usage = usageForOrigin(origin);

    // If the database will fit, allow its creation.
    unsigned long long requirement = usage + std::max<unsigned long long>(1, estimatedSize);
    if (requirement < usage) {
        // The estimated size is so big it causes an overflow; don't allow creation.
        err = DatabaseError::DatabaseSizeOverflowed;
        return false;
    }
    if (requirement <= quotaForOriginNoLock(origin))
        return true;

    err = DatabaseError::DatabaseSizeExceededQuota;
    return false;
}
Example #3
0
void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota)
{
    MutexLocker lockDatabase(m_databaseGuard);

    if (quotaForOriginNoLock(origin) == quota)
        return;

    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return;

    bool originEntryExists = hasEntryForOriginNoLock(origin);
    if (!originEntryExists) {
        SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
        if (statement.prepare() != SQLResultOk) {
            LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data());
        } else {
            statement.bindText(1, origin->databaseIdentifier());
            statement.bindInt64(2, quota);

            if (statement.step() != SQLResultDone)
                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=?");
        bool error = statement.prepare() != SQLResultOk;
        if (!error) {
            statement.bindInt64(1, quota);
            statement.bindText(2, origin->databaseIdentifier());

            error = !statement.executeCommand();
        }

        if (error)
#if OS(WINDOWS)
            LOG_ERROR("Failed to set quota %I64u in tracker database for origin %s", quota, origin->databaseIdentifier().ascii().data());
#else
            LOG_ERROR("Failed to set quota %llu in tracker database for origin %s", quota, origin->databaseIdentifier().ascii().data());
#endif
    }

    if (m_client)
        m_client->dispatchDidModifyOrigin(origin);
}
unsigned long long DatabaseTracker::getMaxSizeForDatabase(const DatabaseBackendBase* database)
{
    // 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
    MutexLocker lockDatabase(m_databaseGuard);
    SecurityOrigin* origin = database->securityOrigin();

    unsigned long long quota = quotaForOriginNoLock(origin);
    unsigned long long diskUsage = usageForOrigin(origin);
    unsigned long long databaseFileSize = SQLiteFileSystem::getDatabaseFileSize(database->fileName());
    ASSERT(databaseFileSize <= diskUsage);

    if (diskUsage > quota)
        return databaseFileSize;

    // A previous error may have allowed the origin to exceed its quota, or may
    // have allowed this database to exceed our cached estimate of the origin
    // disk usage. Don't multiply that error through integer underflow, or the
    // effective quota will permanently become 2^64.
    unsigned long long maxSize = quota - diskUsage + databaseFileSize;
    if (maxSize > quota)
        maxSize = databaseFileSize;
    return maxSize;
}
unsigned long long DatabaseTracker::quotaForOrigin(SecurityOrigin* origin)
{
    MutexLocker lockDatabase(m_databaseGuard);
    return quotaForOriginNoLock(origin);
}