1/* 2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All Rights Reserved. 3 * Copyright 2010, The Android Open Source Project 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#ifndef Geolocation_h 28#define Geolocation_h 29 30#if ENABLE(GEOLOCATION) 31 32#include "ActiveDOMObject.h" 33#include "Geoposition.h" 34#include "PositionCallback.h" 35#include "PositionError.h" 36#include "PositionErrorCallback.h" 37#include "PositionOptions.h" 38#include "ScriptWrappable.h" 39#include "Timer.h" 40 41namespace WebCore { 42 43class Document; 44class Frame; 45class GeolocationController; 46class GeolocationError; 47class GeolocationPosition; 48class Page; 49class ScriptExecutionContext; 50 51class Geolocation : public ScriptWrappable, public RefCounted<Geolocation>, public ActiveDOMObject 52{ 53public: 54 static PassRef<Geolocation> create(ScriptExecutionContext*); 55 ~Geolocation(); 56 57#if PLATFORM(IOS) 58 virtual bool canSuspend() const override; 59 virtual void suspend(ReasonForSuspension) override; 60 virtual void resume() override; 61 void resetAllGeolocationPermission(); 62#endif // PLATFORM(IOS) 63 Document* document() const; 64 Frame* frame() const; 65 66 void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); 67 int watchPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); 68 void clearWatch(int watchID); 69 70 void setIsAllowed(bool); 71 bool isAllowed() const { return m_allowGeolocation == Yes; } 72 73 void positionChanged(); 74 void setError(GeolocationError*); 75 76private: 77 explicit Geolocation(ScriptExecutionContext*); 78 79 Geoposition* lastPosition(); 80 81 // ActiveDOMObject 82 virtual void stop() override; 83 84 bool isDenied() const { return m_allowGeolocation == No; } 85 86 Page* page() const; 87 88 class GeoNotifier : public RefCounted<GeoNotifier> { 89 public: 90 static PassRef<GeoNotifier> create(Geolocation* geolocation, PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(*new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options)); } 91 92 PositionOptions* options() const { return m_options.get(); }; 93 void setFatalError(PassRefPtr<PositionError>); 94 95 bool useCachedPosition() const { return m_useCachedPosition; } 96 void setUseCachedPosition(); 97 98 void runSuccessCallback(Geoposition*); 99 void runErrorCallback(PositionError*); 100 101 void startTimerIfNeeded(); 102 void stopTimer(); 103 void timerFired(Timer<GeoNotifier>&); 104 bool hasZeroTimeout() const; 105 106 private: 107 GeoNotifier(Geolocation*, PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); 108 109 RefPtr<Geolocation> m_geolocation; 110 RefPtr<PositionCallback> m_successCallback; 111 RefPtr<PositionErrorCallback> m_errorCallback; 112 RefPtr<PositionOptions> m_options; 113 Timer<GeoNotifier> m_timer; 114 RefPtr<PositionError> m_fatalError; 115 bool m_useCachedPosition; 116 }; 117 118 typedef Vector<RefPtr<GeoNotifier>> GeoNotifierVector; 119 typedef HashSet<RefPtr<GeoNotifier>> GeoNotifierSet; 120 121 class Watchers { 122 public: 123 bool add(int id, PassRefPtr<GeoNotifier>); 124 GeoNotifier* find(int id); 125 void remove(int id); 126 void remove(GeoNotifier*); 127 bool contains(GeoNotifier*) const; 128 void clear(); 129 bool isEmpty() const; 130 void getNotifiersVector(GeoNotifierVector&) const; 131 private: 132 typedef HashMap<int, RefPtr<GeoNotifier>> IdToNotifierMap; 133 typedef HashMap<RefPtr<GeoNotifier>, int> NotifierToIdMap; 134 IdToNotifierMap m_idToNotifierMap; 135 NotifierToIdMap m_notifierToIdMap; 136 }; 137 138 bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); } 139 140 void sendError(GeoNotifierVector&, PositionError*); 141 void sendPosition(GeoNotifierVector&, Geoposition*); 142 143 static void extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached); 144 static void copyToSet(const GeoNotifierVector&, GeoNotifierSet&); 145 146 static void stopTimer(GeoNotifierVector&); 147 void stopTimersForOneShots(); 148 void stopTimersForWatchers(); 149 void stopTimers(); 150 151 void cancelRequests(GeoNotifierVector&); 152 void cancelAllRequests(); 153 154 void makeSuccessCallbacks(); 155 void handleError(PositionError*); 156 157 void requestPermission(); 158 159 bool startUpdating(GeoNotifier*); 160 void stopUpdating(); 161 162 void handlePendingPermissionNotifiers(); 163 164 void startRequest(GeoNotifier*); 165 166 void fatalErrorOccurred(GeoNotifier*); 167 void requestTimedOut(GeoNotifier*); 168 void requestUsesCachedPosition(GeoNotifier*); 169 bool haveSuitableCachedPosition(PositionOptions*); 170 void makeCachedPositionCallbacks(); 171 172 GeoNotifierSet m_oneShots; 173 Watchers m_watchers; 174 GeoNotifierSet m_pendingForPermissionNotifiers; 175 RefPtr<Geoposition> m_lastPosition; 176 177 enum { 178 Unknown, 179 InProgress, 180 Yes, 181 No 182 } m_allowGeolocation; 183#if PLATFORM(IOS) 184 bool m_isSuspended; 185 bool m_resetOnResume; 186 bool m_hasChangedPosition; 187 RefPtr<PositionError> m_errorWaitingForResume; 188 189 void resumeTimerFired(Timer<Geolocation>&); 190 Timer<Geolocation> m_resumeTimer; 191#endif // PLATFORM(IOS) 192 193 GeoNotifierSet m_requestsAwaitingCachedPosition; 194}; 195 196} // namespace WebCore 197 198#endif // ENABLE(GEOLOCATION) 199 200#endif // Geolocation_h 201 202