src/3rdparty/webkit/WebCore/page/GeolocationPositionCache.cpp
changeset 30 5dc02b23752f
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /*
       
     2  * Copyright 2010, The Android Open Source Project
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *  * Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  *  * Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "GeolocationPositionCache.h"
       
    28 
       
    29 #if ENABLE(GEOLOCATION)
       
    30 
       
    31 #include "Geoposition.h"
       
    32 #include "SQLValue.h"
       
    33 #include "SQLiteDatabase.h"
       
    34 #include "SQLiteFileSystem.h"
       
    35 #include "SQLiteStatement.h"
       
    36 #include "SQLiteTransaction.h"
       
    37 
       
    38 namespace WebCore {
       
    39 
       
    40 static const char* databaseName = "CachedGeoposition.db";
       
    41 
       
    42 int GeolocationPositionCache::s_instances = 0;
       
    43 RefPtr<Geoposition>* GeolocationPositionCache::s_cachedPosition;
       
    44 String* GeolocationPositionCache::s_databaseFile = 0;
       
    45 
       
    46 GeolocationPositionCache::GeolocationPositionCache()
       
    47 {
       
    48     if (!(s_instances++)) {
       
    49         s_cachedPosition = new RefPtr<Geoposition>;
       
    50         *s_cachedPosition = readFromDB();
       
    51     }
       
    52 }
       
    53 
       
    54 GeolocationPositionCache::~GeolocationPositionCache()
       
    55 {
       
    56     if (!(--s_instances)) {
       
    57         if (*s_cachedPosition)
       
    58             writeToDB(s_cachedPosition->get());
       
    59         delete s_cachedPosition;
       
    60     }
       
    61 }
       
    62 
       
    63 void GeolocationPositionCache::setCachedPosition(Geoposition* cachedPosition)
       
    64 {
       
    65     *s_cachedPosition = cachedPosition;
       
    66 }
       
    67 
       
    68 Geoposition* GeolocationPositionCache::cachedPosition()
       
    69 {
       
    70     return s_cachedPosition->get();
       
    71 }
       
    72 
       
    73 void GeolocationPositionCache::setDatabasePath(const String& databasePath)
       
    74 {
       
    75     if (!s_databaseFile)
       
    76         s_databaseFile = new String;
       
    77     *s_databaseFile = SQLiteFileSystem::appendDatabaseFileNameToPath(databasePath, databaseName);
       
    78     // If we don't have have a cached position, attempt to read one from the
       
    79     // DB at the new path.
       
    80     if (s_instances && !(*s_cachedPosition))
       
    81         *s_cachedPosition = readFromDB();
       
    82 }
       
    83 
       
    84 PassRefPtr<Geoposition> GeolocationPositionCache::readFromDB()
       
    85 {
       
    86     SQLiteDatabase database;
       
    87     if (!s_databaseFile || !database.open(*s_databaseFile))
       
    88         return 0;
       
    89 
       
    90     // Create the table here, such that even if we've just created the
       
    91     // DB, the commands below should succeed.
       
    92     if (!database.executeCommand("CREATE TABLE IF NOT EXISTS CachedPosition ("
       
    93             "latitude REAL NOT NULL, "
       
    94             "longitude REAL NOT NULL, "
       
    95             "altitude REAL, "
       
    96             "accuracy REAL NOT NULL, "
       
    97             "altitudeAccuracy REAL, "
       
    98             "heading REAL, "
       
    99             "speed REAL, "
       
   100             "timestamp INTEGER NOT NULL)"))
       
   101         return 0;
       
   102 
       
   103     SQLiteStatement statement(database, "SELECT * FROM CachedPosition");
       
   104     if (statement.prepare() != SQLResultOk)
       
   105         return 0;
       
   106 
       
   107     if (statement.step() != SQLResultRow)
       
   108         return 0;
       
   109 
       
   110     bool providesAltitude = statement.getColumnValue(2).type() != SQLValue::NullValue;
       
   111     bool providesAltitudeAccuracy = statement.getColumnValue(4).type() != SQLValue::NullValue;
       
   112     bool providesHeading = statement.getColumnValue(5).type() != SQLValue::NullValue;
       
   113     bool providesSpeed = statement.getColumnValue(6).type() != SQLValue::NullValue;
       
   114     RefPtr<Coordinates> coordinates = Coordinates::create(statement.getColumnDouble(0), // latitude
       
   115                                                           statement.getColumnDouble(1), // longitude
       
   116                                                           providesAltitude, statement.getColumnDouble(2), // altitude
       
   117                                                           statement.getColumnDouble(3), // accuracy
       
   118                                                           providesAltitudeAccuracy, statement.getColumnDouble(4), // altitudeAccuracy
       
   119                                                           providesHeading, statement.getColumnDouble(5), // heading
       
   120                                                           providesSpeed, statement.getColumnDouble(6)); // speed
       
   121     return Geoposition::create(coordinates.release(), statement.getColumnInt64(7)); // timestamp
       
   122 }
       
   123 
       
   124 void GeolocationPositionCache::writeToDB(const Geoposition* position)
       
   125 {
       
   126     ASSERT(position);
       
   127 
       
   128     SQLiteDatabase database;
       
   129     if (!s_databaseFile || !database.open(*s_databaseFile))
       
   130         return;
       
   131 
       
   132     SQLiteTransaction transaction(database);
       
   133 
       
   134     if (!database.executeCommand("DELETE FROM CachedPosition"))
       
   135         return;
       
   136 
       
   137     SQLiteStatement statement(database, "INSERT INTO CachedPosition ("
       
   138         "latitude, "
       
   139         "longitude, "
       
   140         "altitude, "
       
   141         "accuracy, "
       
   142         "altitudeAccuracy, "
       
   143         "heading, "
       
   144         "speed, "
       
   145         "timestamp) "
       
   146         "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
       
   147     if (statement.prepare() != SQLResultOk)
       
   148         return;
       
   149 
       
   150     statement.bindDouble(1, position->coords()->latitude());
       
   151     statement.bindDouble(2, position->coords()->longitude());
       
   152     if (position->coords()->canProvideAltitude())
       
   153         statement.bindDouble(3, position->coords()->altitude());
       
   154     else
       
   155         statement.bindNull(3);
       
   156     statement.bindDouble(4, position->coords()->accuracy());
       
   157     if (position->coords()->canProvideAltitudeAccuracy())
       
   158         statement.bindDouble(5, position->coords()->altitudeAccuracy());
       
   159     else
       
   160         statement.bindNull(5);
       
   161     if (position->coords()->canProvideHeading())
       
   162         statement.bindDouble(6, position->coords()->heading());
       
   163     else
       
   164         statement.bindNull(6);
       
   165     if (position->coords()->canProvideSpeed())
       
   166         statement.bindDouble(7, position->coords()->speed());
       
   167     else
       
   168         statement.bindNull(7);
       
   169     statement.bindInt64(8, position->timestamp());
       
   170     if (!statement.executeCommand())
       
   171         return;
       
   172 
       
   173     transaction.commit();
       
   174 }
       
   175 
       
   176 } // namespace WebCore
       
   177 
       
   178 #endif // ENABLE(GEOLOCATION)