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