blob: 3e4a425dbed51328c34732ef0504c543ae383abd [file] [log] [blame] [view]
Charlie Reisb33534992020-06-26 05:28:171# Life of a Navigation
Nasko Oskovcf0dd682020-01-16 23:31:092
Charlie Reisb33534992020-06-26 05:28:173Navigation is one of the main functions of a browser. It is the process through
4which the user loads documents. This documentation traces the life of a
5navigation from the time a URL is typed in the URL bar to the time the web page
6is completely loaded. This is one example of many types of navigations, some of
7which may start in different places (e.g., in the renderer process).
8
9See also:
10 * [Life of a Navigation tech talk](https://youtu.be/mX7jQsGCF6E) and
11 [slides](https://docs.google.com/presentation/d/1YVqDmbXI0cllpfXD7TuewiexDNZYfwk6fRdmoXJbBlM/edit),
12 for an overview from Chrome University.
13 * [Navigation Concepts](navigation_concepts.md), for useful notes on
14 navigation-related concepts in Chromium.
15
16[TOC]
Nasko Oskovcf0dd682020-01-16 23:31:0917
18
Charlie Reisb33534992020-06-26 05:28:1719## BeforeUnload
Nasko Oskovcf0dd682020-01-16 23:31:0920
Charlie Reisb33534992020-06-26 05:28:1721Once a URL is entered, the first step of a navigation is to execute the
Nasko Oskovcf0dd682020-01-16 23:31:0922beforeunload event handler of the previous document, if a document is already
23loaded. This allows the previous document to prompt the user whether they want
24to leave, to avoid losing any unsaved data. In this case, the user can cancel
25the navigation and no more work will be performed.
26
27
Charlie Reisb33534992020-06-26 05:28:1728## Network Request and Response
Nasko Oskovcf0dd682020-01-16 23:31:0929
30If there is no beforeunload handler registered, or the user agrees to proceed,
31the next step is making a network request to the specified URL to retrieve the
Charlie Reisb33534992020-06-26 05:28:1732contents of the document to be rendered. (Note that not all navigations will go
33to the actual network, for cases like ServiceWorkers, WebUI, cache, data:, etc.)
34Assuming no network error is encountered (e.g. DNS resolution error, socket
35connection timeout, etc.), the server will respond with data, with the response
36headers coming first. The parsed headers give enough information to determine
37what needs to be done next.
Nasko Oskovcf0dd682020-01-16 23:31:0938
39The HTTP response code allows the browser process to know whether one of the
40following conditions has occurred:
41
42* A successful response follows (2xx)
43* A redirect has been encountered (response 3xx)
44* An HTTP level error has occurred (response 4xx, 5xx)
45
46There are two cases where a navigation network request can complete without
Charlie Reisb33534992020-06-26 05:28:1747resulting in a new document being rendered. The first one is HTTP response code
48204 or 205, which tells the browser that the response was successful, but there
49is no content that follows, and therefore the current document must remain
50active. The other case is when the server responds with a `Content-Disposition`
51response header indicating that the response must be treated as a download
52instead of a navigation.
Nasko Oskovcf0dd682020-01-16 23:31:0953
Charlie Reisb33534992020-06-26 05:28:1754If the server responds with a redirect, Chromium makes another request based on
55the HTTP response code and the Location header. The browser continues following
56redirects until either an error or a successful response is encountered.
Nasko Oskovcf0dd682020-01-16 23:31:0957
Charlie Reisb33534992020-06-26 05:28:1758Once there are no more redirects, the network stack determines if MIME type
59sniffing is needed to detect what type of response the server has sent. This is
60only needed if the response is not a 204/205 nor a download, doesn't already
61have a `Content-Type` response header, and doesn’t include a
62`X-Content-Type-Options: nosniff` response header. If MIME type sniffing is
63needed, the network stack will read a small chunk of the actual response data
64before proceeding with the commit.
Nasko Oskovcf0dd682020-01-16 23:31:0965
66
Charlie Reisb33534992020-06-26 05:28:1767## Commit
Nasko Oskovcf0dd682020-01-16 23:31:0968
69At this point the response is passed from the network stack to the browser
70process to be used for rendering a new document. The browser process selects
71an appropriate renderer process for the new document based on the origin and
72headers of the response as well as the current process model and isolation
73policy. It then sends the response to the chosen process, waiting for it to
74create the document and send an acknowledgement. This acknowledgement from the
75renderer process marks the _commit_ time, when the browser process changes its
76security state to reflect the new document and creates a session history entry
77for the previous document.
78
79As part of creating the new document, the old document needs to be unloaded.
80In navigations that stay in the same renderer process, the old document is
81unloaded by Blink before the new document is created, including running any
82registered unload handlers. In the case of a navigation that goes
83cross-process, any unload handlers are executed in the previous document’s
84process concurrently with the creation of the new document in the new process.
85
86Once the creation of the new document is complete and the browser process
87receives the commit message from the renderer process, the navigation is
88complete.
89
90
Charlie Reisb33534992020-06-26 05:28:1791## Loading
Nasko Oskovcf0dd682020-01-16 23:31:0992
93Even once navigation is complete, the user doesn't actually see the new page
94yet. Most people use the word navigation to describe the act of moving from
95one page to another, but in Chromium we separate that process into two phases.
96So far we have described the _navigation_ phase; once the navigation has been
Charlie Reisb33534992020-06-26 05:28:1797committed, Chromium moves into the _loading_ phase. Loading consists of
Nasko Oskovcf0dd682020-01-16 23:31:0998reading the remaining response data from the server, parsing it, rendering the
99document so it is visible to the user, executing any script accompanying it,
100and loading any subresources specified by the document.
101
Nasko Oskovcf0dd682020-01-16 23:31:09102The main reason for splitting into these two phases is that errors are treated
103differently before and after a navigation commits. Consider the case where the
104server responds with an HTTP error code. When this happens, the browser still
105commits a new document, but that document is an error page. The error page is
106either generated based on the HTTP response code or read as the response data
107from the server. On the other hand, if a successful navigation has committed a
108real document and has moved to the loading phase, it is still possible to
109encounter an error, for example a network connection can be terminated or
110times out. In that case the browser displays as much of the new document as it
111can, without showing an error page.
112
113
Charlie Reisb33534992020-06-26 05:28:17114## WebContentsObserver
Nasko Oskovcf0dd682020-01-16 23:31:09115
116Chromium exposes the various stages of navigation and document loading through
117methods on the [WebContentsObserver] interface.
118
Charlie Reisb33534992020-06-26 05:28:17119### Navigation
Nasko Oskovcf0dd682020-01-16 23:31:09120
Charlie Reisb33534992020-06-26 05:28:17121* `DidStartNavigation` - invoked after executing the beforeunload event handler
Nasko Oskovcf0dd682020-01-16 23:31:09122 and before making the initial network request.
Charlie Reisb33534992020-06-26 05:28:17123* `DidRedirectNavigation` - invoked every time a server redirect is encountered.
124* `ReadyToCommitNavigation` - invoked at the time the browser process has
Nasko Oskovcf0dd682020-01-16 23:31:09125 determined that it will commit the navigation and has picked a renderer
126 process for it, but before it has sent it to the renderer process. It is not
127 invoked for same-document navigations.
Charlie Reisb33534992020-06-26 05:28:17128* `DidFinishNavigation` - invoked once the navigation has committed. The commit
Nasko Oskovcf0dd682020-01-16 23:31:09129 can be either an error page if the server responded with an error code or a
130 successful document.
131
132
Charlie Reisb33534992020-06-26 05:28:17133### Loading
Nasko Oskovcf0dd682020-01-16 23:31:09134
Charlie Reisb33534992020-06-26 05:28:17135* `DidStartLoading` - invoked once per WebContents, when a navigation is about
Nasko Oskovcf0dd682020-01-16 23:31:09136 to start, after executing the beforeunload handler. This is equivalent to the
137 browser UI starting to show a spinner or other visual indicator for
138 navigation and is invoked before the DidStartNavigation method for the
139 navigation.
Charlie Reisb33534992020-06-26 05:28:17140* `DOMContentLoaded` - invoked per RenderFrameHost, when the document itself
Nasko Oskovcf0dd682020-01-16 23:31:09141 has completed loading, but before subresources may have completed loading.
Charlie Reisb33534992020-06-26 05:28:17142* `DidFinishLoad` - invoked per RenderFrameHost, when the document and all of
143 its subresources have finished loading.
144* `DidStopLoading` - invoked once per WebContents, when the top-level document,
Nasko Oskovcf0dd682020-01-16 23:31:09145 all of its subresources, all subframes, and their subresources have completed
146 loading. This is equivalent to the browser UI stop showing a spinner or other
147 visual indicator for navigation and loading.
Charlie Reisb33534992020-06-26 05:28:17148* `DidFailLoad` - invoked per RenderFrameHost, when the document load failed,
149 for example due to network connection termination before reading all of the
Nasko Oskovcf0dd682020-01-16 23:31:09150 response data.
151
152
Charlie Reisb33534992020-06-26 05:28:17153## NavigationThrottles
Nasko Oskovcf0dd682020-01-16 23:31:09154
Charlie Reisb33534992020-06-26 05:28:17155NavigationThrottles allow observing, deferring, blocking, and canceling a given
156navigation. They should not generally be used for modifying a navigation (e.g.,
157simulating a redirect), as discussed in
158[Navigation Concepts](navigation_concepts.md#rules-for-canceling-navigations).
159They are typically registered in
160`NavigationThrottleRunner::RegisterNavigationThrottles` or
161`ContentBrowserClient::CreateThrottlesForNavigation`.
Nasko Oskovcf0dd682020-01-16 23:31:09162
Nate Chapin060cb952023-02-08 21:13:07163The most common NavigationThrottles events are `WillStartRequest`,
164`WillRedirectRequest`, and `WillProcessResponse`, which allow intercepting a
165navigation before sending the network request, during any redirects, and after
166receiving the response. These events are only invoked on navigations that
167require a URLLoader (see NavigationRequest::NeedsUrlLoader).
168A NavigationThrottle that wishes to intercept a non-URLLoader navigation
169(same-document navigations, about:blank, etc.) should register itself in
170`NavigationThrottleRunner::RegisterNavigationThrottlesForCommitWithoutUrlLoader`,
171and will get a single `WillCommitWithoutUrlLoader` event instead of the full
172set of events centered on network requests. Page-activation navigations, such
173as activating a prerendered page or restoring a page from the back-forward
174cache, skip NavigationThrottles entirely.
Nasko Oskovcf0dd682020-01-16 23:31:09175
John Palmer046f9872021-05-24 01:24:56176[WebContentsObserver]: https://source.chromium.org/chromium/chromium/src/+/main:content/public/browser/web_contents_observer.h