void GeolocationPermissions::maybeLoadPermanentPermissions()
{
    if (s_permanentPermissionsLoaded)
        return;
    s_permanentPermissionsLoaded = true;

    SQLiteDatabase database;
    if (!database.open(s_databasePath + databaseName))
        return;

    // Create the table here, such that even if we've just created the DB, the
    // commands below should succeed.
    if (!database.executeCommand("CREATE TABLE IF NOT EXISTS Permissions (origin TEXT UNIQUE NOT NULL, allow INTEGER NOT NULL)")) {
        database.close();
        return;
    }

    SQLiteStatement statement(database, "SELECT * FROM Permissions");
    if (statement.prepare() != SQLResultOk) {
        database.close();
        return;
    }

    ASSERT(s_permanentPermissions.size() == 0);
    while (statement.step() == SQLResultRow)
        s_permanentPermissions.set(statement.getColumnText(0), statement.getColumnInt64(1));

    database.close();
}
예제 #2
0
void GeolocationPositionCache::writeToDatabaseImpl()
{
    SQLiteDatabase database;
    {
        MutexLocker lock(m_databaseFileMutex);
        if (!database.open(m_databaseFile))
            return;
    }

    RefPtr<Geoposition> cachedPosition;
    {
        MutexLocker lock(m_cachedPositionMutex);
        if (m_cachedPosition)
            cachedPosition = m_cachedPosition->threadSafeCopy();
    }

    SQLiteTransaction transaction(database);

    if (!database.executeCommand("DELETE FROM CachedPosition"))
        return;

    SQLiteStatement statement(database, "INSERT INTO CachedPosition ("
        "latitude, "
        "longitude, "
        "altitude, "
        "accuracy, "
        "altitudeAccuracy, "
        "heading, "
        "speed, "
        "timestamp) "
        "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
    if (statement.prepare() != SQLResultOk)
        return;

    statement.bindDouble(1, cachedPosition->coords()->latitude());
    statement.bindDouble(2, cachedPosition->coords()->longitude());
    if (cachedPosition->coords()->canProvideAltitude())
        statement.bindDouble(3, cachedPosition->coords()->altitude());
    else
        statement.bindNull(3);
    statement.bindDouble(4, cachedPosition->coords()->accuracy());
    if (cachedPosition->coords()->canProvideAltitudeAccuracy())
        statement.bindDouble(5, cachedPosition->coords()->altitudeAccuracy());
    else
        statement.bindNull(5);
    if (cachedPosition->coords()->canProvideHeading())
        statement.bindDouble(6, cachedPosition->coords()->heading());
    else
        statement.bindNull(6);
    if (cachedPosition->coords()->canProvideSpeed())
        statement.bindDouble(7, cachedPosition->coords()->speed());
    else
        statement.bindNull(7);
    statement.bindInt64(8, cachedPosition->timestamp());

    if (!statement.executeCommand())
        return;

    transaction.commit();
}
예제 #3
0
// deleteDatabaseFile has to release locks between looking up the list of databases to close and closing them.  While this is in progress, the caller
// is responsible for making sure no new databases are opened in the file to be deleted.
bool DatabaseTracker::deleteDatabaseFile(SecurityOrigin* origin, const String& name, DeletionMode deletionMode)
{
    String fullPath = fullPathForDatabase(origin, name, false);
    if (fullPath.isEmpty())
        return true;

#ifndef NDEBUG
    {
        LockHolder lockDatabase(m_databaseGuard);
        ASSERT(isDeletingDatabaseOrOriginFor(origin, name));
    }
#endif

    Vector<RefPtr<Database>> deletedDatabases;

    // Make sure not to hold the any locks when calling
    // Database::markAsDeletedAndClose(), since that can cause a deadlock
    // during the synchronous DatabaseThread call it triggers.
    {
        LockHolder openDatabaseMapLock(m_openDatabaseMapGuard);
        if (m_openDatabaseMap) {
            // There are some open databases, lets check if they are for this origin.
            DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin);
            if (nameMap && nameMap->size()) {
                // There are some open databases for this origin, let's check
                // if they are this database by name.
                DatabaseSet* databaseSet = nameMap->get(name);
                if (databaseSet && databaseSet->size()) {
                    // We have some database open with this name. Mark them as deleted.
                    for (auto& database : *databaseSet)
                        deletedDatabases.append(database);
                }
            }
        }
    }

    for (auto& database : deletedDatabases)
        database->markAsDeletedAndClose();

#if PLATFORM(IOS)
    if (deletionMode == DeletionMode::Deferred) {
        // On the phone, other background processes may still be accessing this database. Deleting the database directly
        // would nuke the POSIX file locks, potentially causing Safari/WebApp to corrupt the new db if it's running in the background.
        // We'll instead truncate the database file to 0 bytes. If another process is operating on this same database file after
        // the truncation, it should get an error since the database file is no longer valid. When Safari is launched
        // next time, it'll go through the database files and clean up any zero-bytes ones.
        SQLiteDatabase database;
        if (!database.open(fullPath))
            return false;
        return SQLiteFileSystem::truncateDatabaseFile(database.sqlite3Handle());
    }
#else
    UNUSED_PARAM(deletionMode);
#endif

    return SQLiteFileSystem::deleteDatabaseFile(fullPath);
}
예제 #4
0
// A test function.
void SQLiteDatabase::test()
{
//  Sample usage code follows...
	std::string strFileName = "sqlite3.txt";	
	SQLiteDatabase db;	
	try	{
	Verbose::out(1, "*");
	Verbose::out(1, "Create/Open database: sqlite3.txt");
	db.open(strFileName);
	SQLiteRecordset rset(db);

	Verbose::out(1, "create table Test1 (Id int primary key, Name varchar(255))");
	db.execute("create table Test1 (Id int primary key, Name varchar(255))");
	Verbose::out(2, "create table Test1 (Id int primary key, Name varchar(255))");
	db.execute("create table Test2 (Id int primary key, Name varchar(255))");
	
	Verbose::out(1, "Begin transaction...");
	db.beginTransaction();
	for (int iIndex = 1; (iIndex < 10); iIndex++)
	{
		std::string strSQL = "insert into Test1 values (" + ::getInt(iIndex) + ", 'Test1-" + ::getInt(iIndex) + "')";
		Verbose::out(1, "\t" + strSQL);
		db.execute(strSQL);
	}
	for (int iIndex = 1; (iIndex < 10); iIndex++)
	{
		std::string strSQL = "insert into Test2 values (" + ::getInt(iIndex) + ", 'Test2-" + ::getInt(iIndex) + "')";
		Verbose::out(1, "\t" + strSQL);
		db.execute(strSQL);
	}
	Verbose::out(1, "Commit transaction...");
	db.commitTransaction();
	
	Verbose::out(1, "select Test1.id, Test1.Name, Test2.Name from Test1, Test2 where Test1.Id = Test2.id");
	rset.open("select Test1.id, Test1.Name, Test2.Name from Test1, Test2 where Test1.Id = Test2.id");
	while (rset.fetch())
	{
		int iID = rset.getInteger(0);
		std::string strName = rset.getString(1);
		std::string strName2 = rset.getString(2);
		Verbose::out(1, "\tfetched: " + ::getInt(iID) + ", " + strName + ", " + strName2);
	}
	rset.close();	
	
	Verbose::out(1, "drop table Test1");
	db.execute("drop table Test1");
	Verbose::out(1, "drop table Test2");
	db.execute("drop table Test2");
	
	Verbose::out(1, "Closing SQLite database");
	db.close();
	Verbose::out(1, "*");
	} catch (SQLiteException& e) {db.rollbackTransaction(); db.close(); Verbose::out(1, e.getMessage());} 
//  End sample usage code
}
void GeolocationPositionCache::writeToDB(const Geoposition* position)
{
    ASSERT(position);

    SQLiteDatabase database;
    if (!s_databaseFile || !database.open(*s_databaseFile))
        return;

    SQLiteTransaction transaction(database);

    if (!database.executeCommand("DELETE FROM CachedPosition"))
        return;

    SQLiteStatement statement(database, "INSERT INTO CachedPosition ("
        "latitude, "
        "longitude, "
        "altitude, "
        "accuracy, "
        "altitudeAccuracy, "
        "heading, "
        "speed, "
        "timestamp) "
        "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
    if (statement.prepare() != SQLResultOk)
        return;

    statement.bindDouble(1, position->coords()->latitude());
    statement.bindDouble(2, position->coords()->longitude());
    if (position->coords()->canProvideAltitude())
        statement.bindDouble(3, position->coords()->altitude());
    else
        statement.bindNull(3);
    statement.bindDouble(4, position->coords()->accuracy());
    if (position->coords()->canProvideAltitudeAccuracy())
        statement.bindDouble(5, position->coords()->altitudeAccuracy());
    else
        statement.bindNull(5);
    if (position->coords()->canProvideHeading())
        statement.bindDouble(6, position->coords()->heading());
    else
        statement.bindNull(6);
    if (position->coords()->canProvideSpeed())
        statement.bindDouble(7, position->coords()->speed());
    else
        statement.bindNull(7);
    statement.bindInt64(8, position->timestamp());
    if (!statement.executeCommand())
        return;

    transaction.commit();
}
예제 #6
0
void GeolocationPositionCache::readFromDatabaseImpl()
{
    SQLiteDatabase database;
    {
        MutexLocker lock(m_databaseFileMutex);
        if (!database.open(m_databaseFile))
            return;
    }

    // Create the table here, such that even if we've just created the
    // DB, the commands below should succeed.
    if (!database.executeCommand("CREATE TABLE IF NOT EXISTS CachedPosition ("
            "latitude REAL NOT NULL, "
            "longitude REAL NOT NULL, "
            "altitude REAL, "
            "accuracy REAL NOT NULL, "
            "altitudeAccuracy REAL, "
            "heading REAL, "
            "speed REAL, "
            "timestamp INTEGER NOT NULL)"))
        return;

    SQLiteStatement statement(database, "SELECT * FROM CachedPosition");
    if (statement.prepare() != SQLResultOk)
        return;

    if (statement.step() != SQLResultRow)
        return;

    bool providesAltitude = statement.getColumnValue(2).type() != SQLValue::NullValue;
    bool providesAltitudeAccuracy = statement.getColumnValue(4).type() != SQLValue::NullValue;
    bool providesHeading = statement.getColumnValue(5).type() != SQLValue::NullValue;
    bool providesSpeed = statement.getColumnValue(6).type() != SQLValue::NullValue;
    RefPtr<Coordinates> coordinates = Coordinates::create(statement.getColumnDouble(0), // latitude
                                                          statement.getColumnDouble(1), // longitude
                                                          providesAltitude, statement.getColumnDouble(2), // altitude
                                                          statement.getColumnDouble(3), // accuracy
                                                          providesAltitudeAccuracy, statement.getColumnDouble(4), // altitudeAccuracy
                                                          providesHeading, statement.getColumnDouble(5), // heading
                                                          providesSpeed, statement.getColumnDouble(6)); // speed
    DOMTimeStamp timestamp = statement.getColumnInt64(7); // timestamp

    // A position may have been set since we called triggerReadFromDatabase().
    MutexLocker lock(m_cachedPositionMutex);
    if (m_cachedPosition)
        return;
    m_cachedPosition = Geoposition::create(coordinates.release(), timestamp);
}
PassRefPtr<Geoposition> GeolocationPositionCache::readFromDB()
{
    SQLiteDatabase database;
    if (!s_databaseFile || !database.open(*s_databaseFile))
        return 0;

    // Create the table here, such that even if we've just created the
    // DB, the commands below should succeed.
    if (!database.executeCommand("CREATE TABLE IF NOT EXISTS CachedPosition ("
            "latitude REAL NOT NULL, "
            "longitude REAL NOT NULL, "
            "altitude REAL, "
            "accuracy REAL NOT NULL, "
            "altitudeAccuracy REAL, "
            "heading REAL, "
            "speed REAL, "
            "timestamp INTEGER NOT NULL)"))
        return 0;

    SQLiteStatement statement(database, "SELECT * FROM CachedPosition");
    if (statement.prepare() != SQLResultOk)
        return 0;

    if (statement.step() != SQLResultRow)
        return 0;

    bool providesAltitude = statement.getColumnValue(2).type() != SQLValue::NullValue;
    bool providesAltitudeAccuracy = statement.getColumnValue(4).type() != SQLValue::NullValue;
    bool providesHeading = statement.getColumnValue(5).type() != SQLValue::NullValue;
    bool providesSpeed = statement.getColumnValue(6).type() != SQLValue::NullValue;
    RefPtr<Coordinates> coordinates = Coordinates::create(statement.getColumnDouble(0), // latitude
                                                          statement.getColumnDouble(1), // longitude
                                                          providesAltitude, statement.getColumnDouble(2), // altitude
                                                          statement.getColumnDouble(3), // accuracy
                                                          providesAltitudeAccuracy, statement.getColumnDouble(4), // altitudeAccuracy
                                                          providesHeading, statement.getColumnDouble(5), // heading
                                                          providesSpeed, statement.getColumnDouble(6)); // speed
    return Geoposition::create(coordinates.release(), statement.getColumnInt64(7)); // timestamp
}
void GeolocationPermissions::maybeStorePermanentPermissions()
{
    // If the permanent permissions haven't been modified, there's no need to
    // save them to the DB. (If we haven't even loaded them, writing them now
    // would overwrite the stored permissions with the empty set.)
    if (!s_permanentPermissionsModified)
        return;

    SQLiteDatabase database;
    if (!database.open(s_databasePath + databaseName))
        return;

    SQLiteTransaction transaction(database);

    // The number of entries should be small enough that it's not worth trying
    // to perform a diff. Simply clear the table and repopulate it.
    if (!database.executeCommand("DELETE FROM Permissions")) {
        database.close();
        return;
    }

    PermissionsMap::const_iterator end = s_permanentPermissions.end();
    for (PermissionsMap::const_iterator iter = s_permanentPermissions.begin(); iter != end; ++iter) {
         SQLiteStatement statement(database, "INSERT INTO Permissions (origin, allow) VALUES (?, ?)");
         if (statement.prepare() != SQLResultOk)
             continue;
         statement.bindText(1, iter->first);
         statement.bindInt64(2, iter->second);
         statement.executeCommand();
    }

    transaction.commit();
    database.close();

    s_permanentPermissionsModified = false;
}
예제 #9
0
bool DatabaseTracker::deleteDatabaseFileIfEmpty(const String& path)
{
    if (!isZeroByteFile(path))
        return false;
    
    SQLiteDatabase database;
    if (!database.open(path))
        return false;
    
    // Specify that we want the exclusive locking mode, so after the next read,
    // we'll be holding the lock to this database file.
    SQLiteStatement lockStatement(database, "PRAGMA locking_mode=EXCLUSIVE;");
    if (lockStatement.prepare() != SQLITE_OK)
        return false;
    int result = lockStatement.step();
    if (result != SQLITE_ROW && result != SQLITE_DONE)
        return false;
    lockStatement.finalize();

    // Every sqlite database has a sqlite_master table that contains the schema for the database.
    // http://www.sqlite.org/faq.html#q7
    SQLiteStatement readStatement(database, "SELECT * FROM sqlite_master LIMIT 1;");    
    if (readStatement.prepare() != SQLITE_OK)
        return false;
    // We shouldn't expect any result.
    if (readStatement.step() != SQLITE_DONE)
        return false;
    readStatement.finalize();
    
    // At this point, we hold the exclusive lock to this file.  Double-check again to make sure
    // it's still zero bytes.
    if (!isZeroByteFile(path))
        return false;
    
    return SQLiteFileSystem::deleteDatabaseFile(path);
}