diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/docs/session_history.md | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/docs/session_history.md')
-rw-r--r-- | chromium/docs/session_history.md | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/chromium/docs/session_history.md b/chromium/docs/session_history.md new file mode 100644 index 00000000000..5071a7899d2 --- /dev/null +++ b/chromium/docs/session_history.md @@ -0,0 +1,125 @@ +# Session History + +A browser's session history keeps track of the navigations in each tab, to +support back/forward navigations and session restore. This is in contrast to +"history" (e.g., `chrome://history`), which tracks the main frame URLs the user +has visited in any tab for the lifetime of a profile. + +Chromium tracks the session history of each tab in NavigationController, using a +list of NavigationEntry objects to represent the joint session history items. +Each frame creates _session history items_ as it navigates. A _joint session +history item_ contains the state of each frame of a page at a given point in +time, including things like URL, partially entered form data, scroll position, +etc. Each NavigationEntry uses a tree of FrameNavigationEntries to track this +state. + +[TOC] + + +## Pruning Forward Navigations + +If the user goes back and then commits a new navigation, this essentially forks +the joint session history. However, joint session history is tracked as a list +and not as a tree, so the previous forward history is "pruned" and forgotten. +This pruning is performed for all new navigations, unless they commit with +replacement. + + +## Subframe Navigations + +When the first commit occurs within a new subframe of a document, it becomes +part of the existing joint session history item (which we refer to as an "auto +subframe navigation"). The user can't go back to the state before the frame +committed. Any subsequent navigations in the subframe create new joint session +history items (which we refer to as "manual subframe navigations"), such that +clicking back goes back within the subframe. + + +## Navigating with Replacement + +Some types of navigations can replace the previously committed joint session +history item for a frame, rather than creating a new item. These include: + + * `location.replace` (which is usually cross-document, unless it is a fragment + navigation) + * `history.replaceState` (which is always same-document) + * Client redirects + * The first non-blank URL after the initial empty document (unless the frame + was explicitly created with `about:blank` as the URL). + + +## Identifying Same- and Cross-Document Navigations + +Each FrameNavigationEntry contains both an _item sequence number_ (ISN) and a +_document sequence number_ (DSN). Same-document navigations create a new session +history item without changing the document, and thus have a new ISN but the same +DSN. Cross-document navigations create a new ISN and DSN. NavigationController +uses these ISNs and DSNs when deciding which frames need to be navigated during +a session history navigation, using a recursive frame tree walk in +`FindFramesToNavigate`. + + +## Classifying Navigations + +Much of the complexity in NavigationController comes from the bookkeeping needed +to track the various types of navigations as they commit (e.g., same-document vs +cross-document, main frame vs subframe, with or without replacement, etc). These +types may lead to different outcomes for whether a new NavigationEntry is +created, whether an existing one is updated vs replaced, and what events are +exposed to observers. This is handled by `ClassifyNavigation`, which determines +which `RendererDidNavigate` helper methods are used when a navigation commits. + + +## Persistence + +The joint session history of a tab is persisted so that tabs can be restored +(e.g., between Chromium restarts, after closing a tab, or on another device). +This requires serializing the state in each NavigationEntry and its tree of +FrameNavigationEntries, using a PageState object and other metadata. + +Not everything in NavigationEntry is persisted. All data members of +NavigationEntryImpl and FrameNavigationEntry should be documented with whether +they are preserved after commit and whether they need to be persisted. + +Note that the session history of a tab can also be cloned when duplicating a +tab, or when doing a back/forward/reload navigation in a new tab (such as when +middle-clicking the back/forward/reload button). This involves direct clones of +NavigationEntries rather than persisting and restoring. + +## Invariants + + * The `pending_entry_index_` is either -1 or an index into `entries_`. If + `pending_entry_` is defined and `pending_entry_index_` is -1, then it is a + new navigation. If `pending_entry_index_` is a valid index into `entries_`, + then `pending_entry_` must point to that entry and it is a session history + navigation. + * Newly created tabs have NavigationControllers with `is_initial_navigation_` + set to true. They can have `last_committed_entry_index_` defined before the + first commit, however, when session history is cloned from another tab. (In + this case, `pending_entry_index_` indicates which entry is going to be + restored during the initial navigation.) + * Every FrameNavigationEntry that has committed in the current session (as + opposed to those that have been restored) must have a SiteInstance. + * A renderer process can only update FrameNavigationEntries belonging to a + SiteInstance in that process. This especially includes attacker-controlled + data like PageState, which could be dangerous to load into a different + site's process. + * Any cross-SiteInstance navigation should result in a new NavigationEntry + with replacement, rather than updating an existing NavigationEntry. + + +## Caveats + + * Not every NavigationRequest has a pending NavigationEntry. For example, + subframe navigations do not, and renderer-initiated main frame navigations + may clear an existing browser-initiated pending NavigationEntry (using + PendingEntryRef) without replacing it with a new one. + * Some main frame documents may not have a corresponding NavigationEntry + even after commit (e.g., the initial empty document, per + [issue 524208](https://crbug.com/524208)). + * Some subframe documents may not have a corresponding FrameNavigationEntry + after commit (e.g., see [issue 608402](https://crbug.com/608402)). + * FrameNavigationEntries should be shared between NavigationEntries when they + do not change (e.g., to support history.replaceState after subframe + navigations), but this is not yet supported. + See [issue 373041](https://crbug.com/373041). |