0

Adds some documentation of Desktop Reader Mode.

NOTRY=true

Bug: 1065520
Change-Id: I08bc2df7c2ad66f808f42e4695ab7e84b2307932
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2186116
Reviewed-by: Aran Gilman <gilmanmh@google.com>
Commit-Queue: Katie Dektar <katie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#766503}
This commit is contained in:
Katie D
2020-05-07 18:32:22 +00:00
committed by Commit Bot
parent 92ba46baa2
commit eef14e3b69
2 changed files with 168 additions and 0 deletions

@ -8,6 +8,7 @@
* [Offscreen, Invisible and Size](accessibility/offscreen.md)
* [Text to Speech in Chrome and Chrome OS](accessibility/tts.md)
* [Performance Measurement](accessibility/perf.md)
* [Reader Mode on Desktop Platforms](accessibility/reader_mode.md)
## Chrome OS

@ -0,0 +1,167 @@
# Reader Mode on Desktop Platforms
Reader Mode is an accessibility feature which offers a simplified version of the
original page that focuses on the “core” text, stripping out extraneous images,
UI, scripts, and other elements. It is launched on Android as “Simplified View”.
Reader Mode is based on the DOM distiller project which provides functionality
for simplifying a webpage. This document focuses on how the
[DOM distiller](https://chromium.googlesource.com/chromium/dom-distiller)
project is integrated into Chrome on Desktop.
## Overview
Desktop Reader Mode is hidden behind a
[base::Feature](https://source.chromium.org/chromium/chromium/src/+/master:components/dom_distiller/core/dom_distiller_features.cc)
flag, enable-reader-mode. To run Chrome with Reader Mode, set the “Enable
Reader Mode” flag to “Enabled” in chrome://flags or start Chrome with
--enable-feature=”ReaderMode”.
### Code Locations
Most of Reader Mode code is in components/dom_distiller (see the
[DOM distiller project](https://chromium.googlesource.com/chromium/dom-distiller)).
It is tied into Chrome via hooks in chrome/browser/dom_distiller (Desktop) and
chrome/browser/android/dom_distiller (Android).
### Tests
Most Reader Mode tests are in components_unittests or components_browsertests.
Tests for integration with Chrome Desktop are in browser_tests, including tests
of ReaderModeIconView and dom_distiller/tab_utils.h.
### Bugs
Reader Mode bugs should be filed under
[UI>Browser>ReaderMode](https://bugs.chromium.org/p/chromium/issues/list?q=component:UI%3EBrowser%3EReaderMode)
in crbug.com.
## How Reader Mode works in Desktop Chrome
### Deciding whether to offer Reader Mode
Reader Mode classifies all pages visited by the user as “distillable” or
“not distillable”. A page is distillable, roughly speaking, when it has a
http or https scheme, contains an article and when DOM Distiller is likely to
accurately extract its core content. For example, many news articles are
distillable because they mostly consist of a single column of core text. In
contrast, the Wikipedia main page is not distillable because it contains several
unrelated text areas that are of roughly equal importance.
The [DistillabilityAgent](https://cs.chromium.org/chromium/src/components/dom_distiller/content/renderer/distillability_agent.h),
located in the renderer process, examines the page contents whenever the
compositor makes a meaningful change to the layout, which happens 1 to 3 times
as the page loads. It then uses one of several different heuristics to determine
whether the page is distillable or not. The browser receives the result obtained
by the DistillabilityAgent for a given web contents via the
[DistillabilityService](https://cs.chromium.org/chromium/src/components/dom_distiller/content/common/mojom/distillability_service.mojom),
which is wrapped by a helper class, the
[DistillabilityDriver](https://cs.chromium.org/chromium/src/components/dom_distiller/content/browser/distillability_driver.h).
The DistillabilityDriver packages this information as a
[DistillabilityResult](https://cs.chromium.org/chromium/src/components/dom_distiller/content/browser/distillable_page_utils.h),
forwards it to all registered observers, and caches it.
### Toggling Reader Mode
Users can toggle reader mode using an omnibox icon or an option, Toggle Reader
Mode, in the “customize and control Chrome” menu, both of which execute
BrowserCommands [ToggleDistilledView()](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/ui/browser_commands.cc;bpv=1;bpt=1;l=1364?q=browser_commands%20dom_distiller&ss=chromium%2Fchromium%2Fsrc).
[ReaderModeIconView](https://cs.chromium.org/chromium/src/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.h)
is a DistillabilityObserver and sets its visibility based on the latest result
for the currently active web contents. Reader Mode on desktop only considers
whether the page is a distilled page, or, if not, the field
DistillabilityResult::is_distillable when deciding whether to display the icon;
the other fields are ignored. The icons visibility is updated when
* the user navigates to a new page within the same tab,
* the user switches tabs, and
* when a new distillability result is available.
### Representing Reader Mode in the tab strip and omnibox
Reader Mode should be considered a way of viewing a page, rather than a separate
page to users. For this reason, we display most of the original pages
information:
* The omnibox displays the original page URL, minus the scheme.
* The actual URL of the Reader Mode page is still “chrome-distiller://”
which is still returned from WebContents::GetLastCommittedURL() and
WebContents::GetVisibleURL().
* A special case in LocationBarModel::GetFormattedURL converts from
“chrome-distiller://” URLs to the original URL minus the scheme
* However, if a user types in an invalid chrome-distiller:// URL,
it will be displayed in the omnibox, because it doesnt correspond to any
article.
* Users cannot copy the hidden “chrome-distiller://” URLs, instead
OmniboxEditModel::AdjustTextForCopy converts Reader Mode URLs to their
original URLs, if the chrome-distiller:// url encodes a valid original URL.
* The security badge shows a Reader Mode-specific icon plus the phrase
“Reader Mode”
* SecurityStates GetSecurityLevel returns SecurityLevel::NONE for
“chrome-distiller://” scheme pages. Distilled pages should not contain forms,
payment handlers, or other JS from the original URL, so they wont be
affected by downgraded security level.
* The tab strip displays the original pages favicon.
* ChromeFaviconClient is used to check if a URL is a Reader Mode page and
if so gets the original pages URL to use for fetching the favicon.
* Bookmarking the distilled page actually bookmarks the original article
* BookmarkUtils GetURLToBookmark and GetURLAndTitleToBookmark both check for
whether a page is a distilled page before extracting the original page
title/URL from the distilled URL.
The page title is the original page title with “- Reader Mode” added to the end.
For example, if the original pages title is “An Interesting Article - A
Website”, the tab strip will display “An Interesting Article - A Website -
Reader Mode” when the user activates Reader Mode.
#### Representing page security
On desktop Reader Mode there are strict security checks in place to ensure that
SecurityLevel::NONE is appropriate. This includes:
* Only pages with SecurityLevel::SECURE are considered distillable (checked in
DistillabilityDriver::OnDistillability)
* Subresources with mixed content are not loaded on Reader Mode pages (enforced
in DomDistillerViewerSource::StartDataRequest)
* Subresources with certificate errors are not loaded on Reader Mode pages
(checked in ChromeContentBrowserClient::ShouldDenyRequestOnCertificateError)
On Android, we do not show a custom security indicator or have a specific
SecurityLevel, so it is not necessary to do such strict checking.
### Extracting core page content
Reader Mode uses Chromes built-in DOM Distiller to generate the simplified
version of the page. See the
[DOM Distiller project](https://github.com/chromium/dom-distiller) on GitHub and
this (Google-internal) [presentation](https://docs.google.com/presentation/d/1etC7ghAU89ec-UeJQ90q4KbHJHH6owfl7OactTcJvCc/edit#slide=id.p)
for more information on how DOM Distiller works and how to debug it. From
Chromes perspective, distilling the page to extract core page content can be
considered a black box.
In short, content is extracted from the fully rendered article via Javascript
(specifically from the compiled Javascript file built from DOM Distiller,
[domdistiller.js](https://source.chromium.org/chromium/chromium/src/+/master:third_party/dom_distiller_js/dist/js/domdistiller.js))
into a DistilledPageProto.
The DOM Distiller retrieves the currently loaded documents DOM and converts it
to a simplified HTML string using the following process:
1. Remove hidden elements from the set of elements to examine.
2. Identify important elements by passing them through a series of filters,
marking elements as “content” or “not content” based on factors such as number
of words in the element, location on the page relative to other elements, and
image size.
3. Create the output HTML by concatenating the string representation of
elements marked as “content”.
The distilled page is served on a locally stored file with a URI composed of
the following:
* Scheme: chrome-distiller://
* Host: a random string plus a hash of the entire original URL
* Query: parameters giving distillation start time and the original page URL
and title
### Displaying Reader Mode Pages
A [DistilledPageProto](https://source.chromium.org/chromium/chromium/src/+/master:components/dom_distiller/core/proto/distilled_page.proto)
is created for each page distilled, and is used to generate the HTML of the
distilled page.
Pages are loaded by
[DomDistillerViewerSource](https://source.chromium.org/chromium/chromium/src/+/master:components/dom_distiller/content/browser/dom_distiller_viewer_source.h),
which serves the HTML and resources for viewing pages. After the DOM is
initially loaded, the contents are populated via Javascript.