michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsGeoLocation_h michael@0: #define nsGeoLocation_h michael@0: michael@0: // Microsoft's API Name hackery sucks michael@0: #undef CreateEvent michael@0: michael@0: #include "mozilla/StaticPtr.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsTArray.h" michael@0: #include "nsITimer.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsWrapperCache.h" michael@0: michael@0: #include "nsWeakPtr.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: michael@0: #include "nsGeoPosition.h" michael@0: #include "nsIDOMGeoGeolocation.h" michael@0: #include "nsIDOMGeoPosition.h" michael@0: #include "nsIDOMGeoPositionError.h" michael@0: #include "nsIDOMGeoPositionCallback.h" michael@0: #include "nsIDOMGeoPositionErrorCallback.h" michael@0: #include "mozilla/dom/GeolocationBinding.h" michael@0: #include "mozilla/dom/PositionErrorBinding.h" michael@0: #include "mozilla/dom/CallbackObject.h" michael@0: michael@0: #include "nsIGeolocationProvider.h" michael@0: #include "nsIContentPermissionPrompt.h" michael@0: #include "nsIDOMWindow.h" michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: class nsGeolocationService; michael@0: class nsGeolocationRequest; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class Geolocation; michael@0: typedef CallbackObjectHolder GeoPositionCallback; michael@0: typedef CallbackObjectHolder GeoPositionErrorCallback; michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Singleton that manages the geolocation provider michael@0: */ michael@0: class nsGeolocationService MOZ_FINAL : public nsIGeolocationUpdate, public nsIObserver michael@0: { michael@0: public: michael@0: michael@0: static already_AddRefed GetGeolocationService(); michael@0: static mozilla::StaticRefPtr sService; michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIGEOLOCATIONUPDATE michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: nsGeolocationService() { michael@0: mHigherAccuracy = false; michael@0: } michael@0: michael@0: nsresult Init(); michael@0: michael@0: void HandleMozsettingChanged(const char16_t* aData); michael@0: void HandleMozsettingValue(const bool aValue); michael@0: michael@0: // Management of the Geolocation objects michael@0: void AddLocator(mozilla::dom::Geolocation* locator); michael@0: void RemoveLocator(mozilla::dom::Geolocation* locator); michael@0: michael@0: void SetCachedPosition(nsIDOMGeoPosition* aPosition); michael@0: nsIDOMGeoPosition* GetCachedPosition(); michael@0: michael@0: // Find and startup a geolocation device (gps, nmea, etc.) michael@0: nsresult StartDevice(nsIPrincipal* aPrincipal); michael@0: michael@0: // Stop the started geolocation device (gps, nmea, etc.) michael@0: void StopDevice(); michael@0: michael@0: // create, or reinitalize the callback timer michael@0: void SetDisconnectTimer(); michael@0: michael@0: // Update the accuracy and notify the provider if changed michael@0: void UpdateAccuracy(bool aForceHigh = false); michael@0: bool HighAccuracyRequested(); michael@0: michael@0: private: michael@0: michael@0: ~nsGeolocationService(); michael@0: michael@0: // Disconnect timer. When this timer expires, it clears all pending callbacks michael@0: // and closes down the provider, unless we are watching a point, and in that michael@0: // case, we disable the disconnect timer. michael@0: nsCOMPtr mDisconnectTimer; michael@0: michael@0: // The object providing geo location information to us. michael@0: nsCOMPtr mProvider; michael@0: michael@0: // mGeolocators are not owned here. Their constructor michael@0: // adds them to this list, and their destructor removes michael@0: // them from this list. michael@0: nsTArray mGeolocators; michael@0: michael@0: // This is the last geo position that we have seen. michael@0: nsCOMPtr mLastPosition; michael@0: michael@0: // Current state of requests for higher accuracy michael@0: bool mHigherAccuracy; michael@0: }; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: /** michael@0: * Can return a geolocation info michael@0: */ michael@0: class Geolocation MOZ_FINAL : public nsIDOMGeoGeolocation, michael@0: public nsIGeolocationUpdate, michael@0: public nsWrapperCache michael@0: { michael@0: public: michael@0: michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Geolocation, nsIDOMGeoGeolocation) michael@0: michael@0: NS_DECL_NSIGEOLOCATIONUPDATE michael@0: NS_DECL_NSIDOMGEOGEOLOCATION michael@0: michael@0: Geolocation(); michael@0: michael@0: nsresult Init(nsIDOMWindow* contentDom=nullptr); michael@0: michael@0: nsIDOMWindow* GetParentObject() const; michael@0: virtual JSObject* WrapObject(JSContext *aCtx) MOZ_OVERRIDE; michael@0: michael@0: int32_t WatchPosition(PositionCallback& aCallback, PositionErrorCallback* aErrorCallback, const PositionOptions& aOptions, ErrorResult& aRv); michael@0: void GetCurrentPosition(PositionCallback& aCallback, PositionErrorCallback* aErrorCallback, const PositionOptions& aOptions, ErrorResult& aRv); michael@0: michael@0: void SetCachedPosition(Position* aPosition); michael@0: Position* GetCachedPosition(); michael@0: michael@0: // Returns true if any of the callbacks are repeating michael@0: bool HasActiveCallbacks(); michael@0: michael@0: // Register an allowed request michael@0: void NotifyAllowedRequest(nsGeolocationRequest* aRequest); michael@0: michael@0: // Remove request from all callbacks arrays michael@0: void RemoveRequest(nsGeolocationRequest* request); michael@0: michael@0: // Shutting down. michael@0: void Shutdown(); michael@0: michael@0: // Getter for the principal that this Geolocation was loaded from michael@0: nsIPrincipal* GetPrincipal() { return mPrincipal; } michael@0: michael@0: // Getter for the window that this Geolocation is owned by michael@0: nsIWeakReference* GetOwner() { return mOwner; } michael@0: michael@0: // Check to see if the widnow still exists michael@0: bool WindowOwnerStillExists(); michael@0: michael@0: // Check to see if any active request requires high accuracy michael@0: bool HighAccuracyRequested(); michael@0: michael@0: // Notification from the service: michael@0: void ServiceReady(); michael@0: michael@0: private: michael@0: michael@0: ~Geolocation(); michael@0: michael@0: nsresult GetCurrentPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, PositionOptions* aOptions); michael@0: nsresult WatchPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, PositionOptions* aOptions, int32_t* aRv); michael@0: michael@0: bool RegisterRequestWithPrompt(nsGeolocationRequest* request); michael@0: michael@0: // Methods for the service when it's ready to process requests: michael@0: nsresult GetCurrentPositionReady(nsGeolocationRequest* aRequest); michael@0: nsresult WatchPositionReady(nsGeolocationRequest* aRequest); michael@0: michael@0: // Two callback arrays. The first |mPendingCallbacks| holds objects for only michael@0: // one callback and then they are released/removed from the array. The second michael@0: // |mWatchingCallbacks| holds objects until the object is explictly removed or michael@0: // there is a page change. All requests held by either array are active, that michael@0: // is, they have been allowed and expect to be fulfilled. michael@0: michael@0: nsTArray > mPendingCallbacks; michael@0: nsTArray > mWatchingCallbacks; michael@0: michael@0: // window that this was created for. Weak reference. michael@0: nsWeakPtr mOwner; michael@0: michael@0: // where the content was loaded from michael@0: nsCOMPtr mPrincipal; michael@0: michael@0: // owning back pointer. michael@0: nsRefPtr mService; michael@0: michael@0: // cached Position wrapper michael@0: nsRefPtr mCachedPosition; michael@0: michael@0: // Watch ID michael@0: uint32_t mLastWatchId; michael@0: michael@0: // Pending requests are used when the service is not ready michael@0: nsTArray > mPendingRequests; michael@0: }; michael@0: michael@0: class PositionError MOZ_FINAL : public nsIDOMGeoPositionError, michael@0: public nsWrapperCache michael@0: { michael@0: public: michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PositionError) michael@0: michael@0: NS_DECL_NSIDOMGEOPOSITIONERROR michael@0: michael@0: PositionError(Geolocation* aParent, int16_t aCode); michael@0: michael@0: Geolocation* GetParentObject() const; michael@0: michael@0: virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; michael@0: michael@0: int16_t Code() const { michael@0: return mCode; michael@0: } michael@0: michael@0: void NotifyCallback(const GeoPositionErrorCallback& callback); michael@0: private: michael@0: ~PositionError(); michael@0: int16_t mCode; michael@0: nsRefPtr mParent; michael@0: }; michael@0: michael@0: } michael@0: michael@0: inline nsISupports* michael@0: ToSupports(dom::Geolocation* aGeolocation) michael@0: { michael@0: return ToSupports(static_cast(aGeolocation)); michael@0: } michael@0: } michael@0: michael@0: #endif /* nsGeoLocation_h */