diff options
author | Steve Block <steveblock@google.com> | 2009-09-04 14:26:00 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-09-07 21:28:38 +0100 |
commit | dfc37cc0448372eace961f14c698eedd4225c73a (patch) | |
tree | d08b3812456ed00a31f26073bd9fec23056023cf /WebCore | |
parent | bc2cb6973923b5560298950bd824d9627d6ed765 (diff) | |
download | external_webkit-dfc37cc0448372eace961f14c698eedd4225c73a.zip external_webkit-dfc37cc0448372eace961f14c698eedd4225c73a.tar.gz external_webkit-dfc37cc0448372eace961f14c698eedd4225c73a.tar.bz2 |
Store Geolocation cached position between browser sessions.
This fixes bug http://b/issue?id=2054431.
Change-Id: I44b752b0c7fb4529027018c99dd945279b594b89
Diffstat (limited to 'WebCore')
-rw-r--r-- | WebCore/page/Geolocation.cpp | 120 | ||||
-rw-r--r-- | WebCore/page/Geolocation.h | 2 |
2 files changed, 119 insertions, 3 deletions
diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp index adf5eb1..d7e0cc3 100644 --- a/WebCore/page/Geolocation.cpp +++ b/WebCore/page/Geolocation.cpp @@ -32,6 +32,10 @@ #include "Document.h" #include "Frame.h" #include "Page.h" +#include "SQLiteDatabase.h" +#include "SQLiteStatement.h" +#include "SQLiteTransaction.h" +#include "SQLValue.h" namespace WebCore { @@ -96,17 +100,22 @@ void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) m_geolocation->requestTimedOut(this); } +static const char* databaseName = "/CachedPosition.db"; + class CachedPositionManager { public: CachedPositionManager() { - if (s_instances++ == 0) + if (s_instances++ == 0) { s_cachedPosition = new RefPtr<Geoposition>; + *s_cachedPosition = readFromDB(); + } } ~CachedPositionManager() { if (--s_instances == 0) { - // TODO(steveblock): Store cached position between sessions. + if (*s_cachedPosition) + writeToDB(s_cachedPosition->get()); delete s_cachedPosition; } } @@ -119,14 +128,114 @@ class CachedPositionManager { { return s_cachedPosition->get(); } + static void setDatabasePath(String databasePath) + { + s_databaseFile = databasePath + databaseName; + // If we don't have have a cached position, attempt to read one from the + // DB at the new path. + if (s_instances && *s_cachedPosition == 0) + *s_cachedPosition = readFromDB(); + } - private: + private: + static PassRefPtr<Geoposition> readFromDB() + { + SQLiteDatabase database; + if (!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 + } + static void writeToDB(Geoposition* position) + { + ASSERT(position); + + SQLiteDatabase database; + if (!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(); + } static int s_instances; static RefPtr<Geoposition>* s_cachedPosition; + static String s_databaseFile; }; int CachedPositionManager::s_instances = 0; RefPtr<Geoposition>* CachedPositionManager::s_cachedPosition; +String CachedPositionManager::s_databaseFile; Geolocation::Geolocation(Frame* frame) @@ -443,4 +552,9 @@ void Geolocation::geolocationServiceErrorOccurred(GeolocationService* service) handleError(service->lastError()); } +void Geolocation::setDatabasePath(String databasePath) +{ + CachedPositionManager::setDatabasePath(databasePath); +} + } // namespace WebCore diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h index 0a19ec2..c97c3e6 100644 --- a/WebCore/page/Geolocation.h +++ b/WebCore/page/Geolocation.h @@ -72,6 +72,8 @@ public: void setShouldClearCache(bool shouldClearCache) { m_shouldClearCache = shouldClearCache; } bool shouldClearCache() const { return m_shouldClearCache; } + static void setDatabasePath(String); + private: Geolocation(Frame*); |