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