Gecko:FullScreenAPI

From MozillaWiki
Jump to: navigation, search

Requirements

  • Scripts should be able to initiate and terminate full-screen
    • Allows custom, in-page, discoverable UI to active full-screen
  • Arbitrary Web content should be visible full-screen
    • <video>, <canvas>, multicolumn text, etc
    • Required for scripted video controls
  • Entering and exiting full-screen must trigger events
    • To allow scripted changes to content, e.g. resizing of canvas content
  • Scripts should be able to opt in to having alphanumeric keyboard input disabled during full-screen
    • Enables less restrictive anti-spoofing measures
  • Actual full-screen transitions must be allowed to be asynchronous and entirely at the discretion of the UA
    • To enable passive notification/confirmation UI
    • To enable a wide range of security measures to prevent spoofing or other abuse
  • Making a single element full-screen should be as simple as possible
  • Content in IFRAMEs should be able go full-screen
    • To enable "widgets" such as embedded videos to offer full-screen UI

cpearce: Scripts should be able to determine whether full-screen requests are likely to be granted from the current frame (so that video players in an embedded iframe know whether they should show a full-screen button in their UI).

Proposed Specification

A Document can be in the "full-screen state". What exactly this means is up to the UA, but typically it means that the Document covers most or all of the screen and some or all of the normal UA UI is not visible.

It is possible for non-toplevel browsing contexts to have their Document in the full-screen state. The parent browsing context of a browsing context with its Document in the full-screen state must also have its Document in the full-screen state.

The user agent may transition a Document into or out of the full-screen state at any time, whether or not script has requested it. User agents are encouraged to provide standard UI to exit the full-screen state, for example if the user presses the Escape key.

Toplevel browsing contexts can be in a "keys disabled" state. In this state, the user agent must suppress all keyup, keydown and keypress events whose keyCode is not in one of the following ranges:

  • DOM_VK_CANCEL to DOM_VK_CAPS_LOCK, inclusive
  • DOM_VK_SPACE to DOM_VK_DELETE, inclusive
  • DOM_VK_SEMICOLON to DOM_VK_EQUALS, inclusive
  • DOM_VK_MULTIPLY to DOM_VK_META, inclusive

Such events are not dispatched to any nodes in any document of the toplevel browsing context or descendant browsing contexts. This includes suppression of any internal key event processing that would insert text into form controls or editable content. The user agent might respond to such events by leaving full-screen mode (disputed, may be better to stay in full-screen mode and instead put up the in-fullscreen warning, "press esc to exit" etc.).

Keypress whitelist:

  • tab, space, arrow keys, page-up, page-down, home, end
  • shift, ctrl, alt/option, command
    • and combinations thereof, with the previous set of keys (except command/ctrl-tab)

Each document has an optional "current full-screen element".

Document additions

cancelFullScreen method

New method of Document:

  • void cancelFullScreen()

Requests that the UA exit full-screen mode. The UA is not required to honor this, for example the UA might require that only a Document that last triggered full-screen can cancel it.

The current full-screen element for the document is cleared.

fullScreen attribute

New DOM attribute of Document:

  • readonly attribute boolean fullScreen

Returns true while the document is in the full-screen state.

fullScreenKeyboardInputAllowed attribute

New DOM attribute of Document:

  • readonly attribute boolean fullScreenKeyboardInputAllowed

Returns true while the window's toplevel browsing context is full-screen and not in a "keys disabled" state.

fullScreenEnabled attribute

New DOM attribute of Document:

  • readonly attribute boolean fullScreenEnabled

Returns true if requests for full-screen in the current document are likely to not be denied because of security or UA constraints. Typically this means all containing frames have the allowfullscreen attribute present.

Element additions

New methods of Element:

requestFullScreenWithKeys method

  • void requestFullScreenWithKeys()

The current full-screen element for the document is set to this element.

Typically the user agent would react by transitioning the Document to the full-screen state, or by presenting asynchronous confirmation UI and transitioning to the full-screen state if/when the user responds affirmatively. However, the user agent is not required to do anything at all in response to requestFullScreen. The user agent's behavior is allowed to vary depending on whether requestFullScreen is called during a user event (e.g. a mouse click handler).

requestFullScreen method

  • void requestFullScreen()

As requestFullScreenWithKeys, but hints to the UA that while in full-screen state, the toplevel browsing context for this Document should have keys disabled. While keys are disabled, there may be a reduced risk of spoofing attacks inducing the user to input inappropriate data, and the UA may choose to relax restrictions on entering full-screen state with keys disabled.

cpearce: We are planning on dispatching a "fullscreendenied" event when requests for full-screen are denied. We changed to an "ask forgiveness" model, rather than an "ask permission" model, so requests can be approved/denied immediately in requestFullScreen(). UAs which choose to implement requestFullScreen with an "ask permission" model may never end up sending a "fullscreendenied" event however.

fullscreenchange event

New events:

  • fullscreenchange

When a Document enters or leaves the full-screen state, the user agent must queue a task to dispatch this event. When the event is dispatched, if the document's current full-screen element is an element in the document, then the event target is that element, otherwise the event target is the document. The event bubbles and is not cancellable.

onfullscreenchange attribute

The 'onfullscreenchange' event handling attribute is supported on HTML elements.

iframe allowfullscreen attribute

New content attribute of the <iframe> element:

  • allowfullscreen

This is a boolean attribute. When this attribute is not set, UAs must ignore full-screen requests in the iframe or its descendant frames.

CSS additions

full-screen pseudo-class

New CSS pseudo-class:

  •  :full-screen

While a Document is in the full-screen state, and the document's current full-screen element is an element in the document, the 'full-screen' pseudoclass applies to that element. Also, an <iframe>, <object> or <embed> element whose child browsing context's Document is in the full-screen state has the 'full-screen' pseudoclass applied.

full-screen-ancestor pseudo-class

New CSS pseudo-class:

  •  :full-screen-ancestor

While a Document is in the full-screen state, and the document's current full-screen element is an element in the document, the 'full-screen-ancestor' pseudoclass applies to ancestors of the full-screen element.

view-mode

http://www.w3.org/TR/view-mode/ introduces a "view-mode" media feature with possible value "fullscreen". That should be implemented alongside the rest of this specification.

UA stylesheet rules

Suggested UA stylesheet rules:

/* A full-screen element that is not the root element should be stretched
   to cover the viewport. */
:full-screen:not(:root) {
  position:fixed;
  top:0;
  left:0;
  right:0;
  bottom:0;
  z-index:2147483647;
  background:black;
  /* override mapped width and height attributes */
  width:100% !important;
  height:100% !important;
}
/* If there is a full-screen element that is not the root then
   we should hide the viewport scrollbar. */
:root:full-screen-ancestor {
  overflow:hidden;
}
:full-screen-ancestor {
  /* Ancestors of a full-screen element should not induce stacking contexts
     that would prevent the full-screen element from being on top. */
  z-index:auto;
  /* Ancestors of a full-screen element should not be partially transparent,
     since that would apply to the full-screen element and make the page visible
     behind it. It would also create a pseudo-stacking-context that would let content
     draw on top of the full-screen element. */
  opacity:1;
  /* Ancestors of a full-screen element should not apply SVG masking, clipping, or
     filtering, since that would affect the full-screen element and create a pseudo-
     stacking context. */
  mask:none;
  clip:auto;
  filter:none;
}

For these to be effective, we really want their to be higher precedence than non-important author rules. So we need to add a new precedence level for UA style rules that's between "author" and "author important". Gecko already supports this via "override styles sheets" (nsIPresShell::AddOverrideStyleSheet), already used by the editor.

Webkit additions

New CSS pseudo-classes:

  •  :full-screen-document - While a Document is in the fullscreen state, the 'full-screen-document' pseudo-class applies to the root element of that Document.
    • note: webkit has implemented previous name for this :full-screen-doc
  •  :full-screen-root-with-target - While a Document is in the fullscreen state and the document's current fullscreen element is an element in the document, the 'full-screen-root-with-target' pseudoclass applies to the root element of that Document.

These are unnecessary given the above features. ":full-screen-document { ... }" can be written "@media all and (view-mode: fullscreen) { :root { ... } }". ":full-screen-root-with-target { ... }" can be written ":root:full-screen-ancestor, :root:full-screen { ... }".

See feedback on new pseudo-classes and follow-up from RoC (and subsequent thread)

Suggested UA Policy

The specification intentionally gives UAs great freedom in policy, because no one policy can fit all users, devices, and user interface designs. However, here is a policy that should be acceptable for conventional desktop browsers.

  • requestFullScreen while the window is already in the full-screen state is approved.
  • Otherwise, requestFullScreen outside a user action (e.g. a non-synthesized input event handler) is denied.
  • Otherwise, requestFullScreen without the ALLOW_KEYBOARD_INPUT flag is approved.
  • Otherwise, passive confirmation UI is presented and requestFullScreen is approved if and when the user approves it.

Implications

There is no requirement to exit full-screen state when a browsing context is navigated to a new page.

There is no requirement to exit full-screen state if the current full-screen element shifts to another element, or ceases to be an element in the document (e.g. because requestFullScreen was called again in the document or in some descendant document, or because the element is removed).

Nothing in this specification depends on whether the current full-screen element is visible (e.g. whether it has "display:none").

Nothing in this specification affects or depends on focus.

Examples

1. Make a video element display full-screen when clicked and leave full-screen when it ends.

<video src="pelican.webm" autoplay
       onclick="event.target.requestFullScreen()"
       onended="document.cancelFullScreen()">
</video>

2. Make a canvas element display full-screen in response to user input. Resize the canvas to the appropriate resolution while it's full-screen.

<script>
function redrawCanvas(c) { ... }
function resizeCanvas() {
  var c = document.getElementById("c");
  var rect = c.getBoundingClientRect();
  c.width = rect.width;
  c.height = rect.height;
  redrawCanvas(c);
}
</script>
<canvas id="c" onfullscreenchange="resizeCanvas()"></canvas>
<button onclick="document.getElementById('c').requestFullScreen()">
  Go Fullscreen!
</button>

3. Hide advertisements while the window is full-screen.

@media all and (full-screen:on) {
  .advertisement { display:none; }
}

Security

Discussions documented newest first.

Discussion 2011-10-03

Discussion 2011-04-21

Jesse's concerns, added 2011-04-21.

I'm worried about having a full screen mode that does not require user permission. In particular, I have three concerns:

  • It allows spoofing for the purpose of tricking the user into giving away information through mouse input.
    • Spoof your bank, asking you to enter your password or PIN with an on-screen keypad. This is actually a plausible request from a bank! In an attempt to defeat simple keyloggers, some banks require the use of an on-screen keypad. (Examples: Westpac, others)
    • On a touch-screen device, what you think is your on-screen keyboard could actually be part of the web page.
    • (This could be mitigated by replacing "full screen without keys" with "full screen with video-like controls only": any user interaction makes a scrubber and volume controls appear.) roc: this version of full-screen wouldn't address any of the use-cases for full-screen (beyond making a video full-screen with browser controls, which we already support).
  • It allows spoofing for the purpose of tricking the user to take an action later or outside of the browser.
    • Spoof your bank, saying you "Please call us to discuss possible fraud on your account". Supply an attacker-controlled phone number.
    • Spoof https://www.mozilla.org/, asking you to "download the new version of Firefox".
    • Spoof https://twitter.com/, showing tweets indicating your company has been bought by AOL.
    • Spoof https://www.facebook.com/, showing fake evidence that your wife is cheating on you.
    • Spoof the You need to restart your computer screen. Are you going to think of pressing Esc, or are you going to power-cycle? roc: there's no reason for attackers to want to do this.
    • More generally, this makes it more difficult to explain how to find out which site you're on. Instead of "look at the address bar…", instructions must start with "press Esc, then look at the address bar…".
  • Entering full-screen mode reveals the screen size, which is a privacy/fingerprinting hazard (assuming we fix bug 418986).

I should be absolutely sure that after pressing Esc, I'm not in full-screen mode.

  • When I'm in full-screen mode, pressing Esc should leave, even if the site uses preventDefault.
  • When I'm not in full-screen mode, pressing Esc (or Cmd+W, etc) should not as a "user-initiated event that allows popups and full-screening"

I should be sure that after full-screening YouTube, another site cannot navigate me away from YouTube and remain in full-screen mode. That means changing "There is no requirement to exit full-screen state when a browsing context is navigated to a new page."

I'd prefer just putting a full-screen button on our toolbar. Let users choose when to full-screen the page themselves. If the user chooses to hide the button, web pages could be allowed to make it appear again temporarily.

Advantages:

  • No need for a auto-allow-but-limited-input mode, with all the security and usability problems it brings.
  • Fewer clicks. One click (on the toolbar button) instead of two (one in the page, one to allow). roc: not a real advantage since we'd either avoid a prompt-based UI or if we have a prompt-based UI, we'd have 'remember this decision' so most of the time only the in-page click would be needed.
  • We don't have to worry about timing or confusion attacks against the permission UI.
  • Consistent UI across the web.

Disadvantages:

  • Harder for youtube-in-iframe to become full-screen.
  • Uses toolbar space.
  • roc: not clear how to make it work when there's more than one element in the page that you might want to make full-screen.
  • roc: not discoverable by users looking for in-page UI.

Jesse 2011-08-18: Interesting to note that IE previously had fullscreen=yes but removed it in WinXP SP2.

Discussion 2011-04-11

Date of discussion: 2011.04.11

Security Concerns:

  • Ability of website to enter fullscreen and pre-empt keyboard focus
  • User interaction currently not required for entering full screen mode
  • Fullscreen could be used as an attack vector

Responses:

  • There is a mode called without keys that does not take keyboard input
  • Focus is released on tab change or window change

Possible Remediations:

  • ESC key should be used to exit, similar to other well known apps users are familiar with
  • A user preference should be available for users to say allow full-screen or dis-allow full screen for a given URL domain (Ie. Popup or geolocation preferences)
  • Possible use of some indicator to show a user they are in full-screen mode
  • Possible use of permission manager
  • Plug-ins should be disabled when in full-screen mode
To-Do
  • Re-review as spec firms up and code begins to land

Issues

naming one word or two

fullscreen vs full screen

  • fullscreen
    • text of this page repeatedly uses "fullscreen"
    • Wikipedia prefers "fullscreen" and redirects "full screen" to that page.
    • the combined term "fullscreen" is more easily uniquely searchable than separate terms
  • full screen
    • title of this page implies "full screen" from the camelcase: (FullScreenAPI) - but that's just legacy.
    • the Firefox 4 "View" menu item "Full Screen" (shift-command-F)
  • roc: Elika and I resolved to use 'full-screen' everywhere.
    • Why? It would be useful to have reasoning documented for this conclusion so we can avoid re-exploring it. Tantek

avoiding ancestor reflow

Currently, the suggested UA stylesheet rules for a non-root fullscreen element take it out of the flow and make it position fixed, which has the side-effect of causing its ancestors to reflow, which is unnecessary, and thus an undesirable performance hit.

Instead, we should consider simply defining the fullscreened element as creating a new view with itself as the root box of a CSS presentation, with its own opaque CSS canvas (as defined in CSS), thereby avoiding the reflow problem.

The underlying background of this new opaque CSS canvas comes from the fullscreened element, just as the underlying background of a window comes from the root element of the document in that window.

roc: I don't want to do it this way. Creating additional views is very difficult to fit into the architecture of Gecko and other engines. The existing way seems fine in practice. Reflowing the document is not going to be a significant performance issue.

avoiding drawing anything else

Also, the suggested UA stylesheet rules use z-index to put the fullscreened element above everything else. Instead we may want to specify that when something is fullscreened, that we don't bother rendering any other windows/tabs, nor the parent document.

roc: Again this is more invasive to the engine than necessary. The z-index approach should work fine and is simple, without requiring any special engine support.

Documentation to update

  • https://developer.mozilla.org/en/Window.open
    • fullscreen=yes: "Do not use. Not implemented in Mozilla. There are no plans to implement this feature in Mozilla."
    • "Forcing fullscreen onto other users is also extremely unpopular and is considered an outright rude attempt to impose web author's viewing preferences onto users."

Implementations

In progress:

Articles