diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/platform/gtk/GeolocationServiceGtk.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/platform/gtk/GeolocationServiceGtk.cpp')
-rw-r--r-- | Source/WebCore/platform/gtk/GeolocationServiceGtk.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/Source/WebCore/platform/gtk/GeolocationServiceGtk.cpp b/Source/WebCore/platform/gtk/GeolocationServiceGtk.cpp new file mode 100644 index 0000000..5b34c68 --- /dev/null +++ b/Source/WebCore/platform/gtk/GeolocationServiceGtk.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2008 Holger Hans Peter Freyther + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "GeolocationServiceGtk.h" +#if ENABLE(GEOLOCATION) + +#include "GOwnPtr.h" +#include "NotImplemented.h" +#include "PositionOptions.h" +#include <wtf/text/CString.h> + +namespace WTF { + template<> void freeOwnedGPtr<GeoclueAccuracy>(GeoclueAccuracy* accuracy) + { + if (!accuracy) + return; + + geoclue_accuracy_free(accuracy); + } +} + +namespace WebCore { + +GeolocationService* GeolocationServiceGtk::create(GeolocationServiceClient* client) +{ + return new GeolocationServiceGtk(client); +} + +GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &GeolocationServiceGtk::create; + +GeolocationServiceGtk::GeolocationServiceGtk(GeolocationServiceClient* client) + : GeolocationService(client) + , m_geoclueClient(0) + , m_geocluePosition(0) + , m_latitude(0.0) + , m_longitude(0.0) + , m_altitude(0.0) + , m_altitudeAccuracy(0.0) + , m_timestamp(0) +{ +} + +GeolocationServiceGtk::~GeolocationServiceGtk() +{ + if (m_geoclueClient) + g_object_unref(m_geoclueClient); + + if (m_geocluePosition) + g_object_unref(m_geocluePosition); +} + +// +// 1.) Initialize Geoclue with our requirements +// 2.) Try to get a GeocluePosition +// 3.) Update the Information and get the current position +// +// TODO: Also get GeoclueVelocity but there is no master client +// API for that. +// +bool GeolocationServiceGtk::startUpdating(PositionOptions* options) +{ + ASSERT(!m_geoclueClient); + + m_lastPosition = 0; + m_lastError = 0; + + GOwnPtr<GError> error; + GeoclueMaster* master = geoclue_master_get_default(); + GeoclueMasterClient* client = geoclue_master_create_client(master, 0, 0); + g_object_unref(master); + + if (!client) { + setError(PositionError::POSITION_UNAVAILABLE, "Could not connect to location provider."); + return false; + } + + GeoclueAccuracyLevel accuracyLevel = GEOCLUE_ACCURACY_LEVEL_LOCALITY; + int timeout = 0; + if (options) { + accuracyLevel = options->enableHighAccuracy() ? GEOCLUE_ACCURACY_LEVEL_DETAILED : GEOCLUE_ACCURACY_LEVEL_LOCALITY; + if (options->hasTimeout()) + timeout = options->timeout(); + } + + gboolean result = geoclue_master_client_set_requirements(client, accuracyLevel, timeout, + false, GEOCLUE_RESOURCE_ALL, &error.outPtr()); + + if (!result) { + setError(PositionError::POSITION_UNAVAILABLE, error->message); + g_object_unref(client); + return false; + } + + m_geocluePosition = geoclue_master_client_create_position(client, &error.outPtr()); + if (!m_geocluePosition) { + setError(PositionError::POSITION_UNAVAILABLE, error->message); + g_object_unref(client); + return false; + } + + m_geoclueClient = client; + + geoclue_position_get_position_async(m_geocluePosition, (GeocluePositionCallback)getPositionCallback, this); + + g_signal_connect(G_OBJECT(m_geocluePosition), "position-changed", + G_CALLBACK(position_changed), this); + + return true; +} + +void GeolocationServiceGtk::stopUpdating() +{ + if (!m_geoclueClient) + return; + + g_object_unref(m_geocluePosition); + g_object_unref(m_geoclueClient); + + m_geocluePosition = 0; + m_geoclueClient = 0; +} + +void GeolocationServiceGtk::suspend() +{ + // not available with geoclue + notImplemented(); +} + +void GeolocationServiceGtk::resume() +{ + // not available with geoclue + notImplemented(); +} + +Geoposition* GeolocationServiceGtk::lastPosition() const +{ + return m_lastPosition.get(); +} + +PositionError* GeolocationServiceGtk::lastError() const +{ + return m_lastError.get(); +} + +void GeolocationServiceGtk::updatePosition() +{ + m_lastError = 0; + + RefPtr<Coordinates> coordinates = Coordinates::create(m_latitude, m_longitude, + true, m_altitude, m_accuracy, + true, m_altitudeAccuracy, false, 0.0, false, 0.0); + m_lastPosition = Geoposition::create(coordinates.release(), m_timestamp * 1000.0); + positionChanged(); +} + +void GeolocationServiceGtk::getPositionCallback(GeocluePosition *position, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy* accuracy, + GError* error, + GeolocationServiceGtk* that) +{ + if (error) { + that->setError(PositionError::POSITION_UNAVAILABLE, error->message); + g_error_free(error); + return; + } + position_changed(position, fields, timestamp, latitude, longitude, altitude, accuracy, that); +} + +void GeolocationServiceGtk::position_changed(GeocluePosition*, GeocluePositionFields fields, int timestamp, double latitude, double longitude, double altitude, GeoclueAccuracy* accuracy, GeolocationServiceGtk* that) +{ + if (!(fields & GEOCLUE_POSITION_FIELDS_LATITUDE && fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) { + that->setError(PositionError::POSITION_UNAVAILABLE, "Position could not be determined."); + return; + } + + that->m_timestamp = timestamp; + that->m_latitude = latitude; + that->m_longitude = longitude; + that->m_altitude = altitude; + + GeoclueAccuracyLevel level; + geoclue_accuracy_get_details(accuracy, &level, &that->m_accuracy, &that->m_altitudeAccuracy); + that->updatePosition(); +} + +void GeolocationServiceGtk::setError(PositionError::ErrorCode errorCode, const char* message) +{ + m_lastPosition = 0; + m_lastError = PositionError::create(errorCode, String::fromUTF8(message)); +} + +} +#endif // ENABLE(GEOLOCATION) |