Backed out changeset 9742b31c634a (bug 1073419) for bustage

This commit is contained in:
Carsten "Tomcat" Book 2014-10-27 16:56:40 +01:00
parent def2e2924b
commit 69157d7124
8 changed files with 16 additions and 981 deletions

View File

@ -7007,31 +7007,6 @@ elif test -z "$_ENABLE_LOGREFCNT"; then
AC_DEFINE(NO_BUILD_REFCNT_LOGGING)
fi
dnl ========================================================
dnl moz_aproximate_location
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(approximate_location,
[ --enable-approximate-location Enable approximate location ],
MOZ_APPROX_LOCATION=1,
MOZ_APPROX_LOCATION= )
if test -n "$MOZ_APPROX_LOCATION"; then
AC_DEFINE(MOZ_APPROX_LOCATION)
fi
dnl ========================================================
dnl moz_gps_debug
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(gps_debug,
[ --enable-gps-debug Enable gps specific debug messages ],
MOZ_GPS_DEBUG=1,
MOZ_GPS_DEBUG= )
if test -n "$MOZ_GPS_DEBUG"; then
AC_DEFINE(MOZ_GPS_DEBUG)
fi
if test -n "$MOZ_DEBUG"; then
AC_DEFINE(MOZ_GPS_DEBUG)
fi
dnl ========================================================
dnl moz_dump_painting
dnl ========================================================

View File

@ -5,15 +5,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'nsGeolocationSettings.h',
'nsGeoPosition.h',
'nsGeoPositionIPCSerialiser.h',
]
UNIFIED_SOURCES += [
'nsGeoGridFuzzer.cpp',
'nsGeolocation.cpp',
'nsGeolocationSettings.cpp',
'nsGeoPosition.cpp',
]

View File

@ -1,135 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <math.h>
#include "nsGeoGridFuzzer.h"
#include "nsGeoPosition.h"
#ifdef MOZ_APPROX_LOCATION
/* The following constants are taken from the World Geodetic System 1984 (WGS84)
* reference model for the earth ellipsoid [1]. The values in the model are
* an accepted standard for GPS and other navigational systems.
*
* [1] http://www.oosa.unvienna.org/pdf/icg/2012/template/WGS_84.pdf
*/
#define WGS84_a (6378137.0) // equitorial axis
#define WGS84_b (6356752.314245179) // polar axis (a * (1-f))
#define WGS84_f (1.0/298.257223563) // inverse flattening
#define WGS84_EPSILON (5.72957795e-9) // 1e-10 radians in degrees
#define sq(f) ((f) * (f))
#define sign(f) (((f) < 0) ? -1 : 1)
/* if you have an ellipsoid with semi-major axis A and semi-minor axis B, the
* radius at angle phi along the semi-major axis can be calculated with this
* formula. by using the WGS84 values for A and B, we calculate the radius of
* earth, given the angle of latitude, phi.*/
#define LON_RADIUS(phi) (sqrt((sq(sq(WGS84_a) * cos(phi)) + sq(sq(WGS84_b) * sin(phi))) / \
(sq(WGS84_a * cos(phi)) + sq(WGS84_b * sin(phi)))))
/* the radius of earth changes as a function of latitude, to simplify I am
* assuming the fixed radius of the earth halfway between the poles and the
* equator. this is calculated from LON_RADIUS(M_PI/4), or the radius at
* 45 degrees N.*/
#define LAT_RADIUS (6367489.543863)
/* This function figures out the latitudinal grid square that the given
* latitude coordinate falls into and then returns the latitudinal center of
* that grid square. It handles the proper wrapping at the poles +/- 90
* (e.g. +95 wraps to +85 and -95 wraps to -85) */
static double GridAlgorithmLat(int32_t aDistMeters, double aLatDeg)
{
/* switch to radians */
double phi = (aLatDeg * M_PI) / 180;
/* properly wrap the latitude */
phi = atan(sin(phi) / fabs(cos(phi)));
/* calculate grid size in radians */
double gridSizeRad = aDistMeters / LAT_RADIUS;
/* find the southern edge, in radians, of the grid cell, then add half of a
* grid cell to find the center latitude in radians */
double gridCenterPhi = gridSizeRad * floor(phi / gridSizeRad) + gridSizeRad / 2;
/* properly wrap it and return it in degrees */
return atan(sin(gridCenterPhi) / fabs(cos(gridCenterPhi))) * (180.0 / M_PI);
}
/* This function figures out the longitudinal grid square that the given longitude
* coordinate falls into and then returns the longitudinal center of that grid
* square. It handles the proper wrapping at +/- 180 (e.g. +185 wraps to -175
* and -185 wraps to +175) */
static double GridAlgorithmLon(int32_t aDistMeters, double aLatDeg, double aLonDeg)
{
/* switch to radians */
double phi = (aLatDeg * M_PI) / 180;
double theta = (aLonDeg * M_PI) / 180;
/* properly wrap the lat/lon */
phi = atan(sin(phi) / fabs(cos(phi)));
theta = atan2(sin(theta), cos(theta));
/* calculate grid size in radians */
double gridSizeRad = aDistMeters / LON_RADIUS(phi);
/* find the western edge, in radians, of the grid cell, then add half of a
* grid cell to find the center longitude in radians */
double gridCenterTheta = gridSizeRad * floor(theta / gridSizeRad) + gridSizeRad / 2;
/* properly wrap it and return it in degrees */
return atan2(sin(gridCenterTheta), cos(gridCenterTheta)) * (180.0 / M_PI);
}
/* This function takes the grid size and the graticule coordinates of a
* location and calculates which grid cell the coordinates fall within and
* then returns the coordinates of the geographical center of the grid square.
*/
static void CalculateGridCoords(int32_t aDistKm, double& aLatDeg, double& aLonDeg)
{
// a grid size of 0 is the same as precise
if (aDistKm == 0) {
return;
}
aLonDeg = GridAlgorithmLon(aDistKm * 1000, aLatDeg, aLonDeg);
aLatDeg = GridAlgorithmLat(aDistKm * 1000, aLatDeg);
}
already_AddRefed<nsIDOMGeoPosition>
nsGeoGridFuzzer::FuzzLocation(const GeolocationSetting & aSetting,
nsIDOMGeoPosition * aPosition)
{
if (!aPosition) {
return nullptr;
}
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
nsresult rv = aPosition->GetCoords(getter_AddRefs(coords));
NS_ENSURE_SUCCESS(rv, nullptr);
if (!coords) {
return nullptr;
}
double lat = 0.0, lon = 0.0;
coords->GetLatitude(&lat);
coords->GetLongitude(&lon);
// adjust lat/lon to be the center of the grid square
CalculateGridCoords(aSetting.GetApproxDistance(), lat, lon);
GPSLOG("approximate location with delta %d is %f, %f",
aSetting.GetApproxDistance(), lat, lon);
// reusing the timestamp
DOMTimeStamp ts;
rv = aPosition->GetTimestamp(&ts);
NS_ENSURE_SUCCESS(rv, nullptr);
// return a position at sea level, N heading, 0 speed, 0 error.
nsRefPtr<nsGeoPosition> pos = new nsGeoPosition(lat, lon, 0.0, 0.0,
0.0, 0.0, 0.0, ts);
return pos.forget();
}
#endif

View File

@ -1,25 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsGeoGridFuzzer_h
#define nsGeoGridFuzzer_h
#include "nsCOMPtr.h"
#include "nsIDOMGeoPosition.h"
#include "nsGeolocationSettings.h"
class nsGeoGridFuzzer MOZ_FINAL
{
public:
static already_AddRefed<nsIDOMGeoPosition>
FuzzLocation(const GeolocationSetting& aSetting, nsIDOMGeoPosition* aPosition);
private:
nsGeoGridFuzzer() {} // can't construct
nsGeoGridFuzzer(const nsGeoGridFuzzer&) {} // can't copy
};
#endif

View File

@ -10,8 +10,6 @@
#include "nsISettingsService.h"
#include "nsGeolocation.h"
#include "nsGeoGridFuzzer.h"
#include "nsGeolocationSettings.h"
#include "nsDOMClassInfoID.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
@ -28,9 +26,6 @@
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/SettingChangeNotificationBinding.h"
#include "nsJSUtils.h"
#include "prdtoa.h"
class nsIPrincipal;
#ifdef MOZ_ENABLE_QT5GEOPOSITION
@ -53,8 +48,8 @@ class nsIPrincipal;
// that a window can make.
#define MAX_GEO_REQUESTS_PER_WINDOW 1500
// the geolocation enabled setting
#define GEO_SETTINGS_ENABLED "geolocation.enabled"
// The settings key.
#define GEO_SETINGS_ENABLED "geolocation.enabled"
using mozilla::unused; // <snicker>
using namespace mozilla;
@ -81,7 +76,7 @@ class nsGeolocationRequest MOZ_FINAL
int32_t aWatchId = 0);
void Shutdown();
void SendLocation(nsIDOMGeoPosition* aLocation);
void SendLocation(nsIDOMGeoPosition* location);
bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->mEnableHighAccuracy;}
void SetTimeoutTimer();
void StopTimeoutTimer();
@ -93,8 +88,6 @@ class nsGeolocationRequest MOZ_FINAL
private:
virtual ~nsGeolocationRequest();
already_AddRefed<nsIDOMGeoPosition> AdjustedLocation(nsIDOMGeoPosition*);
bool mIsWatchPositionRequest;
nsCOMPtr<nsITimer> mTimeoutTimer;
@ -137,42 +130,22 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
if (aName.EqualsASCII(GEO_SETTINGS_ENABLED)) {
// The geolocation is enabled by default:
bool value = true;
if (aResult.isBoolean()) {
value = aResult.toBoolean();
}
GPSLOG("%s set to %s",
NS_ConvertUTF16toUTF8(aName).get(),
(value ? "ENABLED" : "DISABLED"));
MozSettingValue(value);
} else {
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
if (gs) {
gs->HandleGeolocationSettingsChange(aName, aResult);
}
// The geolocation is enabled by default:
bool value = true;
if (aResult.isBoolean()) {
value = aResult.toBoolean();
}
MozSettingValue(value);
return NS_OK;
}
NS_IMETHOD HandleError(const nsAString& aName)
{
if (aName.EqualsASCII(GEO_SETTINGS_ENABLED)) {
GPSLOG("Unable to get value for '" GEO_SETTINGS_ENABLED "'");
// Default it's enabled:
MozSettingValue(true);
} else {
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
if (gs) {
gs->HandleGeolocationSettingsError(aName);
}
}
NS_WARNING("Unable to get value for '" GEO_SETINGS_ENABLED "'");
// Default it's enabled:
MozSettingValue(true);
return NS_OK;
}
@ -515,65 +488,6 @@ nsGeolocationRequest::StopTimeoutTimer()
}
}
static already_AddRefed<nsIDOMGeoPosition>
SynthesizeLocation(DOMTimeStamp aTimestamp, double aLatitude, double aLongitude)
{
// return a position at sea level, N heading, 0 speed, 0 error.
nsRefPtr<nsGeoPosition> pos = new nsGeoPosition(aLatitude, aLongitude,
0.0, 0.0, 0.0, 0.0, 0.0,
aTimestamp);
return pos.forget();
}
already_AddRefed<nsIDOMGeoPosition>
nsGeolocationRequest::AdjustedLocation(nsIDOMGeoPosition *aPosition)
{
nsCOMPtr<nsIDOMGeoPosition> pos = aPosition;
if (XRE_GetProcessType() == GeckoProcessType_Content) {
GPSLOG("child process just copying position");
return pos.forget();
}
// get the settings cache
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
if (!gs) {
return pos.forget();
}
// make sure ALA is enabled
if (!gs->IsAlaEnabled()) {
GPSLOG("ALA is disabled, returning precise location");
return pos.forget();
}
// look up the geolocation settings via the watch ID
DOMTimeStamp ts(PR_Now() / PR_USEC_PER_MSEC);
GeolocationSetting setting = gs->LookupGeolocationSetting(mWatchId);
switch (setting.GetType()) {
case GEO_ALA_TYPE_PRECISE:
GPSLOG("returning precise location watch ID: %d", mWatchId);
return pos.forget();
#ifdef MOZ_APPROX_LOCATION
case GEO_ALA_TYPE_APPROX:
GPSLOG("returning approximate location for watch ID: %d", mWatchId);
return nsGeoGridFuzzer::FuzzLocation(setting, aPosition);
#endif
case GEO_ALA_TYPE_FIXED:
GPSLOG("returning fixed location for watch ID:: %d", mWatchId);
// use "now" as time stamp
return SynthesizeLocation(ts, setting.GetFixedLatitude(),
setting.GetFixedLongitude());
case GEO_ALA_TYPE_NONE:
GPSLOG("returning no location for watch ID: %d", mWatchId);
// return nullptr so no location callback happens
return nullptr;
}
return nullptr;
}
void
nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
{
@ -599,12 +513,6 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
aPosition->GetCoords(getter_AddRefs(coords));
if (coords) {
#ifdef MOZ_GPS_DEBUG
double lat = 0.0, lon = 0.0;
coords->GetLatitude(&lat);
coords->GetLongitude(&lon);
GPSLOG("returning coordinates: %f, %f", lat, lon);
#endif
wrapped = new Position(ToSupports(mLocator), aPosition);
}
}
@ -651,8 +559,7 @@ nsGeolocationRequest::GetPrincipal()
NS_IMETHODIMP
nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition)
{
nsCOMPtr<nsIDOMGeoPosition> pos = AdjustedLocation(aPosition);
nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(pos, this);
nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(aPosition, this);
NS_DispatchToMainThread(ev);
return NS_OK;
}
@ -739,31 +646,8 @@ nsresult nsGeolocationService::Init()
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<GeolocationSettingsCallback> callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_SETTINGS_ENABLED, callback);
rv = settingsLock->Get(GEO_SETINGS_ENABLED, callback);
NS_ENSURE_SUCCESS(rv, rv);
// look up the geolocation settings
callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_ALA_ENABLED, callback);
NS_ENSURE_SUCCESS(rv, rv);
callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_ALA_TYPE, callback);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef MOZ_APPROX_LOCATION
callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_ALA_APPROX_DISTANCE, callback);
NS_ENSURE_SUCCESS(rv, rv);
#endif
callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_ALA_FIXED_COORDS, callback);
NS_ENSURE_SUCCESS(rv, rv);
callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_ALA_APP_SETTINGS, callback);
NS_ENSURE_SUCCESS(rv, rv);
callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_ALA_ALWAYS_PRECISE, callback);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// If we cannot obtain the settings service, we continue
// assuming that the geolocation is enabled:
@ -840,17 +724,13 @@ nsGeolocationService::HandleMozsettingChanged(nsISupports* aSubject)
if (!WrappedJSToDictionary(cx, aSubject, setting)) {
return;
}
if (!setting.mKey.EqualsASCII(GEO_SETTINGS_ENABLED)) {
if (!setting.mKey.EqualsASCII(GEO_SETINGS_ENABLED)) {
return;
}
if (!setting.mValue.isBoolean()) {
return;
}
GPSLOG("mozsetting changed: %s == %s",
NS_ConvertUTF16toUTF8(setting.mKey).get(),
(setting.mValue.toBoolean() ? "TRUE" : "FALSE"));
HandleMozsettingValue(setting.mValue.toBoolean());
}
@ -1445,7 +1325,6 @@ Geolocation::WatchPosition(GeoPositionCallback& aCallback,
*aRv);
if (!sGeoEnabled) {
GPSLOG("request allow event");
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
NS_DispatchToMainThread(ev);
return NS_OK;
@ -1568,7 +1447,8 @@ Geolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
{
if (Preferences::GetBool("geo.prompt.testing", false)) {
bool allow = Preferences::GetBool("geo.prompt.testing.allow", false);
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(allow, request);
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(allow,
request);
NS_DispatchToMainThread(ev);
return true;
}

View File

@ -1,460 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsXULAppAPI.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/Telemetry.h"
#include "nsISettingsService.h"
#include "nsGeolocation.h"
#include "nsGeolocationSettings.h"
#include "nsDOMClassInfoID.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsContentUtils.h"
#include "nsContentPermissionHelper.h"
#include "nsIDocument.h"
#include "nsIObserverService.h"
#include "nsPIDOMWindow.h"
#include "nsThreadUtils.h"
#include "mozilla/Services.h"
#include "mozilla/unused.h"
#include "mozilla/Preferences.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/SettingChangeNotificationBinding.h"
#include "nsJSUtils.h"
#include "prdtoa.h"
#define GEO_ALA_TYPE_VALUE_PRECISE "precise"
#define GEO_ALA_TYPE_VALUE_APPROX "blur"
#define GEO_ALA_TYPE_VALUE_FIXED "user-defined"
#define GEO_ALA_TYPE_VALUE_NONE "no-location"
using mozilla::unused;
using namespace mozilla;
NS_IMPL_ISUPPORTS(nsGeolocationSettings, nsIObserver)
StaticRefPtr<nsGeolocationSettings> nsGeolocationSettings::sSettings;
already_AddRefed<nsGeolocationSettings>
nsGeolocationSettings::GetGeolocationSettings()
{
// this singleton is only needed in the parent process...
if (XRE_GetProcessType() == GeckoProcessType_Content) {
return nullptr;
}
nsRefPtr<nsGeolocationSettings> result;
if (nsGeolocationSettings::sSettings) {
result = nsGeolocationSettings::sSettings;
return result.forget();
}
result = new nsGeolocationSettings();
if (NS_FAILED(result->Init())) {
return nullptr;
}
ClearOnShutdown(&nsGeolocationSettings::sSettings);
nsGeolocationSettings::sSettings = result;
return result.forget();
}
nsresult nsGeolocationSettings::Init()
{
// query for the current settings...
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return NS_ERROR_FAILURE;
}
// hook up observers
obs->AddObserver(this, "quit-application", false);
obs->AddObserver(this, "mozsettings-changed", false);
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationSettings::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
// remove observers
if (!strcmp("quit-application", aTopic)) {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "quit-application");
obs->RemoveObserver(this, "mozsettings-changed");
}
return NS_OK;
}
if (!strcmp("mozsettings-changed", aTopic)) {
HandleMozsettingsChanged(aSubject);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
GeolocationSetting
nsGeolocationSettings::LookupGeolocationSetting(int32_t aWatchID)
{
nsCString *origin;
if (!mCurrentWatches.Get(aWatchID, &origin) || !origin) {
return mGlobalSetting;
}
// if there is no per-app setting for the given origin, this will
// set gb == nullptr
GeolocationSetting const * const gb =
mPerOriginSettings.Get(NS_ConvertUTF8toUTF16(*origin));
// return a copy of the per-app or global settings
return gb ? *gb : mGlobalSetting;
}
void
nsGeolocationSettings::HandleGeolocationSettingsChange(const nsAString& aKey,
const JS::Value& aVal)
{
if (aKey.EqualsASCII(GEO_ALA_ENABLED)) {
HandleGeolocationAlaEnabledChange(aVal);
} else if (aKey.EqualsASCII(GEO_ALA_TYPE)) {
mGlobalSetting.HandleTypeChange(aVal);
#ifdef MOZ_APPROX_LOCATION
} else if (aKey.EqualsASCII(GEO_ALA_APPROX_DISTANCE)) {
mGlobalSetting.HandleApproxDistanceChange(aVal);
#endif
} else if (aKey.EqualsASCII(GEO_ALA_FIXED_COORDS)) {
mGlobalSetting.HandleFixedCoordsChange(aVal);
} else if (aKey.EqualsASCII(GEO_ALA_APP_SETTINGS)) {
HandleGeolocationPerOriginSettingsChange(aVal);
} else if (aKey.EqualsASCII(GEO_ALA_ALWAYS_PRECISE)) {
HandleGeolocationAlwaysPreciseChange(aVal);
}
}
void
nsGeolocationSettings::HandleMozsettingsChanged(nsISupports* aSubject)
{
MOZ_ASSERT(NS_IsMainThread());
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
RootedDictionary<SettingChangeNotification> setting(cx);
if (!WrappedJSToDictionary(cx, aSubject, setting)) {
return;
}
GPSLOG("mozsettings changed: %s", NS_ConvertUTF16toUTF8(setting.mKey).get());
// and handle the geolocation settings change...
HandleGeolocationSettingsChange(setting.mKey, setting.mValue);
}
void
nsGeolocationSettings::HandleGeolocationSettingsError(const nsAString& aName)
{
if (aName.EqualsASCII(GEO_ALA_ENABLED)) {
GPSLOG("Unable to get value for '" GEO_ALA_ENABLED "'");
} else if (aName.EqualsASCII(GEO_ALA_TYPE)) {
GPSLOG("Unable to get value for '" GEO_ALA_TYPE "'");
#ifdef MOZ_APPROX_LOCATION
} else if (aName.EqualsASCII(GEO_ALA_APPROX_DISTANCE)) {
GPSLOG("Unable to get value for '" GEO_ALA_APPROX_DISTANCE "'");
#endif
} else if (aName.EqualsASCII(GEO_ALA_FIXED_COORDS)) {
GPSLOG("Unable to get value for '" GEO_ALA_FIXED_COORDS "'");
} else if (aName.EqualsASCII(GEO_ALA_APP_SETTINGS)) {
GPSLOG("Unable to get value for '" GEO_ALA_APP_SETTINGS "'");
} else if (aName.EqualsASCII(GEO_ALA_ALWAYS_PRECISE)) {
GPSLOG("Unable to get value for '" GEO_ALA_ALWAYS_PRECISE "'");
}
}
void
nsGeolocationSettings::PutWatchOrigin(int32_t aWatchID,
const nsCString& aOrigin)
{
if (aWatchID < 0) {
return;
}
GPSLOG("mapping watch ID %d to origin %s", aWatchID, aOrigin.get());
mCurrentWatches.Put(static_cast<uint32_t>(aWatchID), new nsCString(aOrigin));
}
void
nsGeolocationSettings::RemoveWatchOrigin(int32_t aWatchID)
{
GPSLOG("unmapping watch ID %d", aWatchID);
mCurrentWatches.Remove(static_cast<uint32_t>(aWatchID));
}
void
nsGeolocationSettings::GetWatchOrigin(int32_t aWatchID, nsCString& aOrigin)
{
nsCString *str;
if (!mCurrentWatches.Get(aWatchID, &str) || !str) {
return;
}
aOrigin = *str;
GPSLOG("returning origin %s for watch ID %d", aOrigin.get(), aWatchID);
}
void
nsGeolocationSettings::HandleGeolocationAlaEnabledChange(const JS::Value& aVal)
{
if (!aVal.isBoolean()) {
return;
}
mAlaEnabled = aVal.toBoolean();
}
void
nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value& aVal)
{
if (!aVal.isObject()) {
return;
}
// clear the hash table
mPerOriginSettings.Clear();
// enumerate the array
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> obj(cx, &aVal.toObject());
JS::AutoIdArray ids(cx, JS_Enumerate(cx, obj));
// if we get no ids then the exception list is empty and we can return here.
if (!ids)
return;
// go through all of the objects in the exceptions dictionary
for (size_t i = 0; i < ids.length(); i++) {
JS::RootedId id(cx);
id = ids[i];
JS::RootedValue v(cx);
if (!JS_IdToValue(cx, id, &v) || !v.isString())
continue;
JS::RootedString str(cx, v.toString());
if (!str)
continue;
// get the origin for the app
nsString origin;
if (!AssignJSString(cx, origin, str))
continue;
// if it is an app that is always precise, skip it
if (mAlwaysPreciseApps.Contains(origin))
continue;
// get the app setting object
JS::RootedValue propertyValue(cx);
if (!JS_GetPropertyById(cx, obj, id, &propertyValue) || !propertyValue.isObject())
continue;
JS::RootedObject settingObj(cx, &propertyValue.toObject());
GeolocationSetting *settings = new GeolocationSetting(origin);
GPSLOG("adding exception for %s", NS_ConvertUTF16toUTF8(origin).get());
// get the geolocation type
JS::RootedValue fm(cx);
if (JS_GetProperty(cx, settingObj, "type", &fm)) {
settings->HandleTypeChange(fm);
}
#ifdef MOZ_APPROX_LOCATION
// get the approximate distance if there is one
JS::RootedValue distance(cx);
if (JS_GetProperty(cx, settingObj, "distance", &distance)) {
settings->HandleApproxDistanceChange(distance);
}
#endif
// get and parse the coords, if any
JS::RootedValue coords(cx);
if (JS_GetProperty(cx, settingObj, "coords", &coords)) {
settings->HandleFixedCoordsChange(coords);
}
// add the per-app setting object to the hashtable
mPerOriginSettings.Put(origin, settings);
}
}
void
nsGeolocationSettings::HandleGeolocationAlwaysPreciseChange(const JS::Value& aVal)
{
if (!aVal.isObject()) {
return;
}
// clear the list of apps that are always precise
mAlwaysPreciseApps.Clear();
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> obj(cx, &aVal.toObject());
if (!JS_IsArrayObject(cx, obj)) {
return;
}
uint32_t length;
if (!JS_GetArrayLength(cx, obj, &length)) {
return;
}
// process the list of apps...
for (uint32_t i = 0; i < length; ++i) {
JS::RootedValue value(cx);
if (!JS_GetElement(cx, obj, i, &value) || !value.isString()) {
continue;
}
nsString origin;
if (!AssignJSString(cx, origin, value.toString())) {
continue;
}
GPSLOG("adding always precise for %s", NS_ConvertUTF16toUTF8(origin).get());
// add the origin to the list of apps that will always receive
// precise location information
mAlwaysPreciseApps.AppendElement(origin);
}
}
void
GeolocationSetting::HandleTypeChange(const JS::Value& aVal)
{
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
nsString str;
if (!aVal.isString() || !AssignJSString(cx, str, aVal.toString())) {
return;
}
GeolocationFuzzMethod fm = GEO_ALA_TYPE_DEFAULT;
if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_PRECISE)) {
fm = GEO_ALA_TYPE_PRECISE;
} else if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_APPROX)) {
#ifdef MOZ_APPROX_LOCATION
fm = GEO_ALA_TYPE_APPROX;
#else
// we are loading a profile from a build with MOZ_APPROX_LOCATION
// enabled, then we need to force the type to a sane value
fm = GEO_ALA_TYPE_NONE;
#endif
} else if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_FIXED)) {
fm = GEO_ALA_TYPE_FIXED;
} else if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_NONE)) {
fm = GEO_ALA_TYPE_NONE;
}
if ((fm >= GEO_ALA_TYPE_FIRST) && (fm <= GEO_ALA_TYPE_LAST)) {
GPSLOG("changing type for %s to %s (%d)",
(mOrigin.IsEmpty() ? "global" : NS_ConvertUTF16toUTF8(mOrigin).get()),
NS_ConvertUTF16toUTF8(str).get(),
static_cast<int>(fm));
mFuzzMethod = fm;
}
// based on the new type, we need to clean up the other settings
switch (mFuzzMethod) {
case GEO_ALA_TYPE_PRECISE:
case GEO_ALA_TYPE_NONE:
#ifdef MOZ_APPROX_LOCATION
mDistance = 0;
#endif
mLatitude = 0.0;
mLongitude = 0.0;
break;
#ifdef MOZ_APPROX_LOCATION
case GEO_ALA_TYPE_APPROX:
mLatitude = 0.0;
mLongitude = 0.0;
break;
#endif
case GEO_ALA_TYPE_FIXED:
#ifdef MOZ_APPROX_LOCATION
mDistance = 0;
#endif
break;
}
}
#ifdef MOZ_APPROX_LOCATION
void
GeolocationSetting::HandleApproxDistanceChange(const JS::Value& aVal)
{
if (!aVal.isInt32()) {
return;
}
GPSLOG("changing approx distance for %s to %d",
(mOrigin.IsEmpty() ? "global" : NS_ConvertUTF16toUTF8(mOrigin).get()),
aVal.toInt32());
// set the approximate distance
mDistance = aVal.toInt32();
}
#endif
void
GeolocationSetting::HandleFixedCoordsChange(const JS::Value& aVal)
{
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
nsString str;
if (!aVal.isString() || !AssignJSString(cx, str, aVal.toString()) || str.IsEmpty()) {
return;
}
// parse the string and store the global lat/lon
// the @ character is present in the GPS coord strings we receive
int32_t const comma = str.Find(",");
if ( (str.CharAt(0) != '@') || (comma == -1) ) {
return;
}
nsresult rv;
nsString slat(Substring(str, 1, comma));
nsString slon(Substring(str, comma + 1));
double lat = slat.ToDouble(&rv);
NS_ENSURE_SUCCESS(rv,);
double lon = slon.ToDouble(&rv);
NS_ENSURE_SUCCESS(rv,);
mLatitude = lat;
mLongitude = lon;
GPSLOG("changing coords for %s to %s (%f, %f)",
(mOrigin.IsEmpty() ? "global" : NS_ConvertUTF16toUTF8(mOrigin).get()),
NS_ConvertUTF16toUTF8(str).get(),
mLatitude, mLongitude);
}

View File

@ -1,165 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsGeolocationSettings_h
#define nsGeolocationSettings_h
#include "mozilla/Attributes.h"
#include "mozilla/StaticPtr.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsClassHashtable.h"
#include "nsString.h"
#include "nsIObserver.h"
#include "nsJSUtils.h"
#include "nsTArray.h"
#if (defined(MOZ_GPS_DEBUG) && defined(ANDROID))
#include <android/log.h>
#define GPSLOG(fmt, ...) __android_log_print(ANDROID_LOG_WARN, "GPS", "%12s:%-5d " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define GPSLOG(...) {;}
#endif // MOZ_GPS_DEBUG && ANDROID
// The settings key.
#define GEO_ENABLED "geolocation.enabled"
#define GEO_ALA_ENABLED "ala.settings.enabled"
#define GEO_ALA_TYPE "geolocation.type"
#define GEO_ALA_FIXED_COORDS "geolocation.fixed_coords"
#define GEO_ALA_APP_SETTINGS "geolocation.app_settings"
#define GEO_ALA_ALWAYS_PRECISE "geolocation.always_precise"
#ifdef MOZ_APPROX_LOCATION
#define GEO_ALA_APPROX_DISTANCE "geolocation.approx_distance"
#endif
enum GeolocationFuzzMethod {
GEO_ALA_TYPE_PRECISE, // default, GPS/AGPS location
GEO_ALA_TYPE_FIXED, // user supplied lat/long
GEO_ALA_TYPE_NONE, // no location given
#ifdef MOZ_APPROX_LOCATION
GEO_ALA_TYPE_APPROX // approximate, grid-based location
#endif
};
#define GEO_ALA_TYPE_DEFAULT (GEO_ALA_TYPE_PRECISE)
#define GEO_ALA_TYPE_FIRST (GEO_ALA_TYPE_PRECISE)
#ifdef MOZ_APPROX_LOCATION
#define GEO_ALA_TYPE_LAST (GEO_ALA_TYPE_APPROX)
#else
#define GEO_ALA_TYPE_LAST (GEO_ALA_TYPE_NONE)
#endif
/**
* Simple class for holding the geolocation settings values.
*/
class GeolocationSetting MOZ_FINAL {
public:
GeolocationSetting(const nsString& aOrigin) :
mFuzzMethod(GEO_ALA_TYPE_DEFAULT),
#ifdef MOZ_APPROX_LOCATION
mDistance(0),
#endif
mLatitude(0.0),
mLongitude(0.0),
mOrigin(aOrigin) {}
GeolocationSetting(const GeolocationSetting& rhs) :
mFuzzMethod(rhs.mFuzzMethod),
#ifdef MOZ_APPROX_LOCATION
mDistance(rhs.mDistance),
#endif
mLatitude(rhs.mLatitude),
mLongitude(rhs.mLongitude),
mOrigin(rhs.mOrigin) {}
~GeolocationSetting() {}
GeolocationSetting& operator=(const GeolocationSetting& rhs) {
mFuzzMethod = rhs.mFuzzMethod;
#ifdef MOZ_APPROX_LOCATION
mDistance = rhs.mDistance;
#endif
mLatitude = rhs.mLatitude;
mLongitude = rhs.mLongitude;
mOrigin = rhs.mOrigin;
return *this;
}
void HandleTypeChange(const JS::Value& aVal);
void HandleApproxDistanceChange(const JS::Value& aVal);
void HandleFixedCoordsChange(const JS::Value& aVal);
inline GeolocationFuzzMethod GetType() const { return mFuzzMethod; }
#ifdef MOZ_APPROX_LOCATION
inline int32_t GetApproxDistance() const { return mDistance; }
#endif
inline double GetFixedLatitude() const { return mLatitude; }
inline double GetFixedLongitude() const { return mLongitude; }
inline const nsString& GetOrigin() const { return mOrigin; }
private:
GeolocationSetting() {} // can't default construct
GeolocationFuzzMethod mFuzzMethod;
#ifdef MOZ_APPROX_LOCATION
int32_t mDistance;
#endif
double mLatitude,
mLongitude;
nsString mOrigin;
};
/**
* Singleton that holds the global and per-origin geolocation settings.
*/
class nsGeolocationSettings MOZ_FINAL : public nsIObserver
{
public:
static already_AddRefed<nsGeolocationSettings> GetGeolocationSettings();
static mozilla::StaticRefPtr<nsGeolocationSettings> sSettings;
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
nsGeolocationSettings() : mAlaEnabled(false), mGlobalSetting(NullString()) {}
nsresult Init();
void HandleGeolocationSettingsChange(const nsAString& aKey, const JS::Value& aVal);
void HandleGeolocationSettingsError(const nsAString& aName);
void PutWatchOrigin(int32_t aWatchID, const nsCString& aOrigin);
void RemoveWatchOrigin(int32_t aWatchID);
void GetWatchOrigin(int32_t aWatchID, nsCString& aOrigin);
inline bool IsAlaEnabled() const { return mAlaEnabled; }
// given a watch ID, retrieve the geolocation settings. the watch ID is
// mapped to the origin of the listener/request which is then used to
// retreive the geolocation settings for the origin.
// if the origin is in the always-precise list, the settings will always be
// 'precise'. if the origin has origin-specific settings, that will be returned
// otherwise the global geolocation settings will be returned.
// NOTE: this returns a copy of the settings to enforce read-only client access
GeolocationSetting LookupGeolocationSetting(int32_t aWatchID);
private:
~nsGeolocationSettings() {}
nsGeolocationSettings(const nsGeolocationSettings&) :
mGlobalSetting(NullString()) {} // can't copy obj
void HandleMozsettingsChanged(nsISupports* aSubject);
void HandleGeolocationAlaEnabledChange(const JS::Value& aVal);
void HandleGeolocationPerOriginSettingsChange(const JS::Value& aVal);
void HandleGeolocationAlwaysPreciseChange(const JS::Value& aVal);
private:
bool mAlaEnabled;
GeolocationSetting mGlobalSetting;
nsClassHashtable<nsStringHashKey, GeolocationSetting> mPerOriginSettings;
nsTArray<nsString> mAlwaysPreciseApps;
nsClassHashtable<nsUint32HashKey, nsCString> mCurrentWatches;
};
#endif /* nsGeolocationSettings_h */

View File

@ -84,7 +84,6 @@
#include "nsConsoleService.h"
#include "nsDebugImpl.h"
#include "nsFrameMessageManager.h"
#include "nsGeolocationSettings.h"
#include "nsHashPropertyBag.h"
#include "nsIAlertsService.h"
#include "nsIAppsService.h"
@ -3688,19 +3687,6 @@ ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
// creation of a new listener.
RecvRemoveGeolocationListener();
mGeolocationWatchID = AddGeolocationListener(this, aHighAccuracy);
// let the the settings cache know the origin of the new listener
nsAutoCString origin;
// hint to the compiler to use the conversion operator to nsIPrincipal*
nsCOMPtr<nsIPrincipal> principal = static_cast<nsIPrincipal*>(aPrincipal);
if (!principal) {
return true;
}
principal->GetOrigin(getter_Copies(origin));
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
if (gs) {
gs->PutWatchOrigin(mGeolocationWatchID, origin);
}
return true;
}
@ -3713,11 +3699,6 @@ ContentParent::RecvRemoveGeolocationListener()
return true;
}
geo->ClearWatch(mGeolocationWatchID);
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
if (gs) {
gs->RemoveWatchOrigin(mGeolocationWatchID);
}
mGeolocationWatchID = -1;
}
return true;
@ -3729,21 +3710,8 @@ ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
// This should never be called without a listener already present,
// so this check allows us to forgo securing privileges.
if (mGeolocationWatchID != -1) {
nsCString origin;
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
// get the origin stored for the curent watch ID
if (gs) {
gs->GetWatchOrigin(mGeolocationWatchID, origin);
}
// remove and recreate a new, high-accuracy listener
RecvRemoveGeolocationListener();
mGeolocationWatchID = AddGeolocationListener(this, aEnable);
// map the new watch ID to the origin
if (gs) {
gs->PutWatchOrigin(mGeolocationWatchID, origin);
}
}
return true;
}