The HTML Geolocation Element

Draft Community Group Report,

This version:
https://wicg.github.io/PEPC/geolocation-element.html
Issue Tracking:
GitHub
Inline In Spec
Editor:
Daniel Vogelheim (Google LLC)

Abstract

An HTML element to let a user trigger access to geolocation.

This specifies a new HTML element, <geolocation>, that provides users with a way to grant apage access to geolocation and the associated capabilities from within the page.

Suitable styling and UI constraints on this new element ensure that the user understands what a click on it means, and thus gives the browser a high level of confidence of user intent to make a permission decision. The geolocation elements aim to be more accessible, more secure, and more user friendly than the current, script-triggered permission flows.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1. Introduction and Background

User agents expose powerful features to web sites, like geolocation or camera access. These features are important to some use cases, but can be easily abused.To handle this, user agents use permissions to ask the user whether they wish for a particular access to be allowed or not.

These permission requests began as a fairly direct passthrough: A site would ask for some capability and the user agent immediately prompts the user to make a decision for the request. Meanwhile, spam and abuse have forced user agents to take a more opinionated approach to protect users' security, privacy, and attention. The status quo is that users get a multitude of permission requests, where it’s oftentimes unclear to users what the consequences of these requests might be.

This spec introduces a new mechanism that requests and initiates access to Geolocation capabilities through in-page elements, with built-in protections against abuse. Giving access to the location through in in-page lement wants to tie capability activation to the actual context in which it will be used , thus reducing "permission spam" and at the same time providing implementations with a better signal of user intent.

The later chapters of this specification are careful to build up the required spec infrastructure to that it can be re-used on other, similarly spirited elements providing access to other powerful features and their associated capabilities.

2. The geolocation Element

The HTML geolocation element can moderate access to the "geolocation" permission and the associated Geolocation capabilities.

Categories:
Flow content.
Phrasing content.
Interactive content.
Palpable content.
Contexts in which this element can be used:
Where phrasing content is expected.
Content model:
Flow content.
Content attributes:
Global attributes.
ActivationBlockersMixin attributes.
PermissionsMixin attributes.
autolocate — Whether to locate right away (if permission has already been granted).
watch — Wether to read the position once, or watch it continously.
Accessibility considerations:
See issues below.
DOM interface:
HTMLGeolocationElement

[WAI-ARIA] specifies roles for in-page content. It is yet unclear whether or how the geolocation element fits into the existing set of roles. Given that this element triggers permission requests, one could argue that whatever accessibility concerns apply there should cover this element as well. On the other hand, more specialized treatment may lead to better support for users.

In § 3.4 Styling, and Styling Restrictions, this specification defines elaborate restrictions on how geolocation elements can be rendered. It’s unclear whether there need to be similarly spirited restrictions on which ARIA attributes can be applied.

The isValid and invalidReason, as well as the global lang and tabindex content attributes, and the onpromptaction, onpromptdismiss, and onvalidationstatuschange event handlers follow the description in § 3 Mixins and Infrastructure.

The autolocate attribute determines whether the geolocation element should start locating immediately (if permission has already been granted).

The watch attribute determine whether the geolocation element report the location once or continously.

[Exposed=Window]
interface HTMLGeolocationElement : HTMLElement {
  [HTMLConstructor] constructor();

  readonly attribute GeolocationPosition? position;
  readonly attribute GeolocationPositionError? error;
  [CEReactions, Reflect] attribute boolean autolocate;
  [CEReactions, Reflect] attribute boolean watch;

  attribute EventHandler onlocation;
};
HTMLGeolocationElement includes ActivationBlockersMixin;
HTMLGeolocationElement includes PermissionsMixin;

If the user has decided to allow access to geolocation information, the readonly attributes position and error reflect the current GeolocationPosition and GeolocationPositionError values, just like the PositionCallback and PositionErrorCallback callbacks (respectively) would have returned

If the boolean attribute autolocate is true, and if the "geolocation" permission has already been granted by the user, then the location should be retrieved immediately when the geolocation element is attached to the document. If the permission has not already been granted at insertion time, then this attribute has no effect.

If the boolean attribute watch is set to true, the onlocation event is called every time the position changes, matching the behaviour of watchPosition.

When a location is available, an Event is dispatched on the onlocation event handler. When the event is dispatched, the location, or information about a failure to retrieve the location, are available in the position or the error attributes. Depending on the watch element this happens once (if absent or false), or continously (if true).

HTMLGeolocationElement wants to mirror the Geolocation interface. There is a direct correspondance:

position Result of PositionCallback.
error Result of PositionErrorCallback.
watch Use watchPosition().
¬ watch Use getCurrentPosition().

The global lang attribute is observed by the element to select localized text.

The default value for the global tabindex content attribute on the element is 0.

2.1. geolocation element internal state

The geolocation element uses all the internal slots from ActivationBlockersMixin and PermissionsMixin. Additionally, geolocation has the following internal slots:

2.1.1. Mixin-supporting state at the navigable

In order to support the HTMLGeolocationElement, the navigable maintains an ordered set of elements, [[PermissionElements]]. This ordered set is used to evaluate the blockers of type unsuccesful_registration.

2.2. geolocation element algorithms

The HTMLGeolocationElement constructor() steps are:
  1. Initialize the internal [[Features]] to « "geolocation" ».

  2. Initialize the internal [[BlockerList]] to «».

  3. Initialize the internal [[LastNotifiedValidState]] with false.

  4. Initialize the internal [[LastNotifiedInvalidReason]] with the empty string.

  5. Initialize the internal [[watchIDs]] to « watchID », where watchID is an implementation-defined unsigned long that is greater than zero.

  6. Initialize the internal [[position]] to null.

  7. Initialize the internal [[positionError]] to null.

  8. Run PermissionsMixin’s initialization steps.

The HTMLGeolocationElement’s insertion steps are:
  1. Initialize the internal [[BlockerList]] to «».

  2. Append this to node navigable’s [[PermissionElements]].

  3. Initialize the internal [[IntersectionRect]] with undefined.

  4. Initialize the internal [[IntersectionObserver]] with the result of constructing a new IntersectionObserver with IntersectionObserver callback and «[ "rootMargin" → "-4px" ]».

  5. Call [[IntersectionObserver]].observe(this).

  6. Run PermissionsMixin’s insertion steps.

  7. If this is not type permissible, then add a temporary blocker with unsuccesful_registration.

  8. Add an expiring blocker with reason recently_attached.

  9. If the traversable navigable of the node navigable of this is a fenced navigable, then add a permanent blocker with illegal_subframe.

  10. Maybe dispatch onvalidstatechange on this.

  11. Maybe autolocate.

The HTMLGeolocationElement removing steps are:
  1. Remove this from node navigable’s [[PermissionElements]].

  2. Recheck type permissibility for this’s node navigable.

  3. Maybe dispatch onvalidstatechange on this.

The HTMLGeolocationElement element’s activation behavior given event is:
  1. Assert: element’s [[Features]] is not null.

  2. If element’s [[Features]] is empty, then return.

  3. If event.isTrusted is false, then return.

  4. If element.isValid is false, then return.

  5. Let descriptor be the result of build a permission descriptor for element.

  6. Request permission to use the powerful features described by descriptor.

  7. If the previous step was cancelled or dismissed by the user, then dispatch onpromptdismiss on this and return.

    The [Permissions] spec assumes that request permission to use will always succeed. That is, it assumes that the user will always make a choice and that the algorithm will always deliver a grant/deny answer corresponding to that choice. But you can’t force a user to do that. Some user agents may have different UI affordances for an explicit denial (e.g. a "deny" button) on one hand, and cancelling or dismissing the request dialog (e.g. an "X" button in the top right corner). Here, we distinguish between these two actions, despite no clear hook for this in the underlying specification.

  8. Dispatch onpromptaction on this.

  9. Fetch location.

The position getter steps are to return the value of [[position]].
The error getter steps are to return the value of [[positionError]].
To maybe autolocate:
  1. If get the current permission state is not granted, then return.

  2. If autolocate is not true, then return.

  3. Fetch location.

To fetch location:
  1. Let positionCallback be a PositionCallback that performs the following steps:

    1. Set this’s [[positionError]] to undefined.

    2. Set this’s [[position]] to PositionCallback’s position argument.

    3. Dispatch onlocation to this.

  2. Let errorCallback be a PositionErrorCallback that performs the following steps:

    1. Set this’s [[position]] to undefined.

    2. Set this’s [[positionError]] to PositionCallback’s positionError argument.

    3. Dispatch onlocation to this.

  3. Let positionOptions be «[]»

  4. Let geolocation be the relevant global object’s Geolocation.

  5. If this’s watch is true:

    1. Request a position with geolocation, positionCallback, errorCallback, positionOptions, and this’s [[watchIDs]].

  6. Otherwise:

    1. Request a position with geolocation, positionCallback, errorCallback, positionOptions.

To determine whether an element is type permissible:
  1. Assert: element’s node navigable’s [[PermissionElements]] contains element.

  2. Let count be 0.

  3. For each current in element’s node navigable’s [[PermissionElements]]:

    1. If current is element, then break.

    2. If element.[[Features]] equals current.[[Features]]

      then increment count by 1.

  4. Return whether count is less than 3.

To recheck type permissibility for a document:
  1. For each current in document’s [[PermissionElements]]:

    1. If current is type permissible, then remove blockers with unsuccesful_registration from current.

To dispatch onlocation for element:
  1. Let event be a new Event.

  2. Initialize event with type "onlocation".

  3. Dispatch event to element.

2.3. geolocation element rendering

The geolocation element is a non-devolvable widget and is chiefly rendered like a button. The button label is largely expected to be determined by the browser, rather than the page, and reflects its function of given access to Geolocation functionality. The element may also convey information about the current permission state of the "geolocation" powerful feature.

The page can influence the permission elements' styling, but with constraints to prevent abuse (e.g. minimum and maximum sizes for fonts and the label itself). These are described in § 3.4 Styling, and Styling Restrictions. The page can also select a locale for the text via the lang attribute.

The permission elements support fallback content, which will be displayed by any browser not yet supporting that element. Note that there are also conditions under which a browser that supports a respective permission element falls back to its fallback content.

3. Mixins and Infrastructure

This section defines several mixins and supporting algorithms.

3.1. Activation Blockers

To support a meaningful user intent signal and to conditionally block element activation, you can use the ActivationBlockersMixin

Content attributes:
isValid — query whether the element can currently be activated.
invalidReason — return a string representation of why the element currently cannot be activated.
onvalidationstatuschange — notifies when the validation status changes.
DOM interface:
interface mixin ActivationBlockersMixin {
  readonly attribute boolean isValid;
  readonly attribute ActivationBlockersMixinBlockerReason invalidReason;
  attribute EventHandler onvalidationstatuschange;
};

The isValid attribute reflects whether the element is currently blocked.

The invalidReason attribute is an enumerated attribute that informs the caller of the reason why activation is currently blocked. If there are multiple reasons, it picks one. Its value set is ActivationBlockersMixinBlockerReason.

The following are the event handler (and their corresponding event handler event type) that must be supported on elements that include the ActivationBlockersMixin:

onvalidationstatuschange Event

The ActivationBlockersMixin attributes are:

3.1.1. Internal state

ActivationBlockersMixin elements have the following internal slots:

3.1.2. Action Blockers, Blocker Reasons, and Blocker Lifetimes

The key goal of the elements in this specification is to reflect a user’s conscious choice, and we need to make sure the user cannot easily be tricked into activating it. To do so, we maintain a list of blocker reasons, which may - permanently or temporarily - prevent the element from being activated.

Conceptually, a blocker reason is just an arbitrary string identifier. We provide an enumeration of its value set. It’s expected that not all users of the ActivationBlockersMixin will support all reasons.

enum ActivationBlockersMixinBlockerReason {
  "",   // No blocker reason.
  "illegal_subframe", "unsuccesful_registration",
  "recently_attached", "intersection_changed",
  "intersection_out_of_viewport_or_clipped",
  "intersection_occluded_or_distorted", "style_invalid",
  "type_invalid",
};

These blockers come with three lifetimes: Permanent, temporary, and expiring.

Permanent blocker

Once an element has a permanent blocker, it will be disabled permanently. There are used for issues that the website owner is expected to fix. An example is an element inside a fencedframe.

Temporary blocker

This is a blocker that will only be valid until the blocking condition no no longer occurs. An example is an element that is not currently in view. All temporary blockers turn into expiring blockers once the condition no longer applies.

Expiring blocker

This is a blocker that is only valid for a fixed period of time. This is used to block abuse scenarios like "click jacking". An example is an element that has recently been moved.

Blocker name Blocker type Example condition Order hint
type_invalid permanent When an unsupported permission type has been set. 1
illegal_subframe permanent When the element is used inside a fencedframe. 2
unsuccesful_registration temporary When too many other elements for the same powerful feature have been inserted into the same document. 3
recently_attached expiring When the element has just been attached to the DOM. 4
intersection_changed expiring When the element is being moved. 6
intersection_out_of_viewport_or_clipped temporary When the element is not or not fully in the viewport. 7
intersection_occluded_or_distorted temporary When the element is fully in the viewport, but still not fully visible (e.g. because it’s partly behind other content). 8
style_invalid temporary 9

3.1.3. Algorithms

To add a blocker with a ActivationBlockersMixinBlockerReason reason and an optional flag expires:
  1. Assert: reason is not "". (The empty string in ActivationBlockersMixinBlockerReason signals no blocker is present. Why would you add a non-blocking empty string blocker?)

  2. Let timestamp be None.

  3. If expires, then let timestamp be current high resolution time plus the blocker delay.

  4. Append an entry to the internal [[BlockerList]] with reason and timestamp.

The blocker delay is 500ms.
To add an expiring blocker with a ActivationBlockersMixinBlockerReason reason:
  1. Assert: reason is listed as "expiring" in the blocker reason table.

  2. Add a blocker with reason and true.

To add a temporary blocker with a ActivationBlockersMixinBlockerReason reason:
  1. Assert: reason is listed as "temporary" in the blocker reason table.

  2. Add a blocker with reason and false.

To add a permanent blocker with a ActivationBlockersMixinBlockerReason reason:
  1. Assert: reason is listed as "permanent" in the blocker reason table.

  2. Add a blocker with reason and false.

To remove blockers with ActivationBlockersMixinBlockerReason reason from an element:
  1. Assert: reason is listed as "temporary" in the blocker reason table.

  2. For each entry in element’s [[BlockerList]]:

    1. If entry’s reason equals reason, then remove entry from element’s [[BlockerList]].

  3. Add a blocker with reason and true.

To determine a ActivationBlockersMixin element’s blocker:
  1. Let blockers be the result of sorting element’s [[BlockerList]] with the blocker ordering algorithm.

  2. If blockers is not empty and blockers[0] is blocking, then return blockers[0].

  3. Return nothing.

To determine blocker ordering for two blockers a and b:
  1. Let really large number be 99.

  2. Assert: No order hint in the blocker reason table is equal to or greater than really large number.

  3. If a is blocking, then let a hint be the order hint of a’s reason in the blocker reason table, otherwise let a hint be really large number.

  4. If b is blocking, then let b hint be the order hint of b’s reason in the blocker reason table, otherwise let b hint be really large number.

  5. Return whether a hint is less than or equal to b hint.

An ActivationBlockersMixin’s blocker list’s entry is blocking if:
  1. entry has no blocker timestamp,

  2. or entry has a blocker timestamp, and the blocker timestamp is greater or equal to the current high resolution time.

NOTE: The spec maintains blockers as a list [[BlockerList]], which may potentially grow indefinitely (since some blocker types simply expire, but are not removed). This structure is chosen for the simplicity of explanation, rather than for efficiency. The details of this blocker structure are not observable except for a handful of algorithms defined here, which should open plenty of opportunities for implementations to handle this more efficiently.

An ActivationBlockersMixin element’s isValid getter steps are:
  1. Return whether element’s blocker is Nothing.

An ActivationBlockersMixin element’s invalidReason getter steps are:
  1. If element’s blocker is Nothing, return "".

  2. Otherwise, element’s blocker’s reason string.

To maybe dispatch onvalidstatechange for element:
  1. Let oldState be [[LastNotifiedValidState]].

  2. Let newState be whether element’s blocker is Nothing.

  3. Set [[LastNotifiedValidState]] to newState.

  4. Let oldReason be [[LastNotifiedInvalidReason]].

  5. Let newReason be whether element’s invalidReason.

  6. Set [[LastNotifiedInvalidReason]] to newReason.

  7. If oldState != newState or oldReason != newReason, then:

    1. Let event be a new Event.

    2. Initialize event with type "onvalidationstatuschange", bubbles true, and cancelable true.

    3. Dispatch event to element.

An ActivationBlockersMixin’s IntersectionObserver callback implements IntersectionObserverCallback and runs the following steps:
  1. Assert: The IntersectionObserver’s root is the document

  2. Let entries be the value of the first callback parameter, the list of intersection observer entries.

  3. Assert: entries is not empty.

  4. Let entry be entries’s last item.

  5. If entry.isVisible, then:

    1. Remove blockers with intersection_occluded_or_distorted.

    2. Remove blockers with intersection_out_of_viewport_or_clipped.

  6. Otherwise:

    1. If entry.intersectionRatio >= 1, then:

      1. Let reason be intersection_occluded_or_distorted.

    2. Otherwise:

      1. Let reason be intersection_out_of_viewport_or_clipped.

    3. Add a temporary blocker with reason.

  7. If [[IntersectionRect]] does not equal entry.intersectionRect then add an expiring blocker with intersection_changed.

  8. Set [[IntersectionRect]] to entry.intersectionRect

  9. Maybe dispatch onvalidstatechange on this.

Do I need to define dictionary equality?

3.2. Powerful Features, aka Permissions

To support elements that gate access to powerful features, you can use the PermissionsMixin.

DOM interface:
interface mixin PermissionsMixin {
  readonly attribute PermissionState initialPermissionStatus;
  readonly attribute PermissionState permissionStatus;
  attribute EventHandler onpromptaction;
  attribute EventHandler onpromptdismiss;
};

The following are the event handlers (and their corresponding event handler event types) that must be supported on elements that include the PermissionsMixin:

onpromptaction Event
onpromptdismiss Event

The PermissionsMixin attributes are:

3.2.1. Internal state

The PermissionsMixin represents capabilities gated by user-requestable permissions, which the user can activate to allow the site to start accessing them. It is core to the these elements that such requests are triggered by the user, and not by the page’s script. To enforce this, the element checks whether the activation event is trusted. Additionally it watches a number of conditions, like whether the element is (partially) occluded, or if it has recently been moved. The element maintains an internal [[BlockerList]] to keep track of this.

PermissionsMixin elements have the following internal slots:

3.2.2. Algorithms

A PermissionsMixin’s initialization steps are:
  1. Assert: The internal [[Features]] slot has been initialized. The including element must define and initialize this.

  2. Initialize the internal [[InitialPermissionStatus]] to the result of get the current permission state.

A PermissionsMixin’s insertion steps are:
  1. If [[Features]] is empty or is null, then add a permanent blocker with reason type_invalid.

An PermissionsMixin element’s initialPermissionStatus getter steps are:
  1. Return element’s internal [[InitialPermissionStatus]].

An PermissionsMixin element’s permissionStatus getter steps are:
  1. Return get the current permission state for element.

To get the current permission state for an PermissionsMixin element:
  1. Let features be element’s internal [[Features]].

  2. If features is null or features is empty, return "prompt".

  3. Let current be "granted".

  4. For each feature of features:

    1. Let state be the result of get the current permission state for feature.

    2. Let current be the smaller of current and state, assuming the following ordering:
      "granted" > "prompt" > "denied".

  5. Return current.

It’s not clear what the PermissionState for 'no valid permission type' should be. Here I pick "prompt" based on Chrome’s implementation; but that choice is arbitrary.

To dispatch onpromptaction for element:
  1. Let event be a new Event.

  2. Initialize event with type "onpromptaction", bubbles true, and cancelable true.

  3. Dispatch event to element.

To dispatch onpromptdismiss for element:
  1. Let event be a new Event.

  2. Initialize event with type "onpromptdismiss", bubbles true, and cancelable true.

  3. Dispatch event to element.

To build a permission descriptor for an element:

The [Permissions] specification assumes a descriptor describes a single permission without parameters (like an equivalent of enableHighAccuracy). Here, we assume a permissions model that is more expressive. This needs to be resolved -- likely upstream, in [Permissions], plus adaptions here.

  1. Let result be a new PermissionDescriptor.

  2. Fill in result, by including the powerful feature names contained in element’s [[Features]].

  3. Return result.

3.2.3. Presentation

There isn’t much precedence for describing the user agent UI in detail. It may be better to leave more freedom to user agents.

An element using the PermissionsMixin contains browser-chosen content, text and maybe an icon. Activating them will often prompt the user to choose. This provides two bits of user interface that a user can interact with. The user agent is largely free to determine these — rendering of the element and the subsequent permission prompt — in whichever way it thinks best convey’s the element’s intent.

UI options for the elements' presentation include:

User agents are encouraged to name or describe the powerful features in a way that’s consistent with similar usage in program or the platform it is running on.

Very non-normative examples might be:

3.3. Falling Back

A user agent that does not support a particular element would recognize them as HTMLUnknownElement and render their children as regular HTML. User agents that support such an element should usually render the element as described in § 3.4 Styling, and Styling Restrictions, but are still required to render the fallback content under one condition:

If the internal [[BlockerList]] contains a record whose blocker reason is type_invalid, then the element should render the fallback content instead of its usual rendering.

3.4. Styling, and Styling Restrictions

Permission elements constrain the styling that can be applied to them. These constraints come in three flavours:

  1. If the condition isn’t met, the element is deactivated.

  2. A user-agent defined stylesheet enforces certain styling.

  3. The user-agent enforces bounds on additional styles, where the bounds cannot be easily expressed in CSS. For example, if the style bounds are expressed relative to the computed style of the element.

3.4.1. Conditions that Deactivate the Element

If one of these conditions is not met, then a temporary blocker is added with type style_invalid.

'color', 'background-color' Set by default to the user agent’s default button colors. The contrast ratio between the 2 colors needs to be at least 3. Alpha has to be 1.
'font-size' If specified value is expressed as <relative-size>:

Define "alpha".

3.4.2. User-Agent Defined Stylesheet

A permission element is expected to render with the following styles:

@namespace "http://www.w3.org/1999/xhtml";
geolocation {
  opacity: 1.0;
  line-height: normal !important;
  whitespace: nowrap !important;
  user-select: none !important;
  appearance: auto !important;
  box-sizing: content-box !important;
  vertical-align: middle !important;
  text-emphasis: initial !important;
  text-shadow: initial !important;
}

3.4.3. Additional User-Agent Defined Style Bounds

Permission elements define several bounds on styles. For example, we want the font size are constraints on the The style bounds are explained below.

For notational convenience, we imagine that the computed value of an element could be accessed in CSS rules with computed, just like the inherited value of an element can via the inherit keyword. Then the following sheet expresses the style bounds:

@namespace "http://www.w3.org/1999/xhtml";
geolocation {
  outline-offset: clamp(0, computed, none); /* No negative outline-offsets. */
  font-weight: clamp(200, computed, none);  /* No font-weights below 200. */
  word-spacing: clamp(0, computed, 0.5em);  /* Word-spacing between 0..0.5em */
  letter-spacing: clamp(-0.05em, commputed, 0.2em);  /* Letter spacing between -0.05..0.2em */

  min-height: clamp(1em, computed, none);
  max-height: clamp(none, computed, 3em);
  min-width: clamp(none, computed, calc(fit-content));

  border-width: clamp(none, computed, 1em);

  font-style: if(computed = "normal" or computed = "italic", computed, "normal");
  display: if (computed = "inline-block" or computed = "none", computed, "inline-block");
  cursor: if (computed = "pointer" or computed = "not-allowed", computed, "pointer")
}

Additionally, some rules apply based on conditions not easily expressible as CSS.

If height is auto, then apply:

@namespace "http://www.w3.org/1999/xhtml";
geolocation {
  padding-top: clamp(1em, computed, none);
  padding-bottom: calc(padding-top);
}

If width is auto, then apply:

@namespace "http://www.w3.org/1999/xhtml";
geolocation {
  padding-left: clamp(none, computed, 5em);
  padding-right: calc(padding-left);
}

Apply the following sheet, if the element does not have all of the following:

@namespace "http://www.w3.org/1999/xhtml";
geolocation {
  max-width: clamp(none, computed, calc(3 * fit-content));
}

The following CSS properties can be used normally:

Properties that are not listed above, or in the rules in this section, and aren’t logically equivalent to one of the properties mentioned here, will be ignored.

4. Security & Privacy Considerations

Note: Security & Privacy Considerations can be found here & there, in the Explainer. This section will eventually contain a specification-worthy transcription of those Explainer sections.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[COMPOSITING-2]
Compositing and Blending Level 2. Editor's Draft. URL: https://drafts.fxtf.org/compositing-2/
[CSS-ALIGN-3]
Elika Etemad; Tab Atkins Jr.. CSS Box Alignment Module Level 3. URL: https://drafts.csswg.org/css-align/
[CSS-ANCHOR-POSITION-1]
Tab Atkins Jr.; Elika Etemad; Ian Kilpatrick. CSS Anchor Positioning Module Level 1. URL: https://drafts.csswg.org/css-anchor-position-1/
[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. URL: https://drafts.csswg.org/css-backgrounds/
[CSS-BORDERS-4]
Elika Etemad; et al. CSS Borders and Box Decorations Module Level 4. URL: https://drafts.csswg.org/css-borders-4/
[CSS-BREAK-3]
Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 3. URL: https://drafts.csswg.org/css-break/
[CSS-COLOR-ADJUST-1]
Elika Etemad; et al. CSS Color Adjustment Module Level 1. URL: https://drafts.csswg.org/css-color-adjust-1/
[CSS-CONDITIONAL-5]
Chris Lilley; et al. CSS Conditional Rules Module Level 5. URL: https://drafts.csswg.org/css-conditional-5/
[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 4. URL: https://drafts.csswg.org/css-display-4/
[CSS-FLEXBOX-1]
Elika Etemad; Tab Atkins Jr.; Rossen Atanassov. CSS Flexible Box Layout Module Level 1. URL: https://drafts.csswg.org/css-flexbox/
[CSS-FONTS-4]
Chris Lilley. CSS Fonts Module Level 4. URL: https://drafts.csswg.org/css-fonts-4/
[CSS-LISTS-3]
Elika Etemad; Tab Atkins Jr.. CSS Lists and Counters Module Level 3. URL: https://drafts.csswg.org/css-lists-3/
[CSS-OVERSCROLL-1]
Majid Valipour. CSS Overscroll Behavior Module Level 1. URL: https://drafts.csswg.org/css-overscroll-1/
[CSS-PAGE-3]
Elika Etemad. CSS Paged Media Module Level 3. URL: https://drafts.csswg.org/css-page-3/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.. CSS Positioned Layout Module Level 3. URL: https://drafts.csswg.org/css-position-3/
[CSS-RUBY-1]
Elika Etemad; et al. CSS Ruby Annotation Layout Module Level 1. URL: https://drafts.csswg.org/css-ruby-1/
[CSS-SCROLL-ANCHORING-1]
Tab Atkins Jr.. CSS Scroll Anchoring Module Level 1. URL: https://drafts.csswg.org/css-scroll-anchoring/
[CSS-SCROLL-SNAP-1]
Matt Rakow; et al. CSS Scroll Snap Module Level 1. URL: https://drafts.csswg.org/css-scroll-snap-1/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad. CSS Box Sizing Module Level 3. URL: https://drafts.csswg.org/css-sizing-3/
[CSS-SIZING-4]
Tab Atkins Jr.; Elika Etemad; Jen Simmons. CSS Box Sizing Module Level 4. URL: https://drafts.csswg.org/css-sizing-4/
[CSS-TEXT-4]
Elika Etemad; et al. CSS Text Module Level 4. URL: https://drafts.csswg.org/css-text-4/
[CSS-UI-4]
Florian Rivoal. CSS Basic User Interface Module Level 4. URL: https://drafts.csswg.org/css-ui-4/
[CSS-WILL-CHANGE-1]
Tab Atkins Jr.. CSS Will Change Module Level 1. URL: https://drafts.csswg.org/css-will-change/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. URL: https://drafts.csswg.org/css2/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[FENCED-FRAME]
Fenced Frame. Draft Community Group Report. URL: https://wicg.github.io/fenced-frame/
[GEOLOCATION]
Marcos Caceres; Reilly Grant. Geolocation. URL: https://w3c.github.io/geolocation/
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. Geometry Interfaces Module Level 1. URL: https://drafts.csswg.org/geometry/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[INTERSECTION-OBSERVER]
Stefan Zager; Emilio Cobos Álvarez; Traian Captan. Intersection Observer. URL: https://w3c.github.io/IntersectionObserver/
[MANIFEST-APP-INFO]
Aaron Gustafson. Web App Manifest - Application Information. URL: https://w3c.github.io/manifest-app-info/
[MEDIAQUERIES-5]
Dean Jackson; et al. Media Queries Level 5. URL: https://drafts.csswg.org/mediaqueries-5/
[Permissions]
Marcos Caceres; Mike Taylor. Permissions. URL: https://w3c.github.io/permissions/
[SVG2]
Amelia Bellamy-Royds; et al. Scalable Vector Graphics (SVG) 2. URL: https://svgwg.org/svg2-draft/
[WAI-ARIA-1.2]
Joanmarie Diggs; et al. Accessible Rich Internet Applications (WAI-ARIA) 1.2. URL: https://w3c.github.io/aria/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

Informative References

[WAI-ARIA]
James Craig; Michael Cooper; et al. Accessible Rich Internet Applications (WAI-ARIA) 1.0. 20 March 2014. REC. URL: https://www.w3.org/TR/wai-aria/

IDL Index

[Exposed=Window]
interface HTMLGeolocationElement : HTMLElement {
  [HTMLConstructor] constructor();

  readonly attribute GeolocationPosition? position;
  readonly attribute GeolocationPositionError? error;
  [CEReactions, Reflect] attribute boolean autolocate;
  [CEReactions, Reflect] attribute boolean watch;

  attribute EventHandler onlocation;
};
HTMLGeolocationElement includes ActivationBlockersMixin;
HTMLGeolocationElement includes PermissionsMixin;

interface mixin ActivationBlockersMixin {
  readonly attribute boolean isValid;
  readonly attribute ActivationBlockersMixinBlockerReason invalidReason;
  attribute EventHandler onvalidationstatuschange;
};

enum ActivationBlockersMixinBlockerReason {
  "",   // No blocker reason.
  "illegal_subframe", "unsuccesful_registration",
  "recently_attached", "intersection_changed",
  "intersection_out_of_viewport_or_clipped",
  "intersection_occluded_or_distorted", "style_invalid",
  "type_invalid",
};

interface mixin PermissionsMixin {
  readonly attribute PermissionState initialPermissionStatus;
  readonly attribute PermissionState permissionStatus;
  attribute EventHandler onpromptaction;
  attribute EventHandler onpromptdismiss;
};

Issues Index

[WAI-ARIA] specifies roles for in-page content. It is yet unclear whether or how the geolocation element fits into the existing set of roles. Given that this element triggers permission requests, one could argue that whatever accessibility concerns apply there should cover this element as well. On the other hand, more specialized treatment may lead to better support for users.
In § 3.4 Styling, and Styling Restrictions, this specification defines elaborate restrictions on how geolocation elements can be rendered. It’s unclear whether there need to be similarly spirited restrictions on which ARIA attributes can be applied.
The [Permissions] spec assumes that request permission to use will always succeed. That is, it assumes that the user will always make a choice and that the algorithm will always deliver a grant/deny answer corresponding to that choice. But you can’t force a user to do that. Some user agents may have different UI affordances for an explicit denial (e.g. a "deny" button) on one hand, and cancelling or dismissing the request dialog (e.g. an "X" button in the top right corner). Here, we distinguish between these two actions, despite no clear hook for this in the underlying specification.
Do I need to define dictionary equality?
It’s not clear what the PermissionState for 'no valid permission type' should be. Here I pick "prompt" based on Chrome’s implementation; but that choice is arbitrary.
The [Permissions] specification assumes a descriptor describes a single permission without parameters (like an equivalent of enableHighAccuracy). Here, we assume a permissions model that is more expressive. This needs to be resolved -- likely upstream, in [Permissions], plus adaptions here.
There isn’t much precedence for describing the user agent UI in detail. It may be better to leave more freedom to user agents.
Define "alpha".