Photo by Steve Petrucelli

Geolocation on the Xbox

What to do when feature detection fails?

If your HTML5 app or site relies on Geolocation you’re probably familiar with the following code:

if (navigator.geolocation) {
// use geolocation
} else {
// use an alternative
}

The concept of feature detection is very simple. Before you use a certain feature you try to detect if the browser offers that feature. And if not, you can give the user an alternative. In case of Geolocation you could use other means to find the location, for example by using the IP address or simply asking the user.

So far so good, but what if the user does not give permission to use the location? We have another way of finding this out:

navigator.geolocation.getCurrentPosition(
function(position) {
// do something with the location
},
function(error) {
// an error, so use an alternative
}
);

If you ask for the location, we can specify a callback function which is called when an error occurs, or when the user does not give permission. And once again we can use an alternative.

Looks easy enough and fool proof, right?

Unfortunately it never is that easy. There is always some browser out there that fails in some unexpected way. In this case it’s Internet Explorer on the Xbox One.

What about the Xbox One?

This is what Microsoft says in the documentation about Geolocation on Internet Explorer for Xbox:

W3C Geolocation isn’t included in Internet Explorer for Xbox.
navigator.geolocation is undefined.

Geolocation is not supported, which is in itself unfortunate, because I’m sure Geolocation is just as useful on a console as it is on a desktop machine. And while there is no GPS chip in the Xbox, there is no reason why it couldn’t do positioning based on Wi-Fi signals or even based on IP address, just like it does on a desktop machine.

But it’s worse. The documentation is not correct. The expression navigator.geolocation is not ‘undefined’. In fact, it looks like there is a full Geolocation implementation, which also means that our feature detection code fails. So instead of showing the alternative, our script actually thinks we are safe to get the current location.

Still not a big problem. If we are going try to get the location, the error callback will surely be called. Right?

No.

Both of the callbacks remain unused. We simply do not get any response at all. And that is a problem, because if the error callback is not called, we can’t give the user the alternative way of positioning. Our app is simply stuck.

The testcase I used to find this bug can be found at lab.html5test.com/
geolocation/

On the Xbox 360 there is a similar problem, but luckily there we do get a call to the error callback.It’s still a bug, but at least there is a chance to give the user an alternative.

The solution

Until Microsoft fixes these bugs, there is not a proper solution. But there is a workaround that will at least prevent the app from getting stuck.

var locationFound = false;
var alternativeUsed = false;

if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
locationFound = true;
if (!alternativeUsed) {
// do something with the location
}
},
function(error) {
if (!alternativeUsed) {
alternativeUsed = true;
// an error, so use an alternative
}
}
);
} else {
alternativeUsed = true;
// use an alternative
}

window.setTimeout(function() {
if (!locationFound && !alternativeUsed) {
alternativeUsed = true;
// use alternative
}
}, 10000)

We simply set a timeout for 10 seconds and if the location isn’t known by then, we use the alternative.

Of course we must be very careful not to trigger the timeout when we get an error or when geolocation isn’t supported.We don’t want to use the alternative twice. Also we must make sure that if the positioning takes longer than the timeout — which could happen — we do not use the detected location once the alternative is already in use.

This bug has been filed at Microsoft Connect (#809818). Thanks to Anna Debenham for letting me do some remote testing on her Xbox One.