diff options
author | Ben Murdoch <benm@google.com> | 2009-08-18 11:35:14 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2009-08-18 11:35:14 +0100 |
commit | e0330ac957b8434cd2c9c7b5447aaa0faabe77ec (patch) | |
tree | 395ba85351595e79b5e357e46af5c28a0dcb5211 /WebCore/page/Geolocation.cpp | |
parent | b32f88b61a9162a5194ab02c12fc3aff6140e30e (diff) | |
parent | 8ca4160fde81af362cf2ea375997797b1df8243d (diff) | |
download | external_webkit-e0330ac957b8434cd2c9c7b5447aaa0faabe77ec.zip external_webkit-e0330ac957b8434cd2c9c7b5447aaa0faabe77ec.tar.gz external_webkit-e0330ac957b8434cd2c9c7b5447aaa0faabe77ec.tar.bz2 |
Merge commit 'goog/master' into merge
Conflicts:
WebCore/bindings/v8/ScriptController.cpp
WebCore/page/Geolocation.cpp
WebCore/platform/android/GeolocationServiceAndroid.cpp
Diffstat (limited to 'WebCore/page/Geolocation.cpp')
-rw-r--r-- | WebCore/page/Geolocation.cpp | 136 |
1 files changed, 104 insertions, 32 deletions
diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp index 5337bcc..e57a8b5 100644 --- a/WebCore/page/Geolocation.cpp +++ b/WebCore/page/Geolocation.cpp @@ -31,32 +31,56 @@ #include "Document.h" #include "Frame.h" #include "Page.h" -#include "PositionError.h" namespace WebCore { -Geolocation::GeoNotifier::GeoNotifier(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) - : m_successCallback(successCallback) +static const char* permissionDeniedErrorMessage = "User denied Geolocation"; + +Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) + : m_geolocation(geolocation) + , m_successCallback(successCallback) , m_errorCallback(errorCallback) , m_options(options) , m_timer(this, &Geolocation::GeoNotifier::timerFired) + , m_fatalError(0) +{ + ASSERT(m_geolocation); + ASSERT(m_successCallback); + // If no options were supplied from JS, we should have created a default set + // of options in JSGeolocationCustom.cpp. + ASSERT(m_options); +} + +void Geolocation::GeoNotifier::setFatalError(PassRefPtr<PositionError> error) { + m_fatalError = error; + m_timer.startOneShot(0); } -void Geolocation::GeoNotifier::startTimer() +void Geolocation::GeoNotifier::startTimerIfNeeded() { - if (m_errorCallback && m_options) + if (m_options->hasTimeout()) m_timer.startOneShot(m_options->timeout() / 1000.0); } void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) { - ASSERT(m_errorCallback); - m_timer.stop(); - RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timed out"); - m_errorCallback->handleEvent(error.get()); + if (m_fatalError) { + if (m_errorCallback) { + m_errorCallback->handleEvent(m_fatalError.get()); + } + // This will cause this notifier to be deleted. + m_geolocation->fatalErrorOccurred(this); + return; + } + + if (m_errorCallback) { + RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timed out"); + m_errorCallback->handleEvent(error.get()); + } + m_geolocation->requestTimedOut(this); } Geolocation::Geolocation(Frame* frame) @@ -81,29 +105,63 @@ void Geolocation::disconnectFrame() void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) { - RefPtr<GeoNotifier> notifier = GeoNotifier::create(successCallback, errorCallback, options); + RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options); - if (!m_service->startUpdating(notifier->m_options.get())) { - if (notifier->m_errorCallback) { - RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, "Unable to Start"); - notifier->m_errorCallback->handleEvent(error.get()); + // Check whether permissions have already been denied. Note that if this is the case, + // the permission state can not change again in the lifetime of this page. + if (isDenied()) { + RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage); + notifier->setFatalError(error.release()); + } else { + if (m_service->startUpdating(notifier->m_options.get())) + notifier->startTimerIfNeeded(); + else { + if (notifier->m_errorCallback) { + RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, "Unable to Start"); + notifier->m_errorCallback->handleEvent(error.get()); + } + return; } - return; } m_oneShots.add(notifier); + +} + +void Geolocation::fatalErrorOccurred(Geolocation::GeoNotifier* notifier) +{ + // This request has failed fatally. Remove it from our lists. + m_oneShots.remove(notifier); + for (GeoNotifierMap::iterator iter = m_watchers.begin(); iter != m_watchers.end(); ++iter) { + if (iter->second == notifier) { + m_watchers.remove(iter); + break; + } + } + + if (!hasListeners()) + m_service->stopUpdating(); } int Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) { - RefPtr<GeoNotifier> notifier = GeoNotifier::create(successCallback, errorCallback, options); + RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options); - if (!m_service->startUpdating(notifier->m_options.get())) { - if (notifier->m_errorCallback) { - RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, "Unable to Start"); - notifier->m_errorCallback->handleEvent(error.get()); + // Check whether permissions have already been denied. Note that if this is the case, + // the permission state can not change again in the lifetime of this page. + if (isDenied()) { + RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage); + notifier->setFatalError(error.release()); + } else { + if (m_service->startUpdating(notifier->m_options.get())) + notifier->startTimerIfNeeded(); + else { + if (notifier->m_errorCallback) { + RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, "Unable to Start"); + notifier->m_errorCallback->handleEvent(error.get()); + } + return 0; } - return 0; } static int sIdentifier = 0; @@ -113,6 +171,15 @@ int Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, Pas return sIdentifier; } +void Geolocation::requestTimedOut(GeoNotifier* notifier) +{ + // If this is a one-shot request, stop it. + m_oneShots.remove(notifier); + + if (!hasListeners()) + m_service->stopUpdating(); +} + void Geolocation::clearWatch(int watchId) { m_watchers.remove(watchId); @@ -138,10 +205,10 @@ void Geolocation::setIsAllowed(bool allowed) m_allowGeolocation = allowed ? Yes : No; if (isAllowed()) { - startTimers(); makeSuccessCallbacks(); } else { - WTF::RefPtr<WebCore::PositionError> error = WebCore::PositionError::create(PositionError::PERMISSION_DENIED, "User disallowed GeoLocation"); + WTF::RefPtr<WebCore::PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage); + error->setIsFatal(true); handleError(error.get()); } } @@ -201,35 +268,35 @@ void Geolocation::sendPositionToWatchers(Geoposition* position) sendPosition(copy, position); } -void Geolocation::startTimer(Vector<RefPtr<GeoNotifier> >& notifiers) +void Geolocation::stopTimer(Vector<RefPtr<GeoNotifier> >& notifiers) { Vector<RefPtr<GeoNotifier> >::const_iterator end = notifiers.end(); for (Vector<RefPtr<GeoNotifier> >::const_iterator it = notifiers.begin(); it != end; ++it) { RefPtr<GeoNotifier> notifier = *it; - notifier->startTimer(); + notifier->m_timer.stop(); } } -void Geolocation::startTimersForOneShots() +void Geolocation::stopTimersForOneShots() { Vector<RefPtr<GeoNotifier> > copy; copyToVector(m_oneShots, copy); - startTimer(copy); + stopTimer(copy); } -void Geolocation::startTimersForWatchers() +void Geolocation::stopTimersForWatchers() { Vector<RefPtr<GeoNotifier> > copy; copyValuesToVector(m_watchers, copy); - startTimer(copy); + stopTimer(copy); } -void Geolocation::startTimers() +void Geolocation::stopTimers() { - startTimersForOneShots(); - startTimersForWatchers(); + stopTimersForOneShots(); + stopTimersForWatchers(); } void Geolocation::handleError(PositionError* error) @@ -240,6 +307,8 @@ void Geolocation::handleError(PositionError* error) sendErrorToWatchers(error); m_oneShots.clear(); + if (error->isFatal()) + m_watchers.clear(); if (!hasListeners()) m_service->stopUpdating(); @@ -267,6 +336,9 @@ void Geolocation::geolocationServicePositionChanged(GeolocationService*) { ASSERT(m_service->lastPosition()); + // Stop all currently running timers. + stopTimers(); + if (!isAllowed()) { // requestPermission() will ask the chrome for permission. This may be // implemented synchronously or asynchronously. In both cases, |