diff --git a/index.html b/index.html index 40ca33b..888c667 100644 --- a/index.html +++ b/index.html @@ -88,8 +88,37 @@

System (GPS) and location inferred from network signals such as IP address, RFID, WiFi and Bluetooth MAC addresses, and GSM/CDMA cell IDs, as well as user input. The API itself is agnostic of the underlying - location information sources, and no guarantee is given that the API - returns the device's actual location. + location information sources, and no guarantee is given that + the API returns the device's actual location. +

+

+ This specification provides two ways for users to share their location: + a precise position and an approximate position. +

+

+ A precise position is a position returned by the underlying + [=location information source=]. By default, any location data is + considered precise, regardless of its accuracy estimate, unless it has + been explicitly coarsened by an [=approximate location information + source=] to be an [=approximate position=]. +

+

+ An approximate position is a less precise, + privacy-preserving representation of the user's location. Instead of + providing precise coordinates, the user agent MUST return a location + that is intentionally coarsened to a larger area, such as the nearest + city, postal code, or a predefined region. This is often sufficient for + applications that don't need to know the user's [=precise position=], + for example, a weather application that only needs a city-level + location. By sharing an [=approximate position=], users can still get + the benefit of a location-aware application without revealing their + [=precise position=]. +

+

+ An approximate location information source is a [=location + information source=] that returns positions that have been + intentionally obfuscated to make it more difficult to recover the true + location.

If an end user [=check permission|grants permission=], @@ -149,7 +178,11 @@

Request the user's current location. If the user allows it, you will - get back a position object. + get back a position object. The website can influence the position's + accuracy by using the `accuracyMode` option. By default, the user + agent will provide a `"precise"` location, but a website can request + an `"approximate"` location if it doesn't require high accuracy, + which helps protect user privacy.

+

@@ -255,17 +298,18 @@

By default, the API always attempts to return a cached position so - long as it has a previously acquired position. In this example, we - accept a position whose age is no greater than 10 minutes. If the - user agent does not have a fresh enough cached position object, it - automatically acquires a new position. + long as it has a previously acquired position that matches the + requested `accuracyMode`. In this example, we accept a precise + position whose age is no greater than 10 minutes. If the user agent + does not have a fresh enough cached position object of the correct + accuracy, it automatically acquires a new position.

-

@@ -329,23 +389,33 @@

Third-party usage can be selectively enabled by adding the - [^iframe/allow^]`="geolocation"` attribute to an [^iframe^] element: + [^iframe/allow^]`="geolocation"` or `allow="geolocation-approximate"` + attribute to an [^iframe^] element. Note that if `geolocation` is + allowed, `geolocation-approximate` is also implicitly allowed.

Alternatively, the API can be disabled in a first-party context by - specifying an HTTP response header: + specifying an HTTP response header. Disabling + `geolocation-approximate` will also disable `geolocation`.

@@ -364,6 +434,19 @@

information also discloses the location of the user of the device, thereby potentially compromising the user's privacy.

+

+ To mitigate this privacy risk, this specification introduces the + {{PositionOptions/accuracyMode}} option, which allows the application + to request an [=approximate position=]. This allows applications to + function without needing the user's [=precise position=], thus offering + a more privacy-friendly alternative. When an application requests an + [=approximate position=], the user agent can provide a less precise + location that still meets the application's needs while protecting the + user's [=precise position=]. Even when a [=precise position=] is + requested, the user agent can provide an [=approximate position=] + instead, for example, if the user has only granted permission for + approximate accuracy. +

User consent @@ -378,7 +461,15 @@

An end-user will generally give [=express permission=] through a user - interface, which usually present a range of permission + interface. [=User agents=] with support for [=approximate position=] + SHOULD allow the user to choose between sharing a [=precise + position=] or an [=approximate position=]. This choice gives users + more control over their privacy, allowing them to share a less + precise location when they are not comfortable sharing their + [=precise position=]. +

+

+ The user interface will usually present a range of permission [=permission/lifetimes=] that the end-user can choose from. The choice of [=permission/lifetimes=] vary across user agents, but they are typically time-based (e.g., "a day"), or until browser is closed, @@ -420,6 +511,17 @@

stored, users need to be allowed to update and delete this information.

+

+ In line with this principle, recipients are strongly encouraged to + request the lowest level of location accuracy that is sufficient for + their application's functionality. For instance, if an application + only needs to know the user's city, it should request an + [=approximate position=] by setting the `accuracyMode` option to + `"approximate"`. This is preferable to requesting a [=precise + position=], which is done by either setting `accuracyMode` to + `"precise"` or by leaving the option unset. This practice of data + minimization is a key aspect of respecting user privacy. +

The recipients of location information need to refrain from retransmitting the location information without the user’s express @@ -460,16 +562,93 @@

- Checking permission to use the API + Checking permission to use the + API

Geolocation is a [=default powerful feature=] identified - by the [=powerful feature/name=] "geolocation". + by the [=powerful feature/name=]s "geolocation" for [=precise position=] and + "geolocation-approximate" + for [=approximate position=].

- When checking permission - to use the API, a user agent MAY suggest time-based [=permission=] + To request geolocation permission for a given + {{PermissionDescriptor}} |descriptor|, the user agent MUST run the + following steps. These steps override the default behavior of + [=request permission to use=] for these features. +

+
    +
  1. If |descriptor|.{{PermissionDescriptor/name}} is "geolocation": +
      +
    1. Prompt the user to choose between granting permission for + [=precise position=], granting permission for [=approximate + position=], or denying permission. +
    2. +
    3. If the user grants permission for [=precise position=]: +
        +
      1. Set the permission state of "geolocation" to "granted". +
      2. +
      3. Set the permission state of "geolocation-approximate" to + "granted". +
      4. +
      5. Return "granted". +
      6. +
      +
    4. +
    5. If the user grants permission for [=approximate position=]: +
        +
      1. Set the permission state of "geolocation-approximate" to + "granted". +
      2. +
      3. Return "prompt". +
      4. +
      +
    6. +
    7. If the user denies permission: +
        +
      1. Set the permission state of "geolocation" to "denied". +
      2. +
      3. Set the permission state of "geolocation-approximate" to + "denied". +
      4. +
      5. Return "denied". +
      6. +
      +
    8. +
    +
  2. +
  3. If |descriptor|.{{PermissionDescriptor/name}} is + "geolocation-approximate": +
      +
    1. Prompt the user to choose between granting permission for + [=approximate position=] or denying permission. +
    2. +
    3. If the user grants permission for [=approximate position=]: +
        +
      1. Set the permission state of "geolocation-approximate" to + "granted". +
      2. +
      3. Return "granted". +
      4. +
      +
    4. +
    5. If the user denies permission: +
        +
      1. Set the permission state of "geolocation" to "denied". +
      2. +
      3. Set the permission state of "geolocation-approximate" to + "denied". +
      4. +
      5. Return "denied". +
      6. +
      +
    6. +
    +
  4. +
+

+ A user agent MAY also suggest time-based [=permission=] [=permission/lifetimes=], such as "24 hours", "1 week", or choose to remember the permission [=permission/grant=] indefinitely. However, it is RECOMMENDED that a user agent prioritize restricting the @@ -479,6 +658,21 @@

the relevant browser tab is closed.

+
+

+ Preventing Precise Location Reconstruction +

+

+ A malicious actor could potentially infer a user's [=precise + position=] by collecting and correlating multiple, distinct + [=approximate position=]s. 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=] + data. A user agent might, for example, use a time window of 15 + minutes. +

+

@@ -549,15 +743,40 @@

- [[\cachedPosition]] + [[\cachedPrecisePosition]] A {{GeolocationPosition}}, initialized to null. It's a reference - to the last acquired position and serves as a cache. A user agent - MAY evict {{Geolocation/[[cachedPosition]]}} by resetting it to + to the last acquired [=precise position=] and serves as a cache. + A user agent MAY evict {{Geolocation/[[cachedPrecisePosition]]}} + by resetting it to null at any time for any reason. + + + + + [[\cachedApproximatePosition]] + + + A {{GeolocationPosition}}, initialized to null. It's a reference + to the last acquired [=approximate position=] and serves as a + cache. A user agent MAY evict + {{Geolocation/[[cachedApproximatePosition]]}} by resetting it to null at any time for any reason. + + + [[\cachedPosition]] + + + A {{GeolocationPosition}}, initialized to null. It's a + reference to the last acquired position and serves as a cache. A + user agent MAY evict {{Geolocation/[[cachedPosition]]}} by + resetting it to null at any time for any reason. + + [[\watchIDs]] @@ -676,8 +895,12 @@

  • Let |document:Document| be the |geolocation|'s [=relevant global object=]'s [=associated `Document`=].
  • +
  • Let |permissionName| be "geolocation-approximate" if + |options|.{{PositionOptions/accuracyMode}} is "approximate", + otherwise let it be "geolocation". +
  • If |document| is not [=allowed to use=] the - "geolocation" feature: + |permissionName| feature:
    1. If |watchId| was passed, [=List/remove=] |watchId| from |watchIDs|. @@ -718,16 +941,14 @@

  • Let |descriptor| be a new {{PermissionDescriptor}} whose - {{PermissionDescriptor/name}} is "geolocation". + {{PermissionDescriptor/name}} is |permissionName|.
  • [=In parallel=]:
      -
    1. Set |permission| to [=request permission to use=] +
    2. Set |permission| to [=request geolocation permission=] for |descriptor|.
    3. -
    4. - If |permission| is "denied", then: +
    5. Let |handle permission denial| be the following steps:
      1. If |watchId| was passed, [=list/remove=] |watchId| from |watchIDs|. @@ -739,6 +960,25 @@

    6. +
    7. + If |permission| is "denied": +
        +
      1. If |options|.{{PositionOptions/accuracyMode}} is + "approximate", then run |handle permission denial|. +
      2. +
      3. Otherwise: +
          +
        1. Let |approximatePermission| be [=get the current + permission state=] of "geolocation-approximate". +
        2. +
        3. If |approximatePermission| is "denied", then run + |handle permission denial|. +
        4. +
        +
      4. +
      +
    8. Wait to [=acquire a position=] passing |successCallback|, |errorCallback|, |options|, and |watchId|.
    9. @@ -804,262 +1044,271 @@

    10. Let |timeoutTime| be the sum of |acquisitionTime| and |options|.{{PositionOptions/timeout}}.
    11. -
    12. Let |cachedPosition:GeolocationPosition| be [=this=]'s - {{Geolocation/[[cachedPosition]]}}. -
    13. Create an implementation-specific |timeout| task that elapses at |timeoutTime|, during which it tries to acquire the device's position by running the following steps:
        -
      1. Let |permission| be [=get the current permission state=] of - "geolocation". +
      2. Let |precisePermission| be [=get the current permission + state=] of "geolocation". +
      3. +
      4. Let |approximatePermission| be [=get the current permission + state=] of "geolocation-approximate". +
      5. +
      6. Let |effectiveAccuracy| be null. +
      7. +
      8. If |options|.{{PositionOptions/accuracyMode}} is + "approximate": +
          +
        1. If |approximatePermission| is "granted", set + |effectiveAccuracy| to "approximate". +
        2. +
        +
      9. +
      10. Otherwise, if |options|.{{PositionOptions/accuracyMode}} is + "precise": +
          +
        1. If |precisePermission| is "granted", set + |effectiveAccuracy| to "precise". +
        2. +
        3. Otherwise, if |approximatePermission| is "granted", set + |effectiveAccuracy| to "approximate". +
        4. +
      11. -
      12. If |permission| is "denied": +
      13. If |effectiveAccuracy| is null:
        1. Stop |timeout|.
        2. Do the user or system denied permission failure case step.
        3. +
        4. Terminate this algorithm. +
      14. -
      15. If |permission| is "granted": +
      16. + Check if an emulated position should be used by + running the following steps:
          -
        1. - Check if an emulated position should be - used by running the following steps: +
        2. Let |emulatedPositionData| be [=get emulated position + data=] passing [=this=]. +
        3. +
        4. If |emulatedPositionData| is not null:
            -
          1. Let |emulatedPositionData| be [=get emulated position - data=] passing [=this=]. -
          2. -
          3. If |emulatedPositionData| is not null: +
          4. If |emulatedPositionData| is a + {{GeolocationPositionError}}:
              -
            1. If |emulatedPositionData| is a - {{GeolocationPositionError}}: -
                -
              1. [=Call back with error=] passing - |errorCallback| and - |emulatedPositionData|.{{GeolocationPositionError/code}}. -
              2. -
              3. Terminate this algorithm. -
              4. -
              -
            2. -
            3. Let |position| be [=a new `GeolocationPosition`=] - passing |emulatedPositionData|, |acquisitionTime| and - |options|.{{PositionOptions/enableHighAccuracy}}. -
            4. -
            5. [=Queue a task=] on the [=geolocation task - source=] with a step that [=invokes=] - |successCallback| with « |position| » and "`report`". +
            6. [=Call back with error=] passing |errorCallback| + and + |emulatedPositionData|.{{GeolocationPositionError/code}}.
            7. Terminate this algorithm.
          5. -
          -
        5. -
        6. Let |position| be null. -
        7. -
        8. If |cachedPosition| is not null, and - |options|.{{PositionOptions/maximumAge}} is greater than 0: -
            -
          1. Let |cacheTime:long| be |acquisitionTime| minus the - value of the |options|.{{PositionOptions/maximumAge}} - member. +
          2. Let |position| be [=a new `GeolocationPosition`=] + passing |emulatedPositionData|, |acquisitionTime|, + |options|.{{PositionOptions/enableHighAccuracy}}, and + |effectiveAccuracy|.
          3. -
          4. - If |cachedPosition|'s - {{GeolocationPosition/timestamp}}'s value is greater - than |cacheTime|, and - |cachedPosition|.{{GeolocationPosition/[[isHighAccuracy]]}} - equals - |options|.{{PositionOptions/enableHighAccuracy}}, - set |position| to |cachedPosition|. : -
              -
            1. [=Queue a task=] on the [=geolocation task - source=] with a step that [=invokes=] - |successCallback| with « |cachedPosition| » and - "`report`". -
            2. -
            3. Terminate this algorithm. -
            4. -
            +
          5. [=Queue a task=] on the [=geolocation task source=] + with a step that [=invokes=] |successCallback| with « + |position| » and "`report`". +
          6. +
          7. Terminate this algorithm.
        9. -
        10. Otherwise, if |position| is not |cachedPosition|, try to - acquire position data from the underlying system, optionally - taking into consideration the value of - |options|.{{PositionOptions/enableHighAccuracy}} during - acquisition. +
        +
      17. +
      18. Let |cachedPosition| be null. +
      19. +
      20. If |effectiveAccuracy| is "precise": +
          +
        1. Set |cachedPosition| to [=this=]'s + {{Geolocation/[[cachedPrecisePosition]]}}. +
        2. +
        +
      21. +
      22. Otherwise, if |effectiveAccuracy| is "approximate": +
          +
        1. Set |cachedPosition| to [=this=]'s + {{Geolocation/[[cachedApproximatePosition]]}}. +
        2. +
        +
      23. +
      24. Let |position| be null. +
      25. +
      26. If |cachedPosition| is not null, and + |options|.{{PositionOptions/maximumAge}} is greater than 0: +
          +
        1. Let |cacheTime:long| be |acquisitionTime| minus the value + of the |options|.{{PositionOptions/maximumAge}} member.
        2. -
        3. If the |timeout| elapses during acquisition, or acquiring - the device's position results in failure: +
        4. + If |cachedPosition|'s + {{GeolocationPosition/timestamp}}'s value is greater than + |cacheTime|, and (|effectiveAccuracy| is "approximate" or + (|effectiveAccuracy| is "precise" and + |cachedPosition|.{{GeolocationPosition/[[isHighAccuracy]]}} + equals + |options|.{{PositionOptions/enableHighAccuracy}})), + set |position| to |cachedPosition|. :
            -
          1. Stop the |timeout|. -
          2. -
          3. Go to dealing with - failures. +
          4. [=Queue a task=] on the [=geolocation task source=] + with a step that [=invokes=] |successCallback| with « + |cachedPosition| » and "`report`".
          5. Terminate this algorithm.
          6. -
          +
      27. -
      28. If acquiring the position data from the - system succeeds: - -
          -
        1. Let |positionData| be a [=map=] with the following - name/value pairs based on the acquired position data: -
          -
          - "longitude" -
          -
          - A {{double}} that represents the longitude - coordinates on the Earth's surface in degrees, - using the [[WGS84]] coordinate system. Longitude - measures how far east or west a point is from the - Prime Meridian. -
          -
          - "altitude" -
          -
          - A {{double?}} that represents the altitude in - meters above the [[WGS84]] ellipsoid, or `null` if - not available. Altitude measures the height above - sea level. -
          -
          - "accuracy" -
          -
          - A non-negative {{double}} that represents the - accuracy value indicating the 95% confidence level - in meters. Accuracy measures how close the measured - coordinates are to the true position. -
          -
          - "altitudeAccuracy" -
          -
          - A non-negative {{double?}} that represents the - altitude accuracy, or `null` if not available, - indicating the 95% confidence level in meters. - Altitude accuracy measures how close the measured - altitude is to the true altitude. -
          -
          - "speed" -
          -
          - A non-negative {{double?}} that represents the - speed in meters per second, or `null` if not - available. Speed measures how fast the device is - moving. -
          -
          - "heading" -
          -
          - A {{double?}} that represents the heading in - degrees, or `null` if not available or the device - is stationary. Heading measures the direction in - which the device is moving relative to true north. -
          -
          -
        2. -
        3. Set |position| to [=a new `GeolocationPosition`=] - passing |positionData|, |acquisitionTime| and - |options|.{{PositionOptions/enableHighAccuracy}}. -
        4. -
        5. Set [=this=]'s {{Geolocation/[[cachedPosition]]}} to - |position|. -
        6. -
        -
          -
        1. Set |position| to [=a new `GeolocationPosition`=] - passing |acquisitionTime| and - |options|.{{PositionOptions/enableHighAccuracy}}. -
        2. -
        3. Set [=this=]'s {{Geolocation/[[cachedPosition]]}} to - |position|. -
        4. -
        +
      +
    14. +
    15. Otherwise, if |position| is not |cachedPosition|, try to + acquire position data from the underlying system, with the + following considerations: +
        +
      1. If |effectiveAccuracy| is "approximate", the user agent + SHOULD acquire a position with a level of accuracy that is + sufficient to protect user privacy (e.g., city-level + accuracy). The {{PositionOptions/enableHighAccuracy}} member + is ignored. +
      2. +
      3. If |effectiveAccuracy| is "precise", the user agent + SHOULD acquire a position, optionally taking into + consideration the value of + |options|.{{PositionOptions/enableHighAccuracy}}.
      4. +
      +
    16. +
    17. If the |timeout| elapses during acquisition, or acquiring the + device's position results in failure: +
      1. Stop the |timeout|.
      2. -
      3. [=Queue a task=] on the [=geolocation task source=] with - a step that [=invokes=] |successCallback| with « |position| » - and "`report`". +
      4. Go to dealing with + failures. +
      5. +
      6. Terminate this algorithm.
    18. -

    -
    -
    - Dealing with failures: -
    -
    -
      -
    • If acquiring a position fails, do one of the following - based on the condition that matches the failure: -
      -
      - User or system denied permission: +
    • If acquiring the position data from the + system succeeds: + +
        +
      1. Let |positionData| be a [=map=] with the following + name/value pairs based on the acquired position data: +
        +
        + "longitude" +
        +
        + A {{double}} that represents the longitude coordinates + on the Earth's surface in degrees, using the [[WGS84]] + coordinate system. Longitude measures how far east or + west a point is from the Prime Meridian. +
        +
        + "altitude" +
        +
        + A {{double?}} that represents the altitude in meters + above the [[WGS84]] ellipsoid, or `null` if not + available. Altitude measures the height above sea + level. +
        +
        + "accuracy" +
        +
        + A non-negative {{double}} that represents the accuracy + value indicating the 95% confidence level in meters. + Accuracy measures how close the measured coordinates + are to the true position. +
        +
        + "altitudeAccuracy"
        -

        - [=Call back with error=] passing |errorCallback| and - {{GeolocationPositionError/PERMISSION_DENIED}}. -

        - + A non-negative {{double?}} that represents the altitude + accuracy, or `null` if not available, indicating the + 95% confidence level in meters. Altitude accuracy + measures how close the measured altitude is to the true + altitude.
        - Timeout elapsed: + "speed"
        - [=Call back with error=] with |errorCallback| and - {{GeolocationPositionError/TIMEOUT}}. + A non-negative {{double?}} that represents the speed in + meters per second, or `null` if not available. Speed + measures how fast the device is moving.
        - Data acquisition error or any other reason: + "heading"
        - [=Call back with error=] passing |errorCallback| and - {{GeolocationPositionError/POSITION_UNAVAILABLE}}. + A {{double?}} that represents the heading in degrees, + or `null` if not available or the device is stationary. + Heading measures the direction in which the device is + moving relative to true north.
      2. -
    -
    -
    +
  • Set |position| to [=a new `GeolocationPosition`=] passing + |positionData|, |acquisitionTime|, + |options|.{{PositionOptions/enableHighAccuracy}}, and + |effectiveAccuracy|. +
  • +
  • If |effectiveAccuracy| is "precise": +
      +
    1. Set [=this=]'s + {{Geolocation/[[cachedPrecisePosition]]}} to |position|. +
    2. +
    +
  • +
  • Otherwise, if |effectiveAccuracy| is "approximate": +
      +
    1. Set [=this=]'s + {{Geolocation/[[cachedApproximatePosition]]}} to + |position|. +
    2. +
    +
  • + +
      +
    1. Set |position| to [=a new `GeolocationPosition`=] passing + |acquisitionTime| and + |options|.{{PositionOptions/enableHighAccuracy}}. +
    2. +
    3. Set [=this=]'s {{Geolocation/[[cachedPosition]]}} to + |position|. +
    4. +
    + +
  • Stop the |timeout|. +
  • +
  • [=Queue a task=] on the [=geolocation task source=] with a + step that [=invokes=] |successCallback| with « |position| » and + "`report`". +
  • +

    @@ -1090,12 +1339,36 @@

    PositionOptions dictionary

    +        enum AccuracyMode {
    +          "precise",
    +          "approximate"
    +        };
    +
             dictionary PositionOptions {
    +          AccuracyMode accuracyMode = "precise";
               boolean enableHighAccuracy = false;
               [Clamp] unsigned long timeout = 0xFFFFFFFF;
               [Clamp] unsigned long maximumAge = 0;
             };
             
    +
    +

    + `accuracyMode` member +

    +

    + The accuracyMode member is used to request a specific + level of accuracy. It can be set to "precise" to request the most + accurate location data available, or "approximate" to receive a less + accurate location that protects user privacy. The default value is + "precise". +

    + +

    `enableHighAccuracy` member @@ -1160,6 +1433,7 @@

    interface GeolocationPosition { readonly attribute GeolocationCoordinates coords; readonly attribute EpochTimeStamp timestamp; + readonly attribute AccuracyMode accuracyMode; [Default] object toJSON(); }; @@ -1180,6 +1454,17 @@

    geographic position of the device was acquired.

    +
    +

    + `accuracyMode` attribute +

    +

    + The accuracyMode attribute indicates the accuracy level of + the position, which can be either `"precise"` or `"approximate"`. + This reflects the level of accuracy that was granted and used to + obtain the position. +

    +

    `toJSON()` method @@ -1346,8 +1631,9 @@

    A new `GeolocationPosition` is constructed with [=map=] - |positionData|, {{EpochTimeStamp}} |timestamp:EpochTimeStamp| and - boolean |isHighAccuracy| by performing the following steps: + |positionData|, {{EpochTimeStamp}} |timestamp:EpochTimeStamp|, + boolean |isHighAccuracy|, and string |effectiveAccuracy| by + performing the following steps:

    1. Let |coords:GeolocationCoordinates| be a newly created @@ -1360,10 +1646,12 @@

  • Return a newly created {{GeolocationPosition}} instance with its - {{GeolocationPosition/coords}} attribute initialized to |coords| and + {{GeolocationPosition/coords}} attribute initialized to |coords|, {{GeolocationPosition/timestamp}} attribute initialized to - |timestamp|, and its {{GeolocationPosition/[[isHighAccuracy]]}} - internal slot set to |isHighAccuracy|. + |timestamp|, {{GeolocationPosition/accuracyMode}} attribute + initialized to |effectiveAccuracy|, and its + {{GeolocationPosition/[[isHighAccuracy]]}} internal slot set to + |isHighAccuracy|.
  • @@ -1504,10 +1792,18 @@

    Permissions policy

    - This specification defines a [=policy-controlled feature=] identified - by the token string "geolocation". Its [=policy-controlled + This specification defines two [=policy-controlled features=] + identified by the token strings "geolocation" and + "geolocation-approximate". Their [=policy-controlled feature/default allowlist=] is [=default allowlist/'self'=].

    +

    + The "geolocation" policy controls access to [=precise position=], while + "geolocation-approximate" controls access to [=approximate position=]. + Granting "geolocation" permission implicitly grants + "geolocation-approximate" permission as well, while restricting + "geolocation-approximate" also restricts "geolocation". +