0

Update WebUIDataSource doc in WebUI explainer

R=dpapad@chromium.org
BUG=none

Change-Id: Ifb796b08338cfd17e0c99a06aaad6f2a934e7748
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2020864
Commit-Queue: Rebekah Potter <rbpotter@chromium.org>
Reviewed-by: dpapad <dpapad@chromium.org>
Auto-Submit: Dan Beam <dbeam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#806666}
This commit is contained in:
rbpotter
2020-09-14 16:38:33 +00:00
committed by Commit Bot
parent d5149d9fb7
commit f50e025a17

@ -134,7 +134,7 @@ class DonutsUI : public content::WebUIController {
content::WebUIDataSource* source =
content::WebUIDataSource::Create("donuts"); // "donuts" == hostname
source->AddString("mmmDonuts", "Mmm, donuts!"); // Translations.
source->SetDefaultResource(IDR_DONUTS_HTML); // Home page.
source->AddResourcePath("", IDR_DONUTS_HTML); // Home page.
content::WebUIDataSource::Add(source);
// Handles messages from JavaScript to C++ via chrome.send().
@ -207,8 +207,46 @@ an existing [`WebUI`](#WebUI) when the correct one is determined via URL
inspection (i.e. chrome://settings creates a generic [`WebUI`](#WebUI) with a
settings-specific `WebUIController`).
<a name="WebUIDataSource"></a>
### WebUIDataSource
The `WebUIDataSource` class provides a place for data to live for WebUI pages.
Examples types of data stored in this class are:
* static resources (i.e. .html files packed into bundles and pulled off of disk)
* translations
* dynamic feature values (i.e. whether a feature is enabled)
Data sources are set up in the browser process (in C++) and are accessed by
loading URLs from the renderer.
Below is an example of a simple data source (in this case, Chrome's history
page):
```c++
content::WebUIDataSource* source = content::WebUIDataSource::Create("history");
source->AddResourcePath("sign_in_promo.svg", IDR_HISTORY_SIGN_IN_PROMO_SVG);
source->AddResourcePath("synced_tabs.html", IDR_HISTORY_SYNCED_TABS_HTML);
source->AddString("title", IDS_HISTORY_TITLE);
source->AddString("moreFromThisSite", IDS_HISTORY_MORE_FROM_THIS_SITE);
source->AddBoolean("showDateRanges",
base::FeatureList::IsEnabled(features::kHistoryShowDateRanges));
webui::SetupWebUIDataSource(
source, base::make_span(kHistoryResources, kHistoryResourcesSize),
kGeneratedPath, IDR_HISTORY_HISTORY_HTML);
content::WebUIDataSource::Add(source);
```
For more about each of the methods called on `WebUIDataSource` and the utility
method that performs additional configuration, see [DataSources](#DataSources)
and [WebUIDataSourceUtils](#WebUIDataSourceUtils)
<a name="WebUIMessageHandler"></a>
### WebUIMessageHandler
@ -242,6 +280,156 @@ $('bakeDonutsButton').onclick = function() {
};
```
<a name="DataSources">
## Data Sources
<a name="Create"></a>
### WebUIDataSource::Create()
This is a factory method required to create a WebUIDataSource instance. The
argument to `Create()` is typically the host name of the page. Caller owns the
result.
<a name="Add"></a>
### WebUIDataSource::Add()
Once you've created and added some things to a data source, it'll need to be
"added". This means transferring ownership. In practice, the data source is
created in the browser process on the UI thread and transferred to the IO
thread. Additionally, calling `Add()` will overwrite any existing data source
with the same name.
<div class="note">
It's unsafe to keep references to a <code>WebUIDataSource</code> after calling
<code>Add()</code>. Don't do this.
</div>
<a name="AddLocalizedString"></a>
### WebUIDataSource::AddLocalizedString()
Using an int reference to a grit string (starts with "IDS" and lives in a .grd
or .grdp file), adding a string with a key name will be possible to reference
via the `$i18n{}` syntax (and will be replaced when requested) or later
dynamically in JavaScript via `loadTimeData.getString()` (or `getStringF`).
<a name="AddResourcePath"></a>
### WebUIDataSource::AddResourcePath()
Using an int reference to a grit resource (starts with "IDR" and lives in a .grd
or .grdp file), adds a resource to the UI with the specified path.
It's generally a good idea to call <code>AddResourcePath()</code> with the empty
path and a resource ID that should be served as the "catch all" resource to
respond with. This resource will be served for requests like "chrome://history",
or "chrome://history/pathThatDoesNotExist". It will not be served for requests
that look like they are attempting to fetch a specific file, like
"chrome://history/file\_that\_does\_not\_exist.js". This is so that if a user
enters a typo when trying to load a subpage like "chrome://history/syncedTabs"
they will be redirected to the main history page, instead of seeing an error,
but incorrect imports in the source code will fail, so that they can be more
easily found and corrected.
<a name="AddBoolean"></a>
### WebUIDataSource::AddBoolean()
Often a page needs to know whether a feature is enabled. This is a good use case
for `WebUIDataSource::AddBoolean()`. Then, in the Javascript, one can write
code like this:
```js
if (loadTimeData.getBoolean('myFeatureIsEnabled')) {
...
}
```
<div class="note">
Data sources are not recreated on refresh, and therefore values that are dynamic
(i.e. that can change while Chrome is running) may easily become stale. It may
be preferable to use <code>cr.sendWithPromise()</code> to initialize dynamic
values and call <code>FireWebUIListener()</code> to update them.
If you really want or need to use <code>AddBoolean()</code> for a dynamic value,
make sure to call <code>WebUIDataSource::Update()</code> when the value changes.
</div>
<a name="WebUIDataSourceUtils"></a>
## WebUI utils for working with data sources
chrome/browser/ui/webui/webui\_util.\* contains a number of methods to simplify
common configuration tasks.
<a name="AddLocalizedStringsBulk"></a>
### webui::AddLocalizedStringsBulk()
Many Web UI data sources need to be set up with a large number of localized
strings. Instead of repeatedly calling <code>AddLocalizedString()</code>, create
an array of all the strings and use <code>AddLocalizedStringsBulk()</code>:
```c++
static constexpr webui::LocalizedString kStrings[] = {
// Localized strings (alphabetical order).
{"actionMenuDescription", IDS_HISTORY_ACTION_MENU_DESCRIPTION},
{"ariaRoleDescription", IDS_HISTORY_ARIA_ROLE_DESCRIPTION},
{"bookmarked", IDS_HISTORY_ENTRY_BOOKMARKED},
};
AddLocalizedStringsBulk(source, kStrings);
```
<a name="AddResourcePathsBulk"></a>
### webui::AddResourcePathsBulk()
Similar to the localized strings, many Web UIs need to add a large number of
resource paths. In this case, use <code>AddResourcePathsBulk()</code> to
replace repeated calls to <code>AddResourcePath()</code>. There are two
versions. One works almost identically to the strings case:
```c++
static constexpr webui::ResourcePath kPdfResources[] = {
{"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS},
{"pdf/constants.js", IDR_PDF_CONSTANTS_JS},
{"pdf/controller.js", IDR_PDF_CONTROLLER_JS},
};
webui::AddResourcePathsBulk(source, kStrings);
```
The second version instead accepts a span of <code>GritResourceMap</code> so
that it can directly use constants defined by autogenerated grit resources map
header files. For example, the autogenerated print\_preview\_resources\_map.h
header defines a <code>GritResourceMap</code> named
<code>kPrintPreviewResources</code> and a
<code>size\_t kPrintPreviewResourcesSize</code>. All the resources in this
resource map can be added as follows:
```c++
webui::AddResourcePathsBulk(
source,
base::make_span(kPrintPreviewResources, kPrintPreviewResourcesSize));
```
<a name="SetupWebUIDataSource"></a>
### webui::SetupWebUIDataSource() and webui::SetupBundledWebUIDataSource()
These methods perform common configuration tasks on a data source for a Web UI
that uses JS modules. When creating a Web UI that uses JS modules, use these
utilities instead of duplicating the configuration steps they perform elsewhere.
Specific setup steps performed by these utilities include:
* Setting the content security policy to allow the data source to load only
resources from its own host (e.g. chrome://history), chrome://resources, and
chrome://test (used to load test files).
* Enabling i18n template replacements by calling <code>UseStringsJs()</code> and
<code>EnableReplaceI18nInJS()</code> on the data source.
* Adding the test loader files to the data source, so that test files can be
loaded as JS modules.
* Setting the resource to load for the empty path.
The version for non-bundled UIs (<code>SetupWebUIDataSource()</code>) also adds
all resources in a GritResourceMap.
The version for bundled UIs (<code>SetupBundledWebUIDataSource()</code>) adds
a single specified bundled resource. Note that this version is only defined when
the optimize_webui build flag is enabled.
## Browser (C++) &rarr; Renderer (JS)
<a name="AllowJavascript"></a>