blob: 36613efbb32e4af32a421baa70591976c44b76bd [file] [log] [blame]
// Copyright 2024 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/toasts/toast_service.h"
#include <memory>
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/commerce/commerce_ui_tab_helper.h"
#include "chrome/browser/ui/tabs/public/tab_features.h"
#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_observer.h"
#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_observer_factory.h"
#include "chrome/browser/ui/toasts/api/toast_id.h"
#include "chrome/browser/ui/toasts/api/toast_registry.h"
#include "chrome/browser/ui/toasts/api/toast_specification.h"
#include "chrome/browser/ui/toasts/toast_controller.h"
#include "chrome/browser/ui/toasts/toast_features.h"
#include "chrome/browser/ui/views/side_panel/side_panel_entry_id.h"
#include "chrome/browser/ui/views/side_panel/side_panel_enums.h"
#include "chrome/browser/ui/views/side_panel/side_panel_ui.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/branded_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/commerce/core/commerce_feature_list.h"
#include "components/data_sharing/public/features.h"
#include "components/omnibox/browser/vector_icons.h"
#include "components/plus_addresses/core/browser/grit/plus_addresses_strings.h"
#include "components/plus_addresses/core/common/features.h"
#include "components/safe_browsing/core/common/features.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/strings/grit/components_strings.h"
#include "components/tabs/public/tab_interface.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/menus/simple_menu_model.h"
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "components/plus_addresses/core/browser/resources/vector_icons.h"
#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
ToastService::ToastService(BrowserWindowInterface* browser_window_interface) {
toast_registry_ = std::make_unique<ToastRegistry>();
toast_controller_ = std::make_unique<ToastController>(
browser_window_interface, toast_registry_.get());
toast_controller_->Init();
RegisterToasts(browser_window_interface);
}
ToastService::~ToastService() = default;
void ToastService::RegisterToasts(
BrowserWindowInterface* browser_window_interface) {
CHECK(toast_registry_->IsEmpty());
toast_registry_->RegisterToast(
ToastId::kLinkCopied,
ToastSpecification::Builder(kLinkChromeRefreshIcon,
IDS_LINK_COPIED_TOAST_BODY)
.Build());
toast_registry_->RegisterToast(
ToastId::kImageCopied,
ToastSpecification::Builder(kCopyMenuIcon, IDS_IMAGE_COPIED_TOAST_BODY)
.Build());
toast_registry_->RegisterToast(
ToastId::kVideoFrameCopied,
ToastSpecification::Builder(kCopyMenuIcon,
IDS_VIDEO_FRAME_COPIED_TOAST_BODY)
.Build());
toast_registry_->RegisterToast(
ToastId::kLinkToHighlightCopied,
ToastSpecification::Builder(kLinkChromeRefreshIcon,
IDS_LINK_COPIED_TO_HIGHLIGHT_TOAST_BODY)
.Build());
toast_registry_->RegisterToast(
ToastId::kAddedToReadingList,
ToastSpecification::Builder(kReadingListIcon, IDS_READING_LIST_TOAST_BODY)
.AddActionButton(IDS_READING_LIST_TOAST_BUTTON,
base::BindRepeating(
[](BrowserWindowInterface* window) {
window->GetFeatures().side_panel_ui()->Show(
SidePanelEntryId::kReadingList,
SidePanelOpenTrigger::kReadingListToast);
},
base::Unretained(browser_window_interface)))
.AddCloseButton()
.Build());
toast_registry_->RegisterToast(
ToastId::kClearBrowsingData,
ToastSpecification::Builder(kTrashCanRefreshIcon,
IDS_CLEAR_BROWSING_DATA_TOAST_BODY)
.Build());
// TODO(crbug.com/357930023): This registration only partially implements the
// non-milestone update toast for testing purposes and will need to be
// updated.
toast_registry_->RegisterToast(
ToastId::kNonMilestoneUpdate,
ToastSpecification::Builder(kBrowserLogoIcon,
IDS_NON_MILESTONE_UPDATE_TOAST_BODY)
.AddGlobalScoped()
.Build());
if (base::FeatureList::IsEnabled(commerce::kProductSpecifications)) {
toast_registry_->RegisterToast(
ToastId::kAddedToComparisonTable,
ToastSpecification::Builder(omnibox::kProductSpecificationsAddedIcon,
IDS_COMPARE_PAGE_ACTION_ADDED)
.AddCloseButton()
.AddActionButton(IDS_COMPARE_ADDED_TO_TABLE_TOAST_ACTION_BUTTON,
base::BindRepeating(
[](BrowserWindowInterface* window) {
window->GetActiveTabInterface()
->GetTabFeatures()
->commerce_ui_tab_helper()
->OnOpenComparePageClicked();
},
base::Unretained(browser_window_interface)))
.Build());
}
if (base::FeatureList::IsEnabled(
plus_addresses::features::kPlusAddressesEnabled)) {
toast_registry_->RegisterToast(
ToastId::kPlusAddressOverride,
ToastSpecification::Builder(
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
plus_addresses::kPlusAddressLogoSmallIcon,
#else
vector_icons::kEmailIcon,
#endif
IDS_PLUS_ADDRESS_FULL_FORM_FILL_TOAST_MESSAGE)
.AddMenu()
.Build());
}
// ESB as a synced setting.
if (base::FeatureList::IsEnabled(safe_browsing::kEsbAsASyncedSetting)) {
toast_registry_->RegisterToast(
ToastId::kSyncEsbOn,
ToastSpecification::Builder(
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
vector_icons::kGshieldIcon,
#else
kSecurityIcon,
#endif
IDS_SETTINGS_SAFEBROWSING_ENHANCED_ON_TOAST_MESSAGE)
.AddActionButton(
IDS_SETTINGS_SETTINGS,
base::BindRepeating(
[](BrowserWindowInterface* window) {
window->OpenGURL(
chrome::GetSettingsUrl(
chrome::kSafeBrowsingEnhancedProtectionSubPage),
WindowOpenDisposition::NEW_FOREGROUND_TAB);
},
base::Unretained(browser_window_interface)))
.AddCloseButton()
.Build());
toast_registry_->RegisterToast(
ToastId::kSyncEsbOnWithoutActionButton,
ToastSpecification::Builder(
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
vector_icons::kGshieldIcon,
#else
kSecurityIcon,
#endif
IDS_SETTINGS_SAFEBROWSING_ENHANCED_ON_TOAST_MESSAGE)
.Build());
toast_registry_->RegisterToast(
ToastId::kSyncEsbOff,
ToastSpecification::Builder(
kInfoIcon, IDS_SETTINGS_SAFEBROWSING_ENHANCED_OFF_TOAST_MESSAGE)
.AddActionButton(
IDS_SETTINGS_SAFEBROWSING_TURN_ON_ENHANCED_TOAST_BUTTON,
base::BindRepeating(
[](BrowserWindowInterface* window) {
Profile* profile = window->GetProfile();
if (profile) {
profile->GetPrefs()->SetBoolean(
prefs::kSafeBrowsingEnhanced, true);
}
},
base::Unretained(browser_window_interface)))
.AddCloseButton()
.Build());
}
if (data_sharing::features::IsDataSharingFunctionalityEnabled()) {
// Current tab has been removed from the group.
toast_registry_->RegisterToast(
ToastId::kTabGroupSyncTabRemoved,
ToastSpecification::Builder(kAccountCircleChromeRefreshIcon,
IDS_DATA_SHARING_TOAST_TAB_REMOVED)
.AddCloseButton()
.AddActionButton(
IDS_DATA_SHARING_TOAST_TAB_REMOVED_ACTION,
base::BindRepeating(
[](BrowserWindowInterface* window) {
Profile* profile = window->GetProfile();
auto* collaboration_messaging_observer =
tab_groups::CollaborationMessagingObserverFactory::
GetForProfile(profile);
if (collaboration_messaging_observer) {
collaboration_messaging_observer
->ReopenTabForCurrentInstantMessage();
}
},
base::Unretained(browser_window_interface)))
.AddGlobalScoped()
.Build());
// Another user has joined an open group (global)
toast_registry_->RegisterToast(
ToastId::kTabGroupSyncUserJoined,
ToastSpecification::Builder(kAccountCircleChromeRefreshIcon,
IDS_DATA_SHARING_TOAST_NEW_MEMBER)
.AddCloseButton()
.AddActionButton(
IDS_DATA_SHARING_TOAST_NEW_MEMBER_ACTION,
base::BindRepeating(
[](BrowserWindowInterface* window) {
Profile* profile = window->GetProfile();
auto* collaboration_messaging_observer =
tab_groups::CollaborationMessagingObserverFactory::
GetForProfile(profile);
if (collaboration_messaging_observer) {
collaboration_messaging_observer
->ManageSharingForCurrentInstantMessage(window);
}
},
base::Unretained(browser_window_interface)))
.AddGlobalScoped()
.Build());
// Profile has been removed from open group (global)
toast_registry_->RegisterToast(
ToastId::kTabGroupSyncRemovedFromGroup,
ToastSpecification::Builder(kTabGroupSharingIcon,
IDS_DATA_SHARING_TOAST_BLOCK_LEAVE)
.AddGlobalScoped()
.Build());
// The version has been updated and shared tab groups is enabled again.
toast_registry_->RegisterToast(
ToastId::kTabGroupSharingVersionUpToDate,
ToastSpecification::Builder(
kTabGroupSharingIcon,
IDS_COLLABORATION_SHARED_TAB_GROUPS_AVAILABLE_AGAIN_IPH_MESSAGE)
.AddGlobalScoped()
.Build());
}
toast_registry_->RegisterToast(
ToastId::kClosePinnedTab,
ToastSpecification::Builder(kKeepIcon, IDS_CLOSE_PINNED_TAB_TOAST_BODY)
.SetToastAsActionable()
.Build());
if (features::kGlicActorUiToast.Get()) {
toast_registry_->RegisterToast(
ToastId::kGeminiWorkingOnTask,
ToastSpecification::Builder(kScreensaverAutoIcon,
IDS_GEMINI_WORKING_ON_TASK_BODY)
.AddCloseButton()
.Build());
}
toast_registry_->RegisterToast(
ToastId::kDiceUserMigrated,
ToastSpecification::Builder(vector_icons::kCelebrationIcon,
IDS_DICE_MIGRATION_CONFIRMATION_TOAST_MESSAGE)
.AddCloseButton()
.AddActionButton(IDS_DICE_MIGRATION_CONFIRMATION_TOAST_BUTTON,
base::BindRepeating(
[](BrowserWindowInterface* window) {
chrome::ShowSettingsSubPageForProfile(
window->GetProfile(),
chrome::kSyncSetupSubPage);
},
base::Unretained(browser_window_interface)))
.AddGlobalScoped()
.Build());
toast_registry_->RegisterToast(
ToastId::kEmailVerified,
ToastSpecification::Builder(vector_icons::kEmailIcon, IDS_EMAIL_VERIFIED)
.AddCloseButton()
.Build());
toast_registry_->RegisterToast(
ToastId::kGlicShareImageFailed,
ToastSpecification::Builder(vector_icons::kInfoRefreshIcon,
IDS_GLIC_SHARE_IMAGE_FAILED_TOAST_BODY)
.AddCloseButton()
.Build());
} // RegisterToasts() end.