• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
39 
40 namespace WebCore {
41 
42 class Document;
43 class LocalFrame;
44 class GeolocationController;
45 class GeolocationError;
46 class GeolocationPosition;
47 class ExecutionContext;
48 
49 class Geolocation FINAL
50     : public GarbageCollectedFinalized<Geolocation>
51     , public ScriptWrappable
52     , public ActiveDOMObject {
53 public:
54     static Geolocation* create(ExecutionContext*);
55     virtual ~Geolocation();
56     void trace(Visitor*);
57 
58     virtual void stop() OVERRIDE;
59     Document* document() const;
60     LocalFrame* frame() const;
61 
62     // Creates a oneshot and attempts to obtain a position that meets the
63     // constraints of the options.
64     void getCurrentPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PositionOptions*);
65 
66     // Creates a watcher that will be notified whenever a new position is
67     // available that meets the constraints of the options.
68     int watchPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PositionOptions*);
69 
70     // Removes all references to the watcher, it will not be updated again.
71     void clearWatch(int watchID);
72 
73     void setIsAllowed(bool);
74 
isAllowed()75     bool isAllowed() const { return m_allowGeolocation == Yes; }
76 
77     // Notifies this that a new position is available. Must never be called
78     // before permission is granted by the user.
79     void positionChanged();
80 
81     // Notifies this that an error has occurred, it must be handled immediately.
82     void setError(GeolocationError*);
83 
84 private:
85     // Returns the last known position, if any. May return null.
86     Geoposition* lastPosition();
87 
isDenied()88     bool isDenied() const { return m_allowGeolocation == No; }
89 
90     explicit Geolocation(ExecutionContext*);
91 
92     // Holds the success and error callbacks and the options that were provided
93     // when a oneshot or watcher were created. Also, if specified in the
94     // options, manages a timer to limit the time to wait for the system to
95     // obtain a position.
96     class GeoNotifier : public GarbageCollectedFinalized<GeoNotifier> {
97     public:
create(Geolocation * geolocation,PassOwnPtr<PositionCallback> positionCallback,PassOwnPtr<PositionErrorCallback> positionErrorCallback,PositionOptions * options)98         static GeoNotifier* create(Geolocation* geolocation, PassOwnPtr<PositionCallback> positionCallback, PassOwnPtr<PositionErrorCallback> positionErrorCallback, PositionOptions* options)
99         {
100             return new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options);
101         }
102         void trace(Visitor*);
103 
options()104         PositionOptions* options() const { return m_options.get(); };
105 
106         // Sets the given error as the fatal error if there isn't one yet.
107         // Starts the timer with an interval of 0.
108         void setFatalError(PositionError*);
109 
useCachedPosition()110         bool useCachedPosition() const { return m_useCachedPosition; }
111 
112         // Tells the notifier to use a cached position and starts its timer with
113         // an interval of 0.
114         void setUseCachedPosition();
115 
116         void runSuccessCallback(Geoposition*);
117         void runErrorCallback(PositionError*);
118 
119         void startTimer();
120         void stopTimer();
121 
122         // Runs the error callback if there is a fatal error. Otherwise, if a
123         // cached position must be used, registers itself for receiving one.
124         // Otherwise, the notifier has expired, and its error callback is run.
125         void timerFired(Timer<GeoNotifier>*);
126 
127     private:
128         GeoNotifier(Geolocation*, PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PositionOptions*);
129 
130         Member<Geolocation> m_geolocation;
131         OwnPtr<PositionCallback> m_successCallback;
132         OwnPtr<PositionErrorCallback> m_errorCallback;
133         Member<PositionOptions> m_options;
134         Timer<GeoNotifier> m_timer;
135         Member<PositionError> m_fatalError;
136         bool m_useCachedPosition;
137     };
138 
139     typedef HeapVector<Member<GeoNotifier> > GeoNotifierVector;
140     typedef HeapHashSet<Member<GeoNotifier> > GeoNotifierSet;
141 
142     class Watchers {
143         DISALLOW_ALLOCATION();
144     public:
145         void trace(Visitor*);
146         bool add(int id, GeoNotifier*);
147         GeoNotifier* find(int id);
148         void remove(int id);
149         void remove(GeoNotifier*);
150         bool contains(GeoNotifier*) const;
151         void clear();
152         bool isEmpty() const;
153         void getNotifiersVector(GeoNotifierVector&) const;
154     private:
155         typedef HeapHashMap<int, Member<GeoNotifier> > IdToNotifierMap;
156         typedef HeapHashMap<Member<GeoNotifier>, int> NotifierToIdMap;
157         IdToNotifierMap m_idToNotifierMap;
158         NotifierToIdMap m_notifierToIdMap;
159     };
160 
hasListeners()161     bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); }
162 
163     void sendError(GeoNotifierVector&, PositionError*);
164     void sendPosition(GeoNotifierVector&, Geoposition*);
165 
166     // Removes notifiers that use a cached position from |notifiers| and
167     // if |cached| is not null they are added to it.
168     static void extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached);
169 
170     // Copies notifiers from |src| vector to |dest| set.
171     static void copyToSet(const GeoNotifierVector& src, GeoNotifierSet& dest);
172 
173     static void stopTimer(GeoNotifierVector&);
174     void stopTimersForOneShots();
175     void stopTimersForWatchers();
176     void stopTimers();
177 
178     // Sets a fatal error on the given notifiers.
179     void cancelRequests(GeoNotifierVector&);
180 
181     // Sets a fatal error on all notifiers.
182     void cancelAllRequests();
183 
184     // Runs the success callbacks on all notifiers. A position must be available
185     // and the user must have given permission.
186     void makeSuccessCallbacks();
187 
188     // Sends the given error to all notifiers, unless the error is not fatal and
189     // the notifier is due to receive a cached position. Clears the oneshots,
190     // and also  clears the watchers if the error is fatal.
191     void handleError(PositionError*);
192 
193     // Requests permission to share positions with the page.
194     void requestPermission();
195 
196     // Attempts to register this with the controller for receiving updates.
197     // Returns false if there is no controller to register with.
198     bool startUpdating(GeoNotifier*);
199 
200     void stopUpdating();
201 
202     // Processes the notifiers that were waiting for a permission decision. If
203     // granted and this can be registered with the controller then the
204     // notifier's timers are started. Otherwise, a fatal error is set on them.
205     void handlePendingPermissionNotifiers();
206 
207     // Attempts to obtain a position for the given notifier, either by using
208     // the cached position or by requesting one from the controller. Sets a
209     // fatal error if permission is denied or no position can be obtained.
210     void startRequest(GeoNotifier*);
211 
212     // Discards the notifier because a fatal error occurred for it.
213     void fatalErrorOccurred(GeoNotifier*);
214 
215     // Discards the notifier if it is a oneshot because it timed it.
216     void requestTimedOut(GeoNotifier*);
217 
218     // Adds the notifier to the set awaiting a cached position. Runs the success
219     // callbacks for them if permission has been granted. Requests permission if
220     // it is unknown.
221     void requestUsesCachedPosition(GeoNotifier*);
222 
223     bool haveSuitableCachedPosition(PositionOptions*);
224 
225     // Runs the success callbacks for the set of notifiers awaiting a cached
226     // position, the set is then cleared. The oneshots are removed everywhere.
227     void makeCachedPositionCallbacks();
228 
229     GeoNotifierSet m_oneShots;
230     Watchers m_watchers;
231     GeoNotifierSet m_pendingForPermissionNotifiers;
232     Member<Geoposition> m_lastPosition;
233 
234     enum {
235         Unknown,
236         InProgress,
237         Yes,
238         No
239     } m_allowGeolocation;
240 
241     GeoNotifierSet m_requestsAwaitingCachedPosition;
242 };
243 
244 } // namespace WebCore
245 
246 #endif // Geolocation_h
247