GeolocationPosition.cpp (5976B)
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 #include "mozilla/dom/GeolocationPosition.h" 8 9 #include "mozilla/FloatingPoint.h" 10 #include "mozilla/dom/GeolocationCoordinates.h" 11 #include "mozilla/dom/GeolocationPositionBinding.h" 12 13 using mozilla::EqualOrBothNaN; 14 15 // NaN() is a more convenient function name. 16 inline double NaN() { return mozilla::UnspecifiedNaN<double>(); } 17 18 //////////////////////////////////////////////////// 19 // nsGeoPositionCoords 20 //////////////////////////////////////////////////// 21 nsGeoPositionCoords::nsGeoPositionCoords(double aLat, double aLong, double aAlt, 22 double aHError, double aVError, 23 double aHeading, double aSpeed) 24 : mLat(aLat), 25 mLong(aLong), 26 mAlt(aAlt), 27 mHError((aHError >= 0) ? aHError : 0) 28 // altitudeAccuracy without an altitude doesn't make any sense. 29 , 30 mVError((aVError >= 0 && !std::isnan(aAlt)) ? aVError : NaN()) 31 // If the hosting device is stationary (i.e. the value of the speed 32 // attribute is 0), then the value of the heading attribute must be NaN 33 // (or null). 34 , 35 mHeading((aHeading >= 0 && aHeading < 360 && aSpeed > 0) ? aHeading 36 : NaN()), 37 mSpeed(aSpeed >= 0 ? aSpeed : NaN()) { 38 // Sanity check the location provider's results in debug builds. If the 39 // location provider is returning bogus results, we'd like to know, but 40 // we prefer to return some position data to JavaScript over a 41 // POSITION_UNAVAILABLE error. 42 MOZ_ASSERT(aLat >= -90 && aLat <= 90); 43 MOZ_ASSERT(aLong >= -180 && aLong <= 180); 44 MOZ_ASSERT(!(aLat == 0 && aLong == 0)); // valid but probably a bug 45 46 MOZ_ASSERT(EqualOrBothNaN(mAlt, aAlt)); 47 MOZ_ASSERT(mHError == aHError); 48 MOZ_ASSERT(EqualOrBothNaN(mVError, aVError)); 49 MOZ_ASSERT(EqualOrBothNaN(mHeading, aHeading)); 50 MOZ_ASSERT(EqualOrBothNaN(mSpeed, aSpeed)); 51 } 52 53 nsGeoPositionCoords::~nsGeoPositionCoords() = default; 54 55 NS_INTERFACE_MAP_BEGIN(nsGeoPositionCoords) 56 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionCoords) 57 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCoords) 58 NS_INTERFACE_MAP_END 59 60 NS_IMPL_ADDREF(nsGeoPositionCoords) 61 NS_IMPL_RELEASE(nsGeoPositionCoords) 62 63 NS_IMETHODIMP 64 nsGeoPositionCoords::GetLatitude(double* aLatitude) { 65 *aLatitude = mLat; 66 return NS_OK; 67 } 68 69 NS_IMETHODIMP 70 nsGeoPositionCoords::GetLongitude(double* aLongitude) { 71 *aLongitude = mLong; 72 return NS_OK; 73 } 74 75 NS_IMETHODIMP 76 nsGeoPositionCoords::GetAltitude(double* aAltitude) { 77 *aAltitude = mAlt; 78 return NS_OK; 79 } 80 81 NS_IMETHODIMP 82 nsGeoPositionCoords::GetAccuracy(double* aAccuracy) { 83 *aAccuracy = mHError; 84 return NS_OK; 85 } 86 87 NS_IMETHODIMP 88 nsGeoPositionCoords::GetAltitudeAccuracy(double* aAltitudeAccuracy) { 89 *aAltitudeAccuracy = mVError; 90 return NS_OK; 91 } 92 93 NS_IMETHODIMP 94 nsGeoPositionCoords::GetHeading(double* aHeading) { 95 *aHeading = mHeading; 96 return NS_OK; 97 } 98 99 NS_IMETHODIMP 100 nsGeoPositionCoords::GetSpeed(double* aSpeed) { 101 *aSpeed = mSpeed; 102 return NS_OK; 103 } 104 105 //////////////////////////////////////////////////// 106 // nsGeoPosition 107 //////////////////////////////////////////////////// 108 109 nsGeoPosition::nsGeoPosition(double aLat, double aLong, double aAlt, 110 double aHError, double aVError, double aHeading, 111 double aSpeed, EpochTimeStamp aTimestamp) 112 : mTimestamp(aTimestamp) { 113 mCoords = new nsGeoPositionCoords(aLat, aLong, aAlt, aHError, aVError, 114 aHeading, aSpeed); 115 } 116 117 nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords* aCoords, 118 EpochTimeStamp aTimestamp) 119 : mTimestamp(aTimestamp), mCoords(aCoords) {} 120 121 nsGeoPosition::~nsGeoPosition() = default; 122 123 NS_INTERFACE_MAP_BEGIN(nsGeoPosition) 124 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPosition) 125 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPosition) 126 NS_INTERFACE_MAP_END 127 128 NS_IMPL_ADDREF(nsGeoPosition) 129 NS_IMPL_RELEASE(nsGeoPosition) 130 131 NS_IMETHODIMP 132 nsGeoPosition::GetTimestamp(EpochTimeStamp* aTimestamp) { 133 *aTimestamp = mTimestamp; 134 return NS_OK; 135 } 136 137 NS_IMETHODIMP 138 nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords** aCoords) { 139 NS_IF_ADDREF(*aCoords = mCoords); 140 return NS_OK; 141 } 142 143 namespace mozilla::dom { 144 145 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(GeolocationPosition, mParent, 146 mCoordinates) 147 NS_IMPL_CYCLE_COLLECTING_ADDREF(GeolocationPosition) 148 NS_IMPL_CYCLE_COLLECTING_RELEASE(GeolocationPosition) 149 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GeolocationPosition) 150 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 151 NS_INTERFACE_MAP_ENTRY(nsISupports) 152 NS_INTERFACE_MAP_END 153 154 GeolocationPosition::GeolocationPosition(nsISupports* aParent, 155 nsIDOMGeoPosition* aGeoPosition) 156 : mParent(aParent), mGeoPosition(aGeoPosition) {} 157 158 GeolocationPosition::~GeolocationPosition() = default; 159 160 nsISupports* GeolocationPosition::GetParentObject() const { return mParent; } 161 162 JSObject* GeolocationPosition::WrapObject(JSContext* aCx, 163 JS::Handle<JSObject*> aGivenProto) { 164 return GeolocationPosition_Binding::Wrap(aCx, this, aGivenProto); 165 } 166 167 GeolocationCoordinates* GeolocationPosition::Coords() { 168 if (!mCoordinates) { 169 nsCOMPtr<nsIDOMGeoPositionCoords> coords; 170 mGeoPosition->GetCoords(getter_AddRefs(coords)); 171 MOZ_ASSERT(coords, "coords should not be null"); 172 173 mCoordinates = new GeolocationCoordinates(this, coords); 174 } 175 176 return mCoordinates; 177 } 178 179 uint64_t GeolocationPosition::Timestamp() const { 180 uint64_t rv; 181 182 mGeoPosition->GetTimestamp(&rv); 183 return rv; 184 } 185 186 } // namespace mozilla::dom