| // Copyright 2025 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/webui_browser/webui_browser_ui.h" |
| |
| #include "base/notimplemented.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/bookmarks/bookmark_bar_controller.h" |
| #include "chrome/browser/ui/browser_element_identifiers.h" |
| #include "chrome/browser/ui/browser_window/public/browser_window_features.h" |
| #include "chrome/browser/ui/interaction/browser_elements.h" |
| #include "chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_feature.h" |
| #include "chrome/browser/ui/views/side_panel/side_panel_entry_id.h" |
| #include "chrome/browser/ui/webui/searchbox/realbox_handler.h" |
| #include "chrome/browser/ui/webui/searchbox/searchbox_handler.h" |
| #include "chrome/browser/ui/webui_browser/bookmark_bar_page_handler.h" |
| #include "chrome/browser/ui/webui_browser/webui_browser.h" |
| #include "chrome/browser/ui/webui_browser/webui_browser_extensions_container.h" |
| #include "chrome/browser/ui/webui_browser/webui_browser_page_handler.h" |
| #include "chrome/browser/ui/webui_browser/webui_browser_side_panel_ui.h" |
| #include "chrome/common/webui_url_constants.h" |
| #include "chrome/grit/branded_strings.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chrome/grit/tab_strip_api_resources_map.h" |
| #include "chrome/grit/webui_browser_resources.h" |
| #include "chrome/grit/webui_browser_resources_map.h" |
| #include "components/guest_contents/browser/guest_contents_host_impl.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_ui.h" |
| #include "content/public/browser/web_ui_data_source.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/views/interaction/element_tracker_views.h" |
| #include "ui/webui/tracked_element/tracked_element_handler.h" |
| #include "ui/webui/webui_util.h" |
| |
| namespace { |
| |
| std::string SidePanelEntryIdToTitle(SidePanelEntryId id) { |
| // TODO(webium): Ideally, the titles should be added to SIDE_PANEL_ENTRY_IDS |
| // macros in chrome/browser/ui/views/side_panel/side_panel_entry_id.h, and |
| // then this conversion function would be written in that same file, |
| // analogously to the other functions it contains. But it appears that some |
| // of the entry ids there are stale and no longer have a matching generated |
| // IDS_*_TITLE string that we can include. |
| // |
| // Since we are currently only explicitly supporting three side panel types, |
| // we do the id to title conversion here manually to minimize modification to |
| // existing code. |
| switch (id) { |
| case SidePanelEntryId::kCustomizeChrome: |
| return l10n_util::GetStringUTF8(IDS_SIDE_PANEL_CUSTOMIZE_CHROME_TITLE); |
| case SidePanelEntryId::kReadingList: |
| return l10n_util::GetStringUTF8(IDS_READ_LATER_TITLE); |
| case SidePanelEntryId::kBookmarks: |
| return l10n_util::GetStringUTF8(IDS_BOOKMARK_MANAGER_TITLE); |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| } // namespace |
| |
| WebUIBrowserUIConfig::WebUIBrowserUIConfig() |
| : DefaultWebUIConfig(content::kChromeUIScheme, |
| chrome::kChromeUIWebuiBrowserHost) {} |
| |
| bool WebUIBrowserUIConfig::IsWebUIEnabled( |
| content::BrowserContext* browser_context) { |
| return webui_browser::IsWebUIBrowserEnabled(); |
| } |
| |
| // realbox uses ui/webui/resources/js/metrics_reporter, which in turn uses |
| // chrome.timeTicks.nowInMicroseconds(). In order to provide it we pass |
| // enable_chrome_send to MojoWebUIController constructor, since they're |
| // a package deal via BindingsPolicyValue::kWebUi. |
| WebUIBrowserUI::WebUIBrowserUI(content::WebUI* web_ui) |
| : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true) { |
| WebUIBrowserWindow* webui_browser_window = |
| WebUIBrowserWindow::FromWebShellWebContents(web_ui->GetWebContents()); |
| browser_ = webui_browser_window->browser(); |
| |
| // Set up the chrome://webui-browser source. |
| content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd( |
| web_ui->GetWebContents()->GetBrowserContext(), |
| chrome::kChromeUIWebuiBrowserHost); |
| |
| // Add required resources. |
| webui::SetupWebUIDataSource(source, kWebuiBrowserResources, |
| IDR_WEBUI_BROWSER_WEBUI_BROWSER_HTML); |
| source->AddResourcePaths(kTabStripApiResources); |
| |
| static constexpr webui::LocalizedString kStrings[] = { |
| // Localized strings (alphabetical order). |
| {"appMenuTooltip", IDS_APPMENU_TOOLTIP}, |
| {"tooltipExtensionsButton", IDS_TOOLTIP_EXTENSIONS_BUTTON}, |
| {"tooltipNewTab", IDS_TOOLTIP_NEW_TAB}, |
| {"tooltipReload", IDS_TOOLTIP_RELOAD}, |
| {"tooltipStop", IDS_TOOLTIP_STOP}, |
| }; |
| source->AddLocalizedStrings(kStrings); |
| |
| SearchboxHandler::SetupWebUIDataSource(source, Profile::FromWebUI(web_ui)); |
| } |
| |
| WebUIBrowserUI::~WebUIBrowserUI() = default; |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<webui_browser::mojom::PageHandlerFactory> receiver) { |
| page_factory_receiver_.reset(); |
| page_factory_receiver_.Bind(std::move(receiver)); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<bookmark_bar::mojom::PageHandlerFactory> receiver) { |
| bookmark_bar_page_factory_receiver_.reset(); |
| bookmark_bar_page_factory_receiver_.Bind(std::move(receiver)); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<extensions_bar::mojom::PageHandlerFactory> receiver) { |
| extensions_bar_page_factory_receiver_.reset(); |
| extensions_bar_page_factory_receiver_.Bind(std::move(receiver)); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<searchbox::mojom::PageHandler> pending_page_handler) { |
| content::WebUI* webui = web_ui(); |
| content::WebContents* web_contents = webui->GetWebContents(); |
| realbox_handler_ = std::make_unique<RealboxHandler>( |
| std::move(pending_page_handler), /*query_controller=*/nullptr, |
| /*composebox_metrics_recorder=*/nullptr, Profile::FromWebUI(webui), |
| web_contents, &metrics_reporter_); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<metrics_reporter::mojom::PageMetricsHost> receiver) { |
| metrics_reporter_.BindInterface(std::move(receiver)); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<guest_contents::mojom::GuestContentsHost> receiver) { |
| guest_contents::GuestContentsHostImpl::Create(web_ui()->GetWebContents(), |
| std::move(receiver)); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<tabs_api::mojom::TabStripService> receiver) { |
| auto* tab_strip_service_feature = |
| browser_->browser_window_features()->tab_strip_service_feature(); |
| CHECK(tab_strip_service_feature) |
| << "Browser missing TabStripService, did you enable " |
| "TabStripBrowserApi feature flag?"; |
| tab_strip_service_feature->Accept(std::move(receiver)); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<tracked_element::mojom::TrackedElementHandler> |
| receiver) { |
| const ui::ElementContext context = |
| BrowserElements::From(browser_)->GetContext(); |
| tracked_element_handler_ = std::make_unique<ui::TrackedElementHandler>( |
| web_ui()->GetWebContents(), std::move(receiver), context, |
| GetKnownElementIdentifiers()); |
| } |
| |
| void WebUIBrowserUI::BindInterface( |
| mojo::PendingReceiver<color_change_listener::mojom::PageHandler> receiver) { |
| color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>( |
| web_ui()->GetWebContents(), std::move(receiver)); |
| } |
| |
| base::WeakPtr<WebUIBrowserUI> WebUIBrowserUI::GetWeakPtr() { |
| return weak_factory_.GetWeakPtr(); |
| } |
| |
| void WebUIBrowserUI::CreatePageHandler( |
| mojo::PendingRemote<webui_browser::mojom::Page> page, |
| mojo::PendingReceiver<webui_browser::mojom::PageHandler> receiver) { |
| page_.reset(); |
| page_.Bind(std::move(page)); |
| auto* render_frame_host = web_ui()->GetRenderFrameHost(); |
| WebUIBrowserPageHandler::CreateForRenderFrameHost(*render_frame_host, |
| std::move(receiver), this); |
| } |
| |
| void WebUIBrowserUI::CreatePageHandler( |
| mojo::PendingRemote<bookmark_bar::mojom::Page> page, |
| mojo::PendingReceiver<bookmark_bar::mojom::PageHandler> receiver) { |
| bookmark_bar_page_handler_ = |
| std::make_unique<WebUIBrowserBookmarkBarPageHandler>( |
| std::move(receiver), std::move(page), web_ui(), browser_); |
| } |
| |
| void WebUIBrowserUI::CreatePageHandler( |
| mojo::PendingRemote<extensions_bar::mojom::Page> page, |
| mojo::PendingReceiver<extensions_bar::mojom::PageHandler> receiver) { |
| static_cast<WebUIBrowserExtensionsContainer*>( |
| browser_window()->GetExtensionsContainer()) |
| ->Bind(std::move(page), std::move(receiver)); |
| } |
| |
| const std::vector<ui::ElementIdentifier>& |
| WebUIBrowserUI::GetKnownElementIdentifiers() const { |
| static const std::vector<ui::ElementIdentifier> kKnownElementIdentifiers{ |
| kContentsContainerViewElementId, kExtensionsMenuButtonElementId, |
| kLocationBarElementId, kLocationIconElementId, |
| kToolbarAppMenuButtonElementId, kToolbarAvatarButtonElementId}; |
| return kKnownElementIdentifiers; |
| } |
| |
| void WebUIBrowserUI::BookmarkBarStateChanged( |
| BookmarkBar::AnimateChangeType change_type) { |
| if (bookmark_bar_page_handler_) { |
| bookmark_bar_page_handler_->SetBookmarkBarState( |
| BookmarkBarController::From(browser_)->bookmark_bar_state(), |
| change_type); |
| } |
| } |
| |
| void WebUIBrowserUI::ShowSidePanel(SidePanelEntryKey side_panel_entry_key) { |
| // Create guest contents. |
| WebUIBrowserSidePanelUI* side_panel_ui = |
| browser_window()->GetWebUIBrowserSidePanelUI(); |
| content::WebContents* web_contents = |
| side_panel_ui->GetWebContentsForId(side_panel_entry_key.id()); |
| web_contents->SetColorProviderSource(browser_window()); |
| CHECK(web_contents); |
| auto* guest_handle = |
| guest_contents::GuestContentsHandle::CreateForWebContents(web_contents); |
| |
| // Notify JS. |
| page_->ShowSidePanel(guest_handle->id(), |
| SidePanelEntryIdToTitle(side_panel_entry_key.id())); |
| } |
| |
| void WebUIBrowserUI::CloseSidePanel() { |
| page_->CloseSidePanel(); |
| } |
| |
| WEB_UI_CONTROLLER_TYPE_IMPL(WebUIBrowserUI) |