WebUI: Migrate more UIs to WebUIConfig, update documentation
Migrate downloads and bookmarks to use WebUIConfig and add information about WebUIConfigs and how to register them to WebUI documentation. This is to reduce developer confusion about how to add UIs with Configs rather than just WebUIControllerFactory. WebUIControllerFactory does not support untrusted UIs. Bug: 1317510 Change-Id: I9332180a306923814abdd6e0dbcb58a1f31e1a72 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4990269 Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org> Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Commit-Queue: Rebekah Potter <rbpotter@chromium.org> Cr-Commit-Position: refs/heads/main@{#1217858}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
182b763e8d
commit
26b32f461c
chrome/browser/ui/webui
docs
@ -16,6 +16,7 @@
|
||||
#include "chrome/browser/ui/webui/favicon_source.h"
|
||||
#include "chrome/browser/ui/webui/managed_ui_handler.h"
|
||||
#include "chrome/browser/ui/webui/metrics_handler.h"
|
||||
#include "chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.h"
|
||||
#include "chrome/browser/ui/webui/plural_string_handler.h"
|
||||
#include "chrome/browser/ui/webui/webui_util.h"
|
||||
#include "chrome/common/url_constants.h"
|
||||
@ -134,6 +135,22 @@ content::WebUIDataSource* CreateAndAddBookmarksUIHTMLSource(Profile* profile) {
|
||||
|
||||
} // namespace
|
||||
|
||||
BookmarksUIConfig::BookmarksUIConfig()
|
||||
: WebUIConfig(content::kChromeUIScheme, chrome::kChromeUIBookmarksHost) {}
|
||||
|
||||
BookmarksUIConfig::~BookmarksUIConfig() = default;
|
||||
|
||||
std::unique_ptr<content::WebUIController>
|
||||
BookmarksUIConfig::CreateWebUIController(content::WebUI* web_ui,
|
||||
const GURL& url) {
|
||||
Profile* profile = Profile::FromWebUI(web_ui);
|
||||
if (profile->IsGuestSession()) {
|
||||
return std::make_unique<PageNotAvailableForGuestUI>(
|
||||
web_ui, chrome::kChromeUIBookmarksHost);
|
||||
}
|
||||
return std::make_unique<BookmarksUI>(web_ui);
|
||||
}
|
||||
|
||||
BookmarksUI::BookmarksUI(content::WebUI* web_ui) : WebUIController(web_ui) {
|
||||
// Set up the chrome://bookmarks/ source.
|
||||
Profile* profile = Profile::FromWebUI(web_ui);
|
||||
|
@ -6,12 +6,24 @@
|
||||
#define CHROME_BROWSER_UI_WEBUI_BOOKMARKS_BOOKMARKS_UI_H_
|
||||
|
||||
#include "content/public/browser/web_ui_controller.h"
|
||||
#include "content/public/browser/webui_config.h"
|
||||
#include "ui/base/resource/resource_scale_factor.h"
|
||||
|
||||
namespace base {
|
||||
class RefCountedMemory;
|
||||
}
|
||||
|
||||
class BookmarksUIConfig : public content::WebUIConfig {
|
||||
public:
|
||||
BookmarksUIConfig();
|
||||
~BookmarksUIConfig() override;
|
||||
|
||||
// content::WebUIConfig:
|
||||
std::unique_ptr<content::WebUIController> CreateWebUIController(
|
||||
content::WebUI* web_ui,
|
||||
const GURL& url) override;
|
||||
};
|
||||
|
||||
class BookmarksUI : public content::WebUIController {
|
||||
public:
|
||||
explicit BookmarksUI(content::WebUI* web_ui);
|
||||
|
@ -9,6 +9,11 @@
|
||||
#include "content/public/browser/webui_config_map.h"
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
#include "chrome/browser/ui/webui/bookmarks/bookmarks_ui.h"
|
||||
#include "chrome/browser/ui/webui/downloads/downloads_ui.h"
|
||||
#endif // !BUILDFLAG(IS_ANDROID)
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
|
||||
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
@ -23,8 +28,17 @@ void RegisterChromeWebUIConfigs() {
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
ash::RegisterAshChromeWebUIConfigs();
|
||||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID) || BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
auto& map = content::WebUIConfigMap::GetInstance();
|
||||
#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
map.AddWebUIConfig(std::make_unique<BookmarksUIConfig>());
|
||||
map.AddWebUIConfig(std::make_unique<DownloadsUIConfig>());
|
||||
#endif // !BUILDFLAG(IS_ANDROID)
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
map.AddWebUIConfig(std::make_unique<printing::PrintPreviewUIConfig>());
|
||||
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
}
|
||||
|
@ -545,7 +545,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
|
||||
#endif // !BUILDFLAG(IS_CHROMEOS)
|
||||
if (profile->IsGuestSession() &&
|
||||
(url.host_piece() == chrome::kChromeUIAppLauncherPageHost ||
|
||||
url.host_piece() == chrome::kChromeUIBookmarksHost ||
|
||||
url.host_piece() == chrome::kChromeUIHistoryHost ||
|
||||
url.host_piece() == chrome::kChromeUIExtensionsHost ||
|
||||
url.host_piece() == chrome::kChromeUINewTabPageHost ||
|
||||
@ -555,17 +554,11 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
|
||||
}
|
||||
if (url.host_piece() == chrome::kChromeUIAppServiceInternalsHost)
|
||||
return &NewWebUI<AppServiceInternalsUI>;
|
||||
// Bookmarks are part of NTP on Android.
|
||||
if (url.host_piece() == chrome::kChromeUIBookmarksHost)
|
||||
return &NewWebUI<BookmarksUI>;
|
||||
if (url.host_piece() == password_manager::kChromeUIPasswordManagerHost) {
|
||||
return &NewWebUI<PasswordManagerUI>;
|
||||
}
|
||||
if (url.host_piece() == chrome::kChromeUICommanderHost)
|
||||
return &NewWebUI<CommanderUI>;
|
||||
// Downloads list on Android uses the built-in download manager.
|
||||
if (url.host_piece() == chrome::kChromeUIDownloadsHost)
|
||||
return &NewWebUI<DownloadsUI>;
|
||||
// Identity API is not available on Android.
|
||||
if (url.host_piece() == chrome::kChromeUIIdentityInternalsHost)
|
||||
return &NewWebUI<IdentityInternalsUI>;
|
||||
|
@ -199,6 +199,23 @@ content::WebUIDataSource* CreateAndAddDownloadsUIHTMLSource(Profile* profile) {
|
||||
|
||||
} // namespace
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DownloadsUIConfig
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DownloadsUIConfig::DownloadsUIConfig()
|
||||
: WebUIConfig(content::kChromeUIScheme, chrome::kChromeUIDownloadsHost) {}
|
||||
|
||||
DownloadsUIConfig::~DownloadsUIConfig() = default;
|
||||
|
||||
std::unique_ptr<content::WebUIController>
|
||||
DownloadsUIConfig::CreateWebUIController(content::WebUI* web_ui,
|
||||
const GURL& url) {
|
||||
return std::make_unique<DownloadsUI>(web_ui);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DownloadsUI
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
|
||||
#include "content/public/browser/webui_config.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
@ -20,6 +21,17 @@ class RefCountedMemory;
|
||||
|
||||
class DownloadsDOMHandler;
|
||||
|
||||
class DownloadsUIConfig : public content::WebUIConfig {
|
||||
public:
|
||||
DownloadsUIConfig();
|
||||
~DownloadsUIConfig() override;
|
||||
|
||||
// content::WebUIConfig:
|
||||
std::unique_ptr<content::WebUIController> CreateWebUIController(
|
||||
content::WebUI* web_ui,
|
||||
const GURL& url) override;
|
||||
};
|
||||
|
||||
class DownloadsUI : public ui::MojoWebUIController,
|
||||
public downloads::mojom::PageHandlerFactory {
|
||||
public:
|
||||
|
@ -100,15 +100,27 @@ When a URL is requested, a new renderer is created to load the URL, and a
|
||||
corresponding class in the browser is set up to handle messages from the
|
||||
renderer to the browser (a `RenderFrameHost`).
|
||||
|
||||
The URL of the request is inspected:
|
||||
One factory that serves WebUI URLs is `WebUIConfigMapWebUIControllerFactory`.
|
||||
This factory looks at a global map from hosts to `WebUIConfig`s to see if any
|
||||
of the configs handle the requested URL, and calls a method to create the
|
||||
corresponding controller if so.
|
||||
|
||||
```c++
|
||||
if (url.SchemeIs("chrome") && url.host_piece() == "donuts") // chrome://donuts
|
||||
return &NewWebUI<DonutsUI>;
|
||||
return nullptr; // Not a known host; no special access.
|
||||
auto* config = config_map_->GetConfig(browser_context, url);
|
||||
if (!config)
|
||||
return nullptr; // Not a known host; no special access.
|
||||
|
||||
return config->CreateWebUIController(web_ui, url);
|
||||
```
|
||||
|
||||
and if a factory knows how to handle a host (returns a `WebUIFactoryFunction`),
|
||||
Configs can be registered with the map by calling `map.AddWebUIConfig()` in
|
||||
`chrome_web_ui_configs.cc`:
|
||||
```c++
|
||||
map.AddWebUIConfig(std::make_unique<donuts::DonutsUIConfig>());
|
||||
|
||||
```
|
||||
|
||||
If a factory knows how to handle a host (returns a `WebUIFactoryFunction`),
|
||||
the navigation machinery [grants the renderer process WebUI
|
||||
bindings](#bindings) via the child security policy.
|
||||
|
||||
@ -120,10 +132,24 @@ if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
|
||||
}
|
||||
```
|
||||
|
||||
The factory creates a [`WebUIController`](#WebUIController) for a tab.
|
||||
The factory creates a [`WebUIController`](#WebUIController) for a tab using
|
||||
the WebUIConfig.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```c++
|
||||
// Config for chrome://donuts
|
||||
DonutsUIConfig::DonutsUIConfig()
|
||||
: WebUIConfig(content::kChromeUIScheme, chrome::kChromeUIDonutsHost) {}
|
||||
|
||||
DonutsUIConfig::~DonutsUIConfig() = default;
|
||||
|
||||
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.
|
||||
class DonutsUI : public content::WebUIController {
|
||||
public:
|
||||
@ -190,6 +216,24 @@ Because they run in a separate process and can exist before a corresponding
|
||||
renderer process has been created, special care is required to communicate with
|
||||
the renderer if reliable message passing is required.
|
||||
|
||||
### WebUIConfig
|
||||
A `WebUIConfig` contains minimal possible logic and information for determining
|
||||
whether a certain subclass of `WebUIController` should be created for a given
|
||||
URL.
|
||||
|
||||
A `WebUIConfig` holds information about the host and scheme (`chrome://` or
|
||||
`chrome-untrusted://`) that the controller serves.
|
||||
|
||||
A `WebUIConfig` may contain logic to check if the WebUI is enabled for a given
|
||||
`BrowserContext` and url (e.g., if relevant feature flags are enabled/disabled,
|
||||
if the url path is valid, etc).
|
||||
|
||||
A `WebUIConfig` can invoke the `WebUIController`'s constructor in its
|
||||
`CreateWebUIControllerForURL` method.
|
||||
|
||||
`WebUIConfig`s are created at startup when factories are registered, so should
|
||||
be lightweight.
|
||||
|
||||
### WebUIController
|
||||
|
||||
A `WebUIController` is the brains of the operation, and is responsible for
|
||||
@ -200,9 +244,10 @@ pages, logic is often split across multiple
|
||||
controller for organizational benefits.
|
||||
|
||||
A `WebUIController` is owned by a [`WebUI`](#WebUI), and is created and set on
|
||||
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`).
|
||||
an existing [`WebUI`](#WebUI) when the corresponding `WebUIConfig` is found in
|
||||
the map matching the URL, or when the correct controller is determined via URL
|
||||
inspection in `ChromeWebUIControllerFactory`. (i.e. chrome://settings creates
|
||||
a generic [`WebUI`](#WebUI) with a settings-specific `WebUIController`).
|
||||
|
||||
### WebUIDataSource
|
||||
|
||||
@ -428,6 +473,9 @@ alongside the C++ code in chrome/browser/ui/webui. For example:
|
||||
```
|
||||
module donuts.mojom;
|
||||
|
||||
// Factory ensures that the Page and PageHandler interfaces are always created
|
||||
// together without requiring an initialization call from the WebUI to the
|
||||
// handler.
|
||||
interface PageHandlerFactory {
|
||||
CreatePageHandler(pending_remote<Page> page,
|
||||
pending_receiver<PageHandler> handler);
|
||||
|
@ -274,9 +274,51 @@ static_library("ui") {
|
||||
}
|
||||
```
|
||||
|
||||
### Adding your WebUI request handler to the Chrome WebUI factory
|
||||
### Option 1: Add a WebUIConfig class and put it in the WebUIConfigMap
|
||||
`WebUIConfig`s contain minimal information about the host and scheme served
|
||||
by the `WebUIController` subclass. You can create a `WebUIConfig` subclass
|
||||
and register it in the `WebUIConfigMap` to ensure your request handler is
|
||||
instantiated and used to handle any requests to the desired scheme + host.
|
||||
|
||||
The Chrome WebUI factory is where you setup your new request handler.
|
||||
`chrome/browser/ui/webui/hello_world/hello_world_ui.h`
|
||||
```c++
|
||||
class HelloWorldUIConfig : public content::WebUIConfig {
|
||||
public:
|
||||
HelloWorldUIConfig();
|
||||
~HelloWorldUIConfig() override;
|
||||
|
||||
// content::WebUIConfig:
|
||||
std::unique_ptr<content::WebUIController> CreateWebUIController(
|
||||
content::WebUI* web_ui,
|
||||
const GURL& url) override;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
`chrome/browser/ui/webui/hello_world/hello_world_ui.cc`
|
||||
```c++
|
||||
HelloWorldUIConfig::HelloWorldUIConfig()
|
||||
: WebUIConfig(content::kChromeUIScheme, chrome::kChromeUIHelloWorldHost) {}
|
||||
|
||||
HelloWorldUIConfig::~HelloWorldUIConfig() = default;
|
||||
|
||||
std::unique_ptr<content::WebUIController>
|
||||
HelloWorldUIConfig::CreateWebUIController(content::WebUI* web_ui,
|
||||
const GURL& url) {
|
||||
return std::make_unique<HelloWorldUI>(web_ui);
|
||||
}
|
||||
```
|
||||
|
||||
`chrome/browser/ui/webui/chrome_web_ui_configs.cc`
|
||||
```c++
|
||||
+ #include "chrome/browser/ui/webui/hello_world/hello_world_ui.h"
|
||||
...
|
||||
+map.AddWebUIConfig(std::make_unique<hello_world::HelloWorldUIConfig>());
|
||||
```
|
||||
|
||||
### Option 2: Add your WebUI request handler to the Chrome WebUI factory
|
||||
|
||||
The Chrome WebUI factory is another way to setup your new request handler.
|
||||
|
||||
`chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc:`
|
||||
```c++
|
||||
|
Reference in New Issue
Block a user