I ran into an issue where if my Mac denied location sharing, then nothing happens in JS code... this is dangerous, anyway to get around this? If system denies location sharing, I would expect an exception to be thrown
Running macOS Mojave 10.14.6
& tested in Chrome 87.0.4280.88
.
In System Preferences > Security & Privacy
, you can check Enable Location Services
and then check Apps that are allowed. If I EITHER uncheck Enable Location Services
entirely OR keep it checked but uncheck Google Chrome
, then the code quietly fails*, by which I mean nothing is logged to console in the sample code below.
Code:
$("#btn").click(function(e){
e.preventDefault();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
# success
function(location) {
console.log("GPS coordinates retrieved")
},
# failure
function(error) {
console.log(error.message)
}
)
} else {
console.log("GPS not supported by browser")
}
})
Is there a meta way to catch this (e.g., determine whether location has been enabled or not in system preferences from JS) so that something gets logged and I can move onto next steps in code?
*The code quietly fails, but technically the browser has ways of alerting you, but only the FIRST time. So basically, assuming your browser has not blocked the URL and you're on HTTPS (e.g., all the browser conditions are met), the FIRST time you click #btn
, you'll get the native pop up that navigator.geolocation.getCurrentPosition
triggers asking you for permission. Now, even if you click allow, because system preferences disallows it, it won't share, the code doesn't log anything. But at least this first time you get a visual of something happening. On subsequent clicks, truly nothing will happen either on browser or in code. Again I'm more concerned with code, just pointing out that I acknowledge browser shows you things.
I ran into an issue where if my Mac denied location sharing, then nothing happens in JS code... this is dangerous, anyway to get around this? If system denies location sharing, I would expect an exception to be thrown
Running macOS Mojave 10.14.6
& tested in Chrome 87.0.4280.88
.
In System Preferences > Security & Privacy
, you can check Enable Location Services
and then check Apps that are allowed. If I EITHER uncheck Enable Location Services
entirely OR keep it checked but uncheck Google Chrome
, then the code quietly fails*, by which I mean nothing is logged to console in the sample code below.
Code:
$("#btn").click(function(e){
e.preventDefault();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
# success
function(location) {
console.log("GPS coordinates retrieved")
},
# failure
function(error) {
console.log(error.message)
}
)
} else {
console.log("GPS not supported by browser")
}
})
Is there a meta way to catch this (e.g., determine whether location has been enabled or not in system preferences from JS) so that something gets logged and I can move onto next steps in code?
*The code quietly fails, but technically the browser has ways of alerting you, but only the FIRST time. So basically, assuming your browser has not blocked the URL and you're on HTTPS (e.g., all the browser conditions are met), the FIRST time you click #btn
, you'll get the native pop up that navigator.geolocation.getCurrentPosition
triggers asking you for permission. Now, even if you click allow, because system preferences disallows it, it won't share, the code doesn't log anything. But at least this first time you get a visual of something happening. On subsequent clicks, truly nothing will happen either on browser or in code. Again I'm more concerned with code, just pointing out that I acknowledge browser shows you things.
- I am exactly on the specified version of the OS and browser, and i ran your code, but its working fine. I am getting an error message on the right part of browser URL "Location Services is turned off in mac system preferences. – raj240 Commented Jan 13, 2021 at 8:05
- @raj240 but in the console, nothing is logged right? the code just fails – james Commented Jan 13, 2021 at 19:03
3 Answers
Reset to default 7 +50On some browsers you can check the permission status without prompting the user like so:
const permissionStatus = await navigator.permissions.query({ name: 'geolocation' })
Compatibility: http://caniuse./#feat=permissions-api
Although note that this only indicates the permissions at browser level. Even when this permission is granted, another layer like the OS can still deny it later in the chain.
Given that navigator.geolocation.getCurrentPosition()
always immediately returns with undefined
no matter what, the best you can do to handle these cases is having a timeout
forcing the error callback to be called after a given duration if no response is provided to the browser. Luckily you can do so easily by passing options
as a third argument to the function.
const options = { timeout: 5000 }
navigator.geolocation.getCurrentPosition(successCb, errorCb, options)
In your case:
$("#btn").click(function(e){
e.preventDefault()
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
// success
function(location) {
console.log("GPS coordinates retrieved")
},
// failure
function(error) {
console.log(error.message)
},
{
timeout: 5000 // ms
}
)
} else {
console.log("GPS not supported by browser")
}
})
Given that the W3C specification details that the browsers must call the callback function on success/error, it is unlikely to be silenced by the browser itself. It is more likely that the OS decides to never respond instead of refusing the access, leaving the function in a pending state indefinitely if no timeout is provided.
Try this:
// pseudo
set location to unknown (yet)
set waiting time
try retrieve location
set location when receive, call as resolved (success)
set error when failure, call resolved (failure)
cancel waiting when receive (location / a sure failure)
resolveLocation after timeout, success or failure
$("#btn").click(function(e){
e.preventDefault()
function resolveLocation(){
if(location){
console.log("Location detected",location)
}else{
console.log("Cannot detect location")
}
}
var location = null;
var wait = setTimeout(resolveLocation, 3000)
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(
// success
function(_location){
clearTimeout(wait)
console.log("GPS coordinates retrieved")
location = _location;
resolveLocation()
},
// error
function(error){
clearTimeout(wait)
console.log("GPS error")
resolveLocation()
}
)
}else{
clearTimeout(wait)
console.log("GPS not supported by browser")
resolveLocation()
}
})
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">Check</button>
According to MDN there's error code for each geolocation API error, you can read details here.
So applying the error code respectively on your code should like this.
$("#btn").click(function(e) {
e.preventDefault();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(#success
function(location) {
console.log("GPS coordinates retrieved")
}, #failure
function(error) {
//when location request is rejected is error code = 1
console.log(error.code)
//when POSITION is UNAVAILABLE is error code = 2
console.log(error.code)
//when there is a timeout error code = 3
console.log(error.code)
}
)
} else {
console.log("GPS not supported by browser")
}
})