function fail never called if user declines to share geolocation in firefox

Solution 1:

For Firefox it seems that PERMISSION_DENIED is raised only if "Never share" is selected; if the dialog is dismissed or "Not now" is selected, effectively nothing happens - even on mozillas geolocation demo if you dismiss the permissions UI nothing happens.

This means that getCurrentPosition can return either because the user closed the confirmation UI, or because it successfully started it asynchronous request - there doesn't appear to be a way to discriminate between the two.

https://bugzilla.mozilla.org/show_bug.cgi?id=675533

Solution 2:

This is a real pain, and definately not desirable functionality.

The workaround I am using to save the user waiting for ever is to set a timeout to check if the wait spinner is showing after 3 seconds, and if so, hide it and show a manual zip code input:

var latlng;

var waitTime = 3000;
try {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function (position) {
            success(position);
        }, showError);
    } else {
        showError("NOT-SUPPORTED");
    }
    var t = setTimeout(function () {
        if ($("#getZip div.loading").css("display") != "none") {
            $("#getZip div.loading").hide();
            $("#errorZip").show();
        }
    }, waitTime);
} catch (evt) {
    alert(evt);
}

Solution 3:

As alexleonard pointed out, the only reliable, cross-browser solution I've found for this is to have a setTimeout() to check the state of your latLng object/variables, as the timeout option of getCurrentPosition() doesn't seem to work reliably. The example below was tested in IE11, Chrome33 and Firefox28.

For a more complete solution that uses a jQuery promise, check out my Gist here: https://gist.github.com/GFoley83/10092929

Example - Hit F12, paste into the console and run

var latLng,
    geoOptions = {
        enableHighAccuracy: false,
        timeout: 5000, // Wait 5 seconds
        maximumAge: 300000 //  Valid for 5 minutes
    };

var userLocationFound = function(position){
    latLng = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
    };
    window.console.log("User confirmed! Location found: " + latLng.lat + ", " + latLng .lng);
}

var userLocationNotFound = function(){
    latLng = {
        lat: -41.29247, // fallback lat 
        lng: 174.7732  // fallback lng
    };
    window.console.log("Fallback set: ", latLng);
}

window.navigator.geolocation.getCurrentPosition(userLocationFound, userLocationNotFound, geoOptions);

setTimeout(function () {
    if(!latLng){
        window.console.log("No confirmation from user, using fallback");
        userLocationNotFound();
    }else{
        window.console.log("Location was set");
    }
}, geoOptions.timeout + 1000); // Wait extra second