diff --git a/README.md b/README.md index 35cb21c..3b84345 100644 --- a/README.md +++ b/README.md @@ -1,168 +1,177 @@ -# Alternate Loading Modes +# Prerendering, revamped -(Thanks to @domenic, @kinu, @yoavweiss, @clelland, and others, for their thoughts which contributed to this proposal.) +In order to making the experience of loading on the web faster, user agents employ prefetching and prerendering techniques. However, they have historically been [underspecified](https://w3c.github.io/resource-hints/#prerender) and [inconsistently implemented](https://caniuse.com/link-rel-prerender). -In order to making the experience of loading on the web faster, user agents employ prefetching and prerendering techniques. However, making cookies and other credentials available to the origin server or script may be inconsistent with the privacy objectives of the user or of the referring site. +The space is full of challenges which have not been comprehensively tackled: most notably, -First, consider the __fetch__ of the resource. User agents would ideally prefetch the content in a way that does not identify the user. For example, the user agent could: +* avoiding user-visible side effects and annoyances from running script on the destination site; and +* fulfilling the privacy objectives of the user and the referring site. -* send a request without credentials (e.g., no `Cookie` or `Authorization` request header) -* establish the connection from a different client IP address (e.g., using a proxy server or virtual private network, if available) -* use a previously fetched response, including one previously fetched by a third party if it can be authenticated +This repository contains a set of explainers and (eventually) specifications which, combined, give a rigorous model for performing such prerendering of content, in an interoperably-implementable way. Each piece is designed to be composable and reusable; for example, [some contribute to prefetching](#prefetching), independent of prerendering, and the [opt-in](./opt-in.md) is designed to be usable by other types of alternate loading modes, such as [fenced frames](https://github.com/shivanigithub/fenced-frame/). -However, because this (intentionally) obscures the user's identity, the response document cannot be personalized for the user. If it is used when the user navigates, the user will notice that they are not logged in (even if they should be), and other surprising behavior. A page designed with this in mind could "upgrade" itself when it loads, by personalizing the page based on data in unpartitioned storage and by fetching personalized content from the server. +## Pieces of the solution -Second, consider __prerendering__ the page. User agents would ideally allow HTML parsing, subresource fetching, and script execution in a way that does not identify the user or cause user-visible annoyance. For example, the user agent could: +We envision prerendering having several related pieces: -* apply mitigations as above to subresource and scripted fetches -* deny scripted access to unpartitioned storage, such as cookies and IndexedDB -* deny permission to invoke `window.alert`, autoplay audio, and other APIs inappropriate at this time +* [**Prerender triggers**](./triggers.md), where a referring site indicates to the user agent what content can or should be prerendered. -In this case, not only is the HTML resource not personalized, but script will observe restrictions that would not ordinarily apply until navigation actually occurs. A page designed with this in mind could tolerate this at prerender time, and "upgrade" itself on navigation by accessing storage or fetching from the network. + Today, we have the underspecified `` element to provide these indications. Although something like this (probably with a different name, to avoid compatibility issues?) might be a good starting point, there are other points in the design space worth considering. For example, allowing the referring site to provide more blanket permission to prerender lets the user agent use its own heuristics. -Since existing web pages are unlikely to behave well with these restrictions today, and it is impractical for user agents to distinguish such pages, we propose a lightweight way for a page to declare that it is prepared for this and will, if necessary, upgrade itself when it gains access to unpartitioned storage and other privileges. +* [**Prerendered content opt-in**](./opt-in.md), which allows pages to opt in to being prerendered by other cross-origin pages. -There has been previous discussion along these lines in [w3c/resource-hints#82](https://github.com/w3c/resource-hints/issues/82#issuecomment-536492276). (It also proposes a new `prenavigate` hint; defining triggers for these loading modes is not yet part of this proposal.) + In order to preserve privacy and avoid side effects, user agents need to prefetch content in a way that avoids identifying the user (e.g., omitting credentials). However, this means the response document cannot be personalized for the user. Pages need to indicate that they are prepared for this eventuality, and will "upgrade" themselves to personalization when they transition from prerendered to active. -## Table of contents +* [**Prerendering fetching modes**](./fetch.md), which modify the way in which cross-origin documents and subresources are fetched in order to preserve privacy and avoid side effects. -- [Declaration](#declaration) -- [JavaScript API](#javascript-api) -- [Request header](#request-header) -- [Risks](#risks) -- [Alternatives considered](#alternatives-considered) + Closely related to the previous bullet, this covers the mechanics of how a document is fetched in order to check for the opt-in, and provide it with no identifying information. The most obvious technique here is omitting credentials, but one could also consider using a proxy server (for IP privacy), or using a previously-fetched response in "memory cache". -## Declaration +* [**Prerendering browsing contexts**](./browsing-context.md), which are special browsing contexts that are not displayed to the user, and within which content is constrained to not perform disruptive or side-effecting operations. -``` -// HTTP response header -Supports-Loading-Mode: uncredentialed-prefetch, uncredentialed-prerender - -// HTML meta tag - -``` - -This is an [HTTP structured header][http-structured-header] which lists tokens indicating the loading modes the content is ready for. They have the following proposed meaning: - -
-
default
-
Implied, even if not listed. Baseline standard behavior.
- -
uncredentialed-prefetch
-
The resource is suitable for any user who meets the cache conditions. Either it is not personalized, or it includes script to modify the document to reflect credentialed state (e.g., to show the user's logged-in state). However, access to credentials will be available when the document loads and script executes.
- -
uncredentialed-prerender
-
Implies uncredentialed-prefetch. The resource can be loaded without access to its credentials and storage. Access to certain other APIs may be limited in this state. Either it is not personalized based on credentials, or it includes script to modify the document when the loading state changes to permit it.
-
+ In all prerendering browsing contexts, side-effecting or disruptive APIs, such as those that could play media, require a permission prompt, or otherwise display UI, will automatically error or no-op. In those tagged as being used for cross-origin prerendering, storage access will not be available (or, perhaps, is partitioned?), and all fetches will need to use the prerendering fetching modes. -The `` tag is processed only if it appears within the `` element and no ` +``` -### No declaration +This indicates to the browser that all of the links it sees, except for any to `/logout`, are safe to prerender and prefetch. The browser can then heuristically perform such prerendering or prefetching when it has spare resources (bandwidth, CPU cycles, memory, ...). The browser could use any triggers it wanted for these heuristics, such as: -Why is a declaration needed at all? Why can't the document be fetched and loaded normally, just without credentials? +* Historical data from the current user +* Historical data aggregated over many users via telemetry +* Behavior patterns for similar sites (e.g., often users click on one of the top N product listings/comments links) +* Just-in-time behavior patterns (e.g., mouse hover) -The origin may already have data in its unpartitioned storage, but from the above, our goal is to provide for prerendering which does not grant access to it until the user actually navigates to the destination site. However, this may cause the content to load and behave differently than it would have with access to its unpartitioned storage. Then, when the prerendered document is preseneted, the user will observe any such differences as brokenness. +This can be supplemented via per-page tweaks to increase the strength of the suggestion. For example, the `