Chromium offers two ways for an end-user to view the source code of a web page: 1) the Developer Tools, and 2) The longstanding view-source viewer. Of these, the Developer Tools have received almost all of the attention over the last decade, but in this post I want to take a quick look at the older view-source feature.

To get to the View Page Source feature, you can use the the Ctrl+U keyboard shortcut, the View page source context menu item, or add view-source: prefix before a URL in the omnibox. No matter what mechanism you use, you’ll get a new tab containing a simple view of the original source code of the page, not the current document’s DOM (which may have been extensively modified by script or the user).


Over the years, I’ve landed a few fixes to the View-Source code, including security fixes and user-experience fixes (e.g. support for rendering Dark Mode). The feature doesn’t get a lot of love, but its implementation is interesting. Why?

First, let’s start with the URL. Chromium uses a BrowserURLHandler to rewrite all URLs with a view-source: prefix by stripping off the prefix; a VirtualUrl is set on the navigation entry so the user continues to see the view-source prefix in the omnibox, even as the renderer uses the inner url as the source location:

If the user tries to use view-source against an unsupported scheme like javascript:, the rewriter changes the inner url to about:blank.

If the user invokes View page source on a given document, the WebContents’ ViewSource() function takes the current document’s URL, slaps a view-source: prefix on the front, massages a few things, and opens the resulting URL in a new tab.

Most interestingly, View Source is implemented as a mode for a Document loaded inside Blink– you simply call SetIsViewSource(true) on the Document, and then the ComputeDocumentType sets things up such that the CreateDocument() function creates a HTMLViewSourceDocument instead of a plain HTMLDocument. The ViewSource document uses a simpler parser and it does not do much beyond adding markup to display basic color highlighting on HTML elements and their attributes. The resulting “source-formatted” HTML is displayed as text to the user.


Generally, products try not to expose multiple features to achieve the same task, especially when they use different code to do it. For a while, the View-Source viewer had some unique features that justified its existence; e.g. it integrated with the XSS Auditor to mark blocks of code that the Auditor had deemed reflected XSS attacks:

However, the XSS Auditor was removed more than two years ago. Similarly, many years ago, a site could link directly to a view-source URL (e.g. a HTML tutorial website might do this), but that capability was removed in 2016 for security reasons.

Nowadays, the viewer offers a subset of the features of the Developer Tools’ Sources tab. The Sources tab offers several cool features, including Pretty Print, red-underlines for script errors, and the ability to switch between all of the sources used by the currently loaded page:

The Elements tab is different than both the Sources tab and the view-source viewer because it reflects the current state of the DOM of the currently-loaded page– modifications made to the page by JavaScript are shown in the Elements tab.

At this point, you might naturally wonder why the old viewer still exists.

Part of the answer is “Well, it’s been there forever, and doesn’t cost too much to maintain.” It’s been proposed that perhaps the CTRL+U shortcut should just open the Developer Tools’ Sources tab. However, there are some non-obvious reasons that the old viewer continues to live on:

  1. For Chromium on Android1, adding the view-source prefix in the omnibox is the only convenient way to view source without first tethering your device to a DevTools instance running on a desktop PC.
  2. The HTMLViewSourceDocument code that makes up the bulk of the feature cannot be deleted because the default XML rendering view depends upon it.

    If the user navigates to an XML file that lacks an XSLT, the XML parser calls GetDocument()->SetIsViewSource(true); which results in the browser rendering the plain XML as a document tree:

May the Source be with you!


1 Unfortunately, Chromium on iOS doesn’t support either view-source or the Developer Tools. If the iOS browser syncs a view-source url from another platform, the prefix is simply stripped off.

Published by ericlaw

Impatient optimist. Dad. Author/speaker. Created Fiddler & SlickRun. PM @ Microsoft 2001-2012, and 2018-2022, working on Office, IE, and Edge. Now a SWE on Microsoft Defender Web Protection. My words are my own, I do not speak for any other entity.

4 thoughts on “View-Source

  1. Minor correction: “No matter what mechanism you use, you’ll get a new tab containing a simple view of the original source code of the page”

    You will actually get a *FRESH* copy of the source from a *BRAND NEW* reload of the request. GRRR! Wrong Implementation!

    Thus if your page did a “one time only” thing… you will not see it :-( You’ll need to use a tool like Fiddler ;-) to capture the original source.

    Firefox will return the *REAL* source of the original request… with the one exception of this new bug they have where the view-source fails after a redirection:

      1. Hmm, yeah in *every* case for a secure application (which, should basically be all of them), the HTML page has a no-cache header, thus the bug listed comes into effect. The various comments sum up the disappointment.

        The developer is *expecting* the source shown to be the source received by the browser, not to fetch a new copy.

        It’s sad that is listed as won’t fix. I’d gladly pay for an “as loaded” view-source.

      2. It’s unclear to me why you’d expect a “secure application” to be specifying “no-cache”? (Commonly, developers expect no-cache to mean “don’t cache this” which isn’t at all what it means.)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: