diff options
| author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
|---|---|---|
| committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
| commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
| tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/Modules/geolocation | |
| parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
| download | qtwebkit-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')
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; } |
