2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All Rights Reserved.
3 * Copyright 2010, The Android Open Source Project
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 #include "bindings/v8/ScriptWrappable.h"
31 #include "core/dom/ActiveDOMObject.h"
32 #include "modules/geolocation/Geoposition.h"
33 #include "modules/geolocation/PositionCallback.h"
34 #include "modules/geolocation/PositionError.h"
35 #include "modules/geolocation/PositionErrorCallback.h"
36 #include "modules/geolocation/PositionOptions.h"
37 #include "platform/Timer.h"
38 #include "platform/heap/Handle.h"
44 class GeolocationController;
45 class GeolocationError;
46 class GeolocationPosition;
48 class ExecutionContext;
50 class Geolocation FINAL : public RefCountedWillBeGarbageCollectedFinalized<Geolocation>, public ScriptWrappable, public ActiveDOMObject
53 static PassRefPtrWillBeRawPtr<Geolocation> create(ExecutionContext*);
54 virtual ~Geolocation();
57 virtual void stop() OVERRIDE;
58 Document* document() const;
59 LocalFrame* frame() const;
61 // Creates a oneshot and attempts to obtain a position that meets the
62 // constraints of the options.
63 void getCurrentPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PassRefPtrWillBeRawPtr<PositionOptions>);
65 // Creates a watcher that will be notified whenever a new position is
66 // available that meets the constraints of the options.
67 int watchPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PassRefPtrWillBeRawPtr<PositionOptions>);
69 // Removes all references to the watcher, it will not be updated again.
70 void clearWatch(int watchID);
72 void setIsAllowed(bool);
74 bool isAllowed() const { return m_allowGeolocation == Yes; }
76 // Notifies this that a new position is available. Must never be called
77 // before permission is granted by the user.
78 void positionChanged();
80 // Notifies this that an error has occurred, it must be handled immediately.
81 void setError(GeolocationError*);
84 // Returns the last known position, if any. May return null.
85 Geoposition* lastPosition();
87 bool isDenied() const { return m_allowGeolocation == No; }
89 explicit Geolocation(ExecutionContext*);
93 // Holds the success and error callbacks and the options that were provided
94 // when a oneshot or watcher were created. Also, if specified in the
95 // options, manages a timer to limit the time to wait for the system to
97 class GeoNotifier : public RefCountedWillBeGarbageCollectedFinalized<GeoNotifier> {
99 static PassRefPtrWillBeRawPtr<GeoNotifier> create(Geolocation* geolocation, PassOwnPtr<PositionCallback> positionCallback, PassOwnPtr<PositionErrorCallback> positionErrorCallback, PassRefPtrWillBeRawPtr<PositionOptions> options)
101 return adoptRefWillBeNoop(new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options));
103 void trace(Visitor*);
105 PositionOptions* options() const { return m_options.get(); };
107 // Sets the given error as the fatal error if there isn't one yet.
108 // Starts the timer with an interval of 0.
109 void setFatalError(PassRefPtrWillBeRawPtr<PositionError>);
111 bool useCachedPosition() const { return m_useCachedPosition; }
113 // Tells the notifier to use a cached position and starts its timer with
115 void setUseCachedPosition();
117 void runSuccessCallback(Geoposition*);
118 void runErrorCallback(PositionError*);
120 // Starts the timer if a timeout was specified on the options.
121 void startTimerIfNeeded();
125 // Runs the error callback if there is a fatal error. Otherwise, if a
126 // cached position must be used, registers itself for receiving one.
127 // Otherwise, the notifier has expired, and its error callback is run.
128 void timerFired(Timer<GeoNotifier>*);
130 bool hasZeroTimeout() const;
133 GeoNotifier(Geolocation*, PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PassRefPtrWillBeRawPtr<PositionOptions>);
135 RefPtrWillBeMember<Geolocation> m_geolocation;
136 OwnPtr<PositionCallback> m_successCallback;
137 OwnPtr<PositionErrorCallback> m_errorCallback;
138 RefPtrWillBeMember<PositionOptions> m_options;
139 Timer<GeoNotifier> m_timer;
140 RefPtrWillBeMember<PositionError> m_fatalError;
141 bool m_useCachedPosition;
144 typedef WillBeHeapVector<RefPtrWillBeMember<GeoNotifier> > GeoNotifierVector;
145 typedef WillBeHeapHashSet<RefPtrWillBeMember<GeoNotifier> > GeoNotifierSet;
148 DISALLOW_ALLOCATION();
150 void trace(Visitor*);
151 bool add(int id, PassRefPtrWillBeRawPtr<GeoNotifier>);
152 GeoNotifier* find(int id);
154 void remove(GeoNotifier*);
155 bool contains(GeoNotifier*) const;
157 bool isEmpty() const;
158 void getNotifiersVector(GeoNotifierVector&) const;
160 typedef WillBeHeapHashMap<int, RefPtrWillBeMember<GeoNotifier> > IdToNotifierMap;
161 typedef WillBeHeapHashMap<RefPtrWillBeMember<GeoNotifier>, int> NotifierToIdMap;
162 IdToNotifierMap m_idToNotifierMap;
163 NotifierToIdMap m_notifierToIdMap;
166 bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); }
168 void sendError(GeoNotifierVector&, PositionError*);
169 void sendPosition(GeoNotifierVector&, Geoposition*);
171 // Removes notifiers that use a cached position from |notifiers| and
172 // if |cached| is not null they are added to it.
173 static void extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached);
175 // Copies notifiers from |src| vector to |dest| set.
176 static void copyToSet(const GeoNotifierVector& src, GeoNotifierSet& dest);
178 static void stopTimer(GeoNotifierVector&);
179 void stopTimersForOneShots();
180 void stopTimersForWatchers();
183 // Sets a fatal error on the given notifiers.
184 void cancelRequests(GeoNotifierVector&);
186 // Sets a fatal error on all notifiers.
187 void cancelAllRequests();
189 // Runs the success callbacks on all notifiers. A position must be available
190 // and the user must have given permission.
191 void makeSuccessCallbacks();
193 // Sends the given error to all notifiers, unless the error is not fatal and
194 // the notifier is due to receive a cached position. Clears the oneshots,
195 // and also clears the watchers if the error is fatal.
196 void handleError(PositionError*);
198 // Requests permission to share positions with the page.
199 void requestPermission();
201 // Attempts to register this with the controller for receiving updates.
202 // Returns false if there is no controller to register with.
203 bool startUpdating(GeoNotifier*);
207 // Processes the notifiers that were waiting for a permission decision. If
208 // granted and this can be registered with the controller then the
209 // notifier's timers are started. Otherwise, a fatal error is set on them.
210 void handlePendingPermissionNotifiers();
212 // Attempts to obtain a position for the given notifier, either by using
213 // the cached position or by requesting one from the controller. Sets a
214 // fatal error if permission is denied or no position can be obtained.
215 void startRequest(GeoNotifier*);
217 // Discards the notifier because a fatal error occurred for it.
218 void fatalErrorOccurred(GeoNotifier*);
220 // Discards the notifier if it is a oneshot because it timed it.
221 void requestTimedOut(GeoNotifier*);
223 // Adds the notifier to the set awaiting a cached position. Runs the success
224 // callbacks for them if permission has been granted. Requests permission if
226 void requestUsesCachedPosition(GeoNotifier*);
228 bool haveSuitableCachedPosition(PositionOptions*);
230 // Runs the success callbacks for the set of notifiers awaiting a cached
231 // position, the set is then cleared. The oneshots are removed everywhere.
232 void makeCachedPositionCallbacks();
234 GeoNotifierSet m_oneShots;
236 GeoNotifierSet m_pendingForPermissionNotifiers;
237 RefPtrWillBeMember<Geoposition> m_lastPosition;
244 } m_allowGeolocation;
246 GeoNotifierSet m_requestsAwaitingCachedPosition;
249 } // namespace WebCore
251 #endif // Geolocation_h