diff options
Diffstat (limited to 'Source/WebCore/Modules/geolocation')
24 files changed, 544 insertions, 482 deletions
diff --git a/Source/WebCore/Modules/geolocation/Coordinates.cpp b/Source/WebCore/Modules/geolocation/Coordinates.cpp index d7b759d37..8981fb55e 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 +std::optional<double> Coordinates::altitude() const { - if (m_canProvideAltitude) - return m_altitude; - - isNull = true; - return 0; + if (!m_canProvideAltitude) + return std::nullopt; + return m_altitude; } -double Coordinates::altitudeAccuracy(bool& isNull) const +std::optional<double> Coordinates::altitudeAccuracy() const { - if (m_canProvideAltitudeAccuracy) - return m_altitudeAccuracy; - - isNull = true; - return 0; + if (!m_canProvideAltitudeAccuracy) + return std::nullopt; + return m_altitudeAccuracy; } -double Coordinates::heading(bool& isNull) const +std::optional<double> Coordinates::heading() const { - if (m_canProvideHeading) - return m_heading; - - isNull = true; - return 0; + if (!m_canProvideHeading) + return std::nullopt; + return m_heading; } -double Coordinates::speed(bool& isNull) const +std::optional<double> Coordinates::speed() const { - if (m_canProvideSpeed) - return m_speed; - - isNull = true; - return 0; + if (!m_canProvideSpeed) + return std::nullopt; + return m_speed; } } // namespace WebCore diff --git a/Source/WebCore/Modules/geolocation/Coordinates.h b/Source/WebCore/Modules/geolocation/Coordinates.h index fb134a502..08c313b18 100644 --- a/Source/WebCore/Modules/geolocation/Coordinates.h +++ b/Source/WebCore/Modules/geolocation/Coordinates.h @@ -23,30 +23,30 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Coordinates_h -#define Coordinates_h +#pragma once #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; + std::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; + std::optional<double> altitudeAccuracy() const; + std::optional<double> heading() const; + std::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) @@ -79,5 +79,3 @@ private: }; } // namespace WebCore - -#endif // Coordinates_h 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..09c4ec960 --- /dev/null +++ b/Source/WebCore/Modules/geolocation/GeoNotifier.cpp @@ -0,0 +1,132 @@ +/* + * 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, Ref<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, 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) +{ +} + +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.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() +{ + 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> protectedThis(*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..b2d30f3da --- /dev/null +++ b/Source/WebCore/Modules/geolocation/GeoNotifier.h @@ -0,0 +1,80 @@ +/* + * 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. + */ + +#pragma once + +#if ENABLE(GEOLOCATION) + +#include "PositionOptions.h" +#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 GeoNotifier : public RefCounted<GeoNotifier> { +public: + static Ref<GeoNotifier> create(Geolocation& geolocation, Ref<PositionCallback>&& positionCallback, RefPtr<PositionErrorCallback>&& positionErrorCallback, PositionOptions&& options) + { + return adoptRef(*new GeoNotifier(geolocation, WTFMove(positionCallback), WTFMove(positionErrorCallback), WTFMove(options))); + } + + const PositionOptions& options() const { return m_options; } + 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&, Ref<PositionCallback>&&, RefPtr<PositionErrorCallback>&&, PositionOptions&&); + + Ref<Geolocation> m_geolocation; + Ref<PositionCallback> m_successCallback; + RefPtr<PositionErrorCallback> m_errorCallback; + PositionOptions m_options; + Timer m_timer; + RefPtr<PositionError> m_fatalError; + bool m_useCachedPosition; +}; + +} // namespace WebCore + +#endif // ENABLE(GEOLOCATION) diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp index 15cd1b80e..36109f35f 100644 --- a/Source/WebCore/Modules/geolocation/Geolocation.cpp +++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp @@ -30,37 +30,41 @@ #if ENABLE(GEOLOCATION) +#include "Coordinates.h" #include "Document.h" #include "Frame.h" -#include "Geoposition.h" -#include "Page.h" -#include <wtf/CurrentTime.h> -#include <wtf/Ref.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> +#include <wtf/text/StringBuilder.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(), - position->canProvideHeading(), position->heading(), position->canProvideSpeed(), position->speed()); - return Geoposition::create(coordinates.release(), convertSecondsToDOMTimeStamp(position->timestamp())); + auto coordinates = Coordinates::create(position->latitude(), position->longitude(), position->canProvideAltitude(), position->altitude(), + position->accuracy(), position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(), + position->canProvideHeading(), position->heading(), position->canProvideSpeed(), position->speed()); + + return Geoposition::create(WTFMove(coordinates), convertSecondsToDOMTimeStamp(position->timestamp())); } -static PassRefPtr<PositionError> createPositionError(GeolocationError* error) +static Ref<PositionError> createPositionError(GeolocationError* error) { PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE; switch (error->code()) { @@ -75,117 +79,17 @@ 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. - 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); -} - -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); return m_idToNotifierMap.get(id); @@ -225,21 +129,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) -#if PLATFORM(IOS) , m_isSuspended(false) , m_hasChangedPosition(false) - , m_resumeTimer(this, &Geolocation::resumeTimerFired) -#endif + , m_resumeTimer(*this, &Geolocation::resumeTimerFired) { } @@ -248,33 +150,24 @@ Geolocation::~Geolocation() ASSERT(m_allowGeolocation != InProgress); } -Document* Geolocation::document() const +SecurityOrigin* Geolocation::securityOrigin() const { - return toDocument(scriptExecutionContext()); -} - -Frame* Geolocation::frame() const -{ - return document() ? document()->frame() : 0; + return scriptExecutionContext()->securityOrigin(); } Page* Geolocation::page() const { - return document() ? document()->page() : 0; + return document() ? document()->page() : nullptr; } -#if PLATFORM(IOS) -bool Geolocation::canSuspend() const +bool Geolocation::canSuspendForDocumentSuspension() const { - return !hasListeners(); + return true; } - + void Geolocation::suspend(ReasonForSuspension reason) { - // Allow pages that no longer have listeners to enter the page cache. - // Have them stop updating and reset geolocation permissions when the page is resumed. - if (reason == ActiveDOMObject::DocumentWillBecomeInactive) { - ASSERT(!hasListeners()); + if (reason == ActiveDOMObject::PageCache) { stop(); m_resetOnResume = true; } @@ -290,14 +183,16 @@ void Geolocation::suspend(ReasonForSuspension reason) void Geolocation::resume() { +#if USE(WEB_THREAD) ASSERT(WebThreadIsLockedOrDisabled()); +#endif ActiveDOMObject::resume(); if (!m_resumeTimer.isActive()) m_resumeTimer.startOneShot(0); } -void Geolocation::resumeTimerFired(Timer<Geolocation>&) +void Geolocation::resumeTimerFired() { m_isSuspended = false; @@ -308,13 +203,12 @@ void Geolocation::resumeTimerFired(Timer<Geolocation>&) // Resume GeoNotifier timeout timers. if (hasListeners()) { - GeoNotifierSet::const_iterator end = m_oneShots.end(); - for (GeoNotifierSet::const_iterator it = m_oneShots.begin(); it != end; ++it) - (*it)->startTimerIfNeeded(); + for (auto& notifier : m_oneShots) + notifier->startTimerIfNeeded(); GeoNotifierVector watcherCopy; m_watchers.getNotifiersVector(watcherCopy); - for (size_t i = 0; i < watcherCopy.size(); ++i) - watcherCopy[i]->startTimerIfNeeded(); + for (auto& watcher : watcherCopy) + watcher->startTimerIfNeeded(); } if ((isAllowed() || isDenied()) && !m_pendingForPermissionNotifiers.isEmpty()) { @@ -369,16 +263,14 @@ void Geolocation::resetAllGeolocationPermission() stopTimers(); // Go over the one shot and re-request permission. - GeoNotifierSet::iterator end = m_oneShots.end(); - for (GeoNotifierSet::iterator it = m_oneShots.begin(); it != end; ++it) - startRequest((*it).get()); + for (auto& notifier : m_oneShots) + startRequest(notifier.get()); // Go over the watchers and re-request permission. GeoNotifierVector watcherCopy; m_watchers.getNotifiersVector(watcherCopy); - for (size_t i = 0; i < watcherCopy.size(); ++i) - startRequest(watcherCopy[i].get()); + for (auto& watcher : watcherCopy) + startRequest(watcher.get()); } -#endif // PLATFORM(IOS) void Geolocation::stop() { @@ -389,13 +281,16 @@ void Geolocation::stop() m_allowGeolocation = Unknown; cancelAllRequests(); stopUpdating(); -#if PLATFORM(IOS) m_hasChangedPosition = false; m_errorWaitingForResume = nullptr; -#endif // PLATFORM(IOS) m_pendingForPermissionNotifiers.clear(); } +const char* Geolocation::activeDOMObjectName() const +{ + return "Geolocation"; +} + Geoposition* Geolocation::lastPosition() { Page* page = this->page(); @@ -407,35 +302,72 @@ Geoposition* Geolocation::lastPosition() return m_lastPosition.get(); } -void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) +void Geolocation::getCurrentPosition(Ref<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, 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(Ref<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, 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) +static void logError(const String& target, const bool isSecure, const bool isMixedContent, Document* document) { + StringBuilder message; + message.append("[blocked] Access to geolocation was blocked over"); + + if (!isSecure) + message.append(" insecure connection to "); + else if (isMixedContent) + message.append(" secure connection with mixed content to "); + else + return; + + message.append(target); + message.append(".\n"); + document->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message.toString()); +} + +bool Geolocation::shouldBlockGeolocationRequests() +{ + bool isSecure = SecurityOrigin::isSecure(document()->url()); + bool hasMixedContent = document()->foundMixedContent(); + bool isLocalFile = document()->url().isLocalFile(); + if (securityOrigin()->canRequestGeolocation()) { + if (isLocalFile || (isSecure && !hasMixedContent)) + return false; + } + + logError(securityOrigin()->toString(), isSecure, hasMixedContent, document()); + return true; +} + +void Geolocation::startRequest(GeoNotifier* notifier) +{ + if (shouldBlockGeolocationRequests()) { + notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, ASCIILiteral(originCannotRequestGeolocationErrorMessage))); + return; + } + document()->setGeolocationAccessed(); + // 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()) @@ -454,7 +386,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); @@ -490,15 +422,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.remove(notifier) && 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))); @@ -520,17 +450,15 @@ void Geolocation::requestTimedOut(GeoNotifier* notifier) stopUpdating(); } -bool Geolocation::haveSuitableCachedPosition(PositionOptions* options) +bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options) { Geoposition* cachedPosition = lastPosition(); if (!cachedPosition) return false; - if (!options->hasMaximumAge()) - return true; - if (!options->maximumAge()) + if (!options.maximumAge) return false; DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime()); - return cachedPosition->timestamp() > currentTimeMillis - options->maximumAge(); + return cachedPosition->timestamp() > currentTimeMillis - options.maximumAge; } void Geolocation::clearWatch(int watchID) @@ -549,16 +477,14 @@ void Geolocation::clearWatch(int watchID) void Geolocation::setIsAllowed(bool allowed) { // Protect the Geolocation object from garbage collection during a callback. - Ref<Geolocation> protect(*this); + Ref<Geolocation> protectedThis(*this); // This may be due to either a new position from the service, or a cached // position. m_allowGeolocation = allowed ? Yes : No; -#if PLATFORM(IOS) if (m_isSuspended) return; -#endif // Permission request was made during the startRequest process if (!m_pendingForPermissionNotifiers.isEmpty()) { @@ -572,10 +498,8 @@ void Geolocation::setIsAllowed(bool allowed) error->setIsFatal(true); handleError(error.get()); m_requestsAwaitingCachedPosition.clear(); -#if PLATFORM(IOS) m_hasChangedPosition = false; m_errorWaitingForResume = nullptr; -#endif return; } @@ -591,26 +515,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() @@ -637,9 +555,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() @@ -654,25 +571,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) @@ -756,24 +668,20 @@ void Geolocation::positionChanged() // Stop all currently running timers. stopTimers(); -#if PLATFORM(IOS) if (m_isSuspended) { m_hasChangedPosition = true; return; } -#endif makeSuccessCallbacks(); } void Geolocation::setError(GeolocationError* error) { -#if PLATFORM(IOS) if (m_isSuspended) { m_errorWaitingForResume = createPositionError(error); return; } -#endif RefPtr<PositionError> positionError = createPositionError(error); handleError(positionError.get()); } @@ -784,7 +692,7 @@ bool Geolocation::startUpdating(GeoNotifier* notifier) if (!page) return false; - GeolocationController::from(page)->addObserver(this, notifier->options()->enableHighAccuracy()); + GeolocationController::from(page)->addObserver(this, notifier->options().enableHighAccuracy); return true; } @@ -801,14 +709,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 ab486443e..3396cdc85 100644 --- a/Source/WebCore/Modules/geolocation/Geolocation.h +++ b/Source/WebCore/Modules/geolocation/Geolocation.h @@ -24,12 +24,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Geolocation_h -#define Geolocation_h +#pragma once #if ENABLE(GEOLOCATION) #include "ActiveDOMObject.h" +#include "Document.h" #include "Geoposition.h" #include "PositionCallback.h" #include "PositionError.h" @@ -37,41 +37,40 @@ #include "PositionOptions.h" #include "ScriptWrappable.h" #include "Timer.h" +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> namespace WebCore { -class Document; class Frame; -class GeolocationController; +class GeoNotifier; class GeolocationError; -class GeolocationPosition; class Page; class ScriptExecutionContext; +class SecurityOrigin; +struct PositionOptions; -class Geolocation : public ScriptWrappable, public RefCounted<Geolocation>, public ActiveDOMObject -{ +class Geolocation : public ScriptWrappable, public RefCounted<Geolocation>, public ActiveDOMObject { + friend class GeoNotifier; public: - static PassRefPtr<Geolocation> create(ScriptExecutionContext*); - ~Geolocation(); - -#if PLATFORM(IOS) - virtual bool canSuspend() const override; - virtual void suspend(ReasonForSuspension) override; - virtual void resume() override; - void resetAllGeolocationPermission(); -#endif // PLATFORM(IOS) - Document* document() const; - Frame* frame() const; - - void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); - int watchPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); + static Ref<Geolocation> create(ScriptExecutionContext*); + WEBCORE_EXPORT ~Geolocation(); + + WEBCORE_EXPORT void resetAllGeolocationPermission(); + Document* document() const { return downcast<Document>(scriptExecutionContext()); } + Frame* frame() const { return document() ? document()->frame() : nullptr; } + + void getCurrentPosition(Ref<PositionCallback>&&, RefPtr<PositionErrorCallback>&&, PositionOptions&&); + int watchPosition(Ref<PositionCallback>&&, RefPtr<PositionErrorCallback>&&, 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*); + bool shouldBlockGeolocationRequests(); private: explicit Geolocation(ScriptExecutionContext*); @@ -79,48 +78,23 @@ private: Geoposition* lastPosition(); // ActiveDOMObject - virtual void stop() override; + void stop() override; + bool canSuspendForDocumentSuspension() const override; + void suspend(ReasonForSuspension) override; + void resume() override; + const char* activeDOMObjectName() const override; bool isDenied() const { return m_allowGeolocation == No; } 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(); - - void runSuccessCallback(Geoposition*); - void runErrorCallback(PositionError*); - - void startTimerIfNeeded(); - void stopTimer(); - void timerFired(Timer<GeoNotifier>&); - bool hasZeroTimeout() const; - - 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; - }; + SecurityOrigin* securityOrigin() const; 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*); @@ -166,7 +140,7 @@ private: void fatalErrorOccurred(GeoNotifier*); void requestTimedOut(GeoNotifier*); void requestUsesCachedPosition(GeoNotifier*); - bool haveSuitableCachedPosition(PositionOptions*); + bool haveSuitableCachedPosition(const PositionOptions&); void makeCachedPositionCallbacks(); GeoNotifierSet m_oneShots; @@ -180,15 +154,13 @@ private: Yes, No } m_allowGeolocation; -#if PLATFORM(IOS) bool m_isSuspended; bool m_resetOnResume; bool m_hasChangedPosition; RefPtr<PositionError> m_errorWaitingForResume; - void resumeTimerFired(Timer<Geolocation>&); - Timer<Geolocation> m_resumeTimer; -#endif // PLATFORM(IOS) + void resumeTimerFired(); + Timer m_resumeTimer; GeoNotifierSet m_requestsAwaitingCachedPosition; }; @@ -196,6 +168,3 @@ private: } // namespace WebCore #endif // ENABLE(GEOLOCATION) - -#endif // Geolocation_h - diff --git a/Source/WebCore/Modules/geolocation/Geolocation.idl b/Source/WebCore/Modules/geolocation/Geolocation.idl index e3ac9ea68..489af42ea 100644 --- a/Source/WebCore/Modules/geolocation/Geolocation.idl +++ b/Source/WebCore/Modules/geolocation/Geolocation.idl @@ -29,14 +29,16 @@ Conditional=GEOLOCATION, GenerateIsReachable=ImplFrame, ] interface Geolocation { - [Custom] void getCurrentPosition(PositionCallback successCallback, - optional PositionErrorCallback errorCallback, - optional PositionOptions options); + // FIXME: PositionErrorCallback should not be nullable + void getCurrentPosition(PositionCallback successCallback, + optional PositionErrorCallback? errorCallback, + optional PositionOptions options); - [Custom] long watchPosition(PositionCallback successCallback, - optional PositionErrorCallback errorCallback, - optional PositionOptions options); + // FIXME: PositionErrorCallback should not be nullable + long watchPosition(PositionCallback successCallback, + optional PositionErrorCallback? errorCallback, + optional PositionOptions options); - void clearWatch(long watchID); + void clearWatch(long watchId); }; diff --git a/Source/WebCore/Modules/geolocation/GeolocationClient.h b/Source/WebCore/Modules/geolocation/GeolocationClient.h index d89387105..b35d5ef1d 100644 --- a/Source/WebCore/Modules/geolocation/GeolocationClient.h +++ b/Source/WebCore/Modules/geolocation/GeolocationClient.h @@ -23,8 +23,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GeolocationClient_h -#define GeolocationClient_h +#pragma once namespace WebCore { @@ -54,8 +53,6 @@ protected: virtual ~GeolocationClient() { } }; -void provideGeolocationTo(Page*, GeolocationClient*); +WEBCORE_EXPORT void provideGeolocationTo(Page*, GeolocationClient*); } // namespace WebCore - -#endif // GeolocationClient_h diff --git a/Source/WebCore/Modules/geolocation/GeolocationController.cpp b/Source/WebCore/Modules/geolocation/GeolocationController.cpp index 95717296c..9e7a085fa 100644 --- a/Source/WebCore/Modules/geolocation/GeolocationController.cpp +++ b/Source/WebCore/Modules/geolocation/GeolocationController.cpp @@ -34,22 +34,22 @@ namespace WebCore { -GeolocationController::GeolocationController(GeolocationClient* client) - : m_client(client) +GeolocationController::GeolocationController(Page& page, GeolocationClient& client) + : m_page(page) + , m_client(client) { + m_page.addActivityStateChangeObserver(*this); } GeolocationController::~GeolocationController() { ASSERT(m_observers.isEmpty()); - if (m_client) - m_client->geolocationDestroyed(); -} + // NOTE: We don't have to remove ourselves from page's ActivityStateChangeObserver set, since + // we are supplement of the Page, and our destructor getting called means the page is being + // torn down. -PassOwnPtr<GeolocationController> GeolocationController::create(GeolocationClient* client) -{ - return adoptPtr(new GeolocationController(client)); + m_client.geolocationDestroyed(); } void GeolocationController::addObserver(Geolocation* observer, bool enableHighAccuracy) @@ -61,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) @@ -77,24 +75,28 @@ 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) @@ -102,16 +104,16 @@ void GeolocationController::positionChanged(GeolocationPosition* position) m_lastPosition = position; 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; 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() @@ -119,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::activityStateDidChange(ActivityState::Flags oldActivityState, ActivityState::Flags newActivityState) +{ + // Toggle GPS based on page visibility to save battery. + ActivityState::Flags changed = oldActivityState ^ newActivityState; + if (changed & ActivityState::IsVisible && !m_observers.isEmpty()) { + if (newActivityState & ActivityState::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() @@ -132,7 +150,9 @@ const char* GeolocationController::supplementName() void provideGeolocationTo(Page* page, GeolocationClient* client) { - Supplement<Page>::provideTo(page, GeolocationController::supplementName(), GeolocationController::create(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 9192c60dc..474708777 100644 --- a/Source/WebCore/Modules/geolocation/GeolocationController.h +++ b/Source/WebCore/Modules/geolocation/GeolocationController.h @@ -23,11 +23,11 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GeolocationController_h -#define GeolocationController_h +#pragma once #if ENABLE(GEOLOCATION) +#include "ActivityStateChangeObserver.h" #include "Geolocation.h" #include "Page.h" #include <wtf/HashSet.h> @@ -39,45 +39,47 @@ namespace WebCore { class GeolocationClient; class GeolocationError; class GeolocationPosition; -class Page; -class GeolocationController : public Supplement<Page> { +class GeolocationController : public Supplement<Page>, private ActivityStateChangeObserver { + WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(GeolocationController); public: + GeolocationController(Page&, GeolocationClient&); ~GeolocationController(); - static PassOwnPtr<GeolocationController> create(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(GeolocationClient*); + Page& m_page; + GeolocationClient& m_client; - GeolocationClient* m_client; + void activityStateDidChange(ActivityState::Flags oldActivityState, ActivityState::Flags newActivityState) override; RefPtr<GeolocationPosition> m_lastPosition; + 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 #endif // ENABLE(GEOLOCATION) - -#endif // GeolocationController_h diff --git a/Source/WebCore/Modules/geolocation/GeolocationError.h b/Source/WebCore/Modules/geolocation/GeolocationError.h index bfb61aabe..b7250a2bb 100644 --- a/Source/WebCore/Modules/geolocation/GeolocationError.h +++ b/Source/WebCore/Modules/geolocation/GeolocationError.h @@ -23,12 +23,9 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GeolocationError_h -#define GeolocationError_h +#pragma once -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> #include <wtf/text/WTFString.h> namespace WebCore { @@ -40,7 +37,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; } @@ -57,5 +54,3 @@ private: }; } // namespace WebCore - -#endif // GeolocationError_h diff --git a/Source/WebCore/Modules/geolocation/GeolocationPosition.h b/Source/WebCore/Modules/geolocation/GeolocationPosition.h index 7b15648f8..d3548b658 100644 --- a/Source/WebCore/Modules/geolocation/GeolocationPosition.h +++ b/Source/WebCore/Modules/geolocation/GeolocationPosition.h @@ -23,20 +23,24 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GeolocationPosition_h -#define GeolocationPosition_h +#pragma once -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> 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; } @@ -103,5 +107,3 @@ private: }; } // namespace WebCore - -#endif // GeolocationPosition_h diff --git a/Source/WebCore/Modules/geolocation/Geoposition.h b/Source/WebCore/Modules/geolocation/Geoposition.h index 27064dddf..cfcf319dc 100644 --- a/Source/WebCore/Modules/geolocation/Geoposition.h +++ b/Source/WebCore/Modules/geolocation/Geoposition.h @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Geoposition_h -#define Geoposition_h +#pragma once #include "Coordinates.h" #include "Event.h" @@ -35,31 +34,28 @@ namespace WebCore { class Geoposition : public RefCounted<Geoposition> { public: - static PassRefPtr<Geoposition> create(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp) + static Ref<Geoposition> create(Ref<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(); } + const Coordinates& coords() const { return m_coordinates.get(); } private: - Geoposition(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp) - : m_coordinates(coordinates) + Geoposition(Ref<Coordinates>&& coordinates, DOMTimeStamp timestamp) + : m_coordinates(WTFMove(coordinates)) , m_timestamp(timestamp) { - ASSERT(m_coordinates); } - RefPtr<Coordinates> m_coordinates; + Ref<Coordinates> m_coordinates; DOMTimeStamp m_timestamp; }; } // namespace WebCore - -#endif // Geoposition_h diff --git a/Source/WebCore/Modules/geolocation/Geoposition.idl b/Source/WebCore/Modules/geolocation/Geoposition.idl index bf8cb09b2..1a8b70caa 100644 --- a/Source/WebCore/Modules/geolocation/Geoposition.idl +++ b/Source/WebCore/Modules/geolocation/Geoposition.idl @@ -23,6 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// FIXME: This should be an implementation provided typedef +// https://heycam.github.io/webidl/#DOMTimeStamp +typedef unsigned long long DOMTimeStamp; + [ NoInterfaceObject, Conditional=GEOLOCATION, diff --git a/Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp b/Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp index cb9e97a28..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,8 +51,9 @@ 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; } @@ -65,9 +66,9 @@ void NavigatorGeolocation::resetAllGeolocationPermission() } #endif // PLATFORM(IOS) -Geolocation* NavigatorGeolocation::geolocation(Navigator* navigator) +Geolocation* NavigatorGeolocation::geolocation(Navigator& navigator) { - return NavigatorGeolocation::from(navigator)->geolocation(); + 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 c5f654002..83f8e25c0 100644 --- a/Source/WebCore/Modules/geolocation/NavigatorGeolocation.h +++ b/Source/WebCore/Modules/geolocation/NavigatorGeolocation.h @@ -17,8 +17,7 @@ Boston, MA 02110-1301, USA. */ -#ifndef NavigatorGeolocation_h -#define NavigatorGeolocation_h +#pragma once #if ENABLE(GEOLOCATION) @@ -32,11 +31,13 @@ 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) @@ -44,7 +45,6 @@ public: #endif // PLATFORM(IOS) private: - NavigatorGeolocation(Frame*); static const char* supplementName(); mutable RefPtr<Geolocation> m_geolocation; @@ -53,5 +53,3 @@ private: } // namespace WebCore #endif // ENABLE(GEOLOCATION) - -#endif // NavigatorGeolocation_h diff --git a/Source/WebCore/Modules/geolocation/PositionCallback.h b/Source/WebCore/Modules/geolocation/PositionCallback.h index 09d7eb692..32ca1bcc6 100644 --- a/Source/WebCore/Modules/geolocation/PositionCallback.h +++ b/Source/WebCore/Modules/geolocation/PositionCallback.h @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PositionCallback_h -#define PositionCallback_h +#pragma once #include <wtf/RefCounted.h> @@ -39,5 +38,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // PositionCallback_h diff --git a/Source/WebCore/Modules/geolocation/PositionCallback.idl b/Source/WebCore/Modules/geolocation/PositionCallback.idl index 51cbde5ac..e2ce962c1 100644 --- a/Source/WebCore/Modules/geolocation/PositionCallback.idl +++ b/Source/WebCore/Modules/geolocation/PositionCallback.idl @@ -24,6 +24,4 @@ [ Conditional=GEOLOCATION, -] callback interface PositionCallback { - boolean handleEvent(Geoposition position); -}; +] callback PositionCallback = void (Geoposition position); diff --git a/Source/WebCore/Modules/geolocation/PositionError.h b/Source/WebCore/Modules/geolocation/PositionError.h index aa51c6a33..26422ef9b 100644 --- a/Source/WebCore/Modules/geolocation/PositionError.h +++ b/Source/WebCore/Modules/geolocation/PositionError.h @@ -23,10 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PositionError_h -#define PositionError_h +#pragma once -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/text/WTFString.h> @@ -40,7 +38,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; } @@ -63,5 +61,3 @@ private: }; } // namespace WebCore - -#endif // PositionError_h diff --git a/Source/WebCore/Modules/geolocation/PositionErrorCallback.h b/Source/WebCore/Modules/geolocation/PositionErrorCallback.h index d152785c1..79650b5dc 100644 --- a/Source/WebCore/Modules/geolocation/PositionErrorCallback.h +++ b/Source/WebCore/Modules/geolocation/PositionErrorCallback.h @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PositionErrorCallback_h -#define PositionErrorCallback_h +#pragma once #include <wtf/RefCounted.h> @@ -39,5 +38,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // PositionErrorCallback_h diff --git a/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl b/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl index 78121b8cf..57b493ccb 100644 --- a/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl +++ b/Source/WebCore/Modules/geolocation/PositionErrorCallback.idl @@ -24,6 +24,4 @@ [ Conditional=GEOLOCATION, -] callback interface PositionErrorCallback { - boolean handleEvent(PositionError error); -}; +] callback PositionErrorCallback = void (PositionError error); diff --git a/Source/WebCore/Modules/geolocation/PositionOptions.h b/Source/WebCore/Modules/geolocation/PositionOptions.h index 5cb66f735..20a62e31c 100644 --- a/Source/WebCore/Modules/geolocation/PositionOptions.h +++ b/Source/WebCore/Modules/geolocation/PositionOptions.h @@ -23,61 +23,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PositionOptions_h -#define PositionOptions_h - -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> +#pragma once namespace WebCore { -class PositionOptions : public RefCounted<PositionOptions> { -public: - static PassRefPtr<PositionOptions> create() { return adoptRef(new PositionOptions()); } - - bool enableHighAccuracy() const { return m_highAccuracy; } - void setEnableHighAccuracy(bool enable) { m_highAccuracy = enable; } - bool hasTimeout() const { return m_hasTimeout; } - int timeout() const - { - ASSERT(hasTimeout()); - return m_timeout; - } - void setTimeout(int timeout) - { - ASSERT(timeout >= 0); - m_hasTimeout = true; - m_timeout = timeout; - } - bool hasMaximumAge() const { return m_hasMaximumAge; } - int maximumAge() const - { - ASSERT(hasMaximumAge()); - return m_maximumAge; - } - void clearMaximumAge() { m_hasMaximumAge = false; } - void setMaximumAge(int age) - { - ASSERT(age >= 0); - m_hasMaximumAge = true; - m_maximumAge = age; - } - -private: - PositionOptions() - : m_highAccuracy(false) - , m_hasTimeout(false) - { - setMaximumAge(0); - } - - bool m_highAccuracy; - bool m_hasTimeout; - int m_timeout; - bool m_hasMaximumAge; - int m_maximumAge; +struct PositionOptions { + bool enableHighAccuracy { false }; + unsigned timeout { 0xFFFFFFFF }; + unsigned maximumAge { 0 }; }; } // namespace WebCore - -#endif // PositionOptions_h diff --git a/Source/WebCore/Modules/geolocation/PositionOptions.idl b/Source/WebCore/Modules/geolocation/PositionOptions.idl new file mode 100644 index 000000000..1f6a73621 --- /dev/null +++ b/Source/WebCore/Modules/geolocation/PositionOptions.idl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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. AND ITS CONTRIBUTORS ``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 ITS 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. + */ + +dictionary PositionOptions { + boolean enableHighAccuracy = false; + [Clamp] unsigned long timeout = 0xFFFFFFFF; + [Clamp] unsigned long maximumAge = 0; +}; |