/*
 * Copyright (C) 2008, 2009, 2010, 2011 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 "Geolocation.h"

#if ENABLE(GEOLOCATION)

#include "Document.h"
#include "EventLoop.h"
#include "FeaturePolicy.h"
#include "Frame.h"
#include "GeoNotifier.h"
#include "GeolocationController.h"
#include "GeolocationCoordinates.h"
#include "GeolocationError.h"
#include "GeolocationPosition.h"
#include "GeolocationPositionData.h"
#include "Navigator.h"
#include "Page.h"
#include "RuntimeApplicationChecks.h"
#include "SecurityOrigin.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/Ref.h>
#include <wtf/text/StringBuilder.h>

namespace WebCore {

static const ASCIILiteral permissionDeniedErrorMessage { "User denied Geolocation"_s };
static const ASCIILiteral failedToStartServiceErrorMessage { "Failed to start Geolocation service"_s };
static const ASCIILiteral framelessDocumentErrorMessage { "Geolocation cannot be used in frameless documents"_s };
static const ASCIILiteral originCannotRequestGeolocationErrorMessage { "Origin does not have permission to use Geolocation service"_s };

WTF_MAKE_ISO_ALLOCATED_IMPL(Geolocation);

static RefPtr<GeolocationPosition> createGeolocationPosition(std::optional<GeolocationPositionData>&& position)
{
    if (!position)
        return nullptr;
    
    EpochTimeStamp timestamp = convertSecondsToEpochTimeStamp(position->timestamp);
    return GeolocationPosition::create(GeolocationCoordinates::create(WTFMove(position.value())), timestamp);
}

static Ref<GeolocationPositionError> createGeolocationPositionError(GeolocationError& error)
{
    auto code = GeolocationPositionError::POSITION_UNAVAILABLE;
    switch (error.code()) {
    case GeolocationError::PermissionDenied:
        code = GeolocationPositionError::PERMISSION_DENIED;
        break;
    case GeolocationError::PositionUnavailable:
        code = GeolocationPositionError::POSITION_UNAVAILABLE;
        break;
    }

    return GeolocationPositionError::create(code, error.message());
}

bool Geolocation::Watchers::add(int id, RefPtr<GeoNotifier>&& notifier)
{
    ASSERT(id > 0);

    if (!m_idToNotifierMap.add(id, notifier.get()).isNewEntry)
        return false;
    m_notifierToIdMap.set(WTFMove(notifier), id);
    return true;
}

GeoNotifier* Geolocation::Watchers::find(int id)
{
    ASSERT(id > 0);
    return m_idToNotifierMap.get(id);
}

void Geolocation::Watchers::remove(int id)
{
    ASSERT(id > 0);
    if (auto notifier = m_idToNotifierMap.take(id))
        m_notifierToIdMap.remove(notifier);
}

void Geolocation::Watchers::remove(GeoNotifier* notifier)
{
    if (auto identifier = m_notifierToIdMap.take(notifier))
        m_idToNotifierMap.remove(identifier);
}

bool Geolocation::Watchers::contains(GeoNotifier* notifier) const
{
    return m_notifierToIdMap.contains(notifier);
}

void Geolocation::Watchers::clear()
{
    m_idToNotifierMap.clear();
    m_notifierToIdMap.clear();
}

bool Geolocation::Watchers::isEmpty() const
{
    return m_idToNotifierMap.isEmpty();
}

void Geolocation::Watchers::getNotifiersVector(GeoNotifierVector& copy) const
{
    copy = copyToVector(m_idToNotifierMap.values());
}

Ref<Geolocation> Geolocation::create(Navigator& navigator)
{
    auto geolocation = adoptRef(*new Geolocation(navigator));
    geolocation.get().suspendIfNeeded();
    return geolocation;
}

Geolocation::Geolocation(Navigator& navigator)
    : ActiveDOMObject(navigator.scriptExecutionContext())
    , m_navigator(navigator)
    , m_resumeTimer(*this, &Geolocation::resumeTimerFired)
{
}

Geolocation::~Geolocation()
{
    ASSERT(m_allowGeolocation != InProgress);
    revokeAuthorizationTokenIfNecessary();
}

SecurityOrigin* Geolocation::securityOrigin() const
{
    return scriptExecutionContext()->securityOrigin();
}

Page* Geolocation::page() const
{
    return document() ? document()->page() : nullptr;
}
    
void Geolocation::suspend(ReasonForSuspension reason)
{
    if (reason == ReasonForSuspension::BackForwardCache) {
        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_s);
}

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(), authorizationToken());
        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);
        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();
    resetIsAllowed();
    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()
{
    Page* page = this->page();
    if (page && m_allowGeolocation == InProgress)
        GeolocationController::from(page)->cancelPermissionRequest(*this);
    // The frame may be moving to a new page and we want to get the permissions from the new page's client.
    resetIsAllowed();
    cancelAllRequests();
    stopUpdating();
    m_hasChangedPosition = false;
    m_errorWaitingForResume = nullptr;
    m_pendingForPermissionNotifiers.clear();
}

const char* Geolocation::activeDOMObjectName() const
{
    return "Geolocation";
}

GeolocationPosition* Geolocation::lastPosition()
{
    Page* page = this->page();
    if (!page)
        return nullptr;

    m_lastPosition = createGeolocationPosition(GeolocationController::from(page)->lastPosition());

    return m_lastPosition.get();
}

void Geolocation::getCurrentPosition(Ref<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, PositionOptions&& options)
{
    if (!document() || !document()->isFullyActive()) {
        if (errorCallback && errorCallback->scriptExecutionContext()) {
            errorCallback->scriptExecutionContext()->eventLoop().queueTask(TaskSource::Geolocation, [errorCallback] {
                errorCallback->handleEvent(GeolocationPositionError::create(GeolocationPositionError::POSITION_UNAVAILABLE, "Document is not fully active"_s));
            });
        }
        return;
    }

    auto notifier = GeoNotifier::create(*this, WTFMove(successCallback), WTFMove(errorCallback), WTFMove(options));
    startRequest(notifier.ptr());

    m_oneShots.add(WTFMove(notifier));
}

int Geolocation::watchPosition(Ref<PositionCallback>&& successCallback, RefPtr<PositionErrorCallback>&& errorCallback, PositionOptions&& options)
{
    if (!document() || !document()->isFullyActive()) {
        if (errorCallback && errorCallback->scriptExecutionContext()) {
            errorCallback->scriptExecutionContext()->eventLoop().queueTask(TaskSource::Geolocation, [errorCallback] {
                errorCallback->handleEvent(GeolocationPositionError::create(GeolocationPositionError::POSITION_UNAVAILABLE, "Document is not fully active"_s));
            });
        }
        return 0;
    }

    auto notifier = GeoNotifier::create(*this, WTFMove(successCallback), WTFMove(errorCallback), WTFMove(options));
    startRequest(notifier.ptr());

    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.copyRef()));
    return watchID;
}

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());
}

// FIXME: remove this function when rdar://problem/32137821 is fixed.
static bool isRequestFromIBooks()
{
#if PLATFORM(COCOA)
    return CocoaApplication::isIBooks();
#endif
    return false;
}
    
bool Geolocation::shouldBlockGeolocationRequests()
{
    if (!isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::Geolocation, *document(), LogFeaturePolicyFailure::Yes))
        return true;

    bool isSecure = SecurityOrigin::isSecure(document()->url()) || document()->isSecureContext();
    bool hasMixedContent = !document()->foundMixedContent().isEmpty();
    bool isLocalOrigin = securityOrigin()->isLocal();
    if (securityOrigin()->canRequestGeolocation()) {
        if (isLocalOrigin || (isSecure && !hasMixedContent) || isRequestFromIBooks())
            return false;
    }

    logError(securityOrigin()->toString(), isSecure, hasMixedContent, document());
    return true;
}

void Geolocation::startRequest(GeoNotifier* notifier)
{
    if (shouldBlockGeolocationRequests()) {
        notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::PERMISSION_DENIED, 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())
        notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
    else if (haveSuitableCachedPosition(notifier->options()))
        notifier->setUseCachedPosition();
    else if (notifier->hasZeroTimeout())
        notifier->startTimerIfNeeded();
    else if (!isAllowed()) {
        // if we don't yet have permission, request for permission before calling startUpdating()
        m_pendingForPermissionNotifiers.add(notifier);
        requestPermission();
    } else if (startUpdating(notifier))
        notifier->startTimerIfNeeded();
    else
        notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
}

void Geolocation::fatalErrorOccurred(GeoNotifier* notifier)
{
    // This request has failed fatally. Remove it from our lists.
    m_oneShots.remove(notifier);
    m_watchers.remove(notifier);

    if (!hasListeners())
        stopUpdating();
}

void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier)
{
    // This is called asynchronously, so the permissions could have been denied
    // since we last checked in startRequest.
    if (isDenied()) {
        notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
        return;
    }

    m_requestsAwaitingCachedPosition.add(notifier);

    // If permissions are allowed, make the callback
    if (isAllowed()) {
        makeCachedPositionCallbacks();
        return;
    }

    // Request permissions, which may be synchronous or asynchronous.
    requestPermission();
}

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.
    for (auto& notifier : m_requestsAwaitingCachedPosition) {
        // FIXME: This seems wrong, since makeCachedPositionCallbacks() is called in a branch where
        // lastPosition() is known to be null in Geolocation::setIsAllowed().
        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.get()) && m_watchers.contains(notifier.get())) {
            if (notifier->hasZeroTimeout() || startUpdating(notifier.get()))
                notifier->startTimerIfNeeded();
            else
                notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
        }
    }

    m_requestsAwaitingCachedPosition.clear();

    if (!hasListeners())
        stopUpdating();
}

void Geolocation::requestTimedOut(GeoNotifier* notifier)
{
    // If this is a one-shot request, stop it.
    m_oneShots.remove(notifier);

    if (!hasListeners())
        stopUpdating();
}

bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options)
{
    auto* cachedPosition = lastPosition();
    if (!cachedPosition)
        return false;
    if (!options.maximumAge)
        return false;
    EpochTimeStamp currentTimeMillis = convertSecondsToEpochTimeStamp(WallTime::now().secondsSinceEpoch());
    return cachedPosition->timestamp() > currentTimeMillis - options.maximumAge;
}

void Geolocation::clearWatch(int watchID)
{
    if (watchID <= 0)
        return;

    if (GeoNotifier* notifier = m_watchers.find(watchID))
        m_pendingForPermissionNotifiers.remove(notifier);
    m_watchers.remove(watchID);
    
    if (!hasListeners())
        stopUpdating();
}

void Geolocation::setIsAllowed(bool allowed, const String& authorizationToken)
{
    // Protect the Geolocation object from garbage collection during a callback.
    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;
    m_authorizationToken = authorizationToken;
    
    if (m_isSuspended)
        return;

    // Permission request was made during the startRequest process
    if (!m_pendingForPermissionNotifiers.isEmpty()) {
        handlePendingPermissionNotifiers();
        m_pendingForPermissionNotifiers.clear();
        return;
    }

    if (!isAllowed()) {
        auto error = GeolocationPositionError::create(GeolocationPositionError::PERMISSION_DENIED, permissionDeniedErrorMessage);
        error->setIsFatal(true);
        handleError(error);
        m_requestsAwaitingCachedPosition.clear();
        m_hasChangedPosition = false;
        m_errorWaitingForResume = nullptr;
        return;
    }

    // If the service has a last position, use it to call back for all requests.
    // If any of the requests are waiting for permission for a cached position,
    // the position from the service will be at least as fresh.
    if (RefPtr<GeolocationPosition> position = lastPosition())
        makeSuccessCallbacks(*position);
    else
        makeCachedPositionCallbacks();
}

void Geolocation::sendError(GeoNotifierVector& notifiers, GeolocationPositionError& error)
{
    for (auto& notifier : notifiers)
        notifier->runErrorCallback(error);
}

void Geolocation::sendPosition(GeoNotifierVector& notifiers, GeolocationPosition& position)
{
    for (auto& notifier : notifiers)
        notifier->runSuccessCallback(&position);
}

void Geolocation::stopTimer(GeoNotifierVector& notifiers)
{
    for (auto& notifier : notifiers)
        notifier->stopTimer();
}

void Geolocation::stopTimersForOneShots()
{
    auto copy = copyToVector(m_oneShots);
    stopTimer(copy);
}

void Geolocation::stopTimersForWatchers()
{
    GeoNotifierVector copy;
    m_watchers.getNotifiersVector(copy);
    
    stopTimer(copy);
}

void Geolocation::stopTimers()
{
    stopTimersForOneShots();
    stopTimersForWatchers();
}

void Geolocation::cancelRequests(GeoNotifierVector& notifiers)
{
    for (auto& notifier : notifiers)
        notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::POSITION_UNAVAILABLE, framelessDocumentErrorMessage));
}

void Geolocation::cancelAllRequests()
{
    auto copy = copyToVector(m_oneShots);
    cancelRequests(copy);
    m_watchers.getNotifiersVector(copy);
    cancelRequests(copy);
}

void Geolocation::extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached)
{
    GeoNotifierVector nonCached;
    for (auto& notifier : notifiers) {
        if (notifier->useCachedPosition()) {
            if (cached)
                cached->append(notifier.get());
        } else
            nonCached.append(notifier.get());
    }
    notifiers.swap(nonCached);
}

void Geolocation::copyToSet(const GeoNotifierVector& src, GeoNotifierSet& dest)
{
    for (auto& notifier : src)
        dest.add(notifier.get());
}

void Geolocation::handleError(GeolocationPositionError& error)
{
    auto oneShotsCopy = copyToVector(m_oneShots);

    GeoNotifierVector watchersCopy;
    m_watchers.getNotifiersVector(watchersCopy);

    // Clear the lists before we make the callbacks, to avoid clearing notifiers
    // added by calls to Geolocation methods from the callbacks, and to prevent
    // further callbacks to these notifiers.
    GeoNotifierVector oneShotsWithCachedPosition;
    m_oneShots.clear();
    if (error.isFatal())
        m_watchers.clear();
    else {
        // Don't send non-fatal errors to notifiers due to receive a cached position.
        extractNotifiersWithCachedPosition(oneShotsCopy, &oneShotsWithCachedPosition);
        extractNotifiersWithCachedPosition(watchersCopy, 0);
    }

    sendError(oneShotsCopy, error);
    sendError(watchersCopy, error);

    // hasListeners() doesn't distinguish between notifiers due to receive a
    // cached position and those requiring a fresh position. Perform the check
    // before restoring the notifiers below.
    if (!hasListeners())
        stopUpdating();

    // Maintain a reference to the cached notifiers until their timer fires.
    copyToSet(oneShotsWithCachedPosition, m_oneShots);
}

void Geolocation::requestPermission()
{
    if (m_allowGeolocation > Unknown)
        return;

    Page* page = this->page();
    if (!page)
        return;

    m_allowGeolocation = InProgress;

    // Ask the embedder: it maintains the geolocation challenge policy itself.
    GeolocationController::from(page)->requestPermission(*this);
}

void Geolocation::revokeAuthorizationTokenIfNecessary()
{
    if (m_authorizationToken.isNull())
        return;

    Page* page = this->page();
    if (!page)
        return;

    GeolocationController::from(page)->revokeAuthorizationToken(std::exchange(m_authorizationToken, String()));
}

void Geolocation::resetIsAllowed()
{
    m_allowGeolocation = Unknown;
    revokeAuthorizationTokenIfNecessary();
}

void Geolocation::makeSuccessCallbacks(GeolocationPosition& position)
{
    ASSERT(lastPosition());
    ASSERT(isAllowed());
    
    auto oneShotsCopy = copyToVector(m_oneShots);
    
    GeoNotifierVector watchersCopy;
    m_watchers.getNotifiersVector(watchersCopy);
    
    // Clear the lists before we make the callbacks, to avoid clearing notifiers
    // added by calls to Geolocation methods from the callbacks, and to prevent
    // further callbacks to these notifiers.
    m_oneShots.clear();

    sendPosition(oneShotsCopy, position);
    sendPosition(watchersCopy, position);

    if (!hasListeners())
        stopUpdating();
}

void Geolocation::positionChanged()
{
    ASSERT(isAllowed());

    // Stop all currently running timers.
    stopTimers();

    if (m_isSuspended) {
        m_hasChangedPosition = true;
        return;
    }

    if (RefPtr position = lastPosition())
        makeSuccessCallbacks(*position);
}

void Geolocation::setError(GeolocationError& error)
{
    if (m_isSuspended) {
        m_errorWaitingForResume = createGeolocationPositionError(error);
        return;
    }

    auto positionError = createGeolocationPositionError(error);
    handleError(positionError);
}

bool Geolocation::startUpdating(GeoNotifier* notifier)
{
    Page* page = this->page();
    if (!page)
        return false;

    GeolocationController::from(page)->addObserver(*this, notifier->options().enableHighAccuracy);
    return true;
}

void Geolocation::stopUpdating()
{
    Page* page = this->page();
    if (!page)
        return;

    GeolocationController::from(page)->removeObserver(*this);
}

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
    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.get()))
                notifier->startTimerIfNeeded();
            else
                notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
        } else
            notifier->setFatalError(GeolocationPositionError::create(GeolocationPositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
    }
}

Navigator* Geolocation::navigator()
{
    return m_navigator.get();
}

Frame* Geolocation::frame() const
{
    return m_navigator ? m_navigator->frame() : nullptr;
}

} // namespace WebCore
                                                        
#endif // ENABLE(GEOLOCATION)
