summaryrefslogtreecommitdiffstats
path: root/WebCore
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-08-12 10:03:06 +0100
committerSteve Block <steveblock@google.com>2009-08-12 17:28:18 +0100
commit0c97c982f069c9d9eee236d7f8461710d2e1d078 (patch)
tree1a0ee3d1a84a12121ba0801847faaeed1f9a6f03 /WebCore
parentfa9da1d0abed2fcdb5ff1d38f47a97190fb769a5 (diff)
downloadexternal_webkit-0c97c982f069c9d9eee236d7f8461710d2e1d078.zip
external_webkit-0c97c982f069c9d9eee236d7f8461710d2e1d078.tar.gz
external_webkit-0c97c982f069c9d9eee236d7f8461710d2e1d078.tar.bz2
Fail fast if Geolocation permissions have already been denied.
Diffstat (limited to 'WebCore')
-rw-r--r--WebCore/page/Geolocation.cpp83
-rw-r--r--WebCore/page/Geolocation.h11
2 files changed, 74 insertions, 20 deletions
diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp
index fd429c4..5421eaa 100644
--- a/WebCore/page/Geolocation.cpp
+++ b/WebCore/page/Geolocation.cpp
@@ -30,22 +30,32 @@
#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()
{
if (m_errorCallback && m_options->hasTimeout())
@@ -54,10 +64,17 @@ void Geolocation::GeoNotifier::startTimer()
void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*)
{
- ASSERT(m_errorCallback);
-
m_timer.stop();
+ 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;
+ }
+
RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timed out");
m_errorCallback->handleEvent(error.get());
}
@@ -82,29 +99,59 @@ 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())) {
+ 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())) {
+ 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;
@@ -142,7 +189,7 @@ void Geolocation::setIsAllowed(bool allowed)
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);
handleError(error.get());
}
}
diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h
index 44a7fe0..547d284 100644
--- a/WebCore/page/Geolocation.h
+++ b/WebCore/page/Geolocation.h
@@ -28,6 +28,7 @@
#include "GeolocationService.h"
#include "PositionCallback.h"
+#include "PositionError.h"
#include "PositionErrorCallback.h"
#include "PositionOptions.h"
#include "Timer.h"
@@ -64,6 +65,7 @@ public:
void setIsAllowed(bool);
bool isAllowed() const { return m_allowGeolocation == Yes; }
+ bool isDenied() const { return m_allowGeolocation == No; }
void setShouldClearCache(bool shouldClearCache) { m_shouldClearCache = shouldClearCache; }
bool shouldClearCache() const { return m_shouldClearCache; }
@@ -73,18 +75,21 @@ private:
class GeoNotifier : public RefCounted<GeoNotifier> {
public:
- static PassRefPtr<GeoNotifier> create(PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(new GeoNotifier(positionCallback, positionErrorCallback, options)); }
+ static PassRefPtr<GeoNotifier> create(Geolocation* geolocation, PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options)); }
+ void setFatalError(PassRefPtr<PositionError> error);
void startTimer();
void timerFired(Timer<GeoNotifier>*);
+ Geolocation* m_geolocation;
RefPtr<PositionCallback> m_successCallback;
RefPtr<PositionErrorCallback> m_errorCallback;
RefPtr<PositionOptions> m_options;
Timer<GeoNotifier> m_timer;
+ RefPtr<PositionError> m_fatalError;
private:
- GeoNotifier(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>);
+ GeoNotifier(Geolocation* geolocation, PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>);
};
bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); }
@@ -108,6 +113,8 @@ private:
virtual void geolocationServicePositionChanged(GeolocationService*);
virtual void geolocationServiceErrorOccurred(GeolocationService*);
+ void fatalErrorOccurred(GeoNotifier* notifier);
+
typedef HashSet<RefPtr<GeoNotifier> > GeoNotifierSet;
typedef HashMap<int, RefPtr<GeoNotifier> > GeoNotifierMap;