Conversation
|
For readability as you iterate on this proposal it's okay for this PR to directly change the specification text however to land this change the changes need to be enclosed in the correct candidate additions/corrections/deletions syntax. |
|
@reillyeon if it's ok, let's move this to CR first (i.e., let's not waste time with the ins/dels). We are close to publishing as CR again. |
99d9b03 to
3fa8869
Compare
There was a problem hiding this comment.
Pull Request Overview
This PR adds support for approximate location positioning to the Geolocation API specification. It introduces a privacy-preserving alternative to precise location sharing, allowing applications to request coarse-grained location data when high accuracy is not needed.
Key changes:
- Introduces
accuracyModeoption with "precise" (default) and "approximate" values - Adds new "geolocation-approximate" permission alongside existing "geolocation" permission
- Implements separate caching for precise and approximate positions
- Updates permission request flows to allow users to choose between precise and approximate location sharing
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
3fa8869 to
8658f5a
Compare
2354ca8 to
d3a4d47
Compare
antosart
left a comment
There was a problem hiding this comment.
A few comments wrt the permission handling.
d3a4d47 to
b0d0589
Compare
|
Hi @reillyeon, |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (1)
index.html:951
- This uses
[=list/remove=](lowercaselist), but elsewhere the spec uses[=List/remove=]for the Infra list operation. The lowercase form likely won’t resolve to the intended definition; please align the casing with the rest of the document.
If |resolvedPermissionState| is "denied", then:
<ol>
<li>If |watchId| was passed, [=list/remove=] |watchId| from
|watchIDs|.
</li>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
marcoscaceres
left a comment
There was a problem hiding this comment.
Looking good @alvinjiooo ... there seems to be some unrelated editorial changes.
Maybe see about splitting those out (get Genini maybe to do them quickly?). Will make this easier to review.
| [=approximate positions=]. To mitigate this risk of a refinement | ||
| attack, when a site receives an [=approximate position=], any | ||
| subsequent calls from that same site within a user-agent-defined time | ||
| window SHOULD return the exact same, cached [=approximate position=] |
There was a problem hiding this comment.
This needs to be in the algorithm (if it's not already).
There was a problem hiding this comment.
I did consider formalizing this caching logic within the algorithm. However, opinions on the practical risk of precise location reconstruction still vary, and there isn't a single standardized approach yet. Coupled with the existing visibility requirements, a caching window (like 15 minutes) already makes reconstruction extremely difficult in practice. Keeping this in the Privacy Considerations section provides strong guidance while leaving implementers flexibility as mitigation strategies evolve. I’m inclined to leave it as a 'SHOULD' recommendation rather than a hard algorithmic requirement for now, but I'd be interested to hear your thoughts on this framing.
| <dl class="switch"> | ||
| <dt id="permission-denied"> | ||
| User or system denied permission: | ||
| <li data-cite="infra">If acquiring the position data from the |
There was a problem hiding this comment.
This change seems unrelated or maybe the white space got screwed up?
There was a problem hiding this comment.
This one is not changed by the PR, the original place is at here. It got moved further down because the introduced change for approximate geolocation.
| </ol> | ||
| </li> | ||
| </ol> | ||
| <dl class="switch"> |
There was a problem hiding this comment.
Does this belong in this PR? Can it be a separate PR?
There was a problem hiding this comment.
This part is not changed too, the original place is at here.
- Rephrase privacy risk mitigation and user choice framing for clarity and neutrality. - Update terminology from 'powerful features' to 'permissions' and 'protecting' to 'obscuring'. - Add cross-references to the 'acquire a position' algorithm and AccuracyMode enum values. - Fix ReSpec linking errors and IDL formatting. - Remove redundant MUST statements from informative notes. - Tidy index.html.
|
Really nice work getting this to a reviewable state, @alvinjiooo. I want to raise a privacy concern about two pieces: The design lets sites request approximate via
Permissions Policy gating: I think Summary:
I'd like to invite @martinthomson, @saschanaz, and @npdoty to weigh in on the privacy model here. Once we converge on the right shape, I think this warrants a formal PING review given the sensitivity of location privacy. |
marcoscaceres
left a comment
There was a problem hiding this comment.
See #195 (comment) ... as I think the permission model needs a significant overhaul... and could be simultaneously significantly simplified.
| </pre> | ||
| </aside> | ||
| <p> | ||
| Similarly, you can request a cached approximate position. |
There was a problem hiding this comment.
| Similarly, you can request a cached approximate position. | |
| Similarly, you can request a cached approximate position: |
| successCallback, | ||
| console.error, | ||
| { maximumAge: 600_000 } | ||
| { maximumAge: 600_000 } // `accuracyMode` defaults to "precise" |
There was a problem hiding this comment.
| { maximumAge: 600_000 } // `accuracyMode` defaults to "precise" | |
| { | |
| maximumAge: 600_000, | |
| // `accuracyMode` defaults to "precise" | |
| } |
| new position. | ||
| </p> | ||
| <aside class="example" title="Getting cached position"> | ||
| <aside class="example" title="Getting a cached precise position"> |
There was a problem hiding this comment.
Just a nit... but it feels like we could cover both cases with just one example.
| The {{PositionOptions/accuracyMode}} option enhances user privacy by | ||
| providing websites with the choice to request an [=approximate | ||
| position=]. This allows applications to function without needing the | ||
| user's [=precise position=], thus offering a more privacy-friendly |
There was a problem hiding this comment.
| user's [=precise position=], thus offering a more privacy-friendly | |
| user's [=precise position=], thus offering a more privacy-preserving |
| the user agent can provide a less precise location that still meets the | ||
| application's needs while obscuring the user's [=precise position=]. |
There was a problem hiding this comment.
The user agent can't know if the position will meet the sites needs. It can only return an approximate position. If it's good enough, that's up to the site to determine.
| the user agent can provide a less precise location that still meets the | |
| application's needs while obscuring the user's [=precise position=]. | |
| a supporting user agent MUST provide a less precise location, | |
| obscuring the user's [=precise position=]. |
| (for approximate location). | ||
| </p> | ||
| <p> | ||
| There is a strict dependency between the [=permission state=]s of |
There was a problem hiding this comment.
| There is a strict dependency between the [=permission state=]s of | |
| There is a strict dependency between the [=permission states=] of |
| implies denying a [=precise position=]. This results in the following | ||
| allowed combinations of states: | ||
| </p> | ||
| <ul> |
There was a problem hiding this comment.
Nit: I wonder if this should be a table?
| <p> | ||
| Implementers MUST ensure that these states remain coherent. For | ||
| example, if a user changes the [=permission state=] of | ||
| <a>"geolocation-approximate"</a> to [=permission/"denied"=] via site |
There was a problem hiding this comment.
Right, but this needs to be an algorithm. We can wire up the Permission side later, but this still needs to be algorithmically defined.
Basically, the algorithm receives the new state, and then it dos all the things defined here.
| <p> | ||
| Implementers MUST ensure that these states remain coherent. For | ||
| example, if a user changes the [=permission state=] of | ||
| <a>"geolocation-approximate"</a> to [=permission/"denied"=] via site |
There was a problem hiding this comment.
Also, this can be very racy, so some kind of coordinator will still be needed where this is queued.
| while <a>"geolocation"</a> is a [=powerful feature=] with: | ||
| </p> | ||
| <ul> | ||
| <li>A custom [=powerful feature/permission result type=] |
There was a problem hiding this comment.
Do we really need to leak the user's choice? This seems like it shouldn't be needed. The site should just get back a portion, but it shouldn't know what the user selected or when it's changed, right?
|
Wrt leaking the granted accuracy (either in As for the |
|
I get that Android's current The spec should push implementations toward privacy (guidance on resisting detectability), not codify worst-case current behavior as the API surface. On the "sites need to know" argument: I think there are two legitimate needs here, and neither requires
So the model would be: CSS media feature for capability → On Permissions Policy: agreed it's non-trivial. I've looked at issues explainers-by-googlers/approximate-geolocation#19 and explainers-by-googlers/approximate-geolocation#20 in the explainer repo. The inheritance problem needs upstream Permissions Policy spec work, but that seems like the right path rather than working around it. |
|
Note that for pre-permission capability detection, as pointed out here, we don't really need anything, and our initial proposal to expose this explicitly was objected to. |
|
I’m not fully following. What I’m saying is that using JS with a getter that throws is a very cool hack (TIL 🤯), but using a CSS media feature would be better developer ergonomics for the intended use case. @antosart, would like to hear your thoughts on the overall reworked proposal. |
|
Regarding the discussion on whether sites need to know the accuracy level via I wanted to share some implementation context. WebKit already masks the geolocation permission state returned by The rationale: the true permission state should only be revealed to a site that is willing to show a prompt. This prevents silent fingerprinting via the Permissions API. Adding This reinforces the proposal I outlined earlier: keep |
I am aware that WebKit implements this additional masking. For the granted That said, I don't have a super strong opinion about this. We added it to the proposal because it seemed ergonomic to offer web developers this information and it didn't seem to expose anything that wasn't already leaked. But I believe we would be fine with dropping it. I would suggest leaving the possibility to query For capability detection, it's not immediately clear to me that a CSS media feature is needed for this particular capability (I mean, why would it make sense for approximate geolocation support in particular to be detected via CSS media feature and not for any of the thousands of other Web APIs?). But I am happy to defer to people who are more expert than me. For the SummarySo my proposal would be:
@marcoscaceres how does this sound? |
|
@marcoscaceres, regarding "post-permission UX adaptation" a use case for this is not just adapting the UX to approximate vs. precise positioning but also informing the user that there are steps they could take to allow the site to function better. For example should they make sure their phone has a clear view of the sky (to improve GPS accuracy) or should they consider granting precise location permission. I acknowledge that "permissions pestering" is a non-goal but we should consider ways to allow the site and browser to give the user a clear path to a potentially desirable experience. Maybe this is something the <geolocation> element can resolve. |
|
@antosart, thank you for the thoughtful summary. I think we're very close. On your three points1. Dropping const geo = await navigator.permissions.query({ name: "geolocation" });
const geoApprox = await navigator.permissions.query({ name: "geolocation-approximate" });
// Can these differ? What if geo is "denied" but geoApprox is "granted"?
// What if the user revokes one but not the other?
// Do I need to watch both?
geo.onchange = () => updateUI();
geoApprox.onchange = () => updateUI();That's unnecessary complexity for no practical benefit. 2. Deferring capability detection: Agreed. The getter-that-throws pattern works today. We can revisit a CSS media feature or other mechanism later if there's demand. 3. Permission Policy sequencing: I'd prefer to land the Permission Policy in this PR rather than a follow-up. Since we're already going to rework the PR to remove Since we're converging on a smaller API surface, the PR will need a rework. I'm happy to help with that, either collaborating on the changes together or drafting the updates myself if that's easier. @alvinjiooo, what would you prefer? On UX adaptation (@reillyeon)@reillyeon, I think the use case you're describing ("tell the user to get a clear view of the sky" vs. "consider granting precise") assumes a relatively static scenario. In practice, Telling a user "go outside for better GPS" based on a momentary accuracy reading would be poor UX, because the value might improve on its own 30 seconds later. And this volatility applies regardless of whether the user chose approximate or has a bad signal. Even with The practical approach is for sites to work with whatever accuracy they get and degrade gracefully. If accuracy is consistently insufficient, a general "location isn't precise enough for this feature" message covers both cases without trying to diagnose the cause. That's also the privacy-preserving approach. I think you're right that the |
|
To make sure we're on the same page, here's what I think we're converging on:
@antosart @alvinjiooo @reillyeon, does this match your understanding? |
|
To clarify: we still need a separate On "geolocation-approximate"Wrt having With that in mind, I think it's nice to keep the invariant that Wrt permission policyI tried to dig a bit in the Permission Policy spec, and for properly supporting I see two ways of doing this:
I would personally say that option 2. is probably easier and nicer, but I guess we should have that discussion on the Permission Policy spec and with the editors. In any case, it seems quite some work. What I've been seeing in other specs is adding a note with how something would work if things where allowed by another spec even if they are not. That could unblock us here even with the dependency on Permissions Policy, but I am not sure it's a good model. But I would ask again if you really think that we can't decouple the "geolocation-approximate" permission policy in a separate PR here. In any case, approximate geolocation is currently gated (as specced in the current version of the PR) by the "geolocation" policy-controlled feature. What we are missing is just a more granular way for websites to allow only approximate and not precise geolocation in third party contexts. While very nice to have (and we should definitely find a way to support it!), it does not seem blocking to me. |
@marcoscaceres , thanks for discussion and sharing the thoughts! |
|
@antosart, you're right that the two permissions can have genuinely different states. That's a real distinction. But I think the progressive UX belongs in the UA's permission dialog, not in the site-queryable API. A UA can offer "approximate or precise?" in a single prompt (or do permanent-approximate + one-time-precise) without the site learning which tier the user chose. The site adapts to Making both queryable creates concerns:
The progressive UX works identically under a single permission. A progressive app requests approximate, later requests precise; the UA re-prompts if needed. The only difference: the site can't detect why accuracy is what it is. That opacity is the privacy feature. Your invariant ( Note that Existing implementation precedentThis model isn't theoretical. In WebKit's iOS implementation, Safari's per-site geolocation prompt is a simple Allow/Don't Allow. The accuracy level is determined by the OS-level permission on the app, not by the website or the per-site prompt. The site gets allow or deny; the accuracy of the position it receives depends on what the OS provides. The website never gets to query which accuracy tier the user configured. This is exactly the model we're proposing for the spec: one permission grant, accuracy controlled by the UA/OS, opaque to content. On Permission PolicyI take your point about the complexity of the Permission Policy spec changes. I looked into it and the iframe-restriction use case (granting a cross-origin iframe approximate-only access) genuinely requires upstream changes to the Permissions Policy spec's inherited policy algorithms. There's no clean local workaround. I'm OK with decoupling this into a follow-up PR, since approximate is already gated by the On capability detectionThis is already solved without spec changes. WebIDL's dictionary member processing means sites can detect function supportsAccuracyMode() {
try {
navigator.geolocation.getCurrentPosition(() => {}, () => {}, {
get accuracyMode() { throw new Error('supported'); }
});
} catch (e) {
return e.message === 'supported';
}
return false;
}I verified this works in Safari today (throws on Updated summary
Point 7 captures the progressive UX benefit without encoding user choices as queryable API state. @alvinjiooo, I think you can start the rework. Happy to collaborate on the spec text. @antosart @reillyeon, does this work? |
|
I'd like to argue again on why I believe that allowing to query First of all, I actually believe that makes developers life easier. Again, the model would be that const geo = await navigator.permissions.query({ name: "geolocation" });
geo.onchange = (status) => {if (status === 'granted') navigator.geolocation.getCurrentPosition()};while a site which is fine with approx-only location can write: const geoApprox = await navigator.permissions.query({ name: "geolocation-approximate" });
geoApprox.onchange = (status) => {
if (status === 'granted')
navigator.geolocation.getCurrentPosition({accuracyMode: 'approximate'})};and work exactly the same way without running into the edge cases in which one of the two permission states changes independently of the other one. A very concrete use case, which might currently be Chrome specific but I believe is nevertheless meaningful, is the following: Chrome can display different permission prompts based on the expectation of whether the user will want to grant or not. When chrome believes the likelihood is low, a omnibox chip is displayed and the geolocation request is autorejected. Users can still go into settings/page info and grant location access: in that case, the onchange() event fires in the page and the page can react and query geolocation. Chrome actually tracks whether the page is listening to onchange(), and suggests the user to reload the page is that's not the case (since the user is explicitly enabling geolocation, they likely expect some functionality on the page to start working, but if the page does not react on the permission change event it's likely it needs a reload). We would like to keep this flow working, and for it to seamlessly work both for For that to be the case, we do need the Given the fact that WebKit can still mask the returned value of |
|
@antosart, I think @marcoscaceres's suggestion here implies that |
onchange can fire only if the permission state changes (otherwise it doesn't make much sense). For how we designed things (as specced in this PR and as currently prototyped in chrome), the permissions (approximate, precise) (i.e.
When the user grants a geolocation request for approximate only, the resulting permission states will be ( On the other hand, when the user grants a gelocation request for precise (which in the current model allows the user to choose between approximate and precise), the permission states will be ( Note that the returned value on
This seems kind of weird, but it maintains the very nice invariant that navigator.query() returns prompt/denied/granted iff getCurrentLocation prompts/throws/return. In particular, this model reaches the following goals:
The model is detailed in the explainer. |
|
(And we are happy to consider suggestions or alternatives, of course! But we have thought about this for quite some time and in depth and we came to the conclusion that this is the easiest model that satisfies the properties above, and that it works quite nice at the end of the day. That is also reflected by our prototype implementation in chrome, which is relatively natural and straightforward because of the invariants we want to preserve, despite the model might seem complex at a first glance.) |
|
@antosart, please know I’m sympathetic and super appreciative of the amount of thinking and work that’s gone into this from you, @alvinjiooo, and other folks that have contributed thus far. It feels like we’ve exhausted laying our use cases, which has been really thought-provoking and worthwhile. Given the length of these discussions, what I’d like to do is spin up a Google doc outlining both approaches, so we can share with PING, Mozilla, and the WG to reach consensus. I’ll share it with you all privately first to make sure it looks okay and captures all your points. Once I have your ok, we can send it out. In the meantime, there’s still some editorial cleanup we can do to get the spec as close to ready to merge as possible. Sound good? |
|
I've put the comparison report up on the Wiki. Please take a look and we can share it from there if you all agree. |
|
Thanks! I will have a look. Please note that I'm also welcoming your input and happy to keep iterating in order to find a solution/compromise that is fine/acceptable for everyone. |
|
I have a couple of comments on https://github.com/w3c/geolocation/wiki/Approximate-Geolocation:-Permissions-Model-Comparison.
|
Closes #182
This commit introduces the ability for users and developers to request a less precise, privacy-preserving "approximate" location.
Key changes include:
The following tasks have been completed:
Implementation commitment (and no objections):
Documentation (new feature):
For documentation, either create an issue or pull request in MDN's Content repo - providing as much information as you can. PR is prefered.
Approximate Geolocation explainer
Preview | Diff