Changeset 55841 in webkit


Ignore:
Timestamp:
Mar 11, 2010, 3:38:39 AM (15 years ago)
Author:
steveblock@google.com
Message:

2010-03-10 Steve Block <steveblock@google.com>

Reviewed by Jeremy Orlow.

Implements Geolocation maximumAge property
https://bugs.webkit.org/show_bug.cgi?id=30676

Test: fast/dom/Geolocation/maximum-age.html

  • WebCore.xcodeproj/project.pbxproj: Modified. Adds GeolocationPositionCache.h to Private headers
  • page/Geolocation.cpp: Modified. (WebCore::Geolocation::GeoNotifier::setUseCachedPosition): Added. (WebCore::Geolocation::GeoNotifier::runSuccessCallback): Added. (WebCore::Geolocation::GeoNotifier::timerFired): Modified. Added logic to handle using a cached position (WebCore::Geolocation::Watchers::contains): Added. Required to determine if a notifier is a watch request (WebCore::Geolocation::startRequest): Modified. Added logic to check for a cached position (WebCore::Geolocation::requestUsesCachedPosition): Added. Callback to Geolocation object when notifier uses a cached position (WebCore::Geolocation::makeCachedPositionCallbacks): Added. (WebCore::Geolocation::haveSuitableCachedPosition): Added. (WebCore::Geolocation::setIsAllowed): Modified. (WebCore::Geolocation::positionChanged): Modified. Make callbacks using cached position where appropriate (WebCore::Geolocation::geolocationServiceErrorOccurred): Modified. Make callbacks using cached position where appropriate
  • page/Geolocation.h: Modified.

2010-03-10 Steve Block <steveblock@google.com>

Reviewed by Jeremy Orlow.

Implements Geolocation maximumAge property
https://bugs.webkit.org/show_bug.cgi?id=30676

  • fast/dom/Geolocation/resources/maximum-age.js: Added. Checks that a cached position is used only when it should be.
  • fast/dom/Geolocation/maximum-age.html: Added. HTML wraper for above test.
  • fast/dom/Geolocation/maximum-age-expected.txt: Added. Expected result for above test.
Location:
trunk
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r55840 r55841  
     12010-03-10  Steve Block  <steveblock@google.com>
     2
     3        Reviewed by Jeremy Orlow.
     4
     5        Implements Geolocation maximumAge property
     6        https://bugs.webkit.org/show_bug.cgi?id=30676
     7
     8        * fast/dom/Geolocation/resources/maximum-age.js: Added. Checks that a cached position is used only when it should be.
     9        * fast/dom/Geolocation/maximum-age.html: Added. HTML wraper for above test.
     10        * fast/dom/Geolocation/maximum-age-expected.txt: Added. Expected result for above test.
     11
    1122010-03-11  Philippe Normand  <pnormand@igalia.com>
    213
  • trunk/WebCore/ChangeLog

    r55838 r55841  
     12010-03-10  Steve Block  <steveblock@google.com>
     2
     3        Reviewed by Jeremy Orlow.
     4
     5        Implements Geolocation maximumAge property
     6        https://bugs.webkit.org/show_bug.cgi?id=30676
     7
     8        Test: fast/dom/Geolocation/maximum-age.html
     9
     10        * WebCore.xcodeproj/project.pbxproj: Modified. Adds GeolocationPositionCache.h to Private headers
     11        * page/Geolocation.cpp: Modified.
     12        (WebCore::Geolocation::GeoNotifier::setUseCachedPosition): Added.
     13        (WebCore::Geolocation::GeoNotifier::runSuccessCallback): Added.
     14        (WebCore::Geolocation::GeoNotifier::timerFired): Modified. Added logic to handle using a cached position
     15        (WebCore::Geolocation::Watchers::contains): Added. Required to determine if a notifier is a watch request
     16        (WebCore::Geolocation::startRequest): Modified. Added logic to check for a cached position
     17        (WebCore::Geolocation::requestUsesCachedPosition): Added. Callback to Geolocation object when notifier uses a cached position
     18        (WebCore::Geolocation::makeCachedPositionCallbacks): Added.
     19        (WebCore::Geolocation::haveSuitableCachedPosition): Added.
     20        (WebCore::Geolocation::setIsAllowed): Modified.
     21        (WebCore::Geolocation::positionChanged): Modified. Make callbacks using cached position where appropriate
     22        (WebCore::Geolocation::geolocationServiceErrorOccurred): Modified. Make callbacks using cached position where appropriate
     23        * page/Geolocation.h: Modified.
     24
    1252010-03-11  Csaba Osztrogonác  <ossy@webkit.org>
    226
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r55825 r55841  
    11241124                5913953D1107584E0083EC55 /* JNIBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5913953C1107584E0083EC55 /* JNIBridge.cpp */; };
    11251125                596229781133EFD700DC4CBB /* GeolocationPositionCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 596229771133EFD700DC4CBB /* GeolocationPositionCache.cpp */; };
    1126                 5962297A1133EFE200DC4CBB /* GeolocationPositionCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 596229791133EFE200DC4CBB /* GeolocationPositionCache.h */; };
     1126                5962297A1133EFE200DC4CBB /* GeolocationPositionCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 596229791133EFE200DC4CBB /* GeolocationPositionCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
    11271127                599E759011055A1F00D904FA /* Bridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 599E758F11055A1F00D904FA /* Bridge.h */; settings = {ATTRIBUTES = (Private, ); }; };
    11281128                59A9E7B01104758800DFB4C1 /* JavaInstanceJSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59A9E7AF1104758800DFB4C1 /* JavaInstanceJSC.cpp */; };
  • trunk/WebCore/page/Geolocation.cpp

    r55136 r55841  
    22 * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
    33 * Copyright (C) 2009 Torch Mobile, Inc.
     4 * Copyright 2010, The Android Open Source Project
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    3233#include "Frame.h"
    3334#include "Page.h"
     35#include <wtf/CurrentTime.h>
    3436
    3537#if ENABLE(CLIENT_BASED_GEOLOCATION)
     
    4446
    4547static const char permissionDeniedErrorMessage[] = "User denied Geolocation";
     48static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocation service";
    4649
    4750#if ENABLE(CLIENT_BASED_GEOLOCATION)
     
    8083    , m_options(options)
    8184    , m_timer(this, &Geolocation::GeoNotifier::timerFired)
     85    , m_useCachedPosition(false)
    8286{
    8387    ASSERT(m_geolocation);
     
    96100}
    97101
     102void Geolocation::GeoNotifier::setUseCachedPosition()
     103{
     104    m_useCachedPosition = true;
     105    m_timer.startOneShot(0);
     106}
     107
    98108bool Geolocation::GeoNotifier::hasZeroTimeout() const
    99109{
    100110    return m_options->hasTimeout() && m_options->timeout() == 0;
     111}
     112
     113void Geolocation::GeoNotifier::runSuccessCallback(Geoposition* position)
     114{
     115    m_successCallback->handleEvent(position);
    101116}
    102117
     
    123138    }
    124139
     140    if (m_useCachedPosition) {
     141        // Clear the cached position flag in case this is a watch request, which
     142        // will continue to run.
     143        m_useCachedPosition = false;
     144        m_geolocation->requestUsesCachedPosition(this);
     145        return;
     146    }
     147
    125148    if (m_errorCallback) {
    126149        RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timeout expired");
     
    154177    m_idToNotifierMap.remove(iter->second);
    155178    m_notifierToIdMap.remove(iter);
     179}
     180
     181bool Geolocation::Watchers::contains(GeoNotifier* notifier) const
     182{
     183    return m_notifierToIdMap.contains(notifier);
    156184}
    157185
     
    179207    , m_allowGeolocation(Unknown)
    180208    , m_shouldClearCache(false)
     209    , m_positionCache(new GeolocationPositionCache)
    181210{
    182211    if (!m_frame)
     
    249278    if (isDenied())
    250279        notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
    251     else {
    252         if (notifier->hasZeroTimeout() || startUpdating(notifier.get())) {
    253 #if ENABLE(CLIENT_BASED_GEOLOCATION)
    254             // Only start timer if we're not waiting for user permission.
    255             if (!m_startRequestPermissionNotifier)
     280    else if (haveSuitableCachedPosition(notifier->m_options.get()))
     281        notifier->setUseCachedPosition();
     282    else if (notifier->hasZeroTimeout() || startUpdating(notifier.get())) {
     283#if ENABLE(CLIENT_BASED_GEOLOCATION)
     284        // Only start timer if we're not waiting for user permission.
     285        if (!m_startRequestPermissionNotifier)
    256286#endif           
    257                 notifier->startTimerIfNeeded();
    258         } else
    259             notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, "Failed to start Geolocation service"));
    260     }
     287            notifier->startTimerIfNeeded();
     288    } else
     289        notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
    261290
    262291    return notifier.release();
     
    273302}
    274303
     304void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier)
     305{
     306    // This is called asynchronously, so the permissions could have been denied
     307    // since we last checked in startRequest.
     308    if (isDenied()) {
     309        notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
     310        return;
     311    }
     312
     313    m_requestsAwaitingCachedPosition.add(notifier);
     314
     315    // If permissions are allowed, make the callback
     316    if (isAllowed()) {
     317        makeCachedPositionCallbacks();
     318        return;
     319    }
     320
     321    // Request permissions, which may be synchronous or asynchronous.
     322    requestPermission();
     323}
     324
     325void Geolocation::makeCachedPositionCallbacks()
     326{
     327    // All modifications to m_requestsAwaitingCachedPosition are done
     328    // asynchronously, so we don't need to worry about it being modified from
     329    // the callbacks.
     330    GeoNotifierSet::const_iterator end = m_requestsAwaitingCachedPosition.end();
     331    for (GeoNotifierSet::const_iterator iter = m_requestsAwaitingCachedPosition.begin(); iter != end; ++iter) {
     332        GeoNotifier* notifier = iter->get();
     333        notifier->runSuccessCallback(m_positionCache->cachedPosition());
     334
     335        // If this is a one-shot request, stop it. Otherwise, if the watch still
     336        // exists, start the service to get updates.
     337        if (m_oneShots.contains(notifier))
     338            m_oneShots.remove(notifier);
     339        else if (m_watchers.contains(notifier)) {
     340            if (notifier->hasZeroTimeout() || startUpdating(notifier))
     341                notifier->startTimerIfNeeded();
     342            else
     343                notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
     344        }
     345    }
     346
     347    m_requestsAwaitingCachedPosition.clear();
     348
     349    if (!hasListeners())
     350        stopUpdating();
     351}
     352
    275353void Geolocation::requestTimedOut(GeoNotifier* notifier)
    276354{
     
    280358    if (!hasListeners())
    281359        stopUpdating();
     360}
     361
     362bool Geolocation::haveSuitableCachedPosition(PositionOptions* options)
     363{
     364    if (!m_positionCache->cachedPosition())
     365        return false;
     366    if (!options->hasMaximumAge())
     367        return true;
     368    if (!options->maximumAge())
     369        return false;
     370    DOMTimeStamp currentTimeMillis = currentTime() * 1000.0;
     371    return m_positionCache->cachedPosition()->timestamp() > currentTimeMillis - options->maximumAge();
    282372}
    283373
     
    308398void Geolocation::setIsAllowed(bool allowed)
    309399{
     400    // This may be due to either a new position from the service, or a cached
     401    // position.
    310402    m_allowGeolocation = allowed ? Yes : No;
    311403   
     
    330422    }
    331423#endif
    332    
    333     if (isAllowed())
    334         makeSuccessCallbacks();
    335     else {
     424
     425    if (!isAllowed()) {
    336426        RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage);
    337427        error->setIsFatal(true);
    338428        handleError(error.get());
    339     }
     429        m_requestsAwaitingCachedPosition.clear();
     430        return;
     431    }
     432
     433    // If the service has a last position, use it to call back for all requests.
     434    // If any of the requests are waiting for permission for a cached position,
     435    // the position from the service will be at least as fresh.
     436    if (lastPosition())
     437        makeSuccessCallbacks();
     438    else
     439        makeCachedPositionCallbacks();
    340440}
    341441
     
    439539    m_currentPosition = newPosition;
    440540
     541    m_positionCache->setCachedPosition(m_currentPosition.get());
     542
    441543    // Stop all currently running timers.
    442544    stopTimers();
     
    504606    ASSERT(service->lastError());
    505607
     608    // Note that we do not stop timers here. For one-shots, the request is
     609    // cleared in handleError. For watchers, the spec requires that the timer is
     610    // not cleared.
    506611    handleError(service->lastError());
    507612}
  • trunk/WebCore/page/Geolocation.h

    r55633 r55841  
    11/*
    22 * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
     3 * Copyright 2010, The Android Open Source Project
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    2728#define Geolocation_h
    2829
     30#include "GeolocationPositionCache.h"
    2931#include "GeolocationService.h"
    3032#include "Geoposition.h"
     
    9698        void setFatalError(PassRefPtr<PositionError>);
    9799        bool hasZeroTimeout() const;
     100        void setUseCachedPosition();
     101        void runSuccessCallback(Geoposition*);
    98102        void startTimerIfNeeded();
    99103        void timerFired(Timer<GeoNotifier>*);
     
    105109        Timer<GeoNotifier> m_timer;
    106110        RefPtr<PositionError> m_fatalError;
     111        bool m_useCachedPosition;
    107112
    108113    private:
     
    115120        void remove(int id);
    116121        void remove(GeoNotifier*);
     122        bool contains(GeoNotifier*) const;
    117123        void clear();
    118124        bool isEmpty() const;
     
    154160    void fatalErrorOccurred(GeoNotifier*);
    155161    void requestTimedOut(GeoNotifier*);
     162    void requestUsesCachedPosition(GeoNotifier*);
     163    bool haveSuitableCachedPosition(PositionOptions*);
     164    void makeCachedPositionCallbacks();
    156165
    157166    typedef HashSet<RefPtr<GeoNotifier> > GeoNotifierSet;
     
    175184    } m_allowGeolocation;
    176185    bool m_shouldClearCache;
     186
     187    OwnPtr<GeolocationPositionCache> m_positionCache;
     188    GeoNotifierSet m_requestsAwaitingCachedPosition;
    177189};
    178190   
Note: See TracChangeset for help on using the changeset viewer.