summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/geolocation
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/Modules/geolocation
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/Modules/geolocation')
-rw-r--r--Source/WebCore/Modules/geolocation/Coordinates.cpp40
-rw-r--r--Source/WebCore/Modules/geolocation/Coordinates.h13
-rw-r--r--Source/WebCore/Modules/geolocation/Coordinates.idl14
-rw-r--r--Source/WebCore/Modules/geolocation/GeoNotifier.cpp137
-rw-r--r--Source/WebCore/Modules/geolocation/GeoNotifier.h83
-rw-r--r--Source/WebCore/Modules/geolocation/Geolocation.cpp376
-rw-r--r--Source/WebCore/Modules/geolocation/Geolocation.h76
-rw-r--r--Source/WebCore/Modules/geolocation/GeolocationClient.h2
-rw-r--r--Source/WebCore/Modules/geolocation/GeolocationController.cpp95
-rw-r--r--Source/WebCore/Modules/geolocation/GeolocationController.h27
-rw-r--r--Source/WebCore/Modules/geolocation/GeolocationError.h3
-rw-r--r--Source/WebCore/Modules/geolocation/GeolocationPosition.h11
-rw-r--r--Source/WebCore/Modules/geolocation/Geoposition.h12
-rw-r--r--Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp19
-rw-r--r--Source/WebCore/Modules/geolocation/NavigatorGeolocation.h9
-rw-r--r--Source/WebCore/Modules/geolocation/PositionCallback.idl1
-rw-r--r--Source/WebCore/Modules/geolocation/PositionError.h3
-rw-r--r--Source/WebCore/Modules/geolocation/PositionErrorCallback.idl1
-rw-r--r--Source/WebCore/Modules/geolocation/PositionOptions.h3
19 files changed, 593 insertions, 332 deletions
diff --git a/Source/WebCore/Modules/geolocation/Coordinates.cpp b/Source/WebCore/Modules/geolocation/Coordinates.cpp
index d7b759d37..bbc76c7dd 100644
--- a/Source/WebCore/Modules/geolocation/Coordinates.cpp
+++ b/Source/WebCore/Modules/geolocation/Coordinates.cpp
@@ -28,40 +28,32 @@
namespace WebCore {
-double Coordinates::altitude(bool& isNull) const
+Optional<double> Coordinates::altitude() const
{
- if (m_canProvideAltitude)
- return m_altitude;
-
- isNull = true;
- return 0;
+ if (!m_canProvideAltitude)
+ return Nullopt;
+ return m_altitude;
}
-double Coordinates::altitudeAccuracy(bool& isNull) const
+Optional<double> Coordinates::altitudeAccuracy() const
{
- if (m_canProvideAltitudeAccuracy)
- return m_altitudeAccuracy;
-
- isNull = true;
- return 0;
+ if (!m_canProvideAltitudeAccuracy)
+ return Nullopt;
+ return m_altitudeAccuracy;
}
-double Coordinates::heading(bool& isNull) const
+Optional<double> Coordinates::heading() const
{
- if (m_canProvideHeading)
- return m_heading;
-
- isNull = true;
- return 0;
+ if (!m_canProvideHeading)
+ return Nullopt;
+ return m_heading;
}
-double Coordinates::speed(bool& isNull) const
+Optional<double> Coordinates::speed() const
{
- if (m_canProvideSpeed)
- return m_speed;
-
- isNull = true;
- return 0;
+ if (!m_canProvideSpeed)
+ return Nullopt;
+ return m_speed;
}
} // namespace WebCore
diff --git a/Source/WebCore/Modules/geolocation/Coordinates.h b/Source/WebCore/Modules/geolocation/Coordinates.h
index fb134a502..e4a436e1e 100644
--- a/Source/WebCore/Modules/geolocation/Coordinates.h
+++ b/Source/WebCore/Modules/geolocation/Coordinates.h
@@ -27,26 +27,27 @@
#define Coordinates_h
#include "Event.h"
+#include <wtf/Optional.h>
#include <wtf/RefCounted.h>
namespace WebCore {
class Coordinates : public RefCounted<Coordinates> {
public:
- static PassRefPtr<Coordinates> create(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(new Coordinates(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed)); }
+ static Ref<Coordinates> create(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(*new Coordinates(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed)); }
- PassRefPtr<Coordinates> isolatedCopy() const
+ Ref<Coordinates> isolatedCopy() const
{
return Coordinates::create(m_latitude, m_longitude, m_canProvideAltitude, m_altitude, m_accuracy, m_canProvideAltitudeAccuracy, m_altitudeAccuracy, m_canProvideHeading, m_heading, m_canProvideSpeed, m_speed);
}
double latitude() const { return m_latitude; }
double longitude() const { return m_longitude; }
- double altitude(bool& isNull) const;
+ Optional<double> altitude() const;
double accuracy() const { return m_accuracy; }
- double altitudeAccuracy(bool& isNull) const;
- double heading(bool& isNull) const;
- double speed(bool& isNull) const;
+ Optional<double> altitudeAccuracy() const;
+ Optional<double> heading() const;
+ Optional<double> speed() const;
private:
Coordinates(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed)
diff --git a/Source/WebCore/Modules/geolocation/Coordinates.idl b/Source/WebCore/Modules/geolocation/Coordinates.idl
index d4fc882cb..5812b6f29 100644
--- a/Source/WebCore/Modules/geolocation/Coordinates.idl
+++ b/Source/WebCore/Modules/geolocation/Coordinates.idl
@@ -28,11 +28,11 @@
Conditional=GEOLOCATION,
ImplementationLacksVTable
] interface Coordinates {
- readonly attribute double latitude;
- readonly attribute double longitude;
- readonly attribute double? altitude;
- readonly attribute double accuracy;
- readonly attribute double? altitudeAccuracy;
- readonly attribute double? heading;
- readonly attribute double? speed;
+ readonly attribute unrestricted double latitude;
+ readonly attribute unrestricted double longitude;
+ readonly attribute unrestricted double? altitude;
+ readonly attribute unrestricted double accuracy;
+ readonly attribute unrestricted double? altitudeAccuracy;
+ readonly attribute unrestricted double? heading;
+ readonly attribute unrestricted double? speed;
};
diff --git a/Source/WebCore/Modules/geolocation/GeoNotifier.cpp b/Source/WebCore/Modules/geolocation/GeoNotifier.cpp
new file mode 100644
index 000000000..1316d2741
--- /dev/null
+++ b/Source/WebCore/Modules/geolocation/GeoNotifier.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008-2011, 2015 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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. ``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
+ * 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 "GeoNotifier.h"
+
+#if ENABLE(GEOLOCATION)
+
+#include "Geolocation.h"
+
+namespace WebCore {
+
+GeoNotifier::GeoNotifier(Geolocation& geolocation, RefPtr<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, RefPtr<PositionOptions>&& options)
+ : m_geolocation(geolocation)
+ , m_successCallback(WTFMove(successCallback))
+ , m_errorCallback(WTFMove(errorCallback))
+ , m_options(WTFMove(options))
+ , m_timer(*this, &GeoNotifier::timerFired)
+ , m_useCachedPosition(false)
+{
+ 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 GeoNotifier::setFatalError(RefPtr<PositionError>&& error)
+{
+ // If a fatal error has already been set, stick with it. This makes sure that
+ // when permission is denied, this is the error reported, as required by the
+ // spec.
+ if (m_fatalError)
+ return;
+
+ m_fatalError = WTFMove(error);
+ // An existing timer may not have a zero timeout.
+ m_timer.stop();
+ m_timer.startOneShot(0);
+}
+
+void GeoNotifier::setUseCachedPosition()
+{
+ m_useCachedPosition = true;
+ m_timer.startOneShot(0);
+}
+
+bool GeoNotifier::hasZeroTimeout() const
+{
+ return m_options->hasTimeout() && !m_options->timeout();
+}
+
+void GeoNotifier::runSuccessCallback(Geoposition* position)
+{
+ // If we are here and the Geolocation permission is not approved, something has
+ // gone horribly wrong.
+ if (!m_geolocation->isAllowed())
+ CRASH();
+
+ m_successCallback->handleEvent(position);
+}
+
+void GeoNotifier::runErrorCallback(PositionError* error)
+{
+ if (m_errorCallback)
+ m_errorCallback->handleEvent(error);
+}
+
+void GeoNotifier::startTimerIfNeeded()
+{
+ if (m_options->hasTimeout())
+ m_timer.startOneShot(m_options->timeout() / 1000.0);
+}
+
+void GeoNotifier::stopTimer()
+{
+ m_timer.stop();
+}
+
+void GeoNotifier::timerFired()
+{
+ m_timer.stop();
+
+ // Protect this GeoNotifier object, since it
+ // could be deleted by a call to clearWatch in a callback.
+ Ref<GeoNotifier> protect(*this);
+
+ // Test for fatal error first. This is required for the case where the Frame is
+ // disconnected and requests are cancelled.
+ if (m_fatalError) {
+ runErrorCallback(m_fatalError.get());
+ // This will cause this notifier to be deleted.
+ m_geolocation->fatalErrorOccurred(this);
+ return;
+ }
+
+ if (m_useCachedPosition) {
+ // Clear the cached position flag in case this is a watch request, which
+ // will continue to run.
+ m_useCachedPosition = false;
+ m_geolocation->requestUsesCachedPosition(this);
+ return;
+ }
+
+ if (m_errorCallback) {
+ RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, ASCIILiteral("Timeout expired"));
+ m_errorCallback->handleEvent(error.get());
+ }
+ m_geolocation->requestTimedOut(this);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(GEOLOCATION)
diff --git a/Source/WebCore/Modules/geolocation/GeoNotifier.h b/Source/WebCore/Modules/geolocation/GeoNotifier.h
new file mode 100644
index 000000000..7257c46cd
--- /dev/null
+++ b/Source/WebCore/Modules/geolocation/GeoNotifier.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008-2011, 2015 Apple Inc. All Rights Reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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. ``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
+ * 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.
+ */
+
+#ifndef GeoNotifier_h
+#define GeoNotifier_h
+
+#if ENABLE(GEOLOCATION)
+
+#include "Timer.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Geoposition;
+class Geolocation;
+class PositionCallback;
+class PositionError;
+class PositionErrorCallback;
+class PositionOptions;
+
+class GeoNotifier : public RefCounted<GeoNotifier> {
+public:
+ static Ref<GeoNotifier> create(Geolocation& geolocation, RefPtr<PositionCallback>&& positionCallback, RefPtr<PositionErrorCallback>&& positionErrorCallback, RefPtr<PositionOptions>&& options)
+ {
+ return adoptRef(*new GeoNotifier(geolocation, WTFMove(positionCallback), WTFMove(positionErrorCallback), WTFMove(options)));
+ }
+
+ PositionOptions* options() const { return m_options.get(); }
+ void setFatalError(RefPtr<PositionError>&&);
+
+ bool useCachedPosition() const { return m_useCachedPosition; }
+ void setUseCachedPosition();
+
+ void runSuccessCallback(Geoposition*);
+ void runErrorCallback(PositionError*);
+
+ void startTimerIfNeeded();
+ void stopTimer();
+ void timerFired();
+ bool hasZeroTimeout() const;
+
+private:
+ GeoNotifier(Geolocation&, RefPtr<PositionCallback>&&, RefPtr<PositionErrorCallback>&&, RefPtr<PositionOptions>&&);
+
+ Ref<Geolocation> m_geolocation;
+ RefPtr<PositionCallback> m_successCallback;
+ RefPtr<PositionErrorCallback> m_errorCallback;
+ RefPtr<PositionOptions> m_options;
+ Timer m_timer;
+ RefPtr<PositionError> m_fatalError;
+ bool m_useCachedPosition;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(GEOLOCATION)
+
+#endif // GeoNotifier_h
diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp
index c7a65c726..fb1211cea 100644
--- a/Source/WebCore/Modules/geolocation/Geolocation.cpp
+++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp
@@ -30,28 +30,31 @@
#if ENABLE(GEOLOCATION)
+#include "Coordinates.h"
#include "Document.h"
#include "Frame.h"
-#include "Geoposition.h"
-#include "Page.h"
-#include <wtf/CurrentTime.h>
-
-#include "Coordinates.h"
+#include "GeoNotifier.h"
#include "GeolocationController.h"
#include "GeolocationError.h"
#include "GeolocationPosition.h"
+#include "Geoposition.h"
+#include "Page.h"
#include "PositionError.h"
+#include "SecurityOrigin.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/Ref.h>
namespace WebCore {
static const char permissionDeniedErrorMessage[] = "User denied Geolocation";
static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocation service";
static const char framelessDocumentErrorMessage[] = "Geolocation cannot be used in frameless documents";
+static const char originCannotRequestGeolocationErrorMessage[] = "Origin does not have permission to use Geolocation service";
-static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position)
+static RefPtr<Geoposition> createGeoposition(GeolocationPosition* position)
{
if (!position)
- return 0;
+ return nullptr;
RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(), position->longitude(), position->canProvideAltitude(), position->altitude(),
position->accuracy(), position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(),
@@ -59,7 +62,7 @@ static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position)
return Geoposition::create(coordinates.release(), convertSecondsToDOMTimeStamp(position->timestamp()));
}
-static PassRefPtr<PositionError> createPositionError(GeolocationError* error)
+static Ref<PositionError> createPositionError(GeolocationError* error)
{
PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE;
switch (error->code()) {
@@ -74,142 +77,33 @@ static PassRefPtr<PositionError> createPositionError(GeolocationError* error)
return PositionError::create(code, error->message());
}
-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_useCachedPosition(false)
-{
- 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)
-{
- // If a fatal error has already been set, stick with it. This makes sure that
- // when permission is denied, this is the error reported, as required by the
- // spec.
- if (m_fatalError)
- return;
-
- m_fatalError = error;
- // An existing timer may not have a zero timeout.
- m_timer.stop();
- m_timer.startOneShot(0);
-}
-
-void Geolocation::GeoNotifier::setUseCachedPosition()
-{
- m_useCachedPosition = true;
- m_timer.startOneShot(0);
-}
-
-bool Geolocation::GeoNotifier::hasZeroTimeout() const
-{
- return m_options->hasTimeout() && m_options->timeout() == 0;
-}
-
-void Geolocation::GeoNotifier::runSuccessCallback(Geoposition* position)
-{
- // If we are here and the Geolocation permission is not approved, something has
- // gone horribly wrong.
- if (!m_geolocation->isAllowed())
- CRASH();
-
- m_successCallback->handleEvent(position);
-}
-
-void Geolocation::GeoNotifier::runErrorCallback(PositionError* error)
-{
- if (m_errorCallback)
- m_errorCallback->handleEvent(error);
-}
-
-void Geolocation::GeoNotifier::startTimerIfNeeded()
-{
- if (m_options->hasTimeout())
- m_timer.startOneShot(m_options->timeout() / 1000.0);
-}
-
-void Geolocation::GeoNotifier::stopTimer()
-{
- m_timer.stop();
-}
-
-void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*)
-{
- m_timer.stop();
-
- // Protect this GeoNotifier object, since it
- // could be deleted by a call to clearWatch in a callback.
- RefPtr<GeoNotifier> protect(this);
-
- // Test for fatal error first. This is required for the case where the Frame is
- // disconnected and requests are cancelled.
- if (m_fatalError) {
- runErrorCallback(m_fatalError.get());
- // This will cause this notifier to be deleted.
- m_geolocation->fatalErrorOccurred(this);
- return;
- }
-
- if (m_useCachedPosition) {
- // Clear the cached position flag in case this is a watch request, which
- // will continue to run.
- m_useCachedPosition = false;
- m_geolocation->requestUsesCachedPosition(this);
- return;
- }
-
- if (m_errorCallback) {
- RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, ASCIILiteral("Timeout expired"));
- m_errorCallback->handleEvent(error.get());
- }
- m_geolocation->requestTimedOut(this);
-}
-
-bool Geolocation::Watchers::add(int id, PassRefPtr<GeoNotifier> prpNotifier)
+bool Geolocation::Watchers::add(int id, RefPtr<GeoNotifier>&& notifier)
{
ASSERT(id > 0);
- RefPtr<GeoNotifier> notifier = prpNotifier;
if (!m_idToNotifierMap.add(id, notifier.get()).isNewEntry)
return false;
- m_notifierToIdMap.set(notifier.release(), id);
+ m_notifierToIdMap.set(WTFMove(notifier), id);
return true;
}
-Geolocation::GeoNotifier* Geolocation::Watchers::find(int id)
+GeoNotifier* Geolocation::Watchers::find(int id)
{
ASSERT(id > 0);
- IdToNotifierMap::iterator iter = m_idToNotifierMap.find(id);
- if (iter == m_idToNotifierMap.end())
- return 0;
- return iter->value.get();
+ return m_idToNotifierMap.get(id);
}
void Geolocation::Watchers::remove(int id)
{
ASSERT(id > 0);
- IdToNotifierMap::iterator iter = m_idToNotifierMap.find(id);
- if (iter == m_idToNotifierMap.end())
- return;
- m_notifierToIdMap.remove(iter->value);
- m_idToNotifierMap.remove(iter);
+ if (auto notifier = m_idToNotifierMap.take(id))
+ m_notifierToIdMap.remove(notifier);
}
void Geolocation::Watchers::remove(GeoNotifier* notifier)
{
- NotifierToIdMap::iterator iter = m_notifierToIdMap.find(notifier);
- if (iter == m_notifierToIdMap.end())
- return;
- m_idToNotifierMap.remove(iter->value);
- m_notifierToIdMap.remove(iter);
+ if (auto identifier = m_notifierToIdMap.take(notifier))
+ m_idToNotifierMap.remove(identifier);
}
bool Geolocation::Watchers::contains(GeoNotifier* notifier) const
@@ -233,16 +127,19 @@ void Geolocation::Watchers::getNotifiersVector(GeoNotifierVector& copy) const
copyValuesToVector(m_idToNotifierMap, copy);
}
-PassRefPtr<Geolocation> Geolocation::create(ScriptExecutionContext* context)
+Ref<Geolocation> Geolocation::create(ScriptExecutionContext* context)
{
- RefPtr<Geolocation> geolocation = adoptRef(new Geolocation(context));
- geolocation->suspendIfNeeded();
- return geolocation.release();
+ auto geolocation = adoptRef(*new Geolocation(context));
+ geolocation.get().suspendIfNeeded();
+ return geolocation;
}
Geolocation::Geolocation(ScriptExecutionContext* context)
: ActiveDOMObject(context)
, m_allowGeolocation(Unknown)
+ , m_isSuspended(false)
+ , m_hasChangedPosition(false)
+ , m_resumeTimer(*this, &Geolocation::resumeTimerFired)
{
}
@@ -253,17 +150,134 @@ Geolocation::~Geolocation()
Document* Geolocation::document() const
{
- return toDocument(scriptExecutionContext());
+ return downcast<Document>(scriptExecutionContext());
+}
+
+SecurityOrigin* Geolocation::securityOrigin() const
+{
+ return scriptExecutionContext()->securityOrigin();
}
Frame* Geolocation::frame() const
{
- return document() ? document()->frame() : 0;
+ return document() ? document()->frame() : nullptr;
}
Page* Geolocation::page() const
{
- return document() ? document()->page() : 0;
+ return document() ? document()->page() : nullptr;
+}
+
+bool Geolocation::canSuspendForDocumentSuspension() const
+{
+ return true;
+}
+
+void Geolocation::suspend(ReasonForSuspension reason)
+{
+ if (reason == ActiveDOMObject::PageCache) {
+ stop();
+ m_resetOnResume = true;
+ }
+
+ // Suspend GeoNotifier timeout timers.
+ if (hasListeners())
+ stopTimers();
+
+ m_isSuspended = true;
+ m_resumeTimer.stop();
+ ActiveDOMObject::suspend(reason);
+}
+
+void Geolocation::resume()
+{
+#if USE(WEB_THREAD)
+ ASSERT(WebThreadIsLockedOrDisabled());
+#endif
+ ActiveDOMObject::resume();
+
+ if (!m_resumeTimer.isActive())
+ m_resumeTimer.startOneShot(0);
+}
+
+void Geolocation::resumeTimerFired()
+{
+ m_isSuspended = false;
+
+ if (m_resetOnResume) {
+ resetAllGeolocationPermission();
+ m_resetOnResume = false;
+ }
+
+ // Resume GeoNotifier timeout timers.
+ if (hasListeners()) {
+ for (auto& notifier : m_oneShots)
+ notifier->startTimerIfNeeded();
+ GeoNotifierVector watcherCopy;
+ m_watchers.getNotifiersVector(watcherCopy);
+ for (auto& watcher : watcherCopy)
+ watcher->startTimerIfNeeded();
+ }
+
+ if ((isAllowed() || isDenied()) && !m_pendingForPermissionNotifiers.isEmpty()) {
+ // The pending permission was granted while the object was suspended.
+ setIsAllowed(isAllowed());
+ ASSERT(!m_hasChangedPosition);
+ ASSERT(!m_errorWaitingForResume);
+ return;
+ }
+
+ if (isDenied() && hasListeners()) {
+ // The permission was revoked while the object was suspended.
+ setIsAllowed(false);
+ return;
+ }
+
+ if (m_hasChangedPosition) {
+ positionChanged();
+ m_hasChangedPosition = false;
+ }
+
+ if (m_errorWaitingForResume) {
+ handleError(m_errorWaitingForResume.get());
+ m_errorWaitingForResume = nullptr;
+ }
+}
+
+void Geolocation::resetAllGeolocationPermission()
+{
+ if (m_isSuspended) {
+ m_resetOnResume = true;
+ return;
+ }
+
+ if (m_allowGeolocation == InProgress) {
+ Page* page = this->page();
+ if (page)
+ GeolocationController::from(page)->cancelPermissionRequest(this);
+
+ // This return is not technically correct as GeolocationController::cancelPermissionRequest() should have cleared the active request.
+ // Neither iOS nor OS X supports cancelPermissionRequest() (https://bugs.webkit.org/show_bug.cgi?id=89524), so we workaround that and let ongoing requests complete. :(
+ return;
+ }
+
+ // 1) Reset our own state.
+ stopUpdating();
+ m_allowGeolocation = Unknown;
+ m_hasChangedPosition = false;
+ m_errorWaitingForResume = nullptr;
+
+ // 2) Request new permission for the active notifiers.
+ stopTimers();
+
+ // Go over the one shot and re-request permission.
+ for (auto& notifier : m_oneShots)
+ startRequest(notifier.get());
+ // Go over the watchers and re-request permission.
+ GeoNotifierVector watcherCopy;
+ m_watchers.getNotifiersVector(watcherCopy);
+ for (auto& watcher : watcherCopy)
+ startRequest(watcher.get());
}
void Geolocation::stop()
@@ -275,9 +289,16 @@ void Geolocation::stop()
m_allowGeolocation = Unknown;
cancelAllRequests();
stopUpdating();
+ m_hasChangedPosition = false;
+ m_errorWaitingForResume = nullptr;
m_pendingForPermissionNotifiers.clear();
}
+const char* Geolocation::activeDOMObjectName() const
+{
+ return "Geolocation";
+}
+
Geoposition* Geolocation::lastPosition()
{
Page* page = this->page();
@@ -289,35 +310,40 @@ Geoposition* Geolocation::lastPosition()
return m_lastPosition.get();
}
-void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
+void Geolocation::getCurrentPosition(RefPtr<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, RefPtr<PositionOptions>&& options)
{
if (!frame())
return;
- RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options);
+ RefPtr<GeoNotifier> notifier = GeoNotifier::create(*this, WTFMove(successCallback), WTFMove(errorCallback), WTFMove(options));
startRequest(notifier.get());
m_oneShots.add(notifier);
}
-int Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
+int Geolocation::watchPosition(RefPtr<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, RefPtr<PositionOptions>&& options)
{
if (!frame())
return 0;
- RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options);
+ RefPtr<GeoNotifier> notifier = GeoNotifier::create(*this, WTFMove(successCallback), WTFMove(errorCallback), WTFMove(options));
startRequest(notifier.get());
int watchID;
// Keep asking for the next id until we're given one that we don't already have.
do {
watchID = m_scriptExecutionContext->circularSequentialID();
- } while (!m_watchers.add(watchID, notifier));
+ } while (!m_watchers.add(watchID, WTFMove(notifier)));
return watchID;
}
-void Geolocation::startRequest(GeoNotifier *notifier)
+void Geolocation::startRequest(GeoNotifier* notifier)
{
+ if (!securityOrigin()->canRequestGeolocation()) {
+ notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, ASCIILiteral(originCannotRequestGeolocationErrorMessage)));
+ return;
+ }
+
// 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())
@@ -336,7 +362,7 @@ void Geolocation::startRequest(GeoNotifier *notifier)
notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, ASCIILiteral(failedToStartServiceErrorMessage)));
}
-void Geolocation::fatalErrorOccurred(Geolocation::GeoNotifier* notifier)
+void Geolocation::fatalErrorOccurred(GeoNotifier* notifier)
{
// This request has failed fatally. Remove it from our lists.
m_oneShots.remove(notifier);
@@ -372,17 +398,13 @@ void Geolocation::makeCachedPositionCallbacks()
// All modifications to m_requestsAwaitingCachedPosition are done
// asynchronously, so we don't need to worry about it being modified from
// the callbacks.
- GeoNotifierSet::const_iterator end = m_requestsAwaitingCachedPosition.end();
- for (GeoNotifierSet::const_iterator iter = m_requestsAwaitingCachedPosition.begin(); iter != end; ++iter) {
- GeoNotifier* notifier = iter->get();
+ for (auto& notifier : m_requestsAwaitingCachedPosition) {
notifier->runSuccessCallback(lastPosition());
// If this is a one-shot request, stop it. Otherwise, if the watch still
// exists, start the service to get updates.
- if (m_oneShots.contains(notifier))
- m_oneShots.remove(notifier);
- else if (m_watchers.contains(notifier)) {
- if (notifier->hasZeroTimeout() || startUpdating(notifier))
+ if (!m_oneShots.remove(notifier.get()) && m_watchers.contains(notifier.get())) {
+ if (notifier->hasZeroTimeout() || startUpdating(notifier.get()))
notifier->startTimerIfNeeded();
else
notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, ASCIILiteral(failedToStartServiceErrorMessage)));
@@ -433,12 +455,15 @@ void Geolocation::clearWatch(int watchID)
void Geolocation::setIsAllowed(bool allowed)
{
// Protect the Geolocation object from garbage collection during a callback.
- RefPtr<Geolocation> protect(this);
+ Ref<Geolocation> protect(*this);
// This may be due to either a new position from the service, or a cached
// position.
m_allowGeolocation = allowed ? Yes : No;
+ if (m_isSuspended)
+ return;
+
// Permission request was made during the startRequest process
if (!m_pendingForPermissionNotifiers.isEmpty()) {
handlePendingPermissionNotifiers();
@@ -451,6 +476,9 @@ void Geolocation::setIsAllowed(bool allowed)
error->setIsFatal(true);
handleError(error.get());
m_requestsAwaitingCachedPosition.clear();
+ m_hasChangedPosition = false;
+ m_errorWaitingForResume = nullptr;
+
return;
}
@@ -465,26 +493,20 @@ void Geolocation::setIsAllowed(bool allowed)
void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error)
{
- GeoNotifierVector::const_iterator end = notifiers.end();
- for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
- RefPtr<GeoNotifier> notifier = *it;
-
- notifier->runErrorCallback(error);
- }
+ for (auto& notifier : notifiers)
+ notifier->runErrorCallback(error);
}
void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* position)
{
- GeoNotifierVector::const_iterator end = notifiers.end();
- for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it)
- (*it)->runSuccessCallback(position);
+ for (auto& notifier : notifiers)
+ notifier->runSuccessCallback(position);
}
void Geolocation::stopTimer(GeoNotifierVector& notifiers)
{
- GeoNotifierVector::const_iterator end = notifiers.end();
- for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it)
- (*it)->stopTimer();
+ for (auto& notifier : notifiers)
+ notifier->stopTimer();
}
void Geolocation::stopTimersForOneShots()
@@ -511,9 +533,8 @@ void Geolocation::stopTimers()
void Geolocation::cancelRequests(GeoNotifierVector& notifiers)
{
- GeoNotifierVector::const_iterator end = notifiers.end();
- for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it)
- (*it)->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, ASCIILiteral(framelessDocumentErrorMessage)));
+ for (auto& notifier : notifiers)
+ notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, ASCIILiteral(framelessDocumentErrorMessage)));
}
void Geolocation::cancelAllRequests()
@@ -528,25 +549,20 @@ void Geolocation::cancelAllRequests()
void Geolocation::extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached)
{
GeoNotifierVector nonCached;
- GeoNotifierVector::iterator end = notifiers.end();
- for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
- GeoNotifier* notifier = it->get();
+ for (auto& notifier : notifiers) {
if (notifier->useCachedPosition()) {
if (cached)
- cached->append(notifier);
+ cached->append(notifier.get());
} else
- nonCached.append(notifier);
+ nonCached.append(notifier.get());
}
notifiers.swap(nonCached);
}
void Geolocation::copyToSet(const GeoNotifierVector& src, GeoNotifierSet& dest)
{
- GeoNotifierVector::const_iterator end = src.end();
- for (GeoNotifierVector::const_iterator it = src.begin(); it != end; ++it) {
- GeoNotifier* notifier = it->get();
- dest.add(notifier);
- }
+ for (auto& notifier : src)
+ dest.add(notifier.get());
}
void Geolocation::handleError(PositionError* error)
@@ -630,11 +646,20 @@ void Geolocation::positionChanged()
// Stop all currently running timers.
stopTimers();
+ if (m_isSuspended) {
+ m_hasChangedPosition = true;
+ return;
+ }
+
makeSuccessCallbacks();
}
void Geolocation::setError(GeolocationError* error)
{
+ if (m_isSuspended) {
+ m_errorWaitingForResume = createPositionError(error);
+ return;
+ }
RefPtr<PositionError> positionError = createPositionError(error);
handleError(positionError.get());
}
@@ -662,14 +687,11 @@ void Geolocation::handlePendingPermissionNotifiers()
{
// While we iterate through the list, we need not worry about list being modified as the permission
// is already set to Yes/No and no new listeners will be added to the pending list
- GeoNotifierSet::const_iterator end = m_pendingForPermissionNotifiers.end();
- for (GeoNotifierSet::const_iterator iter = m_pendingForPermissionNotifiers.begin(); iter != end; ++iter) {
- GeoNotifier* notifier = iter->get();
-
+ for (auto& notifier : m_pendingForPermissionNotifiers) {
if (isAllowed()) {
// start all pending notification requests as permission granted.
// The notifier is always ref'ed by m_oneShots or m_watchers.
- if (startUpdating(notifier))
+ if (startUpdating(notifier.get()))
notifier->startTimerIfNeeded();
else
notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, ASCIILiteral(failedToStartServiceErrorMessage)));
diff --git a/Source/WebCore/Modules/geolocation/Geolocation.h b/Source/WebCore/Modules/geolocation/Geolocation.h
index a1bd9eb83..0a6830677 100644
--- a/Source/WebCore/Modules/geolocation/Geolocation.h
+++ b/Source/WebCore/Modules/geolocation/Geolocation.h
@@ -42,77 +42,60 @@ namespace WebCore {
class Document;
class Frame;
+class GeoNotifier;
class GeolocationController;
class GeolocationError;
class GeolocationPosition;
class Page;
class ScriptExecutionContext;
+class SecurityOrigin;
class Geolocation : public ScriptWrappable, public RefCounted<Geolocation>, public ActiveDOMObject
{
+friend class GeoNotifier;
+
public:
- static PassRefPtr<Geolocation> create(ScriptExecutionContext*);
- ~Geolocation();
+ static Ref<Geolocation> create(ScriptExecutionContext*);
+ WEBCORE_EXPORT ~Geolocation();
- virtual void stop() OVERRIDE;
+ WEBCORE_EXPORT void resetAllGeolocationPermission();
Document* document() const;
- Frame* frame() const;
+ WEBCORE_EXPORT Frame* frame() const;
- void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>);
- int watchPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>);
+ void getCurrentPosition(RefPtr<PositionCallback>&&, RefPtr<PositionErrorCallback>&&, RefPtr<PositionOptions>&&);
+ int watchPosition(RefPtr<PositionCallback>&&, RefPtr<PositionErrorCallback>&&, RefPtr<PositionOptions>&&);
void clearWatch(int watchID);
- void setIsAllowed(bool);
+ WEBCORE_EXPORT void setIsAllowed(bool);
+ void resetIsAllowed() { m_allowGeolocation = Unknown; }
bool isAllowed() const { return m_allowGeolocation == Yes; }
void positionChanged();
void setError(GeolocationError*);
private:
- Geoposition* lastPosition();
-
- bool isDenied() const { return m_allowGeolocation == No; }
-
explicit Geolocation(ScriptExecutionContext*);
- Page* page() const;
-
- class GeoNotifier : public RefCounted<GeoNotifier> {
- public:
- static PassRefPtr<GeoNotifier> create(Geolocation* geolocation, PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options)); }
-
- PositionOptions* options() const { return m_options.get(); };
- void setFatalError(PassRefPtr<PositionError>);
-
- bool useCachedPosition() const { return m_useCachedPosition; }
- void setUseCachedPosition();
+ Geoposition* lastPosition();
- void runSuccessCallback(Geoposition*);
- void runErrorCallback(PositionError*);
+ // ActiveDOMObject
+ void stop() override;
+ bool canSuspendForDocumentSuspension() const override;
+ void suspend(ReasonForSuspension) override;
+ void resume() override;
+ const char* activeDOMObjectName() const override;
- void startTimerIfNeeded();
- void stopTimer();
- void timerFired(Timer<GeoNotifier>*);
- bool hasZeroTimeout() const;
+ bool isDenied() const { return m_allowGeolocation == No; }
- private:
- GeoNotifier(Geolocation*, PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>);
-
- RefPtr<Geolocation> m_geolocation;
- RefPtr<PositionCallback> m_successCallback;
- RefPtr<PositionErrorCallback> m_errorCallback;
- RefPtr<PositionOptions> m_options;
- Timer<GeoNotifier> m_timer;
- RefPtr<PositionError> m_fatalError;
- bool m_useCachedPosition;
- };
+ Page* page() const;
+ SecurityOrigin* securityOrigin() const;
- typedef Vector<RefPtr<GeoNotifier> > GeoNotifierVector;
- typedef HashSet<RefPtr<GeoNotifier> > GeoNotifierSet;
+ typedef Vector<RefPtr<GeoNotifier>> GeoNotifierVector;
+ typedef HashSet<RefPtr<GeoNotifier>> GeoNotifierSet;
class Watchers {
public:
- bool add(int id, PassRefPtr<GeoNotifier>);
+ bool add(int id, RefPtr<GeoNotifier>&&);
GeoNotifier* find(int id);
void remove(int id);
void remove(GeoNotifier*);
@@ -121,7 +104,7 @@ private:
bool isEmpty() const;
void getNotifiersVector(GeoNotifierVector&) const;
private:
- typedef HashMap<int, RefPtr<GeoNotifier> > IdToNotifierMap;
+ typedef HashMap<int, RefPtr<GeoNotifier>> IdToNotifierMap;
typedef HashMap<RefPtr<GeoNotifier>, int> NotifierToIdMap;
IdToNotifierMap m_idToNotifierMap;
NotifierToIdMap m_notifierToIdMap;
@@ -172,6 +155,13 @@ private:
Yes,
No
} m_allowGeolocation;
+ bool m_isSuspended;
+ bool m_resetOnResume;
+ bool m_hasChangedPosition;
+ RefPtr<PositionError> m_errorWaitingForResume;
+
+ void resumeTimerFired();
+ Timer m_resumeTimer;
GeoNotifierSet m_requestsAwaitingCachedPosition;
};
diff --git a/Source/WebCore/Modules/geolocation/GeolocationClient.h b/Source/WebCore/Modules/geolocation/GeolocationClient.h
index d89387105..af6cbe6c6 100644
--- a/Source/WebCore/Modules/geolocation/GeolocationClient.h
+++ b/Source/WebCore/Modules/geolocation/GeolocationClient.h
@@ -54,7 +54,7 @@ protected:
virtual ~GeolocationClient() { }
};
-void provideGeolocationTo(Page*, GeolocationClient*);
+WEBCORE_EXPORT void provideGeolocationTo(Page*, GeolocationClient*);
} // namespace WebCore
diff --git a/Source/WebCore/Modules/geolocation/GeolocationController.cpp b/Source/WebCore/Modules/geolocation/GeolocationController.cpp
index fca4563ea..0a10a8f5b 100644
--- a/Source/WebCore/Modules/geolocation/GeolocationController.cpp
+++ b/Source/WebCore/Modules/geolocation/GeolocationController.cpp
@@ -31,27 +31,25 @@
#include "GeolocationClient.h"
#include "GeolocationError.h"
#include "GeolocationPosition.h"
-#include "InspectorInstrumentation.h"
namespace WebCore {
-GeolocationController::GeolocationController(Page* page, GeolocationClient* client)
- : m_client(client)
- , m_page(page)
+GeolocationController::GeolocationController(Page& page, GeolocationClient& client)
+ : m_page(page)
+ , m_client(client)
{
+ m_page.addViewStateChangeObserver(*this);
}
GeolocationController::~GeolocationController()
{
ASSERT(m_observers.isEmpty());
- if (m_client)
- m_client->geolocationDestroyed();
-}
+ // NOTE: We don't have to remove ourselves from page's ViewStateChangeObserver set, since
+ // we are supplement of the Page, and our destructor getting called means the page is being
+ // torn down.
-PassOwnPtr<GeolocationController> GeolocationController::create(Page* page, GeolocationClient* client)
-{
- return adoptPtr(new GeolocationController(page, client));
+ m_client.geolocationDestroyed();
}
void GeolocationController::addObserver(Geolocation* observer, bool enableHighAccuracy)
@@ -63,12 +61,10 @@ void GeolocationController::addObserver(Geolocation* observer, bool enableHighAc
if (enableHighAccuracy)
m_highAccuracyObservers.add(observer);
- if (m_client) {
- if (enableHighAccuracy)
- m_client->setEnableHighAccuracy(true);
- if (wasEmpty)
- m_client->startUpdating();
- }
+ if (enableHighAccuracy)
+ m_client.setEnableHighAccuracy(true);
+ if (wasEmpty && m_page.isVisible())
+ m_client.startUpdating();
}
void GeolocationController::removeObserver(Geolocation* observer)
@@ -79,46 +75,45 @@ void GeolocationController::removeObserver(Geolocation* observer)
m_observers.remove(observer);
m_highAccuracyObservers.remove(observer);
- if (m_client) {
- if (m_observers.isEmpty())
- m_client->stopUpdating();
- else if (m_highAccuracyObservers.isEmpty())
- m_client->setEnableHighAccuracy(false);
- }
+ if (m_observers.isEmpty())
+ m_client.stopUpdating();
+ else if (m_highAccuracyObservers.isEmpty())
+ m_client.setEnableHighAccuracy(false);
}
void GeolocationController::requestPermission(Geolocation* geolocation)
{
- if (m_client)
- m_client->requestPermission(geolocation);
+ if (!m_page.isVisible()) {
+ m_pendedPermissionRequest.add(geolocation);
+ return;
+ }
+
+ m_client.requestPermission(geolocation);
}
void GeolocationController::cancelPermissionRequest(Geolocation* geolocation)
{
- if (m_client)
- m_client->cancelPermissionRequest(geolocation);
+ if (m_pendedPermissionRequest.remove(geolocation))
+ return;
+
+ m_client.cancelPermissionRequest(geolocation);
}
void GeolocationController::positionChanged(GeolocationPosition* position)
{
- position = InspectorInstrumentation::overrideGeolocationPosition(m_page, position);
- if (!position) {
- errorOccurred(GeolocationError::create(GeolocationError::PositionUnavailable, ASCIILiteral("PositionUnavailable")).get());
- return;
- }
m_lastPosition = position;
- Vector<RefPtr<Geolocation> > observersVector;
+ Vector<RefPtr<Geolocation>> observersVector;
copyToVector(m_observers, observersVector);
- for (size_t i = 0; i < observersVector.size(); ++i)
- observersVector[i]->positionChanged();
+ for (auto& observer : observersVector)
+ observer->positionChanged();
}
void GeolocationController::errorOccurred(GeolocationError* error)
{
- Vector<RefPtr<Geolocation> > observersVector;
+ Vector<RefPtr<Geolocation>> observersVector;
copyToVector(m_observers, observersVector);
- for (size_t i = 0; i < observersVector.size(); ++i)
- observersVector[i]->setError(error);
+ for (auto& observer : observersVector)
+ observer->setError(error);
}
GeolocationPosition* GeolocationController::lastPosition()
@@ -126,10 +121,26 @@ GeolocationPosition* GeolocationController::lastPosition()
if (m_lastPosition.get())
return m_lastPosition.get();
- if (!m_client)
- return 0;
+ return m_client.lastPosition();
+}
+
+void GeolocationController::viewStateDidChange(ViewState::Flags oldViewState, ViewState::Flags newViewState)
+{
+ // Toggle GPS based on page visibility to save battery.
+ ViewState::Flags changed = oldViewState ^ newViewState;
+ if (changed & ViewState::IsVisible && !m_observers.isEmpty()) {
+ if (newViewState & ViewState::IsVisible)
+ m_client.startUpdating();
+ else
+ m_client.stopUpdating();
+ }
+
+ if (!m_page.isVisible())
+ return;
- return m_client->lastPosition();
+ HashSet<RefPtr<Geolocation>> pendedPermissionRequests = WTFMove(m_pendedPermissionRequest);
+ for (auto& permissionRequest : pendedPermissionRequests)
+ m_client.requestPermission(permissionRequest.get());
}
const char* GeolocationController::supplementName()
@@ -139,7 +150,9 @@ const char* GeolocationController::supplementName()
void provideGeolocationTo(Page* page, GeolocationClient* client)
{
- Supplement<Page>::provideTo(page, GeolocationController::supplementName(), GeolocationController::create(page, client));
+ ASSERT(page);
+ ASSERT(client);
+ Supplement<Page>::provideTo(page, GeolocationController::supplementName(), std::make_unique<GeolocationController>(*page, *client));
}
} // namespace WebCore
diff --git a/Source/WebCore/Modules/geolocation/GeolocationController.h b/Source/WebCore/Modules/geolocation/GeolocationController.h
index c4689ac7e..ddea6c5a7 100644
--- a/Source/WebCore/Modules/geolocation/GeolocationController.h
+++ b/Source/WebCore/Modules/geolocation/GeolocationController.h
@@ -30,6 +30,7 @@
#include "Geolocation.h"
#include "Page.h"
+#include "ViewStateChangeObserver.h"
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
#include <wtf/RefPtr.h>
@@ -41,40 +42,44 @@ class GeolocationError;
class GeolocationPosition;
class Page;
-class GeolocationController : public Supplement<Page> {
+class GeolocationController : public Supplement<Page>, private ViewStateChangeObserver {
+ WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(GeolocationController);
public:
+ GeolocationController(Page&, GeolocationClient&);
~GeolocationController();
- static PassOwnPtr<GeolocationController> create(Page*, GeolocationClient*);
-
void addObserver(Geolocation*, bool enableHighAccuracy);
void removeObserver(Geolocation*);
void requestPermission(Geolocation*);
void cancelPermissionRequest(Geolocation*);
- void positionChanged(GeolocationPosition*);
- void errorOccurred(GeolocationError*);
+ WEBCORE_EXPORT void positionChanged(GeolocationPosition*);
+ WEBCORE_EXPORT void errorOccurred(GeolocationError*);
GeolocationPosition* lastPosition();
- GeolocationClient* client() { return m_client; }
+ GeolocationClient& client() { return m_client; }
- static const char* supplementName();
+ WEBCORE_EXPORT static const char* supplementName();
static GeolocationController* from(Page* page) { return static_cast<GeolocationController*>(Supplement<Page>::from(page, supplementName())); }
private:
- GeolocationController(Page*, GeolocationClient*);
+ Page& m_page;
+ GeolocationClient& m_client;
- GeolocationClient* m_client;
- Page* m_page;
+ virtual void viewStateDidChange(ViewState::Flags oldViewState, ViewState::Flags newViewState) override;
RefPtr<GeolocationPosition> m_lastPosition;
- typedef HashSet<RefPtr<Geolocation> > ObserversSet;
+
+ typedef HashSet<RefPtr<Geolocation>> ObserversSet;
// All observers; both those requesting high accuracy and those not.
ObserversSet m_observers;
ObserversSet m_highAccuracyObservers;
+
+ // While the page is not visible, we pend permission requests.
+ HashSet<RefPtr<Geolocation>> m_pendedPermissionRequest;
};
} // namespace WebCore
diff --git a/Source/WebCore/Modules/geolocation/GeolocationError.h b/Source/WebCore/Modules/geolocation/GeolocationError.h
index bfb61aabe..ebb7aa73d 100644
--- a/Source/WebCore/Modules/geolocation/GeolocationError.h
+++ b/Source/WebCore/Modules/geolocation/GeolocationError.h
@@ -26,7 +26,6 @@
#ifndef GeolocationError_h
#define GeolocationError_h
-#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/text/WTFString.h>
@@ -40,7 +39,7 @@ public:
PositionUnavailable
};
- static PassRefPtr<GeolocationError> create(ErrorCode code, const String& message) { return adoptRef(new GeolocationError(code, message)); }
+ static Ref<GeolocationError> create(ErrorCode code, const String& message) { return adoptRef(*new GeolocationError(code, message)); }
ErrorCode code() const { return m_code; }
const String& message() const { return m_message; }
diff --git a/Source/WebCore/Modules/geolocation/GeolocationPosition.h b/Source/WebCore/Modules/geolocation/GeolocationPosition.h
index 7b15648f8..dbdd735b9 100644
--- a/Source/WebCore/Modules/geolocation/GeolocationPosition.h
+++ b/Source/WebCore/Modules/geolocation/GeolocationPosition.h
@@ -26,7 +26,6 @@
#ifndef GeolocationPosition_h
#define GeolocationPosition_h
-#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -34,9 +33,15 @@ namespace WebCore {
class GeolocationPosition : public RefCounted<GeolocationPosition> {
public:
- static PassRefPtr<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy) { return adoptRef(new GeolocationPosition(timestamp, latitude, longitude, accuracy)); }
+ static Ref<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy)
+ {
+ return adoptRef(*new GeolocationPosition(timestamp, latitude, longitude, accuracy));
+ }
- static PassRefPtr<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(new GeolocationPosition(timestamp, latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed)); }
+ static Ref<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed)
+ {
+ return adoptRef(*new GeolocationPosition(timestamp, latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed));
+ }
double timestamp() const { return m_timestamp; }
diff --git a/Source/WebCore/Modules/geolocation/Geoposition.h b/Source/WebCore/Modules/geolocation/Geoposition.h
index 27064dddf..e41372c8f 100644
--- a/Source/WebCore/Modules/geolocation/Geoposition.h
+++ b/Source/WebCore/Modules/geolocation/Geoposition.h
@@ -35,22 +35,22 @@ namespace WebCore {
class Geoposition : public RefCounted<Geoposition> {
public:
- static PassRefPtr<Geoposition> create(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp)
+ static Ref<Geoposition> create(RefPtr<Coordinates>&& coordinates, DOMTimeStamp timestamp)
{
- return adoptRef(new Geoposition(coordinates, timestamp));
+ return adoptRef(*new Geoposition(WTFMove(coordinates), timestamp));
}
- PassRefPtr<Geoposition> isolatedCopy() const
+ Ref<Geoposition> isolatedCopy() const
{
- return Geoposition::create(m_coordinates->isolatedCopy(), m_timestamp);
+ return create(m_coordinates->isolatedCopy(), m_timestamp);
}
DOMTimeStamp timestamp() const { return m_timestamp; }
Coordinates* coords() const { return m_coordinates.get(); }
private:
- Geoposition(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp)
- : m_coordinates(coordinates)
+ Geoposition(RefPtr<Coordinates>&& coordinates, DOMTimeStamp timestamp)
+ : m_coordinates(WTFMove(coordinates))
, m_timestamp(timestamp)
{
ASSERT(m_coordinates);
diff --git a/Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp b/Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp
index 88bd4b97c..ad56fcacf 100644
--- a/Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp
+++ b/Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 2000 Harri Porten (porten@kde.org)
* Copyright (c) 2000 Daniel Molkentin (molkentin@kde.org)
* Copyright (c) 2000 Stefan Schimanski (schimmi@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Inc.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This library is free software; you can redistribute it and/or
@@ -51,15 +51,24 @@ NavigatorGeolocation* NavigatorGeolocation::from(Navigator* navigator)
{
NavigatorGeolocation* supplement = static_cast<NavigatorGeolocation*>(Supplement<Navigator>::from(navigator, supplementName()));
if (!supplement) {
- supplement = new NavigatorGeolocation(navigator->frame());
- provideTo(navigator, supplementName(), adoptPtr(supplement));
+ auto newSupplement = std::make_unique<NavigatorGeolocation>(navigator->frame());
+ supplement = newSupplement.get();
+ provideTo(navigator, supplementName(), WTFMove(newSupplement));
}
return supplement;
}
-Geolocation* NavigatorGeolocation::geolocation(Navigator* navigator)
+#if PLATFORM(IOS)
+void NavigatorGeolocation::resetAllGeolocationPermission()
{
- return NavigatorGeolocation::from(navigator)->geolocation();
+ if (m_geolocation)
+ m_geolocation->resetAllGeolocationPermission();
+}
+#endif // PLATFORM(IOS)
+
+Geolocation* NavigatorGeolocation::geolocation(Navigator& navigator)
+{
+ return NavigatorGeolocation::from(&navigator)->geolocation();
}
Geolocation* NavigatorGeolocation::geolocation() const
diff --git a/Source/WebCore/Modules/geolocation/NavigatorGeolocation.h b/Source/WebCore/Modules/geolocation/NavigatorGeolocation.h
index 0130a2cf0..f68d09162 100644
--- a/Source/WebCore/Modules/geolocation/NavigatorGeolocation.h
+++ b/Source/WebCore/Modules/geolocation/NavigatorGeolocation.h
@@ -32,15 +32,20 @@ class Geolocation;
class Navigator;
class NavigatorGeolocation : public Supplement<Navigator>, public DOMWindowProperty {
+ WTF_MAKE_FAST_ALLOCATED;
public:
+ explicit NavigatorGeolocation(Frame*);
virtual ~NavigatorGeolocation();
static NavigatorGeolocation* from(Navigator*);
- static Geolocation* geolocation(Navigator*);
+ static Geolocation* geolocation(Navigator&);
Geolocation* geolocation() const;
+#if PLATFORM(IOS)
+ void resetAllGeolocationPermission();
+#endif // PLATFORM(IOS)
+
private:
- NavigatorGeolocation(Frame*);
static const char* supplementName();
mutable RefPtr<Geolocation> m_geolocation;
diff --git a/Source/WebCore/Modules/geolocation/PositionCallback.idl b/Source/WebCore/Modules/geolocation/PositionCallback.idl
index 51cbde5ac..819b3852a 100644
--- a/Source/WebCore/Modules/geolocation/PositionCallback.idl
+++ b/Source/WebCore/Modules/geolocation/PositionCallback.idl
@@ -24,6 +24,7 @@
[
Conditional=GEOLOCATION,
+ Callback=FunctionOnly,
] callback interface PositionCallback {
boolean handleEvent(Geoposition position);
};
diff --git a/Source/WebCore/Modules/geolocation/PositionError.h b/Source/WebCore/Modules/geolocation/PositionError.h
index aa51c6a33..81c25b7c4 100644
--- a/Source/WebCore/Modules/geolocation/PositionError.h
+++ b/Source/WebCore/Modules/geolocation/PositionError.h
@@ -26,7 +26,6 @@
#ifndef PositionError_h
#define PositionError_h
-#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
@@ -40,7 +39,7 @@ public:
TIMEOUT = 3
};
- static PassRefPtr<PositionError> create(ErrorCode code, const String& message) { return adoptRef(new PositionError(code, message)); }
+ static Ref<PositionError> create(ErrorCode code, const String& message) { return adoptRef(*new PositionError(code, message)); }
ErrorCode code() const { return m_code; }
const String& message() const { return m_message; }
diff --git a/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl b/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl
index 78121b8cf..2a609d3ef 100644
--- a/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl
+++ b/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl
@@ -24,6 +24,7 @@
[
Conditional=GEOLOCATION,
+ Callback=FunctionOnly,
] callback interface PositionErrorCallback {
boolean handleEvent(PositionError error);
};
diff --git a/Source/WebCore/Modules/geolocation/PositionOptions.h b/Source/WebCore/Modules/geolocation/PositionOptions.h
index 5cb66f735..05dabe19f 100644
--- a/Source/WebCore/Modules/geolocation/PositionOptions.h
+++ b/Source/WebCore/Modules/geolocation/PositionOptions.h
@@ -26,14 +26,13 @@
#ifndef PositionOptions_h
#define PositionOptions_h
-#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
namespace WebCore {
class PositionOptions : public RefCounted<PositionOptions> {
public:
- static PassRefPtr<PositionOptions> create() { return adoptRef(new PositionOptions()); }
+ static Ref<PositionOptions> create() { return adoptRef(*new PositionOptions()); }
bool enableHighAccuracy() const { return m_highAccuracy; }
void setEnableHighAccuracy(bool enable) { m_highAccuracy = enable; }