summaryrefslogtreecommitdiff
path: root/chromium/docs/session_history.md
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/docs/session_history.md
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-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.md125
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).