1 /* 2 * Copyright (C) 2008, 2009 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 #include "GeolocationPositionCache.h" 31 #include "Geoposition.h" 32 #include "PositionCallback.h" 33 #include "PositionError.h" 34 #include "PositionErrorCallback.h" 35 #include "PositionOptions.h" 36 #include "Timer.h" 37 38 #if !ENABLE(CLIENT_BASED_GEOLOCATION) 39 #include "GeolocationService.h" 40 #endif 41 42 namespace WebCore { 43 44 class Frame; 45 46 #if ENABLE(CLIENT_BASED_GEOLOCATION) 47 class GeolocationPosition; 48 class GeolocationError; 49 #endif 50 51 class Geolocation : public RefCounted<Geolocation> 52 #if !ENABLE(CLIENT_BASED_GEOLOCATION) && ENABLE(GEOLOCATION) 53 , public GeolocationServiceClient 54 #endif 55 { 56 public: 57 static PassRefPtr<Geolocation> create(Frame* frame) { return adoptRef(new Geolocation(frame)); } 58 59 ~Geolocation(); 60 61 void reset(); 62 void disconnectFrame(); 63 64 void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); 65 int watchPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); 66 void clearWatch(int watchId); 67 68 // These methods are used by Android. 69 void suspend(); 70 void resume(); 71 72 void setIsAllowed(bool); 73 Frame* frame() const { return m_frame; } 74 75 #if ENABLE(CLIENT_BASED_GEOLOCATION) 76 void positionChanged(); 77 void setError(GeolocationError*); 78 #else 79 GeolocationService* getGeolocationService() const { return m_service.get(); } 80 #endif 81 82 private: 83 Geoposition* lastPosition(); 84 85 bool isAllowed() const { return m_allowGeolocation == Yes; } 86 bool isDenied() const { return m_allowGeolocation == No; } 87 88 Geolocation(Frame*); 89 90 Page* page() const; 91 92 class GeoNotifier : public RefCounted<GeoNotifier> { 93 public: 94 static PassRefPtr<GeoNotifier> create(Geolocation* geolocation, PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options)); } 95 96 void setFatalError(PassRefPtr<PositionError>); 97 bool hasZeroTimeout() const; 98 void setUseCachedPosition(); 99 void runSuccessCallback(Geoposition*); 100 void startTimerIfNeeded(); 101 void timerFired(Timer<GeoNotifier>*); 102 103 Geolocation* m_geolocation; 104 RefPtr<PositionCallback> m_successCallback; 105 RefPtr<PositionErrorCallback> m_errorCallback; 106 RefPtr<PositionOptions> m_options; 107 Timer<GeoNotifier> m_timer; 108 RefPtr<PositionError> m_fatalError; 109 bool m_useCachedPosition; 110 111 private: 112 GeoNotifier(Geolocation*, PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); 113 }; 114 115 typedef Vector<RefPtr<GeoNotifier> > GeoNotifierVector; 116 typedef HashSet<RefPtr<GeoNotifier> > GeoNotifierSet; 117 118 class Watchers { 119 public: 120 void set(int id, PassRefPtr<GeoNotifier>); 121 void remove(int id); 122 void remove(GeoNotifier*); 123 bool contains(GeoNotifier*) const; 124 void clear(); 125 bool isEmpty() const; 126 void getNotifiersVector(GeoNotifierVector&) const; 127 private: 128 typedef HashMap<int, RefPtr<GeoNotifier> > IdToNotifierMap; 129 typedef HashMap<RefPtr<GeoNotifier>, int> NotifierToIdMap; 130 IdToNotifierMap m_idToNotifierMap; 131 NotifierToIdMap m_notifierToIdMap; 132 }; 133 134 class PositionCacheWrapper { 135 public: 136 PositionCacheWrapper() 137 : m_cache(GeolocationPositionCache::instance()) 138 { 139 m_cache->addUser(); 140 } 141 ~PositionCacheWrapper() 142 { 143 m_cache->removeUser(); 144 } 145 void setCachedPosition(Geoposition* cachedPosition) { m_cache->setCachedPosition(cachedPosition); } 146 Geoposition* cachedPosition() { return m_cache->cachedPosition(); } 147 private: 148 GeolocationPositionCache* m_cache; 149 }; 150 151 bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); } 152 153 void sendError(GeoNotifierVector&, PositionError*); 154 void sendPosition(GeoNotifierVector&, Geoposition*); 155 156 static void extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached); 157 static void copyToSet(const GeoNotifierVector&, GeoNotifierSet&); 158 159 static void stopTimer(GeoNotifierVector&); 160 void stopTimersForOneShots(); 161 void stopTimersForWatchers(); 162 void stopTimers(); 163 164 void cancelRequests(GeoNotifierVector&); 165 void cancelAllRequests(); 166 167 void positionChangedInternal(); 168 void makeSuccessCallbacks(); 169 void handleError(PositionError*); 170 171 void requestPermission(); 172 173 bool startUpdating(GeoNotifier*); 174 void stopUpdating(); 175 176 #if USE(PREEMPT_GEOLOCATION_PERMISSION) 177 void handlePendingPermissionNotifiers(); 178 #endif 179 180 #if !ENABLE(CLIENT_BASED_GEOLOCATION) && ENABLE(GEOLOCATION) 181 // GeolocationServiceClient 182 virtual void geolocationServicePositionChanged(GeolocationService*); 183 virtual void geolocationServiceErrorOccurred(GeolocationService*); 184 #endif 185 186 PassRefPtr<GeoNotifier> startRequest(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); 187 188 void fatalErrorOccurred(GeoNotifier*); 189 void requestTimedOut(GeoNotifier*); 190 void requestUsesCachedPosition(GeoNotifier*); 191 bool haveSuitableCachedPosition(PositionOptions*); 192 void makeCachedPositionCallbacks(); 193 194 GeoNotifierSet m_oneShots; 195 Watchers m_watchers; 196 Frame* m_frame; 197 #if !ENABLE(CLIENT_BASED_GEOLOCATION) 198 OwnPtr<GeolocationService> m_service; 199 #endif 200 #if USE(PREEMPT_GEOLOCATION_PERMISSION) 201 GeoNotifierSet m_pendingForPermissionNotifiers; 202 #endif 203 RefPtr<Geoposition> m_lastPosition; 204 205 enum { 206 Unknown, 207 InProgress, 208 Yes, 209 No 210 } m_allowGeolocation; 211 212 #if ENABLE(GEOLOCATION) 213 PositionCacheWrapper m_positionCache; 214 #endif 215 GeoNotifierSet m_requestsAwaitingCachedPosition; 216 }; 217 218 } // namespace WebCore 219 220 #endif // Geolocation_h 221 222