1. Introduction
User agents expose powerful features to web sites, which are features that are important to some use cases, but can be easily abused. The arguably canonical example of such a powerful feature is camera access, which is essential to many use cases like online meetups, but unsolicited camera activation would be a major privacy issue. 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 access to powerful features through an in-page element, with built-in protections against abuse. This wants to tie permission requests to the actual context in which they will be used, thus reducing "permission spam" and at the same time providing implementations with a better signal of user intent.
2.
The
permission
element.
- Categories :
-
Flow
content
.
- Phrasing content .
- Interactive content .
- Palpable content .
- Phrasing content .
- Contexts in which this element can be used :
- Where phrasing content is expected.
- Content model :
- flow content .
- Content attributes :
-
Global
attributes
type
— Type of permission this element applies to.preciseLocation
— Whether access to the "geolocation" powerful feature is requested withenableHighAccuracy
.isValid
— query whether the element can currently be activated.invalidReason
— Return a string representation of why the element currently cannot be activated.onpromptdismiss
— notifies when the user has dismissed the permission prompt.onpromptaction
— notifies when a permission prompt has been answered by the user (positively or negatively).onvalidationstatuschange
— notifies when the validation status changes. - Accessibility considerations :
- DOM interface :
-
[
Exposed =Window ]interface
:HTMLPermissionElement HTMLElement { [HTMLConstructor ]
(); [constructor CEReactions ,Reflect ]attribute DOMString
; [type CEReactions ,Reflect ]attribute boolean
;preciseLocation ;readonly attribute boolean isValid ;readonly attribute PermissionElementBlockerReason invalidReason ;readonly attribute PermissionState initialPermissionStatus ;readonly attribute PermissionState permissionStatus ;);static boolean
(isTypeSupported DOMString
);type attribute EventHandler
;onpromptaction attribute EventHandler
;onpromptdismiss attribute EventHandler
; };onvalidationstatuschange
Add accessibility considerations.
Check attribute & event handler & invalid reason names against current proposal(s).
The
permission
element’s
content,
if
any,
are
its
fallback
content
.
The
type
attribute
controls
the
behavior
of
the
permission
element
when
it
is
activated.
Is
is
an
enumerated
attribute
,
whose
values
are
the
names
of
powerful
features
.
It
has
neither
a
missing
value
default
state
nor
a
invalid
value
default
state.
The
preciseLocation
attribute
reflects
whether
the
"geolocation"
permission
is
meant
for
location
requests
with
enableHighAccuracy
.
The
isValid
attribute
reflects
whether
a
the
permission
element
is
not
currently
blocked.
The
invalidReason
attribute
is
an
enumerated
attribute
that
reflects
the
internal
state
of
the
permission
element.
It’s
value
set
are
PermissionElementBlockerReason
The
isTypeSupported
static
operation
whether
a
gives
type
,
that
is,
a
given
enumeration
of
powerful
features
,
is
supported.
It
predicts
whether
creating
a
permission
element
and
assigning
the
given
type
string
will
work,
or
whether
it
will
create
an
element
blocked
by
a
type_invalid
permanent
blocker
.
The
global
lang
attribute
is
observed
by
the
permission
element
to
select
localized
text.
The
default
value
for
the
global
tabindex
content
attribute
on
the
permission
element
is
0.
The
following
are
the
event
handlers
(and
their
corresponding
event
handler
event
types
)
that
must
be
supported
on
permission
elements
event
handler
IDL
attributes
:
onpromptaction | Event |
---|---|
onpromptdismiss | Event |
onvalidationstatuschange | Event |
onvalidationstatuschange is probably not a simple Event.
2.1.
permission
element
internal
state
The
permission
element
represents
a
user-requestable
permission
,
which
the
user
can
activate
to
enable
(or
disable)
a
particular
permission
or
set
of
permissions.
It
is
core
to
the
permission
element
that
these
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.
The
permission
element
has
the
following
internal
slots:
-
The
[[BlockerList]]
is a list of records, containing a blocker timestamp and a blocker reason . The blocker reason is aPermissionElementBlockerReason
, but not the empty string. -
[[IntersectionObserver]]
is a reference to anIntersectionObserver
. -
[[Types]]
is null or an ordered set of powerful features . Null represents the uninitialized state, which allows the value to be modified. The empty list «[]» is the state in which no permission applies, and which will no longer allow modification. Note that thetype
property reflects this internal state. -
[[IntersectionRect]]
is aDOMRectReadOnly
that stores the most recently seen intersection, i.e. the position of thepermission
relative to the viewport . -
[[LastNotifiedValidState]]
is a boolean that stores the most recently notified state ofisValid
. -
[[LastNotifiedInvalidReason]]
is a string that stores the most recently notified state ofinvalidReason
.[[LastNotifiedValidState]]
and[[LastNotifiedInvalidReason]]
are used to determine whether anonvalidationstatuschange
event needs to be dispatches. -
[[InitialPermissionStatus]]
is aPermissionState
that stores the initialPermissionState
for[[Types]]
.
2.2.
permission
-supporting
state
at
the
navigable
In
order
to
support
the
permission
element,
the
navigable
maintains
an
ordered
set
of
permission
elements,
[[PermissionElements]]
.
This
ordered
set
is
used
to
evaluate
the
blockers
of
type
unsuccesful_registration
.
2.3.
permission
element
interesting
behaviours
The
permission
element
has
a
few
surprising
behaviours,
to
support
its
security
properties:
2.3.1.
The
type
property
The
permission
type
cannot
be
modified.
Modifying
the
permission
type
at
will
may
lead
to
user
confusion,
and
hence
we’d
like
to
prevent
it.
Since,
however,
a
page
may
create
a
permission
element
dynamically
we
still
need
to
offer
an
API
to
modify
it.
To
do
do,
we
distinguish
between
a
freshly
initialized
and
an
empty
or
invalid
(no
permission)
state,
where
the
former
allows
setting
the
type
and
the
latter
does
not.
Example:
// Changing a valid type: var pepc= document. createElement( "permission" ); pepc. type= "camera" ; // Okay. pepc. type; // "camera". pepc. type= "geolocation" ; // Not okay. Would have been okay as initial assignment. pepc. type; // "camera". Reflects the internal state, which has not changed. // Setting an invalid type: pepc= document. createElement( "permission" ); pepc. type= "icecream" ; // Ice cream is not a powerful browser feature. Not okay. pepc. type; // "". Reflects the internal state. pepc. type= "camera" ; // Still Not okay, because type as already been set. // Would have been okay as initial assignment. pepc. type; // "". Reflects the internal state, which has not changed.
type
getter
steps
are:
-
If
[[Types]]
is null: Return""
. -
Return a string, containing the concatenation of all powerful feature names in
[[Types]]
, seperated by " ".
type
setter
steps
are:
-
If
[[Types]]
is not null: Return. -
Set
[[Types]]
to «[]». -
Let features be the result of calling parse a type string with the input string.
-
If features is None, return.
-
Append each powerful feature name to the
[[Types]]
ordered set . -
Set
[[InitialPermissionStatus]]
to the result of get the current permission state .
Note: The supported sets of powerful features is implementation-defined .
To query whether a feature (or group of features) is supported:
isTypeSupported()
method
steps
with
argument
with
DOMString
type
are:
-
Let features be the result of calling parse a type string with type .
-
Return whether features is not None.
-
Let list be the result of parsing type as a string of powerful feature names, seperated by whitespace.
-
If any errors occured, return None.
-
Check if the set of powerful features is supported for the
HTMLPermissionElement
by the user agent . If not, return None. -
Return list .
2.3.2. Activation blockers
The
key
goal
of
the
permission
element
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,
the
permission
maintains
a
list
of
blocker
reasons,
which
may
-
permanently
or
temporarily
-
prevent
the
element
from
being
activated.
enum {
PermissionElementBlockerReason , // No blocker reason.
"" ,
"type_invalid" ,
"illegal_subframe" ,
"unsuccesful_registration" ,
"recently_attached" ,
"intersection_changed" ,
"intersection_out_of_viewport_or_clipped" ,
"intersection_occluded_or_distorted" };
"style_invalid"
The permission element keeps track of "blockers", reasons why the element (currently) cannot be activated. 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 a
permission
element inside afencedframe
. - Temporary blocker
-
This is a blocker that will only be valid until the blocking condition no no longer occurs. An example is a
permission
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 a
permission
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
permission
element
is
used
inside
a
fencedframe
.
| 2 |
unsuccesful_registration
| temporary |
When
too
many
other
permission
elements
for
the
same
powerful
feature
have
been
inserted
into
the
same
document.
| 3 |
recently_attached
| expiring |
When
the
permission
element
has
just
been
attached
to
the
DOM.
| 4 |
intersection_changed
| expiring |
When
the
permission
element
is
being
moved.
| 6 |
intersection_out_of_viewport_or_clipped
| temporary |
When
the
permission
element
is
not
or
not
fully
in
the
viewport
.
| 7 |
intersection_occluded_or_distorted
| temporary |
When
the
permission
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 |
PermissionElementBlockerReason
reason
and
an
optional
flag
expires
:
-
Assert : reason is not
""
. (The empty string inPermissionElementBlockerReason
signals no blocker is present. Why would you add a non-blocking blockern empty string?) -
Let timestamp be None.
-
If expires , then let timestamp be current high resolution time plus the blocker delay .
-
Append an entry to the internal
[[BlockerList]]
with reason and timestamp .
PermissionElementBlockerReason
reason
:
-
Assert : reason is listed as "expiring" in the blocker reason table .
-
Add a blocker with reason and true.
PermissionElementBlockerReason
reason
:
-
Assert : reason is listed as "temporary" in the blocker reason table .
-
Add a blocker with reason and false.
PermissionElementBlockerReason
reason
:
-
Assert : reason is listed as "permanent" in the blocker reason table .
-
Add a blocker with reason and false.
PermissionElementBlockerReason
reason
from
an
element
:
-
Assert : reason is listed as "temporary" in the blocker reason table .
-
For each entry in element ’s
[[BlockerList]]
:-
If entry ’s reason equals reason , then remove entry from element ’s
[[BlockerList]]
.
-
-
Add a blocker with reason and true.
HTMLPermissionElement
element
’s
blocker
:
-
Let blockers be the result of sorting element ’s
[[BlockerList]]
with the blocker ordering algorithm. -
If blockers is not empty and blockers [0] is blocking , then return blockers [0].
-
Return nothing.
-
Let really large number be 99.
-
Assert : No order hint in the blocker reason table is equal to or greater than really large number .
-
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 .
-
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 .
-
Return whether a hint is less than or equal to b hint .
HTMLPermissionElement
’s
blocker
list’s
entry
is
blocking
if:
-
entry has no blocker timestamp ,
-
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.
2.4.
permission
element
algorithms
HTMLPermissionElement
constructor
steps
are:
-
Initialize the internal
[[Types]]
slot to null. -
Initialize the internal
[[BlockerList]]
to «[]». -
Initialize the internal
[[LastNotifiedValidState]]
with false. -
Initialize the internal
[[LastNotifiedInvalidReason]]
with the empty string. -
Initialize the internal
[[InitialPermissionStatus]]
to the result of get the current permission state .
HTMLPermissionElement
insertion
steps
are:
-
Initialize the internal
[[BlockerList]]
to «[]». -
Initialize the internal
[[IntersectionRect]]
with undefined. -
Initialize the internal
[[IntersectionObserver]]
with the result of constructing a newIntersectionObserver
, with IntersectionObserver callback . -
Call
[[IntersectionObserver]]
.observe( this ). -
If
[[Types]]
is empty , then add a permanent blocker with reasontype_invalid
. -
If this is not type permissible , then add a temporary blocker with
unsuccesful_registration
. -
Add an expiring blocker with reason
recently_attached
. -
If the traversable navigable of the node navigable of this is a fenced navigable , then add a permanent blocker with
illegal_subframe
.
HTMLPermissionElement
removing
steps
are:
-
Remove this from node navigable ’s
[[PermissionElements]]
.
isValid
getter
steps
are:
-
Return whether element ’s blocker is Nothing.
invalidReason
getter
steps
are:
initialPermissionStatus
getter
steps
are:
-
Return element ’s internal
[[InitialPermissionStatus]]
.
permissionStatus
getter
steps
are:
-
Return get the current permission state for element .
permission
element
’s
activation
behavior
given
event
is:
-
If event .
isTrusted
is false, then return. -
If element .
isValid
is false, then return. -
Let descriptor be the result of build a permission descriptor for element .
Request permission to use the powerful features
named indescribed byelement ’s [[Types]] .descriptor .-
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.
HTMLPermissionElement
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.
Let result be a new
PermissionDescriptor
.Fill in result :
Include the powerful feature names contained in element ’s
[[Types]]
.If element ’s
[[Types]]
contains"geolocation"
andpreciseLocation
is true, then result applies to position requests withenableHighAccuracy
set to true.
Return result .
IntersectionObserverCallback
and
runs
the
following
steps:
-
Assert : The
IntersectionObserver
’sroot
is the document -
Let entries be the value of the first callback parameter, the list of
intersection observer entries
. -
Let entry be entries ’s last item .
-
If entry .
isVisible
, then: -
Otherwise:
-
If entry .
intersectionRatio
>= 1, then:-
Let reason be
intersection_occluded_or_distorted
.
-
-
Otherwise:
-
Let reason be
intersection_out_of_viewport_or_clipped
.
-
-
Add a temporary blocker with reason .
-
-
If
[[IntersectionRect]]
does not equal entry .intersectionRect
then add an expiring blocker withintersection_changed
. -
Set
[[IntersectionRect]]
to entry .intersectionRect
-
Assert : element ’s node navigable ’s
[[PermissionElements]]
contains element . -
Let count be 0.
-
For each current in element ’s node navigable ’s
[[PermissionElements]]
: -
Return whether count is less than 3.
-
For each current in document ’s
[[PermissionElements]]
:-
If current is type permissible , then remove blockers with
unsuccesful_registration
from current .
-
HTMLPermissionElement
element
:
-
Let types be element ’s internal
[[Types]]
. -
Let current be
granted
. -
For each type of types :
-
Let state be the result of get the current permission state for type .
-
Let current be the smaller of current and state , assuming the following ordering:
granted
>prompt
>denied
.
-
-
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.
2.5.
permission
element
event
algorithms
-
Let oldState be
[[LastNotifiedValidState]]
. -
Let newState be whether element ’s blocker is Nothing.
-
Set
[[LastNotifiedValidState]]
to newState . -
Let oldReason be
[[LastNotifiedInvalidReason]]
. -
Let newReason be whether element ’s
invalidReason
. -
Set
[[LastNotifiedInvalidReason]]
to newReason . -
If oldState != newState or oldReason != newReason , then:
-
Let event be a new
Event
. -
Initialize event with type "
onvalidationstatuschange
", bubbles true, and cancelable true. -
Dispatch event to element .
-
-
Let event be a new
Event
. -
Initialize event with type "
onpromptaction
", bubbles true, and cancelable true. -
Dispatch event to element .
-
Let event be a new
Event
. -
Initialize event with type "
onpromptdismiss
", bubbles true, and cancelable true. -
Dispatch event to element .
3.
Rendering
the
permission
Element
The
permission
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
the
powerful
features
listed
in
[[Types]]
,
expressed
as
text
and
icons.
The
page
can
influence
the
permission
element’s
styling,
but
with
constraints
to
prevent
abuse
(e.g.
minimum
and
maximum
sizes
for
fonts
and
the
label
itself).
The
page
can
also
select
a
locale
for
the
text
via
the
lang
attribute.
The
permission
element
supports
fallback
content
,
which
will
be
displayed
by
any
browser
not
yet
supporting
permission
.
Note
that
there
are
also
conditions
under
which
a
browser
that
supports
permission
falls
back
to
its
fallback
content
.
3.1. 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.
The
permission
element
contains
browser-chosen
content,
text
and
maybe
an
icon.
Activating
it
will
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
permission
element
and
the
subsequent
permission
prompt
—
in
whichever
way
it
thinks
best
convey’s
the
element’s
intent.
UI
options
for
the
permission
element’s
presentation
include:
-
Name the powerful features listed in
[[Types]]
, in the language indicated by the language of the element. Note that this would always be the language indicated by thelang
attribute, if present. -
An icon indicating the powerful feature type or types.
-
The current permission state of the powerful feature in questions. For example, if the permission is already
granted
, thepermission
element might be labeled as "geolocation already in use". -
A modal prompt with a "scrim". (I.e., darkening out the page behind the prompt.) This would normally quite disruptive. But here our goal is to ensure a user means to make this choice.
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:
-
<permission lang="de" types="geolocation">
: "Standort verwenden". -
<permission types="microphone">
(in an English language page): "Use microphone. 🎤". -
Upon activiating
<permission types="microphone">
, when the corresponding permission state isdenied
, modify the text to "Continue blocking".
3.2. Styling
A
permission
element
constrains
the
styling
that
can
be
applied
to
it.
These
constraints
come
in
three
flavours:
-
If the condition isn’t met, the
permission
element in deactivated. -
A user-agent defined stylesheet enforces certain styling.
-
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.2.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>
:
|
3.2.2. User-Agent Defined Stylesheet
A
permission
element
is
expected
to
render
with
the
following
styles:
@namespace "http://www.w3.org/1999/xhtml" ; permission{ opacity : 1.0 ; line-height : normal; whitespace : nowrap; user-select : none; appearance : auto; box-sizing : content-box !important; }
3.2.3. Additional User-Agent Defined Style Bounds
A
permission
element
defines
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" ; permission{ 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.5 em ); /* Word-spacing between 0..0.5em */ letter-spacing:clamp ( -0.05 em , commputed, 0.2 em ); /* Letter spacing between -0.05..0.2em */ min-height:clamp ( 1 em , computed, none); max-height : clamp ( none, computed, 3 em ); min-width : clamp ( none, computed, calc ( fit-content)); border-width : clamp ( none, computed, 1 em ); margin : clamp ( 4 px , computed, none); 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" ; permission{ padding-top : clamp ( 1 em , computed, none); padding-bottom : calc ( padding-top); }
If
width
is
auto
,
then
apply:
@namespace "http://www.w3.org/1999/xhtml" ; permission{ padding-left : clamp ( none, computed, 5 em ); padding-right : calc ( padding-left); }
Apply the following sheet, if the element does not have all of the following:
-
A border width of at least
1px
, -
a color to background-color contrast ratio of at least 3,
-
and alpha of 1.
@namespace "http://www.w3.org/1999/xhtml" ; permission{ max-width : clamp ( none, computed, calc ( 3 * fit-content)); }
The following CSS properties can be used normally:
-
border and all border shorthand properties , border-top , border-right , border-bottom , border-left
-
flex and its longhands, flex-grow , flex-shrink , flex-basis
-
outline and mostly its longhands , outline-color and outline-style .
Note that outline-offset is clamped by the rules above. -
overscroll-behavior and its longhands , overscroll-behavior-inline , overscroll-behavior-block , overscroll-behavior-x , overscroll-behavior-y
-
scroll-margin and its longhands , scroll-margin-top , scroll-margin-right , scroll-margin bottom', scroll-margin-left
-
scroll-padding and its longhands , scroll-padding-top , scroll-padding-right , scroll-padding-bottom , scroll-padding-left , scroll-padding-inline-start , scroll-padding-block-start , scroll-padding-block-start , scroll-padding-inline-end , scroll-padding-block-end
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.
3.3. Falling Back
A
user
agent
that
does
not
support
permission
elements
would
recognize
them
as
HTMLUnknownElement
and
render
their
children
as
regular
HTML.
User
agents
that
support
permission
elements
should
usually
render
the
element
as
described
in
§ 3
Rendering
the
permission
Element
,
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
permission
element
should
render
the
fallback
content
instead
of
the
permission
’s
usual
rendering.
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.