HTML 5

Draft Recommendation — 7 July 2008

5.8 Session history and navigation

5.8.1 The session history of browsing contexts

The sequence of Documents in a browsing context is its session history.

History objects provide a representation of the pages in the session history of browsing contexts. Each browsing context has a distinct session history.

Each Document object in a browsing context's session history is associated with a unique instance of the History object, although they all must model the same underlying session history.

The history attribute of the Window interface must return the object implementing the History interface for that Window object's active document.

History objects represent their browsing context's session history as a flat list of session history entries. Each session history entry consists of either a URL or a state object, or both, and may in addition have a title, a Document object, form data, a scroll position, and other information associated with it.

This does not imply that the user interface need be linear. See the notes below.

URLs without associated state objects are added to the session history as the user (or script) navigates from page to page.

A state object is an object representing a user interface state.

Pages can add state objects between their entry in the session history and the next ("forward") entry. These are then returned to the script when the user (or script) goes back in the history, thus enabling authors to use the "navigation" metaphor even in one-page applications.

Every Document in the session history is defined to have a last activated entry, which is the state object entry associated with that Document which was most recently activated. Initially, the last activated entry of a Document must be the first entry for the Document, representing the fact that no state object entry has yet been activated.

At any point, one of the entries in the session history is the current entry. This is the entry representing the active document of the browsing context. The current entry is usually an entry for the location of the Document. However, it can also be one of the entries for state objects added to the history by that document.

Entries that consist of state objects share the same Document as the entry for the page that was active when they were added.

Contiguous entries that differ just by fragment identifier also share the same Document.

All entries that share the same Document (and that are therefore merely different states of one particular document) are contiguous by definition.

User agents may discard the DOMs of entries other than the current entry that are not referenced from any script, reloading the pages afresh when the user or script navigates back to such pages. This specification does not specify when user agents should discard pages' DOMs and when they should cache them. See the section on the load and unload events for more details.

Entries that have had their DOM discarded must, for the purposes of the algorithms given below, act as if they had not. When the user or script navigates back or forwards to a page which has no in-memory DOM objects, any other entries that shared the same Document object with it must share the new object as well.

When state object entries are added, a URL can be provided. This URL is used to replace the state object entry if the Document is evicted.

When a user agent discards the DOM from an entry in the session history, it must also discard all the entries that share that Document but do not have an associated URL (i.e. entries that only have a state object). Entries that shared that Document object but had a state object and have a different URL must then have their state objects removed. Removed entries are not recreated if the user or script navigates back to the page. If there are no state object entries for that Document object then no entries are removed.

when an entry is discarded, any frozen timers, intervals, XMLHttpRequests, database transactions, etc, must be killed

5.8.2 The History interface

interface History {
  readonly attribute long length;
  void go(in long delta);
  void go();
  void back();
  void forward();
  void pushState(in DOMObject data, in DOMString title);
  void pushState(in DOMObject data, in DOMString title, in DOMString url);
  void clearState();
};

The length attribute of the History interface must return the number of entries in this session history.

The actual entries are not accessible from script.

The go(delta) method causes the UA to move the number of steps specified by delta in the session history.

If the index of the current entry plus delta is less than zero or greater than or equal to the number of items in the session history, then the user agent must do nothing.

If the delta is zero, then the user agent must act as if the location.reload() method was called instead.

Otherwise, the user agent must cause the current browsing context to traverse the history to the specified entry. The specified entry is the one whose index equals the index of the current entry plus delta.

When the user navigates through a browsing context, e.g. using a browser's back and forward buttons, the user agent must translate this action into the equivalent invocations of the history.go(delta) method on the various affected window objects.

Some of the other members of the History interface are defined in terms of the go() method, as follows:

Member Definition
go() Must do the same as go(0)
back() Must do the same as go(-1)
forward() Must do the same as go(1)

The pushState(data, title, url) method adds a state object to the history.

When this method is invoked, the user agent must run the following steps:

  1. If a third argument is specified, run these substeps:

    1. Resolve the value of the third argument.
    2. If that fails, raise a security exception and abort the pushState() steps.
    3. Compare the resulting absolute URL to the document's address. If any part of these two URLs differ other than the <path>, <query>, and <fragment> components, then raise a security exception and abort the pushState() steps.

    For the purposes of the comparison in the above substeps, the <path> and <query> components can only be the same if the URLs use a hierarchical <scheme>.

  2. Remove from the session history any entries for the Document from the entry after the current entry up to the last entry in the session history that references the same Document object, if any. If the current entry is the last entry in the session history, or if there are no entries after the current entry that reference the same Document object, then no entries are removed.

  3. Add a state object entry to the session history, after the current entry, with the specified data as the state object, the given title as the title, and, if the third argument is present, the absolute URL that was found in the first step as the URL of the entry.

  4. Set this new entry as being the last activated entry for the Document.

  5. Update the current entry to be the this newly added entry.

The title is purely advisory. User agents might use the title in the user interface.

User agents may limit the number of state objects added to the session history per page. If a page hits the UA-defined limit, user agents must remove the entry immediately after the first entry for that Document object in the session history after having added the new entry. (Thus the state history acts as a FIFO buffer for eviction, but as a LIFO buffer for navigation.)

The clearState() method removes all the state objects for the Document object from the session history.

When this method is invoked, the user agent must remove from the session history all the entries from the first state object entry for that Document object up to the last entry that references that same Document object, if any.

Then, if the current entry was removed in the previous step, the current entry must be set to the last entry for that Document object in the session history.

5.8.3 Activating state object entries

When an entry in the session history is activated (which happens during session traversal, as described above), the user agent must run the following steps:

  1. First, the user agent must set this new entry as being the last activated entry for the Document to which the entry belongs.

  2. If the entry is a state object entry, let state be that state object. Otherwise, the entry is the first entry for the Document; let state be null.

  3. The user agent must then fire a popstate event in no namespace on the body element using the PopStateEvent interface, with the state attribute set to the value of state. This event bubbles but is not cancelable and has no default action.

interface PopStateEvent : Event {
  readonly attribute DOMObject state;
  void initPopStateEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMObject stateArg);
  void initPopStateEventNS(in DOMString namespaceURIArg, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMObject stateArg);
};

The initPopStateEvent() and initPopStateEventNS() methods must initialise the event in a manner analogous to the similarly-named methods in the DOM3 Events interfaces. [DOM3EVENTS]

The state attribute represents the context information for the event, or null, if the state represented is the initial state of the Document.

5.8.4 The Location interface

Each Document object in a browsing context's session history is associated with a unique instance of a Location object.

The location attribute of the HTMLDocument interface must return the Location object for that Document object.

The location attribute of the Window interface must return the Location object for that Window object's active document.

Location objects provide a representation of their document's address, and allow the current entry of the browsing context's session history to be changed, by adding or replacing entries in the history object.

interface Location {
  readonly attribute DOMString href;
  void assign(in DOMString url);
  void replace(in DOMString url);
  void reload();

    // URL decomposition attributes 
           attribute DOMString protocol;
           attribute DOMString host;
           attribute DOMString hostname;
           attribute DOMString port;
           attribute DOMString pathname;
           attribute DOMString search;
           attribute DOMString hash;
};

The href attribute must return the address of the page represented by the associated Document object, as an absolute URL.

On setting, the user agent must act as if the assign() method had been called with the new value as its argument.

When the assign(url) method is invoked, the UA must navigate the browsing context to the specified url.

When the replace(url) method is invoked, the UA must navigate the browsing context to the specified url with replacement enabled.

Navigation for the assign() and replace() methods must be done with the script browsing context of the script that invoked the method as the source browsing context.

The Location interface also has the complement of URL decomposition attributes, protocol, host, port, hostname, pathname, search, and hash. These must follow the rules given for URL decomposition attributes, with the input being the address of the page represented by the associated Document object, as an absolute URL (same as the href attribute), and the common setter action being the same as setting the href attribute to the new output value.

5.8.4.1. Security

User agents must raise a security exception whenever any of the members of a Location object are accessed by scripts whose effective script origin is not the same as the Location object's associated Document's effective script origin, with the following exceptions:

User agents must not allow scripts to override the href attribute's setter.

5.8.5 Implementation notes for session history

This section is non-normative.

The History interface is not meant to place restrictions on how implementations represent the session history to the user.

For example, session history could be implemented in a tree-like manner, with each page having multiple "forward" pages. This specification doesn't define how the linear list of pages in the history object are derived from the actual session history as seen from the user's perspective.

Similarly, a page containing two iframes has a history object distinct from the iframes' history objects, despite the fact that typical Web browsers present the user with just one "Back" button, with a session history that interleaves the navigation of the two inner frames and the outer page.

Security: It is suggested that to avoid letting a page "hijack" the history navigation facilities of a UA by abusing pushState(), the UA provide the user with a way to jump back to the previous page (rather than just going back to the previous state). For example, the back button could have a drop down showing just the pages in the session history, and not showing any of the states. Similarly, an aural browser could have two "back" commands, one that goes back to the previous state, and one that jumps straight back to the previous page.

In addition, a user agent could ignore calls to pushState() that are invoked on a timer, or from event handlers that do not represent a clear user action, or that are invoked in rapid succession.

5.9 Browsing the Web

Certain actions cause the browsing context to navigate to a new resource. Navigation always involves source browsing context, which is the browsing context which was responsible for starting the navigation.

For example, following a hyperlink, form submission, and the window.open() and location.assign() methods can all cause a browsing context to navigate.

A user agent may provide various ways for the user to explicitly cause a browsing context to navigate, in addition to those defined in this specification.

When a browsing context is navigated to a new resource, the user agent must run the following steps:

  1. Cancel any preexisting attempt to navigate the browsing context.

  2. Resolve the URL of the new resource. If that fails, the user agent may abort these steps, or may treat the URL as identifying some sort of user-agent defined error resource, which could display some sort of inline content, or could be handled using a mechanism that does not affect the browsing context.
  3. If the new resource is to be handled by displaying some sort of inline content, e.g. an error message because the specified scheme is not one of the supported protocols, or an inline prompt to allow the user to select a registered handler for the given scheme, then display the inline content and abort these steps.

  4. If the new resource is to be handled using a mechanism that does not affect the browsing context, then abort these steps and proceed with that mechanism instead.

  5. If the new resource is to be fetched using HTTP GET or equivalent, and if the browsing context being navigated is a top-level browsing context, then check if there are any application caches that have a manifest with the same origin as the URL in question, and that have this URL as one of their entries (excluding entries marked as foreign), and that already contain their manifest, categorized as a manifest. If so, then the user agent must then fetch the resource from the most appropriate application cache of those that match.

    Otherwise, start fetching the new resource in the appropriate manner (e.g. performing an HTTP GET or POST operation, or reading the file from disk, or executing script in the case of a javascript: URL). If this results in a redirect, return to the step labeled "fragment identifiers" with the new resource.

    For example, imagine an HTML page with an associated application cache displaying an image and a form, where the image is also used by several other application caches. If the user right-clicks on the image and chooses "View Image", then the user agent could decide to show the image from any of those caches, but it is likely that the most useful cache for the user would be the one that was used for the aforementioned HTML page. On the other hand, if the user submits the form, and the form does a POST submission, then the user agent will not use an application cache at all; the submission will be made to the network.

  6. Wait for one or more bytes to be available or for the user agent to establish that the resource in question is empty. During this time, the user agent may allow the user to cancel this navigation attempt or start other navigation attempts.

  7. If the resource was not fetched from an application cache, and was to be fetched using HTTP GET or equivalent, and its URL matches the opportunistic caching namespace of one or more application caches, and the user didn't cancel the navigation attempt during the previous step, then:

    If the browsing context being navigated is a top-level browsing context, and the navigation attempt failed (e.g. the server returned a 4xx or 5xx status code or equivalent, or there was a DNS error)

    Let candidate be the fallback resource specified for the opportunistic caching namespace in question. If multiple application caches match, the user agent must use the fallback of the most appropriate application cache of those that match.

    If candidate is not marked as foreign, then the user agent must discard the failed load and instead continue along these steps using candidate as the resource.

    For the purposes of session history (and features that depend on session history, e.g. bookmarking) the user agent must use the URL of the resource that was requested (the one that matched the opportunistic caching namespace), not the fallback resource. However, the user agent may indicate to the user that the original page load failed, that the page used was a fallback resource, and what the URL of the fallback resource actually is.

    Otherwise

    Once the download is complete, if there were no errors and the user didn't cancel the request, the user agent must cache the resource in all the application caches that have a matching opportunistic caching namespace, categorized as opportunistically cached entries. Meanwhile, the user must continue along these steps.

  8. If the document's out-of-band metadata (e.g. HTTP headers), not counting any type information (such as the Content-Type HTTP header), requires some sort of processing that will not affect the browsing context, then perform that processing and abort these steps.

    Such processing might be triggered by, amongst other things, the following:

    • HTTP status codes (e.g. 204 No Content or 205 Reset Content)
    • HTTP Content-Disposition headers
    • Network errors
  9. Let type be the sniffed type of the resource.

  10. If the user agent has been configured to process resources of the given type using some mechanism other than rendering the content in a browsing context, then skip this step. Otherwise, if the type is one of the following types, jump to the appropriate entry in the following list, and process the resource as described there:

    "text/html"
    Follow the steps given in the HTML document section, and abort these steps.
    Any type ending in "+xml"
    "application/xml"
    "text/xml"
    Follow the steps given in the XML document section. If that section determines that the content is not to be displayed as a generic XML document, then proceed to the next step in this overall set of steps. Otherwise, abort these steps.
    "text/plain"
    Follow the steps given in the plain text file section, and abort these steps.
    A supported image type
    Follow the steps given in the image section, and abort these steps.
    A type that will use an external application to render the content in the browsing context
    Follow the steps given in the plugin section, and abort these steps.
  11. Otherwise, the document's type is such that the resource will not affect the browsing context, e.g. because the resource is to be handed to an external application. Process the resource appropriately.

Some of the sections below, to which the above algorithm defers in certain cases, require the user agent to update the session history with the new page. When a user agent is required to do this, it must follows the set of steps given below that is appropriate for the situation at hand. From the point of view of any script, these steps must occur atomically.

  1. pause for scripts

  2. onbeforeunload, and if present set flag that we will kill document

  3. onunload, and if present set flag that we will kill document

  4. if flag is set: reset timers, empty event queue, kill any pending transactions, kill XMLHttpRequests, etc, and set things up so that the document will be discarded asap

  5. If the navigation was initiated for entry update of an entry
    1. Replace the entry being updated with a new entry representing the new resource and its Document object and related state. The user agent may propagate state from the old entry to the new entry (e.g. scroll position).

    2. Traverse the history to the new entry.

    Otherwise
    1. Remove all the entries after the current entry in the browsing context's Document object's History object.

      This doesn't necessarily have to affect the user agent's user interface.

    2. Append a new entry at the end of the History object representing the new resource and its Document object and related state.

    3. Traverse the history to the new entry.

    4. If the navigation was initiated with replacement enabled, remove the entry immediately before the new current entry in the session history.

5.9.2 Page load processing model for HTML files

When an HTML document is to be loaded in a browsing context, the user agent must create a Document object, mark it as being an HTML document, create an HTML parser, associate it with the document, and begin to use the bytes provided for the document as the input stream for that parser.

The input stream converts bytes into characters for use in the tokeniser. This process relies, in part, on character encoding information found in the real Content-Type metadata of the resource; the "sniffed type" is not used for this purpose.

When no more bytes are available, an EOF character is implied, which eventually causes a load event to be fired.

After creating the Document object, but potentially before the page has finished parsing, the user agent must update the session history with the new page.

Application cache selection happens in the HTML parser.

5.9.3 Page load processing model for XML files

When faced with displaying an XML file inline, user agents must first create a Document object, following the requirements of the XML and Namespaces in XML recommendations, RFC 3023, DOM3 Core, and other relevant specifications. [XML] [XMLNS] [RFC3023] [DOM3CORE]

The actual HTTP headers and other metadata, not the headers as mutated or implied by the algorithms given in this specification, are the ones that must be used when determining the character encoding according to the rules given in the above specifications. Once the character encoding is established, the document's character encoding must be set to that character encoding.

If the root element, as parsed according to the XML specifications cited above, is found to be an html element with an attribute manifest, then, as soon as the element is inserted into the DOM, the user agent must resolve the value of that attribute, and if that is successful, must run the application cache selection algorithm with the resulting absolute URL as the manifest URL. Otherwise, if the attribute is absent or resolving it fails, then as soon as the root element is inserted into the DOM, the user agent must run the application cache selection algorithm with no manifest.

Because the processing of the manifest attribute happens only once the root element is parsed, any URLs referenced by processing instructions before the root element (such as <?xml-styleesheet?> and <?xbl?> PIs) will be fetched from the network and cannot be cached.

User agents may examine the namespace of the root Element node of this Document object to perform namespace-based dispatch to alternative processing tools, e.g. determining that the content is actually a syndication feed and passing it to a feed handler. If such processing is to take place, abort the steps in this section, and jump to the next step (labeled "non-document content") in the navigate steps above.

Otherwise, then, with the newly created Document, the user agents must update the session history with the new page. User agents may do this before the complete document has been parsed (thus achieving incremental rendering).

Error messages from the parse process (e.g. namespace well-formedness errors) may be reported inline by mutating the Document.

5.9.4 Page load processing model for text files

When a plain text document is to be loaded in a browsing context, the user agent should create a Document object, mark it as being an HTML document, create an HTML parser, associate it with the document, act as if the tokeniser had emitted a start tag token with the tag name "pre", set the tokenisation stage's content model flag to PLAINTEXT, and begin to pass the stream of characters in the plain text document to that tokeniser.

The rules for how to convert the bytes of the plain text document into actual characters are defined in RFC 2046, RFC 2646, and subsequent versions thereof. [RFC2046] [RFC2646]

The document's character encoding must be set to the character encoding used to decode the document.

Upon creation of the Document object, the user agent must run the application cache selection algorithm with no manifest.

When no more character are available, an EOF character is implied, which eventually causes a load event to be fired.

After creating the Document object, but potentially before the page has finished parsing, the user agent must update the session history with the new page.

User agents may add content to the head element of the Document, e.g. linking to stylesheet or an XBL binding, providing script, giving the document a title, etc.

5.9.5 Page load processing model for images

When an image resource is to be loaded in a browsing context, the user agent should create a Document object, mark it as being an HTML document, append an html element to the Document, append a head element and a body element to the html element, append an img to the body element, and set the src attribute of the img element to the address of the image.

Then, the user agent must act as if it had stopped parsing.

Upon creation of the Document object, the user agent must run the application cache selection algorithm with no manifest.

After creating the Document object, but potentially before the page has finished fully loading, the user agent must update the session history with the new page.

User agents may add content to the head element of the Document, or attributes to the img element, e.g. to link to stylesheet or an XBL binding, to provide a script, to give the document a title, etc.

5.9.6 Page load processing model for content that uses plugins

When a resource that requires an external resource to be rendered is to be loaded in a browsing context, the user agent should create a Document object, mark it as being an HTML document, append an html element to the Document, append a head element and a body element to the html element, append an embed to the body element, and set the src attribute of the img element to the address of the image.

Then, the user agent must act as if it had stopped parsing.

Upon creation of the Document object, the user agent must run the application cache selection algorithm with no manifest.

After creating the Document object, but potentially before the page has finished fully loading, the user agent must update the session history with the new page.

User agents may add content to the head element of the Document, or attributes to the embed element, e.g. to link to stylesheet or an XBL binding, or to give the document a title.

If the sandboxed plugins browsing context flag is set on the browsing context, the synthesized embed element will fail to render the content.

5.9.7 Page load processing model for inline content that doesn't have a DOM

When the user agent is to display a user agent page inline in a browsing context, the user agent should create a Document object, mark it as being an HTML document, and then either associate that Document with a custom rendering that is not rendered using the normal Document rendering rules, or mutate that Document until it represents the content the user agent wants to render.

Once the page has been set up, the user agent must act as if it had stopped parsing.

Upon creation of the Document object, the user agent must run the application cache selection algorithm with no manifest.

After creating the Document object, but potentially before the page has been completely set up, the user agent must update the session history with the new page.

5.9.8 Navigating to a fragment identifier

When a user agent is supposed to navigate to a fragment identifier, then the user agent must update the session history with the new page, where "the new page" has the same Document as before but with the URL having the newly specified fragment identifier.

Part of that algorithm involves the user agent having to scroll to the fragment identifier, which is the important part for this step.

When the user agent is required to scroll to the fragment identifier, it must change the scrolling position of the document, or perform some other action, such that the indicated part of the document is brought to the user's attention. If there is no indicated part, then the user agent must not scroll anywhere.

The indicated part of the document is the one that the fragment identifier, if any, identifies. The semantics of the fragment identifier in terms of mapping it to a specific DOM Node is defined by the MIME type specification of the document's MIME Type (for example, the processing of fragment identifiers for XML MIME types is the responsibility of RFC3023).

For HTML documents (and the text/html MIME type), the following processing model must be followed to determine what the indicated part of the document is.

  1. Parse the URL, and let fragid be the <fragment> component of the URL.

  2. If fragid is the empty string, then the indicated part of the document is the top of the document.

  3. If there is an element in the DOM that has an ID exactly equal to fragid, then the first such element in tree order is the indicated part of the document; stop the algorithm here.

  4. If there is an a element in the DOM that has a name attribute whose value is exactly equal to fragid, then the first such element in tree order is the indicated part of the document; stop the algorithm here.

  5. Otherwise, there is no indicated part of the document.

For the purposes of the interaction of HTML with Selectors' :target pseudo-class, the target element is the indicated part of the document, if that is an element; otherwise there is no target element. [SELECTORS]

5.9.9 History traversal

When a user agent is required to traverse the history to a specified entry, the user agent must act as follows:

  1. If there is no longer a Document object for the entry in question, the user agent must navigate the browsing context to the location for that entry to perform an entry update of that entry, and abort these steps. The "navigate" algorithm reinvokes this "traverse" algorithm to complete the traversal, at which point there is a Document object and so this step gets skipped. The navigation must be done using the same source browsing context as was used the first time this entry was created.

  2. If appropriate, update the current entry in the browsing context's Document object's History object to reflect any state that the user agent wishes to persist.

    For example, some user agents might want to persist the scroll position, or the values of form controls.

  3. If the specified entry has a different Document object than the current entry then the user agent must run the following substeps:

    1. freeze any timers, intervals, XMLHttpRequests, database transactions, etc
    2. The user agent must move any properties that have been added to the browsing context's default view's Window object to the active document's Document's list of added properties.
    3. If the browsing context is a top-level browsing context (and not an auxiliary browsing context), and the origin of the Document of the specified entry is not the same as the origin of the Document of the current entry, then the following sub-sub-steps must be run:
      1. The current browsing context name must be stored with all the entries in the history that are associated with Document objects with the same origin as the active document and that are contiguous with the current entry.
      2. The browsing context's browsing context name must be unset.
    4. The user agent must make the specified entry's Document object the active document of the browsing context. (If it is a top-level browsing context, this might change which application cache it is associated with.)
    5. If the specified entry has a browsing context name stored with it, then the following sub-sub-steps must be run:
      1. The browsing context's browsing context name must be set to the name stored with the specified entry.
      2. Any browsing context name stored with the entries in the history that are associated with Document objects with the same origin as the new active document, and that are contiguous with the specified entry, must be cleared.
    6. The user agent must move any properties that have been added to the active document's Document's list of added properties to browsing context's default view's Window object.
    7. unfreeze any timers, intervals, XMLHttpRequests, database transactions, etc
  4. If there are any entries with state objects between the last activated entry for the Document of the specified entry and the specified entry itself (not inclusive), then the user agent must iterate through every entry between that last activated entry and the specified entry, starting with the entry closest to the current entry, and ending with the one closest to the specified entry. For each entry, if the entry is a state object, the user agent must activate the state object.

  5. If the specified entry is a state object or the first entry for a Document, the user agent must activate that entry.

  6. If the specified entry has a URL that differs from the current entry's only by its fragment identifier, and the two share the same Document object, then fire a simple event with the name hashchanged at the body element, and, if the new URL has a fragment identifier, scroll to the fragment identifier.

  7. User agents may also update other aspects of the document view when the location changes in this way, for instance the scroll position, values of form fields, etc.

  8. The current entry is now the specified entry.

how does the changing of the global attributes affect .watch() when seen from other Windows?