Ejemplo n.º 1
0
void StorageTracker::syncDeleteAllOrigins()
{
    ASSERT(!isMainThread());
    
    MutexLocker locker(m_databaseMutex);
    
    openTrackerDatabase(false);
    if (!m_database.isOpen())
        return;
    
    SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins");
    if (statement.prepare() != SQLResultOk) {
        LOG_ERROR("Failed to prepare statement.");
        return;
    }
    
    int result;
    while ((result = statement.step()) == SQLResultRow) {
        if (!canDeleteOrigin(statement.getColumnText(0)))
            continue;

        SQLiteFileSystem::deleteDatabaseFile(statement.getColumnText(1));

        {
            MutexLocker locker(m_clientMutex);
            if (m_client)
                m_client->dispatchDidModifyOrigin(statement.getColumnText(0));
        }
    }
    
    if (result != SQLResultDone)
        LOG_ERROR("Failed to read in all origins from the database.");
    
    if (m_database.isOpen())
        m_database.close();
    
    if (!SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath())) {
        // In the case where it is not possible to delete the database file (e.g some other program
        // like a virus scanner is accessing it), make sure to remove all entries.
        openTrackerDatabase(false);
        if (!m_database.isOpen())
            return;
        SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins");
        if (deleteStatement.prepare() != SQLResultOk) {
            LOG_ERROR("Unable to prepare deletion of all origins");
            return;
        }
        if (!deleteStatement.executeCommand()) {
            LOG_ERROR("Unable to execute deletion of all origins");
            return;
        }
    }
    SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath);
}
Ejemplo n.º 2
0
bool DatabaseTracker::databaseNamesForOriginNoLock(SecurityOrigin* origin, Vector<String>& resultVector)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return false;

    SQLiteStatement statement(m_database, "SELECT name FROM Databases where origin=?;");

    if (statement.prepare() != SQLResultOk)
        return false;

    statement.bindText(1, origin->databaseIdentifier());

    int result;
    while ((result = statement.step()) == SQLResultRow)
        resultVector.append(statement.getColumnText(0));

    if (result != SQLResultDone) {
        LOG_ERROR("Failed to retrieve all database names for origin %s", origin->databaseIdentifier().ascii().data());
        return false;
    }

    return true;
}
Ejemplo n.º 3
0
DatabaseDetails DatabaseTracker::detailsForNameAndOrigin(const String& name, SecurityOrigin* origin)
{
    String originIdentifier = origin->databaseIdentifier();
    String displayName;
    int64_t expectedUsage;

    {
        MutexLocker lockDatabase(m_databaseGuard);

        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return DatabaseDetails();
        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();
        }
        displayName = statement.getColumnText(0);
        expectedUsage = statement.getColumnInt64(1);
    }

    return DatabaseDetails(name, displayName, expectedUsage, usageForDatabase(name, origin));
}
Ejemplo n.º 4
0
void StorageTracker::syncSetOriginDetails(const String& originIdentifier, const String& databaseFile)
{
    ASSERT(!isMainThread());

    MutexLocker locker(m_databaseMutex);

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

    SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
    if (statement.prepare() != SQLResultOk) {
        LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data());
        return;
    } 
    
    statement.bindText(1, originIdentifier);
    statement.bindText(2, databaseFile);
    
    if (statement.step() != SQLResultDone)
        LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data());

    {
        MutexLocker locker(m_originSetMutex);
        if (!m_originSet.contains(originIdentifier))
            m_originSet.add(originIdentifier);
    }

    {
        MutexLocker locker(m_clientMutex);
        if (m_client)
            m_client->dispatchDidModifyOrigin(originIdentifier);
    }
}
Ejemplo n.º 5
0
bool DatabaseTracker::addDatabase(SecurityOrigin* origin, const String& name, const String& path)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return false;

    // New database should never be added until the origin has been established
    ASSERT(hasEntryForOriginNoLock(origin));

    SQLiteStatement statement(m_database, "INSERT INTO Databases (origin, name, path) VALUES (?, ?, ?);");

    if (statement.prepare() != SQLResultOk)
        return false;

    statement.bindText(1, origin->databaseIdentifier());
    statement.bindText(2, name);
    statement.bindText(3, path);

    if (!statement.executeCommand()) {
        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;
}
void LocalStorageDatabaseTracker::removeDatabaseWithOriginIdentifier(const String& originIdentifier)
{
    openTrackerDatabase(SkipIfNonExistent);
    if (!m_database.isOpen())
        return;

    String path = pathForDatabaseWithOriginIdentifier(originIdentifier);
    if (path.isEmpty())
        return;

    SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?");
    if (deleteStatement.prepare() != SQLITE_OK) {
        LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data());
        return;
    }
    deleteStatement.bindText(1, originIdentifier);
    if (!deleteStatement.executeCommand()) {
        LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data());
        return;
    }

    SQLiteFileSystem::deleteDatabaseFile(path);

    m_origins.remove(originIdentifier);
    if (m_origins.isEmpty()) {
        // There are no origins left; delete the tracker database.
        m_database.close();
        SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
        deleteEmptyDirectory(m_localStorageDirectory);
    }

    // FIXME: Tell clients that the origin was removed.
}
void LocalStorageDatabaseTracker::deleteAllDatabases()
{
    m_origins.clear();

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

    SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Failed to prepare statement.");
        return;
    }

    int result;
    while ((result = statement.step()) == SQLITE_ROW) {
        deleteFile(statement.getColumnText(1));

        // FIXME: Call out to the client.
    }

    if (result != SQLITE_DONE)
        LOG_ERROR("Failed to read in all origins from the database.");

    if (m_database.isOpen())
        m_database.close();

    if (!deleteFile(trackerDatabasePath())) {
        // In the case where it is not possible to delete the database file (e.g some other program
        // like a virus scanner is accessing it), make sure to remove all entries.
        openTrackerDatabase(SkipIfNonExistent);
        if (!m_database.isOpen())
            return;

        SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins");
        if (deleteStatement.prepare() != SQLITE_OK) {
            LOG_ERROR("Unable to prepare deletion of all origins");
            return;
        }
        if (!deleteStatement.executeCommand()) {
            LOG_ERROR("Unable to execute deletion of all origins");
            return;
        }
    }

    deleteEmptyDirectory(m_localStorageDirectory);
}
Ejemplo n.º 8
0
void StorageTracker::syncImportOriginIdentifiers()
{
    ASSERT(m_isActive);
    
    ASSERT(!isMainThread());

    {
        MutexLocker locker(m_databaseMutex);

        // Don't force creation of StorageTracker's db just because a tracker
        // was initialized. It will be created if local storage dbs are found
        // by syncFileSystemAndTrackerDatabse() or the next time a local storage
        // db is created by StorageAreaSync.
        openTrackerDatabase(false);

        if (m_database.isOpen()) {
            SQLiteTransactionInProgressAutoCounter transactionCounter;

            SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
            if (statement.prepare() != SQLResultOk) {
                LOG_ERROR("Failed to prepare statement.");
                return;
            }
            
            int result;
            
            {
                MutexLocker lockOrigins(m_originSetMutex);
                while ((result = statement.step()) == SQLResultRow)
                    m_originSet.add(statement.getColumnText(0).isolatedCopy());
            }
            
            if (result != SQLResultDone) {
                LOG_ERROR("Failed to read in all origins from the database.");
                return;
            }
        }
    }
    
    syncFileSystemAndTrackerDatabase();
    
    {
        MutexLocker locker(m_clientMutex);

        if (m_client) {
            MutexLocker locker(m_originSetMutex);
            OriginSet::const_iterator end = m_originSet.end();
            for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
                m_client->dispatchDidModifyOrigin(*it);
        }
    }

    callOnMainThread([this] {
        finishedImportingOriginIdentifiers();
    });
}
Ejemplo n.º 9
0
void StorageTracker::syncDeleteOrigin(const String& originIdentifier)
{
    ASSERT(!isMainThread());

    MutexLocker locker(m_databaseMutex);
    
    if (!canDeleteOrigin(originIdentifier)) {
        LOG_ERROR("Attempted to delete origin '%s' while it was being created\n", originIdentifier.ascii().data());
        return;
    }
    
    openTrackerDatabase(false);
    if (!m_database.isOpen())
        return;

    String path = databasePathForOrigin(originIdentifier);
    if (path.isEmpty()) {
        // It is possible to get a request from the API to delete the storage for an origin that
        // has no such storage.
        return;
    }
    
    SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?");
    if (deleteStatement.prepare() != SQLResultOk) {
        LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data());
        return;
    }
    deleteStatement.bindText(1, originIdentifier);
    if (!deleteStatement.executeCommand()) {
        LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data());
        return;
    }

    SQLiteFileSystem::deleteDatabaseFile(path);
    
    bool shouldDeleteTrackerFiles = false;
    {
        MutexLocker locker(m_originSetMutex);
        m_originSet.remove(originIdentifier);
        shouldDeleteTrackerFiles = m_originSet.isEmpty();
    }

    if (shouldDeleteTrackerFiles) {
        m_database.close();
        SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
        SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath);
    }

    {
        MutexLocker locker(m_clientMutex);
        if (m_client)
            m_client->dispatchDidModifyOrigin(originIdentifier);
    }
}
Ejemplo n.º 10
0
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);
    }
}
Ejemplo n.º 11
0
bool DatabaseTracker::deleteDatabase(SecurityOrigin* origin, const String& name)
{
    {
        LockHolder lockDatabase(m_databaseGuard);
        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return false;

        if (!canDeleteDatabase(origin, name)) {
            ASSERT_NOT_REACHED();
            return false;
        }
        recordDeletingDatabase(origin, name);
    }

    // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock.
    if (!deleteDatabaseFile(origin, name, DeletionMode::Default)) {
        LOG_ERROR("Unable to delete file for database %s in origin %s", name.ascii().data(), origin->databaseIdentifier().ascii().data());
        LockHolder lockDatabase(m_databaseGuard);
        doneDeletingDatabase(origin, name);
        return false;
    }

    LockHolder lockDatabase(m_databaseGuard);

    SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=? AND name=?");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Unable to prepare deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data());
        doneDeletingDatabase(origin, name);
        return false;
    }

    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());
        doneDeletingDatabase(origin, name);
        return false;
    }

    if (m_client) {
        m_client->dispatchDidModifyOrigin(origin);
        m_client->dispatchDidModifyDatabase(origin, name);
#if PLATFORM(IOS)
        m_client->dispatchDidDeleteDatabase();
#endif
    }
    doneDeletingDatabase(origin, name);
    
    return true;
}
Ejemplo n.º 12
0
void DatabaseTracker::setDatabaseDetails(SecurityOrigin* origin, const String& name, const String& displayName, unsigned long estimatedSize)
{
    String originIdentifier = origin->databaseIdentifier();
    int64_t guid = 0;

    MutexLocker lockDatabase(m_databaseGuard);

    openTrackerDatabase(CreateIfDoesNotExist);
    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);
    statement.finalize();

    if (guid == 0) {
        if (result != SQLResultDone)
            LOG_ERROR("Error to determing existence of database %s in origin %s in tracker database", name.ascii().data(), originIdentifier.ascii().data());
        else {
            // This case should never occur - we should never be setting database details for a database that doesn't already exist in the tracker
            // But since the tracker file is an external resource not under complete control of our code, it's somewhat invalid to make this an ASSERT case
            // So we'll print an error instead
            LOG_ERROR("Could not retrieve guid for database %s in origin %s from the tracker database - it is invalid to set database details on a database that doesn't already exist in the tracker",
                       name.ascii().data(), originIdentifier.ascii().data());
        }
        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;
    }

    if (m_client)
        m_client->dispatchDidModifyDatabase(origin, name);
}
Ejemplo n.º 13
0
bool DatabaseTracker::hasEntryForOriginNoLock(SecurityOrigin* origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return false;

    SQLiteStatement statement(m_database, "SELECT origin FROM Origins where origin=?;");
    if (statement.prepare() != SQLResultOk) {
        LOG_ERROR("Failed to prepare statement.");
        return false;
    }

    statement.bindText(1, origin->databaseIdentifier());

    return statement.step() == SQLResultRow;
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
bool DatabaseTracker::hasEntryForDatabase(SecurityOrigin* origin, const String& databaseIdentifier)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen()) {
        // No "tracker database". Hence, no entry for the database of interest.
        return false;
    }

    // We've got a tracker database. Set up a query to ask for the db of interest:
    SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?;");

    if (statement.prepare() != SQLResultOk)
        return false;

    statement.bindText(1, origin->databaseIdentifier());
    statement.bindText(2, databaseIdentifier);

    return statement.step() == SQLResultRow;
}
Ejemplo n.º 16
0
unsigned long long DatabaseTracker::quotaForOriginNoLock(SecurityOrigin* origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    unsigned long long quota = 0;

    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return quota;

    SQLiteStatement statement(m_database, "SELECT quota FROM Origins where origin=?;");
    if (statement.prepare() != SQLResultOk) {
        LOG_ERROR("Failed to prepare statement.");
        return quota;
    }
    statement.bindText(1, origin->databaseIdentifier());

    if (statement.step() == SQLResultRow)
        quota = statement.getColumnInt64(0);

    return quota;
}
Ejemplo n.º 17
0
void LocalStorageDatabaseTracker::addDatabaseWithOriginIdentifier(const String& originIdentifier, const String& databasePath)
{
    openTrackerDatabase(CreateIfNonExistent);
    if (!m_database.isOpen())
        return;

    SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.utf8().data());
        return;
    }

    statement.bindText(1, originIdentifier);
    statement.bindText(2, databasePath);

    if (statement.step() != SQLITE_DONE)
        LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.utf8().data());

    m_origins.add(originIdentifier);

    // FIXME: Tell clients that the origin was added.
}
Ejemplo n.º 18
0
DatabaseDetails DatabaseTracker::detailsForNameAndOrigin(const String& name, SecurityOrigin* origin)
{
    String originIdentifier = origin->databaseIdentifier();
    String displayName;
    int64_t expectedUsage;

    {
        LockHolder lockDatabase(m_databaseGuard);

        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return DatabaseDetails();
        SQLiteStatement statement(m_database, "SELECT displayName, estimatedSize FROM Databases WHERE origin=? AND name=?");
        if (statement.prepare() != SQLITE_OK)
            return DatabaseDetails();

        statement.bindText(1, originIdentifier);
        statement.bindText(2, name);

        int result = statement.step();
        if (result == SQLITE_DONE)
            return DatabaseDetails();

        if (result != SQLITE_ROW) {
            LOG_ERROR("Error retrieving details for database %s in origin %s from tracker database", name.ascii().data(), originIdentifier.ascii().data());
            return DatabaseDetails();
        }
        displayName = statement.getColumnText(0);
        expectedUsage = statement.getColumnInt64(1);
    }

    String path = fullPathForDatabase(origin, name, false);
    if (path.isEmpty())
        return DatabaseDetails(name, displayName, expectedUsage, 0, 0, 0);
    return DatabaseDetails(name, displayName, expectedUsage, SQLiteFileSystem::getDatabaseFileSize(path), SQLiteFileSystem::databaseCreationTime(path), SQLiteFileSystem::databaseModificationTime(path));
}
Ejemplo n.º 19
0
void LocalStorageDatabaseTracker::importOriginIdentifiers()
{
    openTrackerDatabase(SkipIfNonExistent);

    if (m_database.isOpen()) {
        SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
        if (statement.prepare() != SQLITE_OK) {
            LOG_ERROR("Failed to prepare statement.");
            return;
        }

        int result;

        while ((result = statement.step()) == SQLITE_ROW)
            m_origins.add(statement.getColumnText(0));

        if (result != SQLITE_DONE) {
            LOG_ERROR("Failed to read in all origins from the database.");
            return;
        }
    }

    updateTrackerDatabaseFromLocalStorageDatabaseFiles();
}
Ejemplo n.º 20
0
void DatabaseTracker::origins(Vector<RefPtr<SecurityOrigin>>& originsResult)
{
    MutexLocker lockDatabase(m_databaseGuard);

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

    SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
    if (statement.prepare() != SQLResultOk) {
        LOG_ERROR("Failed to prepare statement.");
        return;
    }

    int result;
    while ((result = statement.step()) == SQLResultRow) {
        RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromDatabaseIdentifier(statement.getColumnText(0));
        originsResult.append(origin->isolatedCopy());
    }
    originsResult.shrinkToFit();

    if (result != SQLResultDone)
        LOG_ERROR("Failed to read in all origins from the database.");
}
void StorageTracker::syncDeleteOrigin(const String& originIdentifier)
{
    ASSERT(!isMainThread());

    MutexLocker lockDatabase(m_databaseGuard);
    
    if (!canDeleteOrigin(originIdentifier)) {
        LOG_ERROR("Attempted to delete origin '%s' while it was being created\n", originIdentifier.ascii().data());
        return;
    }
    
    openTrackerDatabase(false);
    if (!m_database.isOpen())
        return;
    
    // Get origin's db file path, delete entry in tracker's db, then delete db file.
    SQLiteStatement pathStatement(m_database, "SELECT path FROM Origins WHERE origin=?");
    if (pathStatement.prepare() != SQLResultOk) {
        LOG_ERROR("Unable to prepare selection of path for origin '%s'", originIdentifier.ascii().data());
        return;
    }
    pathStatement.bindText(1, originIdentifier);
    int result = pathStatement.step();
    if (result != SQLResultRow) {
        LOG_ERROR("Unable to find origin '%s' in Origins table", originIdentifier.ascii().data());
        return;
    }
    
    String path = pathStatement.getColumnText(0);

    ASSERT(!path.isEmpty());
    
    SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?");
    if (deleteStatement.prepare() != SQLResultOk) {
        LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data());
        return;
    }
    deleteStatement.bindText(1, originIdentifier);
    if (!deleteStatement.executeCommand()) {
        LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data());
        return;
    }

    SQLiteFileSystem::deleteDatabaseFile(path);
    
    bool shouldDeleteTrackerFiles = false;
    {
        MutexLocker originLock(m_originSetGuard);
        m_originSet.remove(originIdentifier);
        shouldDeleteTrackerFiles = m_originSet.isEmpty();
    }

    if (shouldDeleteTrackerFiles) {
        m_database.close();
        SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
        SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath);
    }

    {
        MutexLocker lockClient(m_clientGuard);
        if (m_client)
            m_client->dispatchDidModifyOrigin(originIdentifier);
    }
}
Ejemplo n.º 22
0
void StorageTracker::syncDeleteAllOrigins()
{
    ASSERT(!isMainThread());

    SQLiteTransactionInProgressAutoCounter transactionCounter;
    
    LockHolder locker(m_databaseMutex);
    
    openTrackerDatabase(false);
    if (!m_database.isOpen())
        return;
    
    SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Failed to prepare statement.");
        return;
    }
    
    int result;
    while ((result = statement.step()) == SQLITE_ROW) {
        if (!canDeleteOrigin(statement.getColumnText(0)))
            continue;

        deleteFile(statement.getColumnText(1));

        {
            LockHolder locker(m_clientMutex);
            if (m_client)
                m_client->dispatchDidModifyOrigin(statement.getColumnText(0));
        }
    }
    
    if (result != SQLITE_DONE)
        LOG_ERROR("Failed to read in all origins from the database.");

    if (m_database.isOpen()) {
#if PLATFORM(IOS)
        truncateDatabaseFile(m_database);
#endif
        m_database.close();
    }

#if !PLATFORM(IOS)
    if (!deleteFile(trackerDatabasePath())) {
        // In the case where it is not possible to delete the database file (e.g some other program
        // like a virus scanner is accessing it), make sure to remove all entries.
        openTrackerDatabase(false);
        if (!m_database.isOpen())
            return;
        SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins");
        if (deleteStatement.prepare() != SQLITE_OK) {
            LOG_ERROR("Unable to prepare deletion of all origins");
            return;
        }
        if (!deleteStatement.executeCommand()) {
            LOG_ERROR("Unable to execute deletion of all origins");
            return;
        }
    }
    deleteEmptyDirectory(m_storageDirectoryPath);
#endif
}
Ejemplo n.º 23
0
void DatabaseTracker::removeDeletedOpenedDatabases()
{
    // This is called when another app has deleted a database.  Go through all opened databases in this
    // tracker and close any that's no longer being tracked in the database.
    
    {
        // Acquire the lock before calling openTrackerDatabase.
        LockHolder lockDatabase(m_databaseGuard);
        openTrackerDatabase(DontCreateIfDoesNotExist);
    }

    if (!m_database.isOpen())
        return;
    
    // Keep track of which opened databases have been deleted.
    Vector<RefPtr<Database> > deletedDatabases;
    typedef HashMap<RefPtr<SecurityOrigin>, Vector<String> > DeletedDatabaseMap;
    DeletedDatabaseMap deletedDatabaseMap;
    
    // Make sure not to hold the m_openDatabaseMapGuard mutex when calling
    // Database::markAsDeletedAndClose(), since that can cause a deadlock
    // during the synchronous DatabaseThread call it triggers.
    {
        LockHolder openDatabaseMapLock(m_openDatabaseMapGuard);
        if (m_openDatabaseMap) {
            for (auto& openDatabase : *m_openDatabaseMap) {
                auto& origin = openDatabase.key;
                DatabaseNameMap* databaseNameMap = openDatabase.value;
                Vector<String> deletedDatabaseNamesForThisOrigin;

                // Loop through all opened databases in this origin.  Get the current database file path of each database and see if
                // it still matches the path stored in the opened database object.
                for (auto& databases : *databaseNameMap) {
                    String databaseName = databases.key;
                    String databaseFileName;
                    SQLiteStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;");
                    if (statement.prepare() == SQLITE_OK) {
                        statement.bindText(1, origin->databaseIdentifier());
                        statement.bindText(2, databaseName);
                        if (statement.step() == SQLITE_ROW)
                            databaseFileName = statement.getColumnText(0);
                        statement.finalize();
                    }
                    
                    bool foundDeletedDatabase = false;
                    for (auto& db : *databases.value) {
                        // We are done if this database has already been marked as deleted.
                        if (db->deleted())
                            continue;
                        
                        // If this database has been deleted or if its database file no longer matches the current version, this database is no longer valid and it should be marked as deleted.
                        if (databaseFileName.isNull() || databaseFileName != pathGetFileName(db->fileName())) {
                            deletedDatabases.append(db);
                            foundDeletedDatabase = true;
                        }
                    }
                    
                    // If the database no longer exists, we should remember to remove it from the OriginQuotaManager later.
                    if (foundDeletedDatabase && databaseFileName.isNull())
                        deletedDatabaseNamesForThisOrigin.append(databaseName);
                }
                
                if (!deletedDatabaseNamesForThisOrigin.isEmpty())
                    deletedDatabaseMap.set(origin, deletedDatabaseNamesForThisOrigin);
            }
        }
    }
    
    for (auto& deletedDatabase : deletedDatabases)
        deletedDatabase->markAsDeletedAndClose();

    for (auto& deletedDatabase : deletedDatabaseMap) {
        SecurityOrigin* origin = deletedDatabase.key.get();
        if (m_client)
            m_client->dispatchDidModifyOrigin(origin);
        
        const Vector<String>& databaseNames = deletedDatabase.value;
        for (auto& databaseName : databaseNames) {
            if (m_client)
                m_client->dispatchDidModifyDatabase(origin, databaseName);
        }        
    }
}
Ejemplo n.º 24
0
// It is the caller's responsibility to make sure that nobody is trying to create, delete, open, or close databases in this origin while the deletion is
// taking place.
bool DatabaseTracker::deleteOrigin(SecurityOrigin* origin)
{
    Vector<String> databaseNames;
    {
        MutexLocker lockDatabase(m_databaseGuard);
        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return false;

        if (!databaseNamesForOriginNoLock(origin, databaseNames)) {
            LOG_ERROR("Unable to retrieve list of database names for origin %s", origin->databaseIdentifier().ascii().data());
            return false;
        }
        if (!canDeleteOrigin(origin)) {
            LOG_ERROR("Tried to delete an origin (%s) while either creating database in it or already deleting it", origin->databaseIdentifier().ascii().data());
            ASSERT_NOT_REACHED();
            return false;
        }
        recordDeletingOrigin(origin);
    }

    // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock.
    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());
        }
    }

    {
        MutexLocker lockDatabase(m_databaseGuard);
        deleteOriginLockFor(origin);
        doneDeletingOrigin(origin);

        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 false;
        }

        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 false;
        }

        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());
            return false;
        }

        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 false;
        }

        SQLiteFileSystem::deleteEmptyDatabaseDirectory(originPath(origin));

        RefPtr<SecurityOrigin> originPossiblyLastReference = origin;
        bool isEmpty = true;

        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (m_database.isOpen()) {
            SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
            if (statement.prepare() != SQLResultOk)
                LOG_ERROR("Failed to prepare statement.");
            else if (statement.step() == SQLResultRow)
                isEmpty = false;
        }

        // If we removed the last origin, do some additional deletion.
        if (isEmpty) {
            if (m_database.isOpen())
                m_database.close();
           SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
           SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_databaseDirectoryPath);
        }

        if (m_client) {
            m_client->dispatchDidModifyOrigin(origin);
            for (unsigned i = 0; i < databaseNames.size(); ++i)
                m_client->dispatchDidModifyDatabase(origin, databaseNames[i]);
        }
    }
    return true;
}