/* * Copyright (C) 2012 Igalia S.L. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "GeolocationProviderGeoclue.h" #if ENABLE(GEOLOCATION) && !USE(GEOCLUE2) using namespace WebCore; void GeolocationProviderGeoclue::getPositionCallback(GeocluePosition* position, GeocluePositionFields fields, int timestamp, double latitude, double longitude, double altitude, GeoclueAccuracy* accuracy, GError* error, GeolocationProviderGeoclue* provider) { if (error) { provider->errorOccurred(error->message); g_error_free(error); return; } provider->positionChanged(position, fields, timestamp, latitude, longitude, altitude, accuracy); } void GeolocationProviderGeoclue::positionChangedCallback(GeocluePosition* position, GeocluePositionFields fields, int timestamp, double latitude, double longitude, double altitude, GeoclueAccuracy* accuracy, GeolocationProviderGeoclue* provider) { provider->positionChanged(position, fields, timestamp, latitude, longitude, altitude, accuracy); } void GeolocationProviderGeoclue::createGeocluePositionCallback(GeoclueMasterClient*, GeocluePosition* position, GError *error, GeolocationProviderGeoclue* provider) { if (error) { provider->errorOccurred(error->message); g_error_free(error); return; } provider->initializeGeocluePosition(position); } void GeolocationProviderGeoclue::geoclueClientSetRequirementsCallback(GeoclueMasterClient*, GError* error, GeolocationProviderGeoclue* provider) { if (error) { provider->errorOccurred(error->message); g_error_free(error); } } void GeolocationProviderGeoclue::createGeoclueClientCallback(GeoclueMaster*, GeoclueMasterClient* client, char*, GError* error, GeolocationProviderGeoclue* provider) { if (error) { provider->errorOccurred(error->message); g_error_free(error); return; } provider->initializeGeoclueClient(client); } GeolocationProviderGeoclue::GeolocationProviderGeoclue(GeolocationProviderGeoclueClient* client) : m_client(client) , m_latitude(0) , m_longitude(0) , m_altitude(0) , m_accuracy(0) , m_altitudeAccuracy(0) , m_timestamp(0) , m_enableHighAccuracy(false) , m_isUpdating(false) { ASSERT(m_client); } GeolocationProviderGeoclue::~GeolocationProviderGeoclue() { } void GeolocationProviderGeoclue::startUpdating() { ASSERT(!m_geoclueClient); GRefPtr master = adoptGRef(geoclue_master_get_default()); geoclue_master_create_client_async(master.get(), reinterpret_cast(createGeoclueClientCallback), this); m_isUpdating = true; } void GeolocationProviderGeoclue::stopUpdating() { m_geocluePosition.clear(); m_geoclueClient.clear(); m_isUpdating = false; } void GeolocationProviderGeoclue::setEnableHighAccuracy(bool enable) { m_enableHighAccuracy = enable; // If we're already updating we should report the new requirements in order // to change to a more suitable provider if needed. If not, return. if (!m_isUpdating) return; updateClientRequirements(); } void GeolocationProviderGeoclue::initializeGeoclueClient(GeoclueMasterClient* geoclueClient) { ASSERT(GEOCLUE_IS_MASTER_CLIENT(geoclueClient)); // Store the GeoclueMasterClient object as created by GeoClue. m_geoclueClient = adoptGRef(geoclueClient); // Set the requirement for the client and ask it to create a position associated to it. updateClientRequirements(); geoclue_master_client_create_position_async(m_geoclueClient.get(), reinterpret_cast(createGeocluePositionCallback), this); } void GeolocationProviderGeoclue::initializeGeocluePosition(GeocluePosition* geocluePosition) { ASSERT(GEOCLUE_IS_POSITION(geocluePosition)); // Stores the GeocluePosition object associated with the GeoclueMasterClient. m_geocluePosition = adoptGRef(geocluePosition); // Get the initial position and keep updated of further changes. geoclue_position_get_position_async(m_geocluePosition.get(), reinterpret_cast(getPositionCallback), this); g_signal_connect(m_geocluePosition.get(), "position-changed", G_CALLBACK(positionChangedCallback), this); } void GeolocationProviderGeoclue::updateClientRequirements() { if (!m_geoclueClient) return; GeoclueAccuracyLevel accuracyLevel = m_enableHighAccuracy ? GEOCLUE_ACCURACY_LEVEL_DETAILED : GEOCLUE_ACCURACY_LEVEL_LOCALITY; geoclue_master_client_set_requirements_async(m_geoclueClient.get(), accuracyLevel, 0, false, GEOCLUE_RESOURCE_ALL, reinterpret_cast(geoclueClientSetRequirementsCallback), this); } void GeolocationProviderGeoclue::positionChanged(GeocluePosition*, GeocluePositionFields fields, int timestamp, double latitude, double longitude, double altitude, GeoclueAccuracy* accuracy) { if (!(fields & GEOCLUE_POSITION_FIELDS_LATITUDE && fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) { errorOccurred("Position could not be determined."); return; } m_timestamp = timestamp; m_latitude = latitude; m_longitude = longitude; m_altitude = altitude; geoclue_accuracy_get_details(accuracy, 0, &m_accuracy, &m_altitudeAccuracy); m_client->notifyPositionChanged(m_timestamp, m_latitude, m_longitude, m_altitude, m_accuracy, m_altitudeAccuracy); } void GeolocationProviderGeoclue::errorOccurred(const char* message) { m_client->notifyErrorOccurred(message); } #endif // ENABLE(GEOLOCATION) && !USE(GEOCLUE2)