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:
@ -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++) → Renderer (JS)
|
||||
|
||||
<a name="AllowJavascript"></a>
|
||||
|
Reference in New Issue
Block a user