Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef nsGeoLocation_h
8 : #define nsGeoLocation_h
9 :
10 : // Microsoft's API Name hackery sucks
11 : #undef CreateEvent
12 :
13 : #include "mozilla/StaticPtr.h"
14 : #include "nsCOMPtr.h"
15 : #include "nsTArray.h"
16 : #include "nsITimer.h"
17 : #include "nsIObserver.h"
18 : #include "nsWrapperCache.h"
19 :
20 : #include "nsWeakPtr.h"
21 : #include "nsCycleCollectionParticipant.h"
22 :
23 : #include "nsGeoPosition.h"
24 : #include "nsIDOMGeoGeolocation.h"
25 : #include "nsIDOMGeoPosition.h"
26 : #include "nsIDOMGeoPositionError.h"
27 : #include "nsIDOMGeoPositionCallback.h"
28 : #include "nsIDOMGeoPositionErrorCallback.h"
29 : #include "mozilla/dom/BindingDeclarations.h"
30 : #include "mozilla/dom/GeolocationBinding.h"
31 : #include "mozilla/dom/PositionErrorBinding.h"
32 : #include "mozilla/dom/CallbackObject.h"
33 :
34 : #include "nsIGeolocationProvider.h"
35 : #include "nsIContentPermissionPrompt.h"
36 : #include "mozilla/Attributes.h"
37 :
38 : class nsGeolocationService;
39 : class nsGeolocationRequest;
40 :
41 : namespace mozilla {
42 : namespace dom {
43 : class Geolocation;
44 : typedef CallbackObjectHolder<PositionCallback, nsIDOMGeoPositionCallback> GeoPositionCallback;
45 : typedef CallbackObjectHolder<PositionErrorCallback, nsIDOMGeoPositionErrorCallback> GeoPositionErrorCallback;
46 : } // namespace dom
47 : } // namespace mozilla
48 :
49 0 : struct CachedPositionAndAccuracy {
50 : nsCOMPtr<nsIDOMGeoPosition> position;
51 : bool isHighAccuracy;
52 : };
53 :
54 : /**
55 : * Singleton that manages the geolocation provider
56 : */
57 0 : class nsGeolocationService final : public nsIGeolocationUpdate,
58 : public nsIObserver
59 : {
60 : public:
61 :
62 : static already_AddRefed<nsGeolocationService> GetGeolocationService();
63 : static mozilla::StaticRefPtr<nsGeolocationService> sService;
64 :
65 : NS_DECL_THREADSAFE_ISUPPORTS
66 : NS_DECL_NSIGEOLOCATIONUPDATE
67 : NS_DECL_NSIOBSERVER
68 :
69 0 : nsGeolocationService() {
70 0 : mHigherAccuracy = false;
71 0 : }
72 :
73 : nsresult Init();
74 :
75 : // Management of the Geolocation objects
76 : void AddLocator(mozilla::dom::Geolocation* locator);
77 : void RemoveLocator(mozilla::dom::Geolocation* locator);
78 :
79 : void SetCachedPosition(nsIDOMGeoPosition* aPosition);
80 : CachedPositionAndAccuracy GetCachedPosition();
81 :
82 : // Find and startup a geolocation device (gps, nmea, etc.)
83 : nsresult StartDevice(nsIPrincipal* aPrincipal);
84 :
85 : // Stop the started geolocation device (gps, nmea, etc.)
86 : void StopDevice();
87 :
88 : // create, or reinitalize the callback timer
89 : void SetDisconnectTimer();
90 :
91 : // Update the accuracy and notify the provider if changed
92 : void UpdateAccuracy(bool aForceHigh = false);
93 : bool HighAccuracyRequested();
94 :
95 : private:
96 :
97 : ~nsGeolocationService();
98 :
99 : // Disconnect timer. When this timer expires, it clears all pending callbacks
100 : // and closes down the provider, unless we are watching a point, and in that
101 : // case, we disable the disconnect timer.
102 : nsCOMPtr<nsITimer> mDisconnectTimer;
103 :
104 : // The object providing geo location information to us.
105 : nsCOMPtr<nsIGeolocationProvider> mProvider;
106 :
107 : // mGeolocators are not owned here. Their constructor
108 : // adds them to this list, and their destructor removes
109 : // them from this list.
110 : nsTArray<mozilla::dom::Geolocation*> mGeolocators;
111 :
112 : // This is the last geo position that we have seen.
113 : CachedPositionAndAccuracy mLastPosition;
114 :
115 : // Current state of requests for higher accuracy
116 : bool mHigherAccuracy;
117 : };
118 :
119 : namespace mozilla {
120 : namespace dom {
121 :
122 : /**
123 : * Can return a geolocation info
124 : */
125 : class Geolocation final : public nsIDOMGeoGeolocation,
126 : public nsIGeolocationUpdate,
127 : public nsWrapperCache
128 : {
129 : public:
130 :
131 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
132 0 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Geolocation, nsIDOMGeoGeolocation)
133 :
134 : NS_DECL_NSIGEOLOCATIONUPDATE
135 : NS_DECL_NSIDOMGEOGEOLOCATION
136 :
137 : Geolocation();
138 :
139 : nsresult Init(nsPIDOMWindowInner* aContentDom = nullptr);
140 :
141 : nsPIDOMWindowInner* GetParentObject() const;
142 : virtual JSObject* WrapObject(JSContext *aCtx, JS::Handle<JSObject*> aGivenProto) override;
143 :
144 : int32_t WatchPosition(PositionCallback& aCallback,
145 : PositionErrorCallback* aErrorCallback,
146 : const PositionOptions& aOptions,
147 : CallerType aCallerType,
148 : ErrorResult& aRv);
149 : void GetCurrentPosition(PositionCallback& aCallback,
150 : PositionErrorCallback* aErrorCallback,
151 : const PositionOptions& aOptions,
152 : CallerType aCallerType,
153 : ErrorResult& aRv);
154 :
155 : // Returns true if any of the callbacks are repeating
156 : bool HasActiveCallbacks();
157 :
158 : // Register an allowed request
159 : void NotifyAllowedRequest(nsGeolocationRequest* aRequest);
160 :
161 : // Remove request from all callbacks arrays
162 : void RemoveRequest(nsGeolocationRequest* request);
163 :
164 : // Check if there is already ClearWatch called for current
165 : // request & clear if yes
166 : bool ClearPendingRequest(nsGeolocationRequest* aRequest);
167 :
168 : // Shutting down.
169 : void Shutdown();
170 :
171 : // Getter for the principal that this Geolocation was loaded from
172 0 : nsIPrincipal* GetPrincipal() { return mPrincipal; }
173 :
174 : // Getter for the window that this Geolocation is owned by
175 0 : nsIWeakReference* GetOwner() { return mOwner; }
176 :
177 : // Check to see if the window still exists
178 : bool WindowOwnerStillExists();
179 :
180 : // Check to see if any active request requires high accuracy
181 : bool HighAccuracyRequested();
182 :
183 : private:
184 :
185 : ~Geolocation();
186 :
187 : nsresult GetCurrentPosition(GeoPositionCallback aCallback,
188 : GeoPositionErrorCallback aErrorCallback,
189 : UniquePtr<PositionOptions>&& aOptions,
190 : CallerType aCallerType);
191 : nsresult WatchPosition(GeoPositionCallback aCallback,
192 : GeoPositionErrorCallback aErrorCallback,
193 : UniquePtr<PositionOptions>&& aOptions,
194 : CallerType aCallerType,
195 : int32_t* aRv);
196 :
197 : bool RegisterRequestWithPrompt(nsGeolocationRequest* request);
198 :
199 : // Check if clearWatch is already called
200 : bool IsAlreadyCleared(nsGeolocationRequest* aRequest);
201 :
202 : // Returns whether the Geolocation object should block requests
203 : // within a context that is not secure.
204 : bool ShouldBlockInsecureRequests() const;
205 :
206 : // Two callback arrays. The first |mPendingCallbacks| holds objects for only
207 : // one callback and then they are released/removed from the array. The second
208 : // |mWatchingCallbacks| holds objects until the object is explictly removed or
209 : // there is a page change. All requests held by either array are active, that
210 : // is, they have been allowed and expect to be fulfilled.
211 :
212 : nsTArray<RefPtr<nsGeolocationRequest> > mPendingCallbacks;
213 : nsTArray<RefPtr<nsGeolocationRequest> > mWatchingCallbacks;
214 :
215 : // window that this was created for. Weak reference.
216 : nsWeakPtr mOwner;
217 :
218 : // where the content was loaded from
219 : nsCOMPtr<nsIPrincipal> mPrincipal;
220 :
221 : // the protocols we want to measure
222 : enum class ProtocolType: uint8_t { OTHER, HTTP, HTTPS };
223 :
224 : // the protocol used to load the content
225 : ProtocolType mProtocolType;
226 :
227 : // owning back pointer.
228 : RefPtr<nsGeolocationService> mService;
229 :
230 : // Watch ID
231 : uint32_t mLastWatchId;
232 :
233 : // Pending requests are used when the service is not ready
234 : nsTArray<RefPtr<nsGeolocationRequest> > mPendingRequests;
235 :
236 : // Array containing already cleared watch IDs
237 : nsTArray<int32_t> mClearedWatchIDs;
238 : };
239 :
240 0 : class PositionError final : public nsIDOMGeoPositionError,
241 : public nsWrapperCache
242 : {
243 : public:
244 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
245 0 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PositionError)
246 :
247 : NS_DECL_NSIDOMGEOPOSITIONERROR
248 :
249 : PositionError(Geolocation* aParent, int16_t aCode);
250 :
251 : Geolocation* GetParentObject() const;
252 :
253 : virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
254 :
255 0 : int16_t Code() const {
256 0 : return mCode;
257 : }
258 :
259 : void NotifyCallback(const GeoPositionErrorCallback& callback);
260 : private:
261 : ~PositionError();
262 : int16_t mCode;
263 : RefPtr<Geolocation> mParent;
264 : };
265 :
266 : } // namespace dom
267 :
268 : inline nsISupports*
269 0 : ToSupports(dom::Geolocation* aGeolocation)
270 : {
271 0 : return ToSupports(static_cast<nsIDOMGeoGeolocation*>(aGeolocation));
272 : }
273 :
274 : } // namespace mozilla
275 :
276 : #endif /* nsGeoLocation_h */
|