15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All Rights Reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Torch Mobile, Inc.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright 2010, The Android Open Source Project
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/geolocation/Geolocation.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Frame.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Page.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/geolocation/Geoposition.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/CurrentTime.h"
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/geolocation/Coordinates.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/geolocation/GeolocationController.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/geolocation/GeolocationError.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/geolocation/GeolocationPosition.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/geolocation/PositionError.h"
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const char permissionDeniedErrorMessage[] = "User denied Geolocation";
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocation service";
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const char framelessDocumentErrorMessage[] = "Geolocation cannot be used in frameless documents";
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!position)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
5302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(), position->longitude(), position->canProvideAltitude(), position->altitude(),
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                          position->accuracy(), position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(),
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                          position->canProvideHeading(), position->heading(), position->canProvideSpeed(), position->speed());
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Geoposition::create(coordinates.release(), convertSecondsToDOMTimeStamp(position->timestamp()));
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static PassRefPtr<PositionError> createPositionError(GeolocationError* error)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (error->code()) {
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case GeolocationError::PermissionDenied:
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        code = PositionError::PERMISSION_DENIED;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case GeolocationError::PositionUnavailable:
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        code = PositionError::POSITION_UNAVAILABLE;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return PositionError::create(code, error->message());
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_geolocation(geolocation)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_successCallback(successCallback)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_errorCallback(errorCallback)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_options(options)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_timer(this, &Geolocation::GeoNotifier::timerFired)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_useCachedPosition(false)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_geolocation);
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_successCallback);
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If no options were supplied from JS, we should have created a default set
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // of options in JSGeolocationCustom.cpp.
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_options);
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::GeoNotifier::setFatalError(PassRefPtr<PositionError> error)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If a fatal error has already been set, stick with it. This makes sure that
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // when permission is denied, this is the error reported, as required by the
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // spec.
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_fatalError)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_fatalError = error;
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // An existing timer may not have a zero timeout.
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_timer.stop();
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_timer.startOneShot(0);
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::GeoNotifier::setUseCachedPosition()
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_useCachedPosition = true;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_timer.startOneShot(0);
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Geolocation::GeoNotifier::hasZeroTimeout() const
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_options->hasTimeout() && m_options->timeout() == 0;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::GeoNotifier::runSuccessCallback(Geoposition* position)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we are here and the Geolocation permission is not approved, something has
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // gone horribly wrong.
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_geolocation->isAllowed())
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        CRASH();
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_successCallback->handleEvent(position);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::GeoNotifier::runErrorCallback(PositionError* error)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_errorCallback)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_errorCallback->handleEvent(error);
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::GeoNotifier::startTimerIfNeeded()
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_options->hasTimeout())
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_timer.startOneShot(m_options->timeout() / 1000.0);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::GeoNotifier::stopTimer()
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_timer.stop();
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*)
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_timer.stop();
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Protect this GeoNotifier object, since it
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // could be deleted by a call to clearWatch in a callback.
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<GeoNotifier> protect(this);
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Test for fatal error first. This is required for the case where the Frame is
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // disconnected and requests are cancelled.
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_fatalError) {
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        runErrorCallback(m_fatalError.get());
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This will cause this notifier to be deleted.
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_geolocation->fatalErrorOccurred(this);
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_useCachedPosition) {
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Clear the cached position flag in case this is a watch request, which
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // will continue to run.
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_useCachedPosition = false;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_geolocation->requestUsesCachedPosition(this);
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_errorCallback) {
168d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timeout expired");
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_errorCallback->handleEvent(error.get());
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_geolocation->requestTimedOut(this);
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool Geolocation::Watchers::add(int id, PassRefPtr<GeoNotifier> prpNotifier)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(id > 0);
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<GeoNotifier> notifier = prpNotifier;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!m_idToNotifierMap.add(id, notifier.get()).isNewEntry)
180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_notifierToIdMap.set(notifier.release(), id);
182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return true;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Geolocation::GeoNotifier* Geolocation::Watchers::find(int id)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(id > 0);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IdToNotifierMap::iterator iter = m_idToNotifierMap.find(id);
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (iter == m_idToNotifierMap.end())
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return iter->value.get();
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::Watchers::remove(int id)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(id > 0);
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IdToNotifierMap::iterator iter = m_idToNotifierMap.find(id);
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (iter == m_idToNotifierMap.end())
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_notifierToIdMap.remove(iter->value);
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_idToNotifierMap.remove(iter);
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::Watchers::remove(GeoNotifier* notifier)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NotifierToIdMap::iterator iter = m_notifierToIdMap.find(notifier);
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (iter == m_notifierToIdMap.end())
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_idToNotifierMap.remove(iter->value);
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_notifierToIdMap.remove(iter);
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Geolocation::Watchers::contains(GeoNotifier* notifier) const
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_notifierToIdMap.contains(notifier);
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::Watchers::clear()
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_idToNotifierMap.clear();
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_notifierToIdMap.clear();
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Geolocation::Watchers::isEmpty() const
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_idToNotifierMap.isEmpty();
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::Watchers::getNotifiersVector(GeoNotifierVector& copy) const
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    copyValuesToVector(m_idToNotifierMap, copy);
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Geolocation> Geolocation::create(ScriptExecutionContext* context)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Geolocation> geolocation = adoptRef(new Geolocation(context));
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    geolocation->suspendIfNeeded();
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return geolocation.release();
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Geolocation::Geolocation(ScriptExecutionContext* context)
242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : ActiveDOMObject(context)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_allowGeolocation(Unknown)
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
24553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ScriptWrappable::init(this);
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Geolocation::~Geolocation()
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_allowGeolocation != InProgress);
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Document* Geolocation::document() const
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return toDocument(scriptExecutionContext());
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Frame* Geolocation::frame() const
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return document() ? document()->frame() : 0;
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Page* Geolocation::page() const
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return document() ? document()->page() : 0;
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::stop()
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Page* page = this->page();
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (page && m_allowGeolocation == InProgress)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        GeolocationController::from(page)->cancelPermissionRequest(this);
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The frame may be moving to a new page and we want to get the permissions from the new page's client.
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_allowGeolocation = Unknown;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cancelAllRequests();
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopUpdating();
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_pendingForPermissionNotifiers.clear();
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Geoposition* Geolocation::lastPosition()
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Page* page = this->page();
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!page)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_lastPosition = createGeoposition(GeolocationController::from(page)->lastPosition());
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_lastPosition.get();
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!frame())
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options);
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startRequest(notifier.get());
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_oneShots.add(notifier);
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!frame())
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options);
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startRequest(notifier.get());
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    int watchID;
311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Keep asking for the next id until we're given one that we don't already have.
312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    do {
313ede7d0ec43b4c8737d917f2c5ad872a7b36ca9a8Torne (Richard Coles)        watchID = scriptExecutionContext()->circularSequentialID();
314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } while (!m_watchers.add(watchID, notifier));
315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return watchID;
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::startRequest(GeoNotifier *notifier)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check whether permissions have already been denied. Note that if this is the case,
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the permission state can not change again in the lifetime of this page.
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isDenied())
323d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (haveSuitableCachedPosition(notifier->options()))
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        notifier->setUseCachedPosition();
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (notifier->hasZeroTimeout())
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        notifier->startTimerIfNeeded();
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (!isAllowed()) {
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // if we don't yet have permission, request for permission before calling startUpdating()
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_pendingForPermissionNotifiers.add(notifier);
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        requestPermission();
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (startUpdating(notifier))
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        notifier->startTimerIfNeeded();
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
335d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::fatalErrorOccurred(Geolocation::GeoNotifier* notifier)
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This request has failed fatally. Remove it from our lists.
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_oneShots.remove(notifier);
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_watchers.remove(notifier);
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasListeners())
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stopUpdating();
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier)
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is called asynchronously, so the permissions could have been denied
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // since we last checked in startRequest.
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isDenied()) {
353d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_requestsAwaitingCachedPosition.add(notifier);
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If permissions are allowed, make the callback
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isAllowed()) {
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        makeCachedPositionCallbacks();
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Request permissions, which may be synchronous or asynchronous.
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    requestPermission();
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::makeCachedPositionCallbacks()
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // All modifications to m_requestsAwaitingCachedPosition are done
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // asynchronously, so we don't need to worry about it being modified from
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the callbacks.
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierSet::const_iterator end = m_requestsAwaitingCachedPosition.end();
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (GeoNotifierSet::const_iterator iter = m_requestsAwaitingCachedPosition.begin(); iter != end; ++iter) {
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        GeoNotifier* notifier = iter->get();
377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        notifier->runSuccessCallback(lastPosition());
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If this is a one-shot request, stop it. Otherwise, if the watch still
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // exists, start the service to get updates.
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_oneShots.contains(notifier))
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_oneShots.remove(notifier);
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (m_watchers.contains(notifier)) {
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (notifier->hasZeroTimeout() || startUpdating(notifier))
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                notifier->startTimerIfNeeded();
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
387d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch                notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_requestsAwaitingCachedPosition.clear();
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasListeners())
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stopUpdating();
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::requestTimedOut(GeoNotifier* notifier)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If this is a one-shot request, stop it.
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_oneShots.remove(notifier);
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasListeners())
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stopUpdating();
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Geolocation::haveSuitableCachedPosition(PositionOptions* options)
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Geoposition* cachedPosition = lastPosition();
409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cachedPosition)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!options->hasMaximumAge())
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!options->maximumAge())
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime());
416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return cachedPosition->timestamp() > currentTimeMillis - options->maximumAge();
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void Geolocation::clearWatch(int watchID)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (watchID <= 0)
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (GeoNotifier* notifier = m_watchers.find(watchID))
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_pendingForPermissionNotifiers.remove(notifier);
426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_watchers.remove(watchID);
42702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasListeners())
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stopUpdating();
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::setIsAllowed(bool allowed)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Protect the Geolocation object from garbage collection during a callback.
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Geolocation> protect(this);
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This may be due to either a new position from the service, or a cached
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // position.
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_allowGeolocation = allowed ? Yes : No;
44002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Permission request was made during the startRequest process
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_pendingForPermissionNotifiers.isEmpty()) {
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        handlePendingPermissionNotifiers();
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_pendingForPermissionNotifiers.clear();
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isAllowed()) {
449d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage);
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        error->setIsFatal(true);
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        handleError(error.get());
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_requestsAwaitingCachedPosition.clear();
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the service has a last position, use it to call back for all requests.
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If any of the requests are waiting for permission for a cached position,
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the position from the service will be at least as fresh.
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lastPosition())
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        makeSuccessCallbacks();
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        makeCachedPositionCallbacks();
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     GeoNotifierVector::const_iterator end = notifiers.end();
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         RefPtr<GeoNotifier> notifier = *it;
47002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         notifier->runErrorCallback(error);
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     }
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* position)
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector::const_iterator end = notifiers.end();
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it)
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        (*it)->runSuccessCallback(position);
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::stopTimer(GeoNotifierVector& notifiers)
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector::const_iterator end = notifiers.end();
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it)
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        (*it)->stopTimer();
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::stopTimersForOneShots()
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector copy;
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    copyToVector(m_oneShots, copy);
49302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopTimer(copy);
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::stopTimersForWatchers()
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector copy;
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_watchers.getNotifiersVector(copy);
50102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopTimer(copy);
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::stopTimers()
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopTimersForOneShots();
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopTimersForWatchers();
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::cancelRequests(GeoNotifierVector& notifiers)
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector::const_iterator end = notifiers.end();
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it)
515d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        (*it)->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, framelessDocumentErrorMessage));
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::cancelAllRequests()
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector copy;
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    copyToVector(m_oneShots, copy);
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cancelRequests(copy);
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_watchers.getNotifiersVector(copy);
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cancelRequests(copy);
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached)
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector nonCached;
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector::iterator end = notifiers.end();
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        GeoNotifier* notifier = it->get();
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (notifier->useCachedPosition()) {
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (cached)
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                cached->append(notifier);
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            nonCached.append(notifier);
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    notifiers.swap(nonCached);
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::copyToSet(const GeoNotifierVector& src, GeoNotifierSet& dest)
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     GeoNotifierVector::const_iterator end = src.end();
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     for (GeoNotifierVector::const_iterator it = src.begin(); it != end; ++it) {
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         GeoNotifier* notifier = it->get();
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         dest.add(notifier);
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     }
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::handleError(PositionError* error)
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(error);
55402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector oneShotsCopy;
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    copyToVector(m_oneShots, oneShotsCopy);
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector watchersCopy;
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_watchers.getNotifiersVector(watchersCopy);
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Clear the lists before we make the callbacks, to avoid clearing notifiers
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // added by calls to Geolocation methods from the callbacks, and to prevent
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // further callbacks to these notifiers.
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector oneShotsWithCachedPosition;
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_oneShots.clear();
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (error->isFatal())
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_watchers.clear();
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Don't send non-fatal errors to notifiers due to receive a cached position.
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        extractNotifiersWithCachedPosition(oneShotsCopy, &oneShotsWithCachedPosition);
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        extractNotifiersWithCachedPosition(watchersCopy, 0);
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sendError(oneShotsCopy, error);
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sendError(watchersCopy, error);
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // hasListeners() doesn't distinguish between notifiers due to receive a
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // cached position and those requiring a fresh position. Perform the check
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // before restoring the notifiers below.
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasListeners())
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stopUpdating();
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Maintain a reference to the cached notifiers until their timer fires.
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    copyToSet(oneShotsWithCachedPosition, m_oneShots);
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::requestPermission()
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_allowGeolocation > Unknown)
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Page* page = this->page();
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!page)
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_allowGeolocation = InProgress;
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Ask the embedder: it maintains the geolocation challenge policy itself.
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeolocationController::from(page)->requestPermission(this);
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::makeSuccessCallbacks()
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(lastPosition());
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isAllowed());
60602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector oneShotsCopy;
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    copyToVector(m_oneShots, oneShotsCopy);
60902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierVector watchersCopy;
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_watchers.getNotifiersVector(watchersCopy);
61202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Clear the lists before we make the callbacks, to avoid clearing notifiers
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // added by calls to Geolocation methods from the callbacks, and to prevent
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // further callbacks to these notifiers.
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_oneShots.clear();
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sendPosition(oneShotsCopy, lastPosition());
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sendPosition(watchersCopy, lastPosition());
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasListeners())
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stopUpdating();
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::positionChanged()
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isAllowed());
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Stop all currently running timers.
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopTimers();
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    makeSuccessCallbacks();
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::setError(GeolocationError* error)
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<PositionError> positionError = createPositionError(error);
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    handleError(positionError.get());
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Geolocation::startUpdating(GeoNotifier* notifier)
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Page* page = this->page();
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!page)
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeolocationController::from(page)->addObserver(this, notifier->options()->enableHighAccuracy());
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::stopUpdating()
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Page* page = this->page();
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!page)
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeolocationController::from(page)->removeObserver(this);
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Geolocation::handlePendingPermissionNotifiers()
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
66202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // While we iterate through the list, we need not worry about list being modified as the permission
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // is already set to Yes/No and no new listeners will be added to the pending list
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GeoNotifierSet::const_iterator end = m_pendingForPermissionNotifiers.end();
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (GeoNotifierSet::const_iterator iter = m_pendingForPermissionNotifiers.begin(); iter != end; ++iter) {
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        GeoNotifier* notifier = iter->get();
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isAllowed()) {
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // start all pending notification requests as permission granted.
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // The notifier is always ref'ed by m_oneShots or m_watchers.
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (startUpdating(notifier))
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                notifier->startTimerIfNeeded();
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
674d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch                notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
675d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        } else {
676d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch            notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
677d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch        }
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
682