| // Copyright 2022 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/side_panel/bookmarks/bookmarks_side_panel_ui.h" |
| |
| #include <string> |
| #include <utility> |
| |
| #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/commerce/shopping_service_factory.h" |
| #include "chrome/browser/feature_engagement/tracker_factory.h" |
| #include "chrome/browser/image_service/image_service_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profiles_state.h" |
| #include "chrome/browser/ui/ui_features.h" |
| #include "chrome/browser/ui/webui/bookmarks/bookmark_prefs.h" |
| #include "chrome/browser/ui/webui/commerce/shopping_list_context_menu_controller.h" |
| #include "chrome/browser/ui/webui/favicon_source.h" |
| #include "chrome/browser/ui/webui/plural_string_handler.h" |
| #include "chrome/browser/ui/webui/sanitized_image_source.h" |
| #include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h" |
| #include "chrome/browser/ui/webui/webui_util.h" |
| #include "chrome/common/webui_url_constants.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chrome/grit/side_panel_bookmarks_resources.h" |
| #include "chrome/grit/side_panel_bookmarks_resources_map.h" |
| #include "chrome/grit/side_panel_shared_resources.h" |
| #include "chrome/grit/side_panel_shared_resources_map.h" |
| #include "components/bookmarks/browser/bookmark_model.h" |
| #include "components/bookmarks/browser/bookmark_node.h" |
| #include "components/bookmarks/common/bookmark_pref_names.h" |
| #include "components/bookmarks/managed/managed_bookmark_service.h" |
| #include "components/commerce/core/commerce_feature_list.h" |
| #include "components/commerce/core/shopping_service.h" |
| #include "components/commerce/core/webui/shopping_list_handler.h" |
| #include "components/favicon_base/favicon_url_parser.h" |
| #include "components/page_image_service/features.h" |
| #include "components/page_image_service/image_service.h" |
| #include "components/page_image_service/image_service_handler.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/strings/grit/components_strings.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/accessibility/accessibility_features.h" |
| #include "ui/base/ui_base_features.h" |
| #include "ui/base/webui/web_ui_util.h" |
| #include "ui/views/style/platform_style.h" |
| #include "ui/webui/color_change_listener/color_change_handler.h" |
| |
| BookmarksSidePanelUI::BookmarksSidePanelUI(content::WebUI* web_ui) |
| : ui::MojoBubbleWebUIController(web_ui, true) { |
| Profile* const profile = Profile::FromWebUI(web_ui); |
| content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd( |
| profile, chrome::kChromeUIBookmarksSidePanelHost); |
| static constexpr webui::LocalizedString kLocalizedStrings[] = { |
| {"bookmarksTabTitle", IDS_BOOKMARK_MANAGER_TITLE}, |
| {"bookmarkCopied", IDS_BOOKMARK_MANAGER_TOAST_ITEM_COPIED}, |
| {"bookmarkDeleted", IDS_BOOKMARK_MANAGER_TOAST_ITEM_DELETED}, |
| {"bookmarkCreated", IDS_BOOKMARK_SCREEN_READER_CREATED}, |
| {"bookmarkFolderCreated", IDS_BOOKMARK_SCREEN_READER_FOLDER_CREATED}, |
| {"bookmarkReordered", IDS_BOOKMARK_SCREEN_READER_REORDERED}, |
| {"bookmarkMoved", IDS_BOOKMARK_SCREEN_READER_MOVED}, |
| {"tooltipClose", IDS_CLOSE}, |
| {"tooltipDelete", IDS_DELETE}, |
| {"tooltipMore", IDS_BOOKMARKS_EDIT_MORE}, |
| {"tooltipMove", IDS_BOOKMARKS_EDIT_MOVE_TO_ANOTHER_FOLDER}, |
| {"tooltipOrganize", IDS_BOOKMARK_MANAGER_ORGANIZE_MENU}, |
| {"tooltipNewFolder", IDS_BOOKMARKS_NEW_FOLDER_TOOLTIP}, |
| {"tooltipEdit", IDS_EDIT}, |
| {"tooltipBack", IDS_BOOKMARKS_BACK_BUTTON_TOOLTIP}, |
| {"shoppingListFolderTitle", IDS_SIDE_PANEL_TRACKED_PRODUCTS}, |
| {"shoppingListTrackPriceButtonDescription", |
| IDS_PRICE_TRACKING_TRACK_PRODUCT_ACCESSIBILITY}, |
| {"shoppingListUntrackPriceButtonDescription", |
| IDS_PRICE_TRACKING_UNTRACK_PRODUCT_ACCESSIBILITY}, |
| {"shoppingListErrorMessage", IDS_PRICE_TRACKING_SIDE_PANEL_ERROR_MESSAGE}, |
| {"shoppingListErrorButton", IDS_PRICE_TRACKING_SIDE_PANEL_ERROR_BUTTON}, |
| {"sortByType", IDS_BOOKMARKS_SORT_BY_TYPE}, |
| {"allBookmarks", IDS_BOOKMARKS_ALL_BOOKMARKS}, |
| {"priceTrackingLabel", IDS_BOOKMARKS_LABEL_TRACKED_PRODUCTS}, |
| {"sortNewest", IDS_BOOKMARKS_SORT_NEWEST}, |
| {"sortNewestLower", IDS_BOOKMARKS_SORT_NEWEST_LOWER}, |
| {"sortOldest", IDS_BOOKMARKS_SORT_OLDEST}, |
| {"sortOldestLower", IDS_BOOKMARKS_SORT_OLDEST_LOWER}, |
| {"sortAlphabetically", IDS_BOOKMARKS_SORT_ALPHABETICALLY}, |
| {"sortReverseAlphabetically", IDS_BOOKMARKS_SORT_REVERSE_ALPHABETICALLY}, |
| {"sortLastOpened", IDS_BOOKMARKS_SORT_LAST_OPENED}, |
| {"sortLastOpenedLower", IDS_BOOKMARKS_SORT_LAST_OPENED_LOWER}, |
| {"visualView", IDS_BOOKMARKS_VISUAL_VIEW}, |
| {"compactView", IDS_BOOKMARKS_COMPACT_VIEW}, |
| {"sortMenuA11yLabel", IDS_BOOKMARKS_SORT_MENU_A11Y_LABEL}, |
| {"createNewFolderA11yLabel", IDS_BOOKMARKS_CREATE_NEW_FOLDER_A11Y_LABEL}, |
| {"editBookmarkListA11yLabel", |
| IDS_BOOKMARKS_EDIT_BOOKMARK_LIST_A11Y_LABEL}, |
| {"cancelA11yLabel", IDS_CANCEL}, |
| {"bookmarkNameA11yLabel", IDS_BOOKMARK_AX_EDITOR_NAME_LABEL}, |
| {"addCurrentTab", IDS_READ_LATER_ADD_CURRENT_TAB}, |
| {"emptyTitle", IDS_BOOKMARKS_EMPTY_STATE_TITLE}, |
| {"emptyBody", IDS_BOOKMARKS_EMPTY_STATE_BODY}, |
| {"emptyTitleFolder", IDS_BOOKMARKS_EMPTY_STATE_TITLE_FOLDER}, |
| {"emptyBodyFolder", IDS_BOOKMARKS_EMPTY_STATE_BODY_FOLDER}, |
| {"emptyTitleGuest", IDS_BOOKMARKS_EMPTY_STATE_TITLE_GUEST}, |
| {"emptyBodyGuest", IDS_BOOKMARKS_EMPTY_STATE_BODY_GUEST}, |
| {"emptyTitleSearch", IDS_BOOKMARKS_EMPTY_STATE_TITLE_SEARCH}, |
| {"emptyBodySearch", IDS_BOOKMARKS_EMPTY_STATE_BODY_SEARCH}, |
| {"searchBookmarks", IDS_BOOKMARK_MANAGER_SEARCH_BUTTON}, |
| {"clearSearch", IDS_BOOKMARK_MANAGER_CLEAR_SEARCH}, |
| {"selectedBookmarkCount", IDS_BOOKMARK_MANAGER_ITEMS_SELECTED}, |
| {"menuOpenNewTab", IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB}, |
| {"menuOpenNewTabWithCount", |
| IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_WITH_COUNT}, |
| {"menuOpenNewWindow", IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_WINDOW}, |
| {"menuOpenNewWindowWithCount", |
| IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_WINDOW_WITH_COUNT}, |
| {"menuOpenIncognito", IDS_BOOKMARK_MANAGER_MENU_OPEN_INCOGNITO}, |
| {"menuOpenIncognitoWithCount", |
| IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_INCOGNITO_WITH_COUNT}, |
| {"menuOpenNewTabGroup", IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB_GROUP}, |
| {"menuOpenNewTabGroupWithCount", |
| IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_TAB_GROUP_WITH_COUNT}, |
| {"menuMoveToBookmarksBar", IDS_BOOKMARKS_MOVE_TO_BOOKMARKS_BAR}, |
| {"menuMoveToAllBookmarks", IDS_BOOKMARKS_MOVE_TO_ALL_BOOKMARKS}, |
| {"menuTrackPrice", IDS_SIDE_PANEL_TRACK_BUTTON}, |
| {"menuUntrackPrice", IDS_SIDE_PANEL_UNTRACK_BUTTON}, |
| {"menuEdit", IDS_BOOKMARKS_EDIT}, |
| {"menuRename", IDS_BOOKMARKS_RENAME}, |
| {"newFolderTitle", IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME}, |
| {"undoBookmarkDeletion", IDS_UNDO_BOOKMARK_DELETION}, |
| {"urlFolderDescription", IDS_BOOKMARKS_URL_FOLDER_DESCRIPTION}, |
| {"editBookmark", IDS_BOOKMARKS_EDIT_BOOKMARK}, |
| {"editMoveFolderTo", IDS_BOOKMARKS_EDIT_MOVE_TO}, |
| {"editNewFolder", IDS_BOOKMARKS_EDIT_NEW_FOLDER}, |
| {"editCancel", IDS_BOOKMARKS_EDIT_CANCEL}, |
| {"editSave", IDS_BOOKMARKS_EDIT_SAVE}, |
| {"editName", IDS_BOOKMARKS_EDIT_NAME}, |
| {"editUrl", IDS_BOOKMARKS_EDIT_URL}, |
| {"disabledFeature", IDS_BOOKMARKS_DISABLED_FEATURE}, |
| {"backButtonLabel", IDS_BOOKMARKS_BACK_BUTTON_LABEL}, |
| {"forwardButtonLabel", IDS_BOOKMARKS_FORWARD_BUTTON_LABEL}, |
| {"bookmarkMenuLabel", IDS_BOOKMARK_OPTIONS_LABEL}, |
| {"folderMenuLabel", IDS_FOLDER_OPTIONS_LABEL}, |
| {"openFolderLabel", IDS_BOOKMARKS_OPEN_FOLDER_LABEL}, |
| {"openBookmarkLabel", IDS_BOOKMARKS_OPEN_BOOKMARK_LABEL}, |
| {"selectFolderLabel", IDS_BOOKMARKS_SELECT_FOLDER_LABEL}, |
| {"selectBookmarkLabel", IDS_BOOKMARKS_SELECT_BOOKMARK_LABEL}, |
| {"a11yDescriptionPriceTracking", |
| IDS_BOOKMARK_ACCESSIBLE_DESCRIPTION_PRICE_TRACKING}, |
| {"a11yDescriptionPriceChange", |
| IDS_BOOKMARK_ACCESSIBLE_DESCRIPTION_PRICE_CHANGE}, |
| {"checkboxA11yLabel", IDS_BOOKMARKS_CHECKBOX_LABEL}, |
| {"editInvalidUrl", IDS_BOOKMARK_MANAGER_INVALID_URL}, |
| }; |
| for (const auto& str : kLocalizedStrings) |
| webui::AddLocalizedString(source, str.name, str.id); |
| |
| source->AddBoolean("useRipples", views::PlatformStyle::kUseRipples); |
| |
| PrefService* prefs = profile->GetPrefs(); |
| source->AddBoolean( |
| "editBookmarksEnabled", |
| prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled)); |
| source->AddBoolean( |
| "hasManagedBookmarks", |
| !prefs->GetList(bookmarks::prefs::kManagedBookmarks).empty()); |
| source->AddBoolean("shoppingListEnabled", |
| commerce::IsShoppingListAllowedForEnterprise(prefs)); |
| source->AddBoolean( |
| "urlImagesEnabled", |
| base::FeatureList::IsEnabled(page_image_service::kImageService)); |
| |
| source->AddBoolean("guestMode", profile->IsGuestSession()); |
| source->AddBoolean("incognitoMode", profile->IsIncognitoProfile()); |
| source->AddInteger( |
| "sortOrder", |
| prefs->GetInteger(bookmarks_webui::prefs::kBookmarksSortOrder)); |
| source->AddInteger( |
| "viewType", |
| prefs->GetInteger(bookmarks_webui::prefs::kBookmarksViewType)); |
| |
| bookmarks::BookmarkModel* bookmark_model = |
| BookmarkModelFactory::GetForBrowserContext(profile); |
| source->AddString( |
| "bookmarksBarId", |
| base::NumberToString( |
| bookmark_model ? bookmark_model->bookmark_bar_node()->id() : -1)); |
| source->AddString( |
| "otherBookmarksId", |
| base::NumberToString(bookmark_model ? bookmark_model->other_node()->id() |
| : -1)); |
| source->AddString( |
| "mobileBookmarksId", |
| base::NumberToString(bookmark_model ? bookmark_model->mobile_node()->id() |
| : -1)); |
| bookmarks::ManagedBookmarkService* managed = |
| ManagedBookmarkServiceFactory::GetForProfile(profile); |
| source->AddString("managedBookmarksFolderId", |
| managed && managed->managed_node() |
| ? base::NumberToString(managed->managed_node()->id()) |
| : ""); |
| |
| webui::SetupChromeRefresh2023(source); |
| |
| content::URLDataSource::Add( |
| profile, std::make_unique<FaviconSource>( |
| profile, chrome::FaviconUrlFormat::kFavicon2)); |
| const int resource = |
| base::FeatureList::IsEnabled(features::kPowerBookmarksSidePanel) |
| ? IDR_SIDE_PANEL_BOOKMARKS_POWER_BOOKMARKS_HTML |
| : IDR_SIDE_PANEL_BOOKMARKS_BOOKMARKS_HTML; |
| webui::SetupWebUIDataSource(source, |
| base::make_span(kSidePanelBookmarksResources, |
| kSidePanelBookmarksResourcesSize), |
| resource); |
| source->AddResourcePaths(base::make_span(kSidePanelSharedResources, |
| kSidePanelSharedResourcesSize)); |
| |
| // Add a handler to provide pluralized strings. |
| auto plural_string_handler = std::make_unique<PluralStringHandler>(); |
| plural_string_handler->AddLocalizedString("bookmarkFolderChildCount", |
| IDS_BOOKMARK_FOLDER_CHILD_COUNT); |
| plural_string_handler->AddLocalizedString("bookmarkDeletionCount", |
| IDS_BOOKMARK_DELETION_COUNT); |
| web_ui->AddMessageHandler(std::move(plural_string_handler)); |
| |
| content::URLDataSource::Add(profile, |
| std::make_unique<SanitizedImageSource>(profile)); |
| } |
| |
| BookmarksSidePanelUI::~BookmarksSidePanelUI() = default; |
| |
| WEB_UI_CONTROLLER_TYPE_IMPL(BookmarksSidePanelUI) |
| |
| void BookmarksSidePanelUI::BindInterface( |
| mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandlerFactory> |
| receiver) { |
| bookmarks_page_factory_receiver_.reset(); |
| bookmarks_page_factory_receiver_.Bind(std::move(receiver)); |
| } |
| |
| void BookmarksSidePanelUI::BindInterface( |
| mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandlerFactory> |
| receiver) { |
| shopping_list_factory_receiver_.reset(); |
| shopping_list_factory_receiver_.Bind(std::move(receiver)); |
| } |
| |
| void BookmarksSidePanelUI::BindInterface( |
| mojo::PendingReceiver<color_change_listener::mojom::PageHandler> |
| pending_receiver) { |
| color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>( |
| web_ui()->GetWebContents(), std::move(pending_receiver)); |
| } |
| |
| void BookmarksSidePanelUI::BindInterface( |
| mojo::PendingReceiver<page_image_service::mojom::PageImageServiceHandler> |
| pending_image_handler) { |
| base::WeakPtr<page_image_service::ImageService> image_service_weak; |
| if (auto* image_service = |
| page_image_service::ImageServiceFactory::GetForBrowserContext( |
| Profile::FromWebUI(web_ui()))) { |
| image_service_weak = image_service->GetWeakPtr(); |
| } |
| image_service_handler_ = |
| std::make_unique<page_image_service::ImageServiceHandler>( |
| std::move(pending_image_handler), std::move(image_service_weak)); |
| } |
| |
| commerce::ShoppingListContextMenuController* |
| BookmarksSidePanelUI::GetShoppingListContextMenuController() { |
| return shopping_list_context_menu_controller_.get(); |
| } |
| |
| void BookmarksSidePanelUI::CreateBookmarksPageHandler( |
| mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) { |
| bookmarks_page_handler_ = |
| std::make_unique<BookmarksPageHandler>(std::move(receiver), this); |
| } |
| |
| void BookmarksSidePanelUI::CreateShoppingListHandler( |
| mojo::PendingRemote<shopping_list::mojom::Page> page, |
| mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandler> receiver) { |
| Profile* const profile = Profile::FromWebUI(web_ui()); |
| bookmarks::BookmarkModel* bookmark_model = |
| BookmarkModelFactory::GetForBrowserContext(profile); |
| commerce::ShoppingService* shopping_service = |
| commerce::ShoppingServiceFactory::GetForBrowserContext(profile); |
| feature_engagement::Tracker* const tracker = |
| feature_engagement::TrackerFactory::GetForBrowserContext(profile); |
| shopping_list_handler_ = std::make_unique<commerce::ShoppingListHandler>( |
| std::move(page), std::move(receiver), bookmark_model, shopping_service, |
| profile->GetPrefs(), tracker, g_browser_process->GetApplicationLocale(), |
| nullptr); |
| shopping_list_context_menu_controller_ = |
| std::make_unique<commerce::ShoppingListContextMenuController>( |
| bookmark_model, shopping_service, shopping_list_handler_.get()); |
| } |