1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// 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.
#ifndef CHROME_BROWSER_UI_VIEWS_USER_EDUCATION_CUSTOM_WEBUI_HELP_BUBBLE_H_
#define CHROME_BROWSER_UI_VIEWS_USER_EDUCATION_CUSTOM_WEBUI_HELP_BUBBLE_H_
#include "base/functional/callback_forward.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h"
#include "chrome/browser/ui/views/user_education/custom_webui_help_bubble_controller.h"
#include "chrome/browser/ui/webui/top_chrome/webui_contents_wrapper.h"
#include "components/strings/grit/components_strings.h"
#include "components/user_education/common/feature_promo/feature_promo_specification.h"
#include "components/user_education/common/help_bubble/help_bubble_params.h"
#include "components/user_education/views/help_bubble_views.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/interaction/element_tracker.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/interaction/element_tracker_views.h"
#include "url/gurl.h"
// Class that wraps a WebUI whose controller is a `CustomHelpBubbleUi` in a
// dialog and shows it as a help bubble.
//
// Most of the time you will want to use the function
// `MakeCustomWebUIHelpBubbleFactoryCallback()` below to tell the User Education
// system how to create your custom IPH UI, rather than using this class
// directly.
class CustomWebUIHelpBubble : public user_education::CustomHelpBubbleViews {
public:
~CustomWebUIHelpBubble() override;
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kHelpBubbleIdForTesting);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kWebViewIdForTesting);
// Most WebUI custom help bubbles should be fine using a vanilla
// `WebUIBubbleDialogView`, but this allows you to override that with your own
// derived class when constructing a custom WebUI-based help bubble, in case
// you need to e.g. change preferred size behavior.
using BuildCustomWebUIHelpBubbleViewCallback =
base::RepeatingCallback<std::unique_ptr<WebUIBubbleDialogView>(
views::View* anchor_view,
views::BubbleBorder::Arrow arrow,
base::WeakPtr<WebUIContentsWrapper> contents_wrapper)>;
static BuildCustomWebUIHelpBubbleViewCallback
GetDefaultBuildBubbleViewCallback();
// Method for constructing a `CustomWebUIHelpBubble` from a set of parameters.
// Used by `MakeCustomWebUIHelpBubbleFactoryCallback()`; you probably don't
// need to call this directly.
template <typename T>
requires IsCustomWebUIHelpBubbleController<T>
static std::unique_ptr<CustomWebUIHelpBubble> CreateForController(
const GURL& webui_url,
ui::ElementContext from_context,
user_education::HelpBubbleArrow arrow,
user_education::FeaturePromoSpecification::BuildHelpBubbleParams params,
const BuildCustomWebUIHelpBubbleViewCallback& build_bubble_view_callback =
GetDefaultBuildBubbleViewCallback());
protected:
template <typename T>
requires IsCustomWebUIHelpBubbleController<T>
CustomWebUIHelpBubble(std::unique_ptr<views::Widget> widget,
WebUIBubbleDialogView* bubble,
std::unique_ptr<WebUIContentsWrapperT<T>> wrapper,
ui::TrackedElement* anchor_element);
private:
std::unique_ptr<WebUIContentsWrapper> wrapper_;
};
template <typename T>
requires IsCustomWebUIHelpBubbleController<T>
user_education::FeaturePromoSpecification::CustomHelpBubbleFactoryCallback<
CustomWebUIHelpBubble>
MakeCustomWebUIHelpBubbleFactoryCallback(
GURL webui_url,
const CustomWebUIHelpBubble::BuildCustomWebUIHelpBubbleViewCallback&
build_bubble_view_callback =
CustomWebUIHelpBubble::GetDefaultBuildBubbleViewCallback()) {
return base::BindRepeating(
[](const GURL& webui_url,
const CustomWebUIHelpBubble::BuildCustomWebUIHelpBubbleViewCallback&
build_bubble_view_callback,
ui::ElementContext from_context, user_education::HelpBubbleArrow arrow,
user_education::FeaturePromoSpecification::BuildHelpBubbleParams
params) {
auto bubble = CustomWebUIHelpBubble::CreateForController<T>(
webui_url, from_context, arrow, std::move(params),
build_bubble_view_callback);
return bubble;
},
webui_url, build_bubble_view_callback);
}
// Template class member definitions.
template <typename T>
requires IsCustomWebUIHelpBubbleController<T>
CustomWebUIHelpBubble::CustomWebUIHelpBubble(
std::unique_ptr<views::Widget> widget,
WebUIBubbleDialogView* bubble,
std::unique_ptr<WebUIContentsWrapperT<T>> wrapper,
ui::TrackedElement* anchor_element)
: CustomHelpBubbleViews(std::move(widget),
bubble,
*wrapper->GetWebUIController(),
anchor_element,
std::nullopt,
std::nullopt),
wrapper_(std::move(wrapper)) {}
// static
template <typename T>
requires IsCustomWebUIHelpBubbleController<T>
std::unique_ptr<CustomWebUIHelpBubble>
CustomWebUIHelpBubble::CreateForController(
const GURL& webui_url,
ui::ElementContext from_context,
user_education::HelpBubbleArrow arrow,
user_education::FeaturePromoSpecification::BuildHelpBubbleParams params,
const BuildCustomWebUIHelpBubbleViewCallback& build_bubble_view_callback) {
Browser* const browser =
chrome::FindBrowserWithUiElementContext(from_context); // NOLINT
CHECK(browser);
auto wrapper = std::make_unique<WebUIContentsWrapperT<T>>(
webui_url, browser->profile(), IDS_HELP_BUBBLE);
auto ui = wrapper->GetWebUIController()->GetCustomUiAsWeakPtr();
auto bubble_ptr = build_bubble_view_callback.Run(
params.anchor_element->AsA<views::TrackedElementViews>()->view(),
user_education::HelpBubbleViews::TranslateArrow(arrow),
wrapper->GetWeakPtr());
auto* const bubble = bubble_ptr.get();
auto widget = base::WrapUnique(views::BubbleDialogDelegateView::CreateBubble(
std::move(bubble_ptr), views::Widget::InitParams::CLIENT_OWNS_WIDGET));
wrapper->ShowUI();
return base::WrapUnique(new CustomWebUIHelpBubble(
std::move(widget), bubble, std::move(wrapper), params.anchor_element));
}
#endif // CHROME_BROWSER_UI_VIEWS_USER_EDUCATION_CUSTOM_WEBUI_HELP_BUBBLE_H_
|