Weather App
A weather app only needs city-level location. It declares what
accuracy it needs and handles the result. Under both models, this
works identically.
const status = await navigator.permissions.query({
name: "geolocation"
});
navigator.geolocation.getCurrentPosition(
showWeather, showManualEntry, {accuracyMode: "approximate"}
);
Upgrade Flow
A ride-sharing app starts with approximate location (show nearby
drivers), then requests precise when the user taps "Set pickup
location." In both models, the approximate call succeeds. The precise
call prompts when only "geolocation-approximate" was
granted, because the user is being asked for more. The difference:
under the two-permission model, the developer can predict this prompt
via query(). Under the single-permission model, they call
the API and handle the result.
navigator.geolocation.getCurrentPosition(
showNearbyDrivers, showManualAddress, {accuracyMode: "approximate"}
);
navigator.geolocation.getCurrentPosition(
setPrecisePickup, handleError, {accuracyMode: "precise"}
);
The enableHighAccuracy Precedent
Today, enableHighAccuracy is a
PositionOptions hint with no separate queryable
permission and no result attribute reporting what the UA did.
query({name: "geolocation"}) returning
"granted" has never guaranteed high-accuracy results. The
developer checks coords.accuracy after the call. This is
the existing precedent for how option hints interact with the
permission model.
const status = await navigator.permissions.query({
name: "geolocation"
});
navigator.geolocation.getCurrentPosition(success, error, {
enableHighAccuracy: true
});
Passive Queryability
Under the two-permission model, a script can determine whether the
user chose approximate-only by querying both permission names on page
load, without calling getCurrentPosition() and without a
user gesture. Under the single-permission model, only
"geolocation" is queryable, so this distinction is not
observable until the API is actually called. See
w3c/permissions#52
for background on passive queryability concerns.
const approx = await navigator.permissions.query({
name: "geolocation-approximate"
});
const precise = await navigator.permissions.query({
name: "geolocation"
});
if (approx.state === "granted" && precise.state === "prompt") {
trackUserPrivacyPreference("approximate-only");
}
The onchange Scenario
Under the two-permission model, a script can subscribe to permission
state changes via onchange. This has a legitimate use: a
site adapts its UI when the user changes settings. It also has a
privacy concern: a third-party script can subscribe, wait for the user
to grant access to the embedding page, then call the API at that
moment without an additional prompt appearing.
const status = await navigator.permissions.query({
name: "geolocation-approximate"
});
status.onchange = () => {
if (status.state === "granted") {
navigator.geolocation.getCurrentPosition(callback);
}
};
Full 12-scenario matrix
| State |
Action |
Two-Permission predicts? |
Single-Permission predicts? |