18a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block/*
28a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * Copyright 2010, The Android Open Source Project
38a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block *
48a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * Redistribution and use in source and binary forms, with or without
58a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * modification, are permitted provided that the following conditions
68a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * are met:
78a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block *  * Redistributions of source code must retain the above copyright
88a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block *    notice, this list of conditions and the following disclaimer.
98a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block *  * Redistributions in binary form must reproduce the above copyright
108a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block *    notice, this list of conditions and the following disclaimer in the
118a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block *    documentation and/or other materials provided with the distribution.
128a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block *
138a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
148a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
178a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block */
258a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
268a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block#include "config.h"
278a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block#include "GeolocationPositionCache.h"
288a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if ENABLE(GEOLOCATION)
30dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
31f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "CrossThreadTask.h"
328a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block#include "Geoposition.h"
338a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block#include "SQLValue.h"
348a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block#include "SQLiteDatabase.h"
35602f856d9f84c00d87576a9d5314f42a695d9850Steve Block#include "SQLiteFileSystem.h"
368a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block#include "SQLiteStatement.h"
378a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block#include "SQLiteTransaction.h"
38f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <wtf/PassOwnPtr.h>
39f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <wtf/Threading.h>
40f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
41f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochusing namespace WTF;
428a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
438a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Blocknamespace WebCore {
448a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic int numUsers = 0;
468a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
47f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochGeolocationPositionCache* GeolocationPositionCache::instance()
48f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
49f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    DEFINE_STATIC_LOCAL(GeolocationPositionCache*, instance, (0));
50f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!instance)
51f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        instance = new GeolocationPositionCache();
52f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return instance;
53f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
548a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
558a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve BlockGeolocationPositionCache::GeolocationPositionCache()
56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    : m_threadId(0)
57f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
58f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
59f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
60f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::addUser()
618a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block{
62f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(numUsers >= 0);
63cad810f21b803229eb11403f9209855525a25d57Steve Block    MutexLocker databaseLock(m_databaseFileMutex);
64cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!numUsers && !m_threadId && !m_databaseFile.isNull()) {
65f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        startBackgroundThread();
66f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        MutexLocker lock(m_cachedPositionMutex);
67f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!m_cachedPosition)
68f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            triggerReadFromDatabase();
698a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    }
70f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ++numUsers;
718a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block}
728a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::removeUser()
748a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block{
75f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    MutexLocker lock(m_cachedPositionMutex);
76f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    --numUsers;
77f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(numUsers >= 0);
78cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!numUsers && m_cachedPosition && m_threadId)
79f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        triggerWriteToDatabase();
80f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
81f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
82f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::setDatabasePath(const String& path)
83f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
84f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    static const char* databaseName = "CachedGeoposition.db";
85f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    String newFile = SQLiteFileSystem::appendDatabaseFileNameToPath(path, databaseName);
86f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    MutexLocker lock(m_databaseFileMutex);
87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_databaseFile != newFile) {
88f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_databaseFile = newFile;
89cad810f21b803229eb11403f9209855525a25d57Steve Block        if (numUsers && !m_threadId) {
90cad810f21b803229eb11403f9209855525a25d57Steve Block            startBackgroundThread();
91cad810f21b803229eb11403f9209855525a25d57Steve Block            if (!m_cachedPosition)
92cad810f21b803229eb11403f9209855525a25d57Steve Block                triggerReadFromDatabase();
93cad810f21b803229eb11403f9209855525a25d57Steve Block        }
948a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    }
958a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block}
968a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
978a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Blockvoid GeolocationPositionCache::setCachedPosition(Geoposition* cachedPosition)
988a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block{
99f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    MutexLocker lock(m_cachedPositionMutex);
100f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_cachedPosition = cachedPosition;
1018a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block}
1028a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
1038a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve BlockGeoposition* GeolocationPositionCache::cachedPosition()
1048a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block{
105f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    MutexLocker lock(m_cachedPositionMutex);
106f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return m_cachedPosition.get();
107f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
108f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
109f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::startBackgroundThread()
110f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // FIXME: Consider sharing this thread with other background tasks.
112cad810f21b803229eb11403f9209855525a25d57Steve Block    m_threadId = createThread(threadEntryPoint, this, "WebCore: Geolocation cache");
113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid* GeolocationPositionCache::threadEntryPoint(void* object)
116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    static_cast<GeolocationPositionCache*>(object)->threadEntryPointImpl();
118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return 0;
119f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
120f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::threadEntryPointImpl()
122f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    while (OwnPtr<ScriptExecutionContext::Task> task = m_queue.waitForMessage()) {
124f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        // We don't need a ScriptExecutionContext in the callback, so pass 0 here.
125f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        task->performTask(0);
126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::triggerReadFromDatabase()
130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_queue.append(createCallbackTask(&GeolocationPositionCache::readFromDatabase, this));
1328a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block}
1338a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::readFromDatabase(ScriptExecutionContext*, GeolocationPositionCache* cache)
1358a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block{
136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    cache->readFromDatabaseImpl();
1378a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block}
1388a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
139f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::readFromDatabaseImpl()
1408a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block{
1418a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    SQLiteDatabase database;
142f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    {
143f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        MutexLocker lock(m_databaseFileMutex);
144f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!database.open(m_databaseFile))
145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            return;
146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
1478a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
1488a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    // Create the table here, such that even if we've just created the
1498a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    // DB, the commands below should succeed.
1508a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    if (!database.executeCommand("CREATE TABLE IF NOT EXISTS CachedPosition ("
1518a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "latitude REAL NOT NULL, "
1528a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "longitude REAL NOT NULL, "
1538a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "altitude REAL, "
1548a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "accuracy REAL NOT NULL, "
1558a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "altitudeAccuracy REAL, "
1568a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "heading REAL, "
1578a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "speed REAL, "
1588a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block            "timestamp INTEGER NOT NULL)"))
159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
1608a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
1618a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    SQLiteStatement statement(database, "SELECT * FROM CachedPosition");
1628a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    if (statement.prepare() != SQLResultOk)
163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
1648a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
1658a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    if (statement.step() != SQLResultRow)
166f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
1678a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
1688a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    bool providesAltitude = statement.getColumnValue(2).type() != SQLValue::NullValue;
1698a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    bool providesAltitudeAccuracy = statement.getColumnValue(4).type() != SQLValue::NullValue;
1708a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    bool providesHeading = statement.getColumnValue(5).type() != SQLValue::NullValue;
1718a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    bool providesSpeed = statement.getColumnValue(6).type() != SQLValue::NullValue;
172602f856d9f84c00d87576a9d5314f42a695d9850Steve Block    RefPtr<Coordinates> coordinates = Coordinates::create(statement.getColumnDouble(0), // latitude
173602f856d9f84c00d87576a9d5314f42a695d9850Steve Block                                                          statement.getColumnDouble(1), // longitude
1748a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block                                                          providesAltitude, statement.getColumnDouble(2), // altitude
175602f856d9f84c00d87576a9d5314f42a695d9850Steve Block                                                          statement.getColumnDouble(3), // accuracy
1768a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block                                                          providesAltitudeAccuracy, statement.getColumnDouble(4), // altitudeAccuracy
1778a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block                                                          providesHeading, statement.getColumnDouble(5), // heading
1788a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block                                                          providesSpeed, statement.getColumnDouble(6)); // speed
179f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    DOMTimeStamp timestamp = statement.getColumnInt64(7); // timestamp
180f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
181f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // A position may have been set since we called triggerReadFromDatabase().
182f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    MutexLocker lock(m_cachedPositionMutex);
183f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_cachedPosition)
184f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
185f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_cachedPosition = Geoposition::create(coordinates.release(), timestamp);
1868a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block}
1878a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
188f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::triggerWriteToDatabase()
1898a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block{
190f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_queue.append(createCallbackTask(writeToDatabase, this));
191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
1928a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::writeToDatabase(ScriptExecutionContext*, GeolocationPositionCache* cache)
194f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
195f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    cache->writeToDatabaseImpl();
196f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
198f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GeolocationPositionCache::writeToDatabaseImpl()
199f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
2008a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    SQLiteDatabase database;
201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    {
202f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        MutexLocker lock(m_databaseFileMutex);
203f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!database.open(m_databaseFile))
204f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            return;
205f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
206f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
207f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RefPtr<Geoposition> cachedPosition;
208f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    {
209f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        MutexLocker lock(m_cachedPositionMutex);
210f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (m_cachedPosition)
211f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            cachedPosition = m_cachedPosition->threadSafeCopy();
212f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
2138a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
2148a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    SQLiteTransaction transaction(database);
2158a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
2168a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    if (!database.executeCommand("DELETE FROM CachedPosition"))
2178a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        return;
2188a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
2198a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    SQLiteStatement statement(database, "INSERT INTO CachedPosition ("
2208a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "latitude, "
2218a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "longitude, "
2228a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "altitude, "
2238a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "accuracy, "
2248a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "altitudeAccuracy, "
2258a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "heading, "
2268a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "speed, "
2278a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "timestamp) "
2288a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
2298a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    if (statement.prepare() != SQLResultOk)
2308a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        return;
2318a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
232f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    statement.bindDouble(1, cachedPosition->coords()->latitude());
233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    statement.bindDouble(2, cachedPosition->coords()->longitude());
234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (cachedPosition->coords()->canProvideAltitude())
235f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        statement.bindDouble(3, cachedPosition->coords()->altitude());
2368a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    else
2378a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        statement.bindNull(3);
238f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    statement.bindDouble(4, cachedPosition->coords()->accuracy());
239f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (cachedPosition->coords()->canProvideAltitudeAccuracy())
240f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        statement.bindDouble(5, cachedPosition->coords()->altitudeAccuracy());
2418a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    else
2428a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        statement.bindNull(5);
243f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (cachedPosition->coords()->canProvideHeading())
244f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        statement.bindDouble(6, cachedPosition->coords()->heading());
2458a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    else
2468a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        statement.bindNull(6);
247f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (cachedPosition->coords()->canProvideSpeed())
248f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        statement.bindDouble(7, cachedPosition->coords()->speed());
2498a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    else
2508a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        statement.bindNull(7);
251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    statement.bindInt64(8, cachedPosition->timestamp());
252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
2538a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    if (!statement.executeCommand())
2548a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block        return;
2558a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
2568a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    transaction.commit();
2578a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block}
2588a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block
2598a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block} // namespace WebCore
260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif // ENABLE(GEOLOCATION)
262