blob: 637308ec98974df6418905dc2a62098ff4b5bc97 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/user_education/feature_promo_registry.h"
#include "base/no_destructor.h"
#include "build/buildflag.h"
#include "build/chromeos_buildflags.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/browser/ui/user_education/feature_promo_bubble_params.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_controller.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "chrome/browser/ui/views/read_later/read_later_button.h"
#include "chrome/browser/ui/views/tab_search_bubble_host.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/common/buildflags.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/accelerators/accelerator.h"
#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
#include "chrome/browser/ui/views/frame/webui_tab_strip_container_view.h"
#endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
namespace {
// Functions to get an anchor view for an IPH should go here.
// kIPHDesktopPwaInstallFeature:
views::View* GetDesktopPwaInstallView(BrowserView* browser_view) {
return browser_view->toolbar()
->location_bar()
->page_action_icon_controller()
->GetIconView(PageActionIconType::kPwaInstall);
}
// kIPHUpdatedConnectionSecurityIndicatorsFeature:
views::View* GetLocationIconView(BrowserView* browser_view) {
return browser_view->toolbar()->location_bar()->location_icon_view();
}
// kIPHDesktopTabGroupsNewGroupFeature:
views::View* GetTabGroupsAnchorView(BrowserView* browser_view) {
constexpr int kPreferredAnchorTab = 2;
return browser_view->tabstrip()->GetTabViewForPromoAnchor(
kPreferredAnchorTab);
}
// kIPHLiveCaptionFeature:
views::View* GetMediaButton(BrowserView* browser_view) {
return browser_view->toolbar()->media_button();
}
// kIPHReadingListDiscoveryFeature:
views::View* GetReadingListButton(BrowserView* browser_view) {
if (browser_view->right_aligned_side_panel())
return browser_view->toolbar()->read_later_button();
if (browser_view->bookmark_bar()->read_later_button()->IsDrawn())
return browser_view->bookmark_bar()->read_later_button();
return nullptr;
}
// kIPHReadingListEntryPointFeature:
views::View* GetReadingListStarView(BrowserView* browser_view) {
return browser_view->toolbar()
->location_bar()
->page_action_icon_controller()
->GetIconView(PageActionIconType::kBookmarkStar);
}
// kIPHReadingListInSidePanelFeature:
views::View* GetSidePanelButton(BrowserView* browser_view) {
return browser_view->toolbar()->read_later_button();
}
// kIPHReopenTabFeature:
views::View* GetAppMenuButton(BrowserView* browser_view) {
return browser_view->toolbar()->app_menu_button();
}
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// kIPHProfileSwitchFeature:
views::View* GetAvatarToolbarButton(BrowserView* browser_view) {
return browser_view->toolbar_button_provider()->GetAvatarToolbarButton();
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
#if BUILDFLAG(ENABLE_SIDE_SEARCH)
// kIPHSideSearchFeature:
views::View* GetSideSearchButton(BrowserView* browser_view) {
return browser_view->toolbar()->left_side_panel_button();
}
#endif
// kIPHTabSearchFeature:
views::View* GetTabSearchButton(BrowserView* browser_view) {
auto* tab_search_host = browser_view->GetTabSearchBubbleHost();
return tab_search_host ? tab_search_host->button() : nullptr;
}
#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
// kIPHWebUITabStripFeature:
views::View* GetWebUITabStripAnchorView(BrowserView* browser_view) {
WebUITabStripContainerView* const webui_tab_strip =
browser_view->webui_tab_strip();
if (!webui_tab_strip)
return nullptr;
return webui_tab_strip->tab_counter();
}
#endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
} // namespace
FeaturePromoRegistry::FeaturePromoRegistry() {
RegisterKnownFeatures();
}
FeaturePromoRegistry::~FeaturePromoRegistry() = default;
// static
FeaturePromoRegistry* FeaturePromoRegistry::GetInstance() {
static base::NoDestructor<FeaturePromoRegistry> instance;
return instance.get();
}
absl::optional<std::pair<FeaturePromoBubbleParams, views::View*>>
FeaturePromoRegistry::GetParamsForFeature(const base::Feature& iph_feature,
BrowserView* browser_view) {
auto data_it = feature_promo_data_.find(&iph_feature);
DCHECK(data_it != feature_promo_data_.end());
views::View* const anchor_view =
data_it->second.get_anchor_view_callback.Run(browser_view);
if (!anchor_view)
return absl::nullopt;
FeaturePromoBubbleParams params = data_it->second.params;
if (params.feature_command_id) {
// Only one of the two should be specified.
DCHECK(!params.feature_accelerator);
int command_id = params.feature_command_id.value();
params.feature_command_id.reset();
// Get the actual accelerator from |browser_view|.
ui::Accelerator accelerator;
if (browser_view->GetAccelerator(command_id, &accelerator))
params.feature_accelerator = accelerator;
}
return std::make_pair(params, anchor_view);
}
void FeaturePromoRegistry::RegisterFeature(
const base::Feature& iph_feature,
const FeaturePromoBubbleParams& params,
GetAnchorViewCallback get_anchor_view_callback) {
FeaturePromoData data;
data.params = params;
data.get_anchor_view_callback = std::move(get_anchor_view_callback);
feature_promo_data_.emplace(&iph_feature, std::move(data));
}
void FeaturePromoRegistry::ClearFeaturesForTesting() {
feature_promo_data_.clear();
}
void FeaturePromoRegistry::ReinitializeForTesting() {
ClearFeaturesForTesting();
RegisterKnownFeatures();
}
void FeaturePromoRegistry::RegisterKnownFeatures() {
{
// kIPHDesktopPwaInstallFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_DESKTOP_PWA_INSTALL_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHDesktopPwaInstallFeature, params,
base::BindRepeating(GetDesktopPwaInstallView));
}
{
// kIPHUpdatedConnectionSecurityIndicatorsFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier =
IDS_UPDATED_CONNECTION_SECURITY_INDICATORS_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_LEFT;
RegisterFeature(
feature_engagement::kIPHUpdatedConnectionSecurityIndicatorsFeature,
params, base::BindRepeating(GetLocationIconView));
}
{
// kIPHDesktopTabGroupsNewGroupFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_TAB_GROUPS_NEW_GROUP_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_CENTER;
// Turn on IPH Snooze for Tab Group.
if (base::FeatureList::IsEnabled(
feature_engagement::kIPHDesktopSnoozeFeature)) {
params.focus_on_create = true;
params.allow_snooze = true;
}
RegisterFeature(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
params, base::BindRepeating(GetTabGroupsAnchorView));
}
{
// kIPHLiveCaptionFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_LIVE_CAPTION_PROMO;
params.screenreader_string_specifier = IDS_LIVE_CAPTION_PROMO_SCREENREADER;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHLiveCaptionFeature, params,
base::BindRepeating(GetMediaButton));
}
{
// kIPHGMCCastStartStopFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier =
IDS_GLOBAL_MEDIA_CONTROLS_CONTROL_CAST_SESSIONS_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHGMCCastStartStopFeature, params,
base::BindRepeating(GetMediaButton));
}
#if !BUILDFLAG(IS_CHROMEOS_ASH)
{
// kIPHSwitchProfileFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_PROFILE_SWITCH_PROMO;
params.screenreader_string_specifier =
IDS_PROFILE_SWITCH_PROMO_SCREENREADER;
params.feature_command_id = IDC_SHOW_AVATAR_MENU;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHProfileSwitchFeature, params,
base::BindRepeating(GetAvatarToolbarButton));
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
{
// kReadingListDiscoveryFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_READING_LIST_DISCOVERY_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHReadingListDiscoveryFeature, params,
base::BindRepeating(GetReadingListButton));
}
{
// kIPHReadingListEntryPointFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_READING_LIST_ENTRY_POINT_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
// Turn on IPH Snooze for Read Later entry point.
if (base::FeatureList::IsEnabled(
feature_engagement::kIPHDesktopSnoozeFeature)) {
params.focus_on_create = true;
params.allow_snooze = true;
}
RegisterFeature(feature_engagement::kIPHReadingListEntryPointFeature,
params, base::BindRepeating(GetReadingListStarView));
}
{
// kIPHReadingListInSidePanelFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_READING_LIST_IN_SIDE_PANEL_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHReadingListInSidePanelFeature,
params, base::BindRepeating(GetSidePanelButton));
}
{
// kIPHReopenTabFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_REOPEN_TAB_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
params.feature_command_id = IDC_RESTORE_TAB;
RegisterFeature(feature_engagement::kIPHReopenTabFeature, params,
base::BindRepeating(GetAppMenuButton));
}
#if BUILDFLAG(ENABLE_SIDE_SEARCH)
{
// kIPHSideSearchFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_SIDE_SEARCH_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_LEFT;
RegisterFeature(feature_engagement::kIPHSideSearchFeature, params,
base::BindRepeating(GetSideSearchButton));
}
#endif
{
// kIPHTabSearchFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_TAB_SEARCH_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHTabSearchFeature, params,
base::BindRepeating(GetTabSearchButton));
}
#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
{
// kIPHWebUITabStripFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_WEBUI_TAB_STRIP_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHWebUITabStripFeature, params,
base::BindRepeating(GetWebUITabStripAnchorView));
}
#endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
}
FeaturePromoRegistry::FeaturePromoData::FeaturePromoData() = default;
FeaturePromoRegistry::FeaturePromoData::FeaturePromoData(FeaturePromoData&&) =
default;
FeaturePromoRegistry::FeaturePromoData::~FeaturePromoData() = default;