Update WebUI explainer doc
Using this doc as a reference for creating a new WebUI, there are a couple minor friction points. * Fix syntax errors and missing variables/members * Use DefaultWebUIConfig - simplest method and best starting point * Export Browser Proxy interface - otherwise need to refactor when it comes time to write browser tests Ideally, there would be a doc to literally copy/paste from, but this adds a maintenance burden and the files would get long with includes and such. Change-Id: I06243596985f89d571827e67e2e469364154bfcd Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5668492 Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org> Commit-Queue: Mickey Burks <mickeyburks@chromium.org> Cr-Commit-Position: refs/heads/main@{#1322107}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
112cf3db90
commit
463e6f5b87
@ -142,20 +142,23 @@ if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
|
|||||||
The factory creates a [`WebUIController`](#WebUIController) for a tab using
|
The factory creates a [`WebUIController`](#WebUIController) for a tab using
|
||||||
the WebUIConfig.
|
the WebUIConfig.
|
||||||
|
|
||||||
Here's an example:
|
Here's an example using the DefaultWebUIConfig:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
|
class DonutsUI;
|
||||||
|
|
||||||
|
// This would go in chrome/common/webui_url_constants.cc
|
||||||
|
namespace chrome {
|
||||||
|
const char kChromeUIDonutsHost[] = "donuts";
|
||||||
|
} // namespace chrome
|
||||||
|
|
||||||
// Config for chrome://donuts
|
// Config for chrome://donuts
|
||||||
DonutsUIConfig::DonutsUIConfig()
|
class DonutsUIConfig : public content::DefaultWebUIConfig<DonutsUI> {
|
||||||
: WebUIConfig(content::kChromeUIScheme, chrome::kChromeUIDonutsHost) {}
|
public:
|
||||||
|
DonutsUIConfig()
|
||||||
DonutsUIConfig::~DonutsUIConfig() = default;
|
: DefaultWebUIConfig(content::kChromeUIScheme,
|
||||||
|
chrome::kChromeUIDonutsHost) {}
|
||||||
std::unique_ptr<content::WebUIController>
|
};
|
||||||
DonutsUIConfig::CreateWebUIController(content::WebUI* web_ui,
|
|
||||||
const GURL& url) {
|
|
||||||
return std::make_unique<DonutsUI>(web_ui);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Controller for chrome://donuts.
|
// Controller for chrome://donuts.
|
||||||
class DonutsUI : public content::WebUIController {
|
class DonutsUI : public content::WebUIController {
|
||||||
@ -610,13 +613,17 @@ class DonutsPageHandler : public donuts::mojom::PageHandler {
|
|||||||
~DonutsPageHandler() override;
|
~DonutsPageHandler() override;
|
||||||
|
|
||||||
// Triggered by some outside event
|
// Triggered by some outside event
|
||||||
void DonutsPageHandler::OnBakingDonutsFinished(uint32_t num_donuts);
|
void OnBakingDonutsFinished(uint32_t num_donuts);
|
||||||
|
|
||||||
// donuts::mojom::PageHandler:
|
// donuts::mojom::PageHandler:
|
||||||
void StartPilotLight() override;
|
void StartPilotLight() override;
|
||||||
void BakeDonuts(uint32_t num_donuts) override;
|
void BakeDonuts(uint32_t num_donuts) override;
|
||||||
void GetNumberOfDonuts(GetNumberOfDonutsCallback callback) override;
|
void GetNumberOfDonuts(GetNumberOfDonutsCallback callback) override;
|
||||||
}
|
|
||||||
|
private:
|
||||||
|
mojo::Receiver<donuts::mojom::PageHandler> receiver_;
|
||||||
|
mojo::Remote<donuts::mojom::Page> page_;
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
The message handler needs to implement all the methods on the PageHandler
|
The message handler needs to implement all the methods on the PageHandler
|
||||||
@ -646,7 +653,7 @@ void DonutsPageHandler::StartPilotLight() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Triggered by bakeDonuts() call in TS.
|
// Triggered by bakeDonuts() call in TS.
|
||||||
void DonutsPageHandler::BakeDonuts(int32_t num_donuts) {
|
void DonutsPageHandler::BakeDonuts(uint32_t num_donuts) {
|
||||||
GetOven()->BakeDonuts();
|
GetOven()->BakeDonuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,14 +674,22 @@ added to the build and served from the root (e.g.
|
|||||||
|
|
||||||
**chrome/browser/resources/donuts/BUILD.gn**
|
**chrome/browser/resources/donuts/BUILD.gn**
|
||||||
```
|
```
|
||||||
|
import("//ui/webui/resources/tools/build_webui.gni")
|
||||||
|
|
||||||
build_webui("build") {
|
build_webui("build") {
|
||||||
# ... Other arguments go here
|
grd_prefix = "donuts"
|
||||||
|
|
||||||
|
# You will add these files in the next step:
|
||||||
|
non_web_component_files = [
|
||||||
|
"donuts.ts",
|
||||||
|
"browser_proxy.ts",
|
||||||
|
]
|
||||||
|
|
||||||
mojo_files_deps =
|
mojo_files_deps =
|
||||||
[ "//chrome/browser/ui/webui/donuts:mojo_bindings_ts__generator" ]
|
[ "//chrome/browser/ui/webui/donuts:mojo_bindings_ts__generator" ]
|
||||||
mojo_files = [
|
mojo_files = [
|
||||||
"$root_gen_dir/chrome/browser/ui/webui/donuts/donuts.mojom-webui.ts",
|
"$root_gen_dir/chrome/browser/ui/webui/donuts/donuts.mojom-webui.ts",
|
||||||
]
|
]
|
||||||
# ... Other arguments can go here
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -683,19 +698,23 @@ class:
|
|||||||
|
|
||||||
**chrome/browser/resources/donuts/browser_proxy.ts**
|
**chrome/browser/resources/donuts/browser_proxy.ts**
|
||||||
```js
|
```js
|
||||||
import {PageCallbackRouter, PageHandlerFactory, PageHandlerInterface, PageHandlerRemote} from './donuts.mojom-webui.js';
|
import {PageCallbackRouter, PageHandlerFactory, PageHandlerRemote} from './donuts.mojom-webui.js';
|
||||||
|
import type {PageHandlerInterface} from './donuts.mojom-webui.js';
|
||||||
|
|
||||||
class BrowserProxy {
|
// Exporting the interface helps when creating a TestBrowserProxy wrapper.
|
||||||
|
export interface BrowserProxy {
|
||||||
|
callbackRouter: PageCallbackRouter;
|
||||||
|
handler: PageHandlerInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BrowserProxyImpl implements BrowserProxy {
|
||||||
callbackRouter: PageCallbackRouter;
|
callbackRouter: PageCallbackRouter;
|
||||||
handler: PageHandlerInterface;
|
handler: PageHandlerInterface;
|
||||||
|
|
||||||
constructor() {
|
private constructor() {
|
||||||
this.callbackRouter = new PageCallbackRouter();
|
this.callbackRouter = new PageCallbackRouter();
|
||||||
|
|
||||||
this.handler = new PageHandlerRemote();
|
this.handler = new PageHandlerRemote();
|
||||||
|
PageHandlerFactory.getRemote().createPageHandler(
|
||||||
const factory = PageHandlerFactory.getRemote();
|
|
||||||
factory.createPageHandler(
|
|
||||||
this.callbackRouter.$.bindNewPipeAndPassRemote(),
|
this.callbackRouter.$.bindNewPipeAndPassRemote(),
|
||||||
(this.handler as PageHandlerRemote).$.bindNewPipeAndPassReceiver());
|
(this.handler as PageHandlerRemote).$.bindNewPipeAndPassReceiver());
|
||||||
}
|
}
|
||||||
@ -704,8 +723,8 @@ class BrowserProxy {
|
|||||||
return instance || (instance = new BrowserProxy());
|
return instance || (instance = new BrowserProxy());
|
||||||
}
|
}
|
||||||
|
|
||||||
static setInstance(obj: BrowserProxy) {
|
static setInstance(proxy: BrowserProxy) {
|
||||||
instance = obj;
|
instance = proxy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,13 +742,13 @@ response from the browser.
|
|||||||
|
|
||||||
**chrome/browser/resources/donuts/donuts.ts**
|
**chrome/browser/resources/donuts/donuts.ts**
|
||||||
```js
|
```js
|
||||||
import {BrowserProxy} from './browser_proxy.js';
|
import {BrowserProxyImpl} from './browser_proxy.js';
|
||||||
|
|
||||||
let numDonutsBaked: number = 0;
|
let numDonutsBaked: number = 0;
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
// Other page initialization steps go here
|
// Other page initialization steps go here
|
||||||
const proxy = BrowserProxy.getInstance();
|
const proxy = BrowserProxyImpl.getInstance();
|
||||||
// Tells the browser to start the pilot light.
|
// Tells the browser to start the pilot light.
|
||||||
proxy.handler.startPilotLight();
|
proxy.handler.startPilotLight();
|
||||||
// Adds a listener for the asynchronous "donutsBaked" event.
|
// Adds a listener for the asynchronous "donutsBaked" event.
|
||||||
@ -742,7 +761,7 @@ window.onload = function() {
|
|||||||
function CheckNumberOfDonuts() {
|
function CheckNumberOfDonuts() {
|
||||||
// Requests the number of donuts from the browser, and alerts with the
|
// Requests the number of donuts from the browser, and alerts with the
|
||||||
// response.
|
// response.
|
||||||
BrowserProxy.getInstance().handler.getNumberOfDonuts().then(
|
BrowserProxyImpl.getInstance().handler.getNumberOfDonuts().then(
|
||||||
(numDonuts: number) => {
|
(numDonuts: number) => {
|
||||||
alert('Yay, there are ' + numDonuts + ' delicious donuts left!');
|
alert('Yay, there are ' + numDonuts + ' delicious donuts left!');
|
||||||
});
|
});
|
||||||
@ -750,7 +769,7 @@ function CheckNumberOfDonuts() {
|
|||||||
|
|
||||||
function BakeDonuts(numDonuts: number) {
|
function BakeDonuts(numDonuts: number) {
|
||||||
// Tells the browser to bake |numDonuts| donuts.
|
// Tells the browser to bake |numDonuts| donuts.
|
||||||
BrowserProxy.getInstance().handler.bakeDonuts(numDonuts);
|
BrowserProxyImpl.getInstance().handler.bakeDonuts(numDonuts);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user