Bug 777594 - Use mozSettings to turn on/off Geolocation. r=jdm

This commit is contained in:
Doug Turner 2012-07-26 20:19:01 -07:00
parent c4f893f231
commit 7bc5a04e33
5 changed files with 235 additions and 7 deletions

View File

@ -518,6 +518,7 @@ nsresult nsGeolocationService::Init()
return NS_ERROR_FAILURE;
obs->AddObserver(this, "quit-application", false);
obs->AddObserver(this, "mozsettings-changed", false);
nsCOMPtr<nsISimpleEnumerator> geoproviders;
catMan->EnumerateCategory("geolocation-provider", getter_AddRefs(geoproviders));
@ -575,6 +576,61 @@ nsGeolocationService::~nsGeolocationService()
{
}
void
nsGeolocationService::HandleMozsettingChanged(const PRUnichar* aData)
{
// The string that we're interested in will be a JSON string that looks like:
// {"key":"gelocation.enabled","value":true}
nsCOMPtr<nsIThreadJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
if (!stack) {
return;
}
JSContext *cx = stack->GetSafeJSContext();
if (!cx) {
return;
}
nsDependentString dataStr(aData);
JS::Value val;
if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) || !val.isObject()) {
return;
}
JSObject &obj(val.toObject());
JS::Value key;
if (!JS_GetProperty(cx, &obj, "key", &key) || !key.isString()) {
return;
}
JSBool match;
if (!JS_StringEqualsAscii(cx, key.toString(), "geolocation.enabled", &match) || (match != JS_TRUE)) {
return;
}
JS::Value value;
if (!JS_GetProperty(cx, &obj, "value", &value) || !value.isBoolean()) {
return;
}
if (value.toBoolean() == false)
{
// turn things off
for (PRUint32 i = 0; i< mGeolocators.Length(); i++)
{
mGeolocators[i]->Shutdown();
}
StopDevice();
Update(nsnull);
mLastPosition = nsnull;
sGeoEnabled = false;
}
else {
sGeoEnabled = true;
}
}
NS_IMETHODIMP
nsGeolocationService::Observe(nsISupports* aSubject,
const char* aTopic,
@ -585,6 +641,7 @@ nsGeolocationService::Observe(nsISupports* aSubject,
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "quit-application");
obs->RemoveObserver(this, "mozsettings-changed");
}
for (PRUint32 i = 0; i< mGeolocators.Length(); i++)
@ -594,6 +651,12 @@ nsGeolocationService::Observe(nsISupports* aSubject,
return NS_OK;
}
if (!strcmp("mozsettings-changed", aTopic))
{
HandleMozsettingChanged(aData);
return NS_OK;
}
if (!strcmp("timer-callback", aTopic))
{
@ -909,9 +972,6 @@ nsGeolocation::GetCurrentPosition(nsIDOMGeoPositionCallback *callback,
{
NS_ENSURE_ARG_POINTER(callback);
if (!sGeoEnabled)
return NS_ERROR_NOT_AVAILABLE;
if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW)
return NS_ERROR_NOT_AVAILABLE;
@ -925,6 +985,12 @@ nsGeolocation::GetCurrentPosition(nsIDOMGeoPositionCallback *callback,
nsresult rv = request->Init(cx, options);
NS_ENSURE_SUCCESS(rv, rv);
if (!sGeoEnabled) {
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
NS_DispatchToMainThread(ev);
return NS_OK;
}
if (mOwner) {
if (!RegisterRequestWithPrompt(request))
return NS_ERROR_NOT_AVAILABLE;
@ -954,9 +1020,6 @@ nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *callback,
NS_ENSURE_ARG_POINTER(callback);
if (!sGeoEnabled)
return NS_ERROR_NOT_AVAILABLE;
if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW)
return NS_ERROR_NOT_AVAILABLE;
@ -970,7 +1033,18 @@ nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *callback,
nsresult rv = request->Init(cx, options);
NS_ENSURE_SUCCESS(rv, rv);
if (mOwner) {
if (!sGeoEnabled) {
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
// need to hand back an index/reference.
mWatchingCallbacks.AppendElement(request);
*_retval = mWatchingCallbacks.Length() - 1;
NS_DispatchToMainThread(ev);
return NS_OK;
}
if (mOwner) {
if (!RegisterRequestWithPrompt(request))
return NS_ERROR_NOT_AVAILABLE;

View File

@ -107,6 +107,8 @@ public:
nsresult Init();
void HandleMozsettingChanged(const PRUnichar* aData);
// Management of the nsGeolocation objects
void AddLocator(nsGeolocation* locator);
void RemoveLocator(nsGeolocation* locator);

View File

@ -25,6 +25,8 @@ MOCHITEST_FILES = \
test_optional_api_params.html \
test_shutdown.html \
test_windowClose.html \
test_mozsettings.html \
test_mozsettingsWatch.html \
test_timerRestartWatch.html \
test_worseAccuracyDoesNotBlockCallback.html \
geolocation.html \

View File

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=478911
-->
<head>
<title>Test for getCurrentPosition </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="geolocation_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=777594">Mozilla Bug 777594</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
function toggleGeolocationSetting(value, callback) {
var mozSettings = window.navigator.mozSettings;
var lock = mozSettings.getLock();
var geoenabled = {"geolocation.enabled": value};
req = lock.set(geoenabled);
req.onsuccess = function () {
ok(true, "set done");
callback();
}
}
SimpleTest.waitForExplicitFinish();
resume_geolocationProvider();
force_prompt(true);
var comp = SpecialPowers.wrap(Components);
SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
SpecialPowers.addPermission("websettings-read", true, document);
SpecialPowers.addPermission("websettings-readwrite", true, document);
comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
toggleGeolocationSetting(false, function() {
ok(true, "turned off geolocation via mozSettings");
setTimeout(function() {
navigator.geolocation.getCurrentPosition(successCallbackAfterMozsetting, failureCallbackAfterMozsetting);
}, 500); // need to wait a bit for all of these async callbacks to finish
});
function successCallbackAfterMozsetting(position) {
ok(false, "Success callback should not have been called after setting geolocation.enabled to false.");
toggleGeolocationSetting(true, function() {
reset_prompt();
SimpleTest.finish();
});
}
function failureCallbackAfterMozsetting(error) {
ok(true, "Geolocation didn't work after setting geolocation.enabled to false.");
toggleGeolocationSetting(true, function() {
reset_prompt();
SimpleTest.finish();
});
}
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=478911
-->
<head>
<title>Test for getCurrentPosition </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="geolocation_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=777594">Mozilla Bug 777594</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
function toggleGeolocationSetting(value, callback) {
var mozSettings = window.navigator.mozSettings;
var lock = mozSettings.getLock();
var geoenabled = {"geolocation.enabled": value};
req = lock.set(geoenabled);
req.onsuccess = function () {
ok(true, "set done");
callback();
}
}
SimpleTest.waitForExplicitFinish();
resume_geolocationProvider();
force_prompt(true);
var comp = SpecialPowers.wrap(Components);
SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
SpecialPowers.addPermission("websettings-read", true, document);
SpecialPowers.addPermission("websettings-readwrite", true, document);
comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
toggleGeolocationSetting(false, function() {
ok(true, "turned off geolocation via mozSettings");
setTimeout(function() {
navigator.geolocation.watchPosition(successCallbackAfterMozsetting, failureCallbackAfterMozsetting);
}, 500); // need to wait a bit for all of these async callbacks to finish
});
function successCallbackAfterMozsetting(position) {
ok(false, "Success callback should not have been called after setting geolocation.enabled to false.");
toggleGeolocationSetting(true, function() {
reset_prompt();
SimpleTest.finish();
});
}
function failureCallbackAfterMozsetting(error) {
ok(true, "Geolocation didn't work after setting geolocation.enabled to false.");
toggleGeolocationSetting(true, function() {
reset_prompt();
SimpleTest.finish();
});
}
</script>
</pre>
</body>
</html>