/*
 * 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->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 = 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 (document()->canAccessResource(ScriptExecutionContext::ResourceType::Geolocation) != ScriptExecutionContext::HasResourceAccess::No) {
        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)
