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#include "bindings/core/v8/ScriptWrappable.h" 31#include "core/dom/ActiveDOMObject.h" 32#include "modules/geolocation/GeoNotifier.h" 33#include "modules/geolocation/GeolocationWatchers.h" 34#include "modules/geolocation/Geoposition.h" 35#include "modules/geolocation/PositionCallback.h" 36#include "modules/geolocation/PositionError.h" 37#include "modules/geolocation/PositionErrorCallback.h" 38#include "modules/geolocation/PositionOptions.h" 39#include "platform/Timer.h" 40#include "platform/heap/Handle.h" 41 42namespace blink { 43 44class Dictionary; 45class Document; 46class LocalFrame; 47class GeolocationController; 48class GeolocationError; 49class GeolocationPosition; 50class ExecutionContext; 51 52class Geolocation FINAL 53 : public GarbageCollectedFinalized<Geolocation> 54 , public ScriptWrappable 55 , public ActiveDOMObject { 56 DEFINE_WRAPPERTYPEINFO(); 57public: 58 static Geolocation* create(ExecutionContext*); 59 virtual ~Geolocation(); 60 void trace(Visitor*); 61 62 virtual void stop() OVERRIDE; 63 Document* document() const; 64 LocalFrame* frame() const; 65 66 // Creates a oneshot and attempts to obtain a position that meets the 67 // constraints of the options. 68 void getCurrentPosition(PositionCallback*, PositionErrorCallback*, const Dictionary&); 69 70 // Creates a watcher that will be notified whenever a new position is 71 // available that meets the constraints of the options. 72 int watchPosition(PositionCallback*, PositionErrorCallback*, const Dictionary&); 73 74 // Removes all references to the watcher, it will not be updated again. 75 void clearWatch(int watchID); 76 77 void setIsAllowed(bool); 78 79 bool isAllowed() const { return m_geolocationPermission == PermissionAllowed; } 80 81 // Notifies this that a new position is available. Must never be called 82 // before permission is granted by the user. 83 void positionChanged(); 84 85 // Notifies this that an error has occurred, it must be handled immediately. 86 void setError(GeolocationError*); 87 88 // Discards the notifier because a fatal error occurred for it. 89 void fatalErrorOccurred(GeoNotifier*); 90 91 // Adds the notifier to the set awaiting a cached position. Runs the success 92 // callbacks for them if permission has been granted. Requests permission if 93 // it is unknown. 94 void requestUsesCachedPosition(GeoNotifier*); 95 96 // Discards the notifier if it is a oneshot because it timed it. 97 void requestTimedOut(GeoNotifier*); 98 99private: 100 // Returns the last known position, if any. May return null. 101 Geoposition* lastPosition(); 102 103 bool isDenied() const { return m_geolocationPermission == PermissionDenied; } 104 105 explicit Geolocation(ExecutionContext*); 106 107 typedef HeapVector<Member<GeoNotifier> > GeoNotifierVector; 108 typedef HeapHashSet<Member<GeoNotifier> > GeoNotifierSet; 109 110 bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); } 111 112 void sendError(GeoNotifierVector&, PositionError*); 113 void sendPosition(GeoNotifierVector&, Geoposition*); 114 115 // Removes notifiers that use a cached position from |notifiers| and 116 // if |cached| is not null they are added to it. 117 static void extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached); 118 119 // Copies notifiers from |src| vector to |dest| set. 120 static void copyToSet(const GeoNotifierVector& src, GeoNotifierSet& dest); 121 122 static void stopTimer(GeoNotifierVector&); 123 void stopTimersForOneShots(); 124 void stopTimersForWatchers(); 125 void stopTimers(); 126 127 // Sets a fatal error on the given notifiers. 128 void cancelRequests(GeoNotifierVector&); 129 130 // Sets a fatal error on all notifiers. 131 void cancelAllRequests(); 132 133 // Runs the success callbacks on all notifiers. A position must be available 134 // and the user must have given permission. 135 void makeSuccessCallbacks(); 136 137 // Sends the given error to all notifiers, unless the error is not fatal and 138 // the notifier is due to receive a cached position. Clears the oneshots, 139 // and also clears the watchers if the error is fatal. 140 void handleError(PositionError*); 141 142 // Requests permission to share positions with the page. 143 void requestPermission(); 144 145 // Attempts to register this with the controller for receiving updates. 146 // Returns false if there is no controller to register with. 147 bool startUpdating(GeoNotifier*); 148 149 void stopUpdating(); 150 151 // Processes the notifiers that were waiting for a permission decision. If 152 // granted and this can be registered with the controller then the 153 // notifier's timers are started. Otherwise, a fatal error is set on them. 154 void handlePendingPermissionNotifiers(); 155 156 // Attempts to obtain a position for the given notifier, either by using 157 // the cached position or by requesting one from the controller. Sets a 158 // fatal error if permission is denied or no position can be obtained. 159 void startRequest(GeoNotifier*); 160 161 bool haveSuitableCachedPosition(PositionOptions*); 162 163 // Runs the success callbacks for the set of notifiers awaiting a cached 164 // position, the set is then cleared. The oneshots are removed everywhere. 165 void makeCachedPositionCallbacks(); 166 167 GeoNotifierSet m_oneShots; 168 GeolocationWatchers m_watchers; 169 GeoNotifierSet m_pendingForPermissionNotifiers; 170 Member<Geoposition> m_lastPosition; 171 172 // States of Geolocation permission as granted by the embedder. Unknown 173 // means that the embedder still has to be asked for the current permission 174 // level; Requested means that the user has yet to make a decision. 175 enum Permission { 176 PermissionUnknown, 177 PermissionRequested, 178 PermissionAllowed, 179 PermissionDenied 180 }; 181 182 Permission m_geolocationPermission; 183 184 GeoNotifierSet m_requestsAwaitingCachedPosition; 185}; 186 187} // namespace blink 188 189#endif // Geolocation_h 190