diff --git a/app/brave_main_delegate_browsertest.cc b/app/brave_main_delegate_browsertest.cc
index 55d1ca93d0c8..7e436d13c957 100644
--- a/app/brave_main_delegate_browsertest.cc
+++ b/app/brave_main_delegate_browsertest.cc
@@ -150,7 +150,6 @@ IN_PROC_BROWSER_TEST_F(BraveMainDelegateBrowserTest, DisabledFeatures) {
&permissions::features::kPermissionOnDeviceNotificationPredictions,
&privacy_sandbox::kOverridePrivacySandboxSettingsLocalTesting,
&privacy_sandbox::kPrivacySandboxSettings3,
- &reading_list::switches::kReadLater,
&shared_highlighting::kSharedHighlightingAmp,
#if !BUILDFLAG(IS_ANDROID)
&translate::kTFLiteLanguageDetectionEnabled,
diff --git a/app/theme/brave_theme_resources.grd b/app/theme/brave_theme_resources.grd
index 9512f0fd1202..2a219d52acfd 100644
--- a/app/theme/brave_theme_resources.grd
+++ b/app/theme/brave_theme_resources.grd
@@ -42,6 +42,7 @@
+
diff --git a/app/theme/default_100_percent/brave/sidebar_reading_list_focused.png b/app/theme/default_100_percent/brave/sidebar_reading_list_focused.png
new file mode 100644
index 000000000000..1996ed38860b
Binary files /dev/null and b/app/theme/default_100_percent/brave/sidebar_reading_list_focused.png differ
diff --git a/app/theme/default_200_percent/brave/sidebar_reading_list_focused.png b/app/theme/default_200_percent/brave/sidebar_reading_list_focused.png
new file mode 100644
index 000000000000..ed1d26378d48
Binary files /dev/null and b/app/theme/default_200_percent/brave/sidebar_reading_list_focused.png differ
diff --git a/app/vector_icons/BUILD.gn b/app/vector_icons/BUILD.gn
index 3c40f3fdaa1d..61f7403cf9be 100644
--- a/app/vector_icons/BUILD.gn
+++ b/app/vector_icons/BUILD.gn
@@ -35,6 +35,7 @@ aggregate_vector_icons("brave_vector_icons") {
"sidebar_item_added_check.icon",
"sidebar_items_down_arrow.icon",
"sidebar_items_up_arrow.icon",
+ "sidebar_reading_list.icon",
"sidebar_settings.icon",
"sidebar_trash.icon",
]
diff --git a/app/vector_icons/sidebar_reading_list.icon b/app/vector_icons/sidebar_reading_list.icon
new file mode 100644
index 000000000000..cbe587c704b7
--- /dev/null
+++ b/app/vector_icons/sidebar_reading_list.icon
@@ -0,0 +1,77 @@
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 15.33f, 14,
+H_LINE_TO, 10,
+R_CUBIC_TO, -0.74f, 0, -1.34f, 0.6f, -1.34f, 1.33f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, -1.33f, 0,
+CUBIC_TO, 7.33f, 14.6f, 6.73f, 14, 5.99f, 14,
+H_LINE_TO, 0.67f,
+ARC_TO, 0.67f, 0.67f, 0, 0, 1, 0, 13.33f,
+V_LINE_TO, 0.67f,
+CUBIC_TO, 0, 0.3f, 0.3f, 0, 0.67f, 0,
+H_LINE_TO, 6.04f,
+R_CUBIC_TO, 0.78f, 0, 1.48f, 0.35f, 1.96f, 0.89f,
+ARC_TO, 2.61f, 2.61f, 0, 0, 1, 9.95f, 0,
+R_LINE_TO, 0.01f, 0,
+R_LINE_TO, 0.01f, 0,
+R_H_LINE_TO, 5.36f,
+R_CUBIC_TO, 0.37f, 0, 0.67f, 0.3f, 0.67f, 0.67f,
+R_V_LINE_TO, 12.67f,
+R_ARC_TO, 0.67f, 0.67f, 0, 0, 1, -0.67f, 0.67f,
+CLOSE,
+MOVE_TO, 7.33f, 2.62f,
+R_ARC_TO, 1.29f, 1.29f, 0, 0, 0, -1.29f, -1.29f,
+H_LINE_TO, 1.34f,
+R_V_LINE_TO, 11.33f,
+H_LINE_TO, 6.03f,
+R_CUBIC_TO, 0.01f, 0, 0.02f, 0.01f, 0.04f, 0.01f,
+R_CUBIC_TO, 0.46f, 0.01f, 0.89f, 0.14f, 1.26f, 0.36f,
+V_LINE_TO, 2.62f,
+CLOSE,
+R_MOVE_TO, 7.34f, -1.29f,
+H_LINE_TO, 9.97f,
+R_LINE_TO, -0.01f, 0,
+R_LINE_TO, -0.01f, 0,
+R_ARC_TO, 1.29f, 1.29f, 0, 0, 0, -1.29f, 1.29f,
+R_V_LINE_TO, 10.42f,
+R_ARC_TO, 2.64f, 2.64f, 0, 0, 1, 1.28f, -0.37f,
+R_CUBIC_TO, 0.01f, 0, 0.02f, 0, 0.03f, 0,
+R_H_LINE_TO, 4.7f,
+V_LINE_TO, 1.33f,
+CLOSE,
+R_MOVE_TO, -5.34f, 8,
+R_CUBIC_TO, 0, -0.37f, 0.3f, -0.67f, 0.67f, -0.67f,
+R_H_LINE_TO, 3.34f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, 1.33f,
+H_LINE_TO, 10,
+R_ARC_TO, 0.67f, 0.67f, 0, 0, 1, -0.67f, -0.67f,
+CLOSE,
+R_MOVE_TO, 4, -2,
+H_LINE_TO, 10,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, -1.33f,
+R_H_LINE_TO, 3.34f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, 1.33f,
+CLOSE,
+R_MOVE_TO, 0, -2.67f,
+H_LINE_TO, 10,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, -1.33f,
+R_H_LINE_TO, 3.34f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, 1.33f,
+CLOSE,
+MOVE_TO, 2.66f, 10,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, -1.33f,
+R_H_LINE_TO, 3.34f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, 1.33f,
+H_LINE_TO, 2.66f,
+CLOSE,
+R_MOVE_TO, 3.34f, -2.67f,
+H_LINE_TO, 2.66f,
+ARC_TO, 0.67f, 0.67f, 0, 1, 1, 2.66f, 6,
+R_H_LINE_TO, 3.34f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, 1.33f,
+CLOSE,
+R_MOVE_TO, 0, -2.67f,
+H_LINE_TO, 2.66f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, -1.33f,
+R_H_LINE_TO, 3.34f,
+R_ARC_TO, 0.67f, 0.67f, 0, 1, 1, 0, 1.33f,
+CLOSE
diff --git a/brave_paks.gni b/brave_paks.gni
index 8ed899f6c49a..566ec2a8378a 100644
--- a/brave_paks.gni
+++ b/brave_paks.gni
@@ -3,7 +3,6 @@
# You can obtain one at http://mozilla.org/MPL/2.0/.
import("//brave/components/brave_webtorrent/browser/buildflags/buildflags.gni")
-import("//brave/components/sidebar/buildflags/buildflags.gni")
import("//brave/components/tor/buildflags/buildflags.gni")
import("//build/config/locales.gni")
import("//chrome/common/features.gni")
@@ -90,13 +89,6 @@ template("brave_extra_paks") {
]
}
- if (enable_sidebar) {
- sources += [
- "$root_gen_dir/brave/browser/resources/sidebar/sidebar_resources.pak",
- ]
- deps += [ "//brave/browser/resources/sidebar:resources" ]
- }
-
if (enable_tor) {
sources +=
[ "$root_gen_dir/brave/components/tor/resources/tor_resources.pak" ]
diff --git a/browser/brave_content_browser_client.cc b/browser/brave_content_browser_client.cc
index 1f604c4360ef..8b4243fac948 100644
--- a/browser/brave_content_browser_client.cc
+++ b/browser/brave_content_browser_client.cc
@@ -186,11 +186,6 @@ using extensions::ChromeContentBrowserClientExtensionsPart;
#include "brave/browser/ethereum_remote_client/ethereum_remote_client_service_factory.h"
#endif
-#if BUILDFLAG(ENABLE_SIDEBAR)
-#include "brave/browser/ui/webui/sidebar/sidebar.mojom.h"
-#include "brave/browser/ui/webui/sidebar/sidebar_bookmarks_ui.h"
-#endif
-
#if !BUILDFLAG(IS_ANDROID)
#include "brave/browser/new_tab/new_tab_shows_navigation_throttle.h"
#include "brave/browser/ui/webui/brave_federated/federated_internals.mojom.h"
@@ -594,11 +589,6 @@ void BraveContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
}
#endif
-#if BUILDFLAG(ENABLE_SIDEBAR)
- chrome::internal::RegisterWebUIControllerInterfaceBinder<
- sidebar::mojom::BookmarksPageHandlerFactory, SidebarBookmarksUI>(map);
-#endif
-
// Brave News
#if !BUILDFLAG(IS_ANDROID)
if (base::FeatureList::IsEnabled(brave_today::features::kBraveNewsFeature)) {
diff --git a/browser/net/brave_network_audit_browsertest.cc b/browser/net/brave_network_audit_browsertest.cc
index 2dbf5d26bfba..913dd749420d 100644
--- a/browser/net/brave_network_audit_browsertest.cc
+++ b/browser/net/brave_network_audit_browsertest.cc
@@ -307,9 +307,9 @@ IN_PROC_BROWSER_TEST_F(BraveNetworkAuditTest, BasicTests) {
auto* sidebar_controller =
static_cast(browser())->sidebar_controller();
auto* sidebar_model = sidebar_controller->model();
- auto all_items = sidebar_model->GetAllSidebarItems();
+ const auto& all_items = sidebar_model->GetAllSidebarItems();
const int item_num = all_items.size();
- const int builtin_panel_item_total = 1;
+ const int builtin_panel_item_total = 2;
int builtin_panel_item_count = 0;
for (int i = 0; i < item_num; ++i) {
auto item = all_items[i];
diff --git a/browser/resources/sidebar/BUILD.gn b/browser/resources/sidebar/BUILD.gn
deleted file mode 100644
index e0a2b7165c75..000000000000
--- a/browser/resources/sidebar/BUILD.gn
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2022 The Brave Authors. All rights reserved.
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import("//brave/resources/brave_grit.gni")
-import("//chrome/common/features.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
-
-brave_grit("resources") {
- defines = chrome_grit_defines
-
- enable_input_discovery_for_gn_analyze = false
- source = "$target_gen_dir/sidebar_resources.grd"
- deps = [ ":build_grd" ]
-
- outputs = [
- "grit/sidebar_resources.h",
- "grit/sidebar_resources_map.cc",
- "grit/sidebar_resources_map.h",
- "sidebar_resources.pak",
- ]
-}
-
-generate_grd("build_grd") {
- grd_prefix = "sidebar"
- out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
- grdp_files = [ "$target_gen_dir/bookmarks/resources.grdp" ]
- deps = [ "bookmarks:build_grdp" ]
-}
diff --git a/browser/resources/sidebar/bookmarks/BUILD.gn b/browser/resources/sidebar/bookmarks/BUILD.gn
deleted file mode 100644
index b227f7ebcec3..000000000000
--- a/browser/resources/sidebar/bookmarks/BUILD.gn
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (c) 2022 The Brave Authors. All rights reserved.
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import("//tools/grit/preprocess_if_expr.gni")
-import("//tools/polymer/html_to_js.gni")
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
-
-preprocess_folder =
- "$root_gen_dir/brave/browser/resources/sidebar/bookmarks/preprocessed"
-
-generate_grd("build_grdp") {
- grd_prefix = "sidebar_bookmarks"
- out_grd = "$target_gen_dir/resources.grdp"
- deps = [ ":build_ts" ]
- manifest_files = [
- "$root_gen_dir/brave/browser/resources/sidebar/bookmarks/tsconfig.manifest",
- ]
- input_files = [ "bookmarks.html" ]
- input_files_base_dir = rebase_path(".", "//")
-}
-
-preprocess_if_expr("preprocess") {
- in_folder = "./"
- out_folder = preprocess_folder
- in_files = [
- "bookmarks_api_proxy.ts",
- "bookmarks_drag_manager.ts",
- ]
-}
-
-preprocess_if_expr("preprocess_generated") {
- deps = [ ":web_components" ]
- in_folder = target_gen_dir
- out_folder = preprocess_folder
- in_files = [
- "bookmark_folder.ts",
- "bookmarks_list.ts",
- ]
-}
-
-preprocess_if_expr("preprocess_mojo") {
- deps = [ "//brave/browser/ui/webui/sidebar:mojo_bindings_webui_js" ]
- in_folder = "$root_gen_dir/mojom-webui/brave/browser/ui/webui/sidebar/"
- out_folder = preprocess_folder
- out_manifest = "$target_gen_dir/preprocessed_mojo_manifest.json"
- in_files = [ "sidebar.mojom-webui.js" ]
-}
-
-html_to_js("web_components") {
- js_files = [
- "bookmark_folder.ts",
- "bookmarks_list.ts",
- ]
-}
-
-ts_library("build_ts") {
- tsconfig_base = "tsconfig_base.json"
- root_dir = "$target_gen_dir/preprocessed"
- out_dir = "$target_gen_dir/tsc"
- in_files = [
- "bookmark_folder.ts",
- "bookmarks_list.ts",
- "bookmarks_api_proxy.ts",
- "bookmarks_drag_manager.ts",
- "sidebar.mojom-webui.js",
- ]
- definitions = [
- "//tools/typescript/definitions/bookmark_manager_private.d.ts",
- "//tools/typescript/definitions/bookmarks.d.ts",
- "//tools/typescript/definitions/chrome_event.d.ts",
- ]
- deps = [
- "//third_party/polymer/v3_0:library",
- "//ui/webui/resources:library",
- "//ui/webui/resources/mojo:library",
- ]
- extra_deps = [
- ":preprocess",
- ":preprocess_generated",
- ":preprocess_mojo",
- ]
-}
diff --git a/browser/resources/sidebar/bookmarks/bookmark_folder.html b/browser/resources/sidebar/bookmarks/bookmark_folder.html
deleted file mode 100644
index 43d9ddc7d08a..000000000000
--- a/browser/resources/sidebar/bookmarks/bookmark_folder.html
+++ /dev/null
@@ -1,239 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/browser/resources/sidebar/bookmarks/bookmark_folder.ts b/browser/resources/sidebar/bookmarks/bookmark_folder.ts
deleted file mode 100644
index 6bf101bfd645..000000000000
--- a/browser/resources/sidebar/bookmarks/bookmark_folder.ts
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2021 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.
-
-import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
-import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import 'chrome://resources/cr_elements/mwb_element_shared_style.css.js';
-
-import {getFaviconForPageURL} from 'chrome://resources/js/icon.js';
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {BookmarksApiProxy} from './bookmarks_api_proxy.js';
-
-/** Event interface for dom-repeat. */
-interface RepeaterMouseEvent extends MouseEvent {
- clientX: number;
- clientY: number;
- model: {
- item: chrome.bookmarks.BookmarkTreeNode,
- };
-}
-
-export interface BookmarkFolderElement {
- $: {
- children: HTMLElement,
- };
-}
-
-// Event name for open state of a folder being changed.
-export const FOLDER_OPEN_CHANGED_EVENT = 'bookmark-folder-open-changed';
-
-export class BookmarkFolderElement extends PolymerElement {
- static get is() {
- return 'bookmark-folder';
- }
-
- static get template() {
- return html`{__html_template__}`;
- }
-
- static get properties() {
- return {
- childDepth_: {
- type: Number,
- value: 1,
- },
-
- depth: {
- type: Number,
- observer: 'onDepthChanged_',
- value: 0,
- },
-
- folder: Object,
-
- open_: {
- type: Boolean,
- value: false,
- },
-
- openFolders: {
- type: Array,
- observer: 'onOpenFoldersChanged_',
- },
- };
- }
-
- private childDepth_: number;
- depth: number;
- folder: chrome.bookmarks.BookmarkTreeNode;
- private open_: boolean;
- openFolders: string[];
- private bookmarksApi_: BookmarksApiProxy = BookmarksApiProxy.getInstance();
-
- static get observers() {
- return [
- 'onChildrenLengthChanged_(folder.children.length)',
- ];
- }
-
- private getAriaExpanded_(): string|undefined {
- if (!this.folder.children || this.folder.children.length === 0) {
- // Remove the attribute for empty folders that cannot be expanded.
- return undefined;
- }
-
- return this.open_ ? 'true' : 'false';
- }
-
- private onBookmarkAuxClick_(event: RepeaterMouseEvent) {
- if (event.button !== 1) {
- // Not a middle click.
- return;
- }
-
- event.preventDefault();
- event.stopPropagation();
- this.bookmarksApi_.openBookmark(event.model.item.url!, this.depth, {
- middleButton: true,
- altKey: event.altKey,
- ctrlKey: event.ctrlKey,
- metaKey: event.metaKey,
- shiftKey: event.shiftKey,
- });
- }
-
- private onBookmarkClick_(event: RepeaterMouseEvent) {
- event.preventDefault();
- event.stopPropagation();
- this.bookmarksApi_.openBookmark(event.model.item.url!, this.depth, {
- middleButton: false,
- altKey: event.altKey,
- ctrlKey: event.ctrlKey,
- metaKey: event.metaKey,
- shiftKey: event.shiftKey,
- });
- }
-
- private onBookmarkContextMenu_(event: RepeaterMouseEvent) {
- event.preventDefault();
- event.stopPropagation();
- this.bookmarksApi_.showContextMenu(
- event.model.item.id, event.clientX, event.clientY);
- }
-
- private onFolderContextMenu_(event: MouseEvent) {
- event.preventDefault();
- event.stopPropagation();
- this.bookmarksApi_.showContextMenu(
- this.folder.id, event.clientX, event.clientY);
- }
-
- private getBookmarkIcon_(url: string): string {
- return getFaviconForPageURL(url, false);
- }
-
- private onChildrenLengthChanged_() {
- if (this.folder.children) {
- this.style.setProperty(
- '--child-count', this.folder.children!.length.toString());
- } else {
- this.style.setProperty('--child-count', '0');
- }
- }
-
- private onDepthChanged_() {
- this.childDepth_ = this.depth + 1;
- this.style.setProperty('--node-depth', `${this.depth}`);
- this.style.setProperty('--child-depth', `${this.childDepth_}`);
- }
-
- private onFolderClick_(event: Event) {
- event.preventDefault();
- event.stopPropagation();
-
- if (!this.folder.children || this.folder.children.length === 0) {
- // No reason to open if there are no children to show.
- return;
- }
-
- this.open_ = !this.open_;
- this.dispatchEvent(new CustomEvent(FOLDER_OPEN_CHANGED_EVENT, {
- bubbles: true,
- composed: true,
- detail: {
- id: this.folder.id,
- open: this.open_,
- }
- }));
- }
-
- private onOpenFoldersChanged_() {
- this.open_ =
- Boolean(this.openFolders) && this.openFolders.includes(this.folder.id);
- }
-
- private getFocusableRows_(): HTMLElement[] {
- return Array.from(
- this.shadowRoot!.querySelectorAll('.row, bookmark-folder'));
- }
-
- moveFocus(delta: -1|1): boolean {
- const currentFocus = this.shadowRoot!.activeElement;
- if (currentFocus instanceof BookmarkFolderElement &&
- currentFocus.moveFocus(delta)) {
- // If focus is already inside a nested folder, delegate the focus to the
- // nested folder and return early if successful.
- return true;
- }
-
- let moveFocusTo = null;
- const focusableRows = this.getFocusableRows_();
- if (currentFocus) {
- // If focus is in this folder, move focus to the next or previous
- // focusable row.
- const currentFocusIndex =
- focusableRows.indexOf(currentFocus as HTMLElement);
- moveFocusTo = focusableRows[currentFocusIndex + delta];
- } else {
- // If focus is not in this folder yet, move focus to either end.
- moveFocusTo = delta === 1 ? focusableRows[0] :
- focusableRows[focusableRows.length - 1];
- }
-
- if (moveFocusTo instanceof BookmarkFolderElement) {
- return moveFocusTo.moveFocus(delta);
- } else if (moveFocusTo) {
- moveFocusTo.focus();
- return true;
- } else {
- return false;
- }
- }
-}
-
-customElements.define(BookmarkFolderElement.is, BookmarkFolderElement);
-
-interface DraggableElement extends HTMLElement {
- dataBookmark: chrome.bookmarks.BookmarkTreeNode;
-}
-
-export function getBookmarkFromElement(element: HTMLElement) {
- return (element as DraggableElement).dataBookmark;
-}
-
-export function isValidDropTarget(element: HTMLElement) {
- return element.id === 'folder' || element.classList.contains('bookmark');
-}
-
-export function isBookmarkFolderElement(element: HTMLElement): boolean {
- return element.id === 'folder';
-}
\ No newline at end of file
diff --git a/browser/resources/sidebar/bookmarks/bookmarks.html b/browser/resources/sidebar/bookmarks/bookmarks.html
deleted file mode 100644
index f720ed28842a..000000000000
--- a/browser/resources/sidebar/bookmarks/bookmarks.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- $i18n{bookmarksTitle}
-
-
-
-
-
-
-
-
-
-
diff --git a/browser/resources/sidebar/bookmarks/bookmarks_api_proxy.ts b/browser/resources/sidebar/bookmarks/bookmarks_api_proxy.ts
deleted file mode 100644
index 322ea97b9ca8..000000000000
--- a/browser/resources/sidebar/bookmarks/bookmarks_api_proxy.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2021 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.
-
-import {ChromeEvent} from '/tools/typescript/definitions/chrome_event.js';
-import {ClickModifiers} from 'chrome://resources/mojo/ui/base/mojom/window_open_disposition.mojom-webui.js';
-
-import {BookmarksPageHandlerFactory, BookmarksPageHandlerRemote} from './sidebar.mojom-webui.js';
-
-let instance: BookmarksApiProxy|null = null;
-
-export class BookmarksApiProxy {
- callbackRouter: {[key: string]: ChromeEvent};
- handler: BookmarksPageHandlerRemote;
-
- constructor() {
- this.callbackRouter = {
- onChanged: chrome.bookmarks.onChanged,
- onChildrenReordered: chrome.bookmarks.onChildrenReordered,
- onCreated: chrome.bookmarks.onCreated,
- onMoved: chrome.bookmarks.onMoved,
- onRemoved: chrome.bookmarks.onRemoved,
- };
-
- this.handler = new BookmarksPageHandlerRemote();
-
- const factory = BookmarksPageHandlerFactory.getRemote();
- factory.createBookmarksPageHandler(
- this.handler.$.bindNewPipeAndPassReceiver());
- }
-
- cutBookmark(id: string): Promise {
- chrome.bookmarkManagerPrivate.cut([id]);
- return Promise.resolve();
- }
-
- copyBookmark(id: string): Promise {
- return new Promise(resolve => {
- chrome.bookmarkManagerPrivate.copy([id], resolve);
- });
- }
-
- getFolders(): Promise {
- return new Promise(resolve => chrome.bookmarks.getTree(results => {
- if (results[0] && results[0].children) {
- resolve(results[0].children);
- return;
- }
- resolve([]);
- }));
- }
-
- openBookmark(url: string, depth: number, clickModifiers: ClickModifiers) {
- this.handler.openBookmark({url}, depth, clickModifiers);
- }
-
- pasteToBookmark(parentId: string, destinationId?: string): Promise {
- const destination = destinationId ? [destinationId] : [];
- return new Promise(resolve => {
- chrome.bookmarkManagerPrivate.paste(parentId, destination, resolve);
- });
- }
-
- showContextMenu(id: string, x: number, y: number) {
- this.handler.showContextMenu(id, {x, y});
- }
-
- static getInstance() {
- return instance || (instance = new BookmarksApiProxy());
- }
-
- static setInstance(obj: BookmarksApiProxy) {
- instance = obj;
- }
-}
\ No newline at end of file
diff --git a/browser/resources/sidebar/bookmarks/bookmarks_drag_manager.ts b/browser/resources/sidebar/bookmarks/bookmarks_drag_manager.ts
deleted file mode 100644
index 04cabff4f163..000000000000
--- a/browser/resources/sidebar/bookmarks/bookmarks_drag_manager.ts
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2021 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.
-
-import '../strings.m.js';
-
-import {EventTracker} from 'chrome://resources/js/event_tracker.m.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-
-import {getBookmarkFromElement, isBookmarkFolderElement, isValidDropTarget} from './bookmark_folder.js';
-
-export const DROP_POSITION_ATTR = 'drop-position';
-
-const ROOT_FOLDER_ID = '0';
-
-// Ms to wait during a dragover to open closed folder.
-let folderOpenerTimeoutDelay = 1000;
-export function overrideFolderOpenerTimeoutDelay(ms: number) {
- folderOpenerTimeoutDelay = ms;
-}
-
-export enum DropPosition {
- ABOVE = 'above',
- INTO = 'into',
- BELOW = 'below',
-}
-
-interface BookmarksDragDelegate extends HTMLElement {
- getAscendants(bookmarkId: string): string[];
- getIndex(bookmark: chrome.bookmarks.BookmarkTreeNode): number;
- isFolderOpen(bookmark: chrome.bookmarks.BookmarkTreeNode): boolean;
- openFolder(folderId: string): void;
-}
-
-class DragSession {
- private delegate_: BookmarksDragDelegate;
- private dragData_: chrome.bookmarkManagerPrivate.DragData;
- private lastDragOverElement_: HTMLElement|null = null;
- private lastPointerWasTouch_ = false;
- private folderOpenerTimeout_: number|null = null;
-
- constructor(
- delegate: BookmarksDragDelegate,
- dragData: chrome.bookmarkManagerPrivate.DragData) {
- this.delegate_ = delegate;
- this.dragData_ = dragData;
- }
-
- start(e: DragEvent) {
- chrome.bookmarkManagerPrivate.startDrag(
- this.dragData_.elements!.map(bookmark => bookmark.id), 0,
- this.lastPointerWasTouch_, e.clientX, e.clientY);
- }
-
- update(e: DragEvent) {
- const dragOverElement = e.composedPath().find(target => {
- return target instanceof HTMLElement && isValidDropTarget(target);
- }) as HTMLElement;
- if (!dragOverElement) {
- return;
- }
-
- if (dragOverElement !== this.lastDragOverElement_) {
- this.resetState_();
- }
-
- const dragOverBookmark = getBookmarkFromElement(dragOverElement);
- const ascendants = this.delegate_.getAscendants(dragOverBookmark.id);
- const isInvalidDragOverTarget = dragOverBookmark.unmodifiable ||
- this.dragData_.elements &&
- this.dragData_.elements.some(
- element => ascendants.indexOf(element.id) !== -1);
- if (isInvalidDragOverTarget) {
- this.lastDragOverElement_ = null;
- return;
- }
-
- const isDraggingOverFolder = isBookmarkFolderElement(dragOverElement);
- const dragOverElRect = dragOverElement.getBoundingClientRect();
- const dragOverYRatio =
- (e.clientY - dragOverElRect.top) / dragOverElRect.height;
-
- let dropPosition;
- if (isDraggingOverFolder) {
- const folderIsOpen = this.delegate_.isFolderOpen(dragOverBookmark);
- if (dragOverBookmark.parentId === ROOT_FOLDER_ID) {
- // Cannot drag above or below children of root folder.
- dropPosition = DropPosition.INTO;
- } else if (dragOverYRatio <= .25) {
- dropPosition = DropPosition.ABOVE;
- } else if (dragOverYRatio <= .75) {
- dropPosition = DropPosition.INTO;
- } else if (folderIsOpen) {
- // If a folder is open, its child bookmarks appear immediately below it
- // so it should not be possible to drop a bookmark right below an open
- // folder.
- dropPosition = DropPosition.INTO;
- } else {
- dropPosition = DropPosition.BELOW;
- }
- } else {
- dropPosition =
- dragOverYRatio <= .5 ? DropPosition.ABOVE : DropPosition.BELOW;
- }
- dragOverElement.setAttribute(DROP_POSITION_ATTR, dropPosition);
-
- if (dropPosition === DropPosition.INTO &&
- !this.delegate_.isFolderOpen(dragOverBookmark) &&
- !this.folderOpenerTimeout_) {
- // Queue a timeout to auto-open the dragged over folder.
- this.folderOpenerTimeout_ = setTimeout(() => {
- this.delegate_.openFolder(dragOverBookmark.id);
- this.folderOpenerTimeout_ = null;
- }, folderOpenerTimeoutDelay);
- }
-
- this.lastDragOverElement_ = dragOverElement;
- }
-
- cancel() {
- this.resetState_();
- this.lastDragOverElement_ = null;
- }
-
- finish() {
- if (!this.lastDragOverElement_) {
- return;
- }
-
- const dropTargetBookmark =
- getBookmarkFromElement(this.lastDragOverElement_);
- const dropPosition = this.lastDragOverElement_.getAttribute(
- DROP_POSITION_ATTR) as DropPosition;
- this.resetState_();
-
- if (isBookmarkFolderElement(this.lastDragOverElement_) &&
- dropPosition === DropPosition.INTO) {
- chrome.bookmarkManagerPrivate.drop(
- dropTargetBookmark.id, /* index */ undefined,
- /* callback */ undefined);
- return;
- }
-
- let toIndex = this.delegate_.getIndex(dropTargetBookmark);
- toIndex += dropPosition === DropPosition.BELOW ? 1 : 0;
- chrome.bookmarkManagerPrivate.drop(
- dropTargetBookmark.parentId!, toIndex, /* callback */ undefined);
- }
-
- private resetState_() {
- if (this.lastDragOverElement_) {
- this.lastDragOverElement_.removeAttribute(DROP_POSITION_ATTR);
- }
-
- if (this.folderOpenerTimeout_ !== null) {
- clearTimeout(this.folderOpenerTimeout_);
- this.folderOpenerTimeout_ = null;
- }
- }
-
- static createFromBookmark(
- delegate: BookmarksDragDelegate,
- bookmark: chrome.bookmarks.BookmarkTreeNode) {
- return new DragSession(delegate, {
- elements: [bookmark],
- sameProfile: true,
- });
- }
-}
-
-export class BookmarksDragManager {
- private delegate_: BookmarksDragDelegate;
- private dragSession_: DragSession|null;
- private eventTracker_: EventTracker = new EventTracker();
-
- constructor(delegate: BookmarksDragDelegate) {
- this.delegate_ = delegate;
- }
-
- startObserving() {
- this.eventTracker_.add(
- this.delegate_, 'dragstart', e => this.onDragStart_(e as DragEvent));
- this.eventTracker_.add(
- this.delegate_, 'dragover', e => this.onDragOver_(e as DragEvent));
- this.eventTracker_.add(
- this.delegate_, 'dragleave', () => this.onDragLeave_());
- this.eventTracker_.add(this.delegate_, 'dragend', () => this.cancelDrag_());
- this.eventTracker_.add(
- this.delegate_, 'drop', e => this.onDrop_(e as DragEvent));
-
- if (loadTimeData.getBoolean('bookmarksDragAndDropEnabled')) {
- chrome.bookmarkManagerPrivate.onDragEnter.addListener(
- (dragData: chrome.bookmarkManagerPrivate.DragData) =>
- this.onChromeDragEnter_(dragData));
- chrome.bookmarkManagerPrivate.onDragLeave.addListener(
- () => this.cancelDrag_());
- }
- }
-
- stopObserving() {
- this.eventTracker_.removeAll();
- }
-
- private cancelDrag_() {
- if (!this.dragSession_) {
- return;
- }
- this.dragSession_.cancel();
- this.dragSession_ = null;
- }
-
- private onChromeDragEnter_(dragData: chrome.bookmarkManagerPrivate.DragData) {
- if (this.dragSession_) {
- // A drag session is already in flight.
- return;
- }
-
- this.dragSession_ = new DragSession(this.delegate_, dragData);
- }
-
- private onDragStart_(e: DragEvent) {
- e.preventDefault();
- if (!loadTimeData.getBoolean('bookmarksDragAndDropEnabled')) {
- return;
- }
-
- const bookmark = getBookmarkFromElement(
- e.composedPath().find(target => (target as HTMLElement).draggable) as
- HTMLElement);
- if (!bookmark ||
- /* Cannot drag root's children. */ bookmark.parentId ===
- ROOT_FOLDER_ID ||
- bookmark.unmodifiable) {
- return;
- }
-
- this.dragSession_ =
- DragSession.createFromBookmark(this.delegate_, bookmark);
- this.dragSession_.start(e);
- }
-
- private onDragOver_(e: DragEvent) {
- e.preventDefault();
- if (!this.dragSession_) {
- return;
- }
- this.dragSession_.update(e);
- }
-
- private onDragLeave_() {
- if (!this.dragSession_) {
- return;
- }
-
- this.dragSession_.cancel();
- }
-
- private onDrop_(e: DragEvent) {
- if (!this.dragSession_) {
- return;
- }
-
- e.preventDefault();
- this.dragSession_.finish();
- }
-}
\ No newline at end of file
diff --git a/browser/resources/sidebar/bookmarks/bookmarks_list.html b/browser/resources/sidebar/bookmarks/bookmarks_list.html
deleted file mode 100644
index e24c1622e104..000000000000
--- a/browser/resources/sidebar/bookmarks/bookmarks_list.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/browser/resources/sidebar/bookmarks/bookmarks_list.ts b/browser/resources/sidebar/bookmarks/bookmarks_list.ts
deleted file mode 100644
index efb0123bc58d..000000000000
--- a/browser/resources/sidebar/bookmarks/bookmarks_list.ts
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright 2021 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.
-
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {BookmarkFolderElement, FOLDER_OPEN_CHANGED_EVENT, getBookmarkFromElement, isBookmarkFolderElement} from './bookmark_folder.js';
-import {BookmarksApiProxy} from './bookmarks_api_proxy.js';
-import {BookmarksDragManager} from './bookmarks_drag_manager.js';
-
-// Key for localStorage object that refers to all the open folders.
-export const LOCAL_STORAGE_OPEN_FOLDERS_KEY = 'openFolders';
-
-export class BookmarksListElement extends PolymerElement {
- static get is() {
- return 'bookmarks-list';
- }
-
- static get template() {
- return html`{__html_template__}`;
- }
-
- static get properties() {
- return {
- folders_: {
- type: Array,
- value: () => [],
- },
-
- openFolders_: {
- type: Array,
- value: () => [],
- },
- };
- }
-
- private bookmarksApi_: BookmarksApiProxy = BookmarksApiProxy.getInstance();
- private bookmarksDragManager_: BookmarksDragManager =
- new BookmarksDragManager(this);
- private listeners_ = new Map();
- private folders_: chrome.bookmarks.BookmarkTreeNode[];
- private openFolders_: string[];
-
- override ready() {
- super.ready();
- this.addEventListener(
- FOLDER_OPEN_CHANGED_EVENT,
- e => this.onFolderOpenChanged_(
- e as CustomEvent<{id: string, open: boolean}>));
- this.addEventListener('keydown', e => this.onKeydown_(e));
- }
-
- override connectedCallback() {
- super.connectedCallback();
- this.setAttribute('role', 'tree');
- this.bookmarksApi_.getFolders().then(folders => {
- this.folders_ = folders;
-
- this.addListener_(
- 'onChildrenReordered',
- (id: string, reorderedInfo: chrome.bookmarks.ReorderInfo) =>
- this.onChildrenReordered_(id, reorderedInfo));
- this.addListener_(
- 'onChanged',
- (id: string, changedInfo: chrome.bookmarks.ChangeInfo) =>
- this.onChanged_(id, changedInfo));
- this.addListener_(
- 'onCreated',
- (_id: string, node: chrome.bookmarks.BookmarkTreeNode) =>
- this.onCreated_(node));
- this.addListener_(
- 'onMoved',
- (_id: string, movedInfo: chrome.bookmarks.MoveInfo) =>
- this.onMoved_(movedInfo));
- this.addListener_('onRemoved', (id: string) => this.onRemoved_(id));
-
- try {
- const openFolders = window.localStorage[LOCAL_STORAGE_OPEN_FOLDERS_KEY];
- this.openFolders_ = JSON.parse(openFolders);
- } catch (error) {
- this.openFolders_ = [this.folders_[0]!.id];
- window.localStorage[LOCAL_STORAGE_OPEN_FOLDERS_KEY] =
- JSON.stringify(this.openFolders_);
- }
-
- this.bookmarksDragManager_.startObserving();
- });
- }
-
- override disconnectedCallback() {
- for (const [eventName, callback] of this.listeners_.entries()) {
- this.bookmarksApi_.callbackRouter[eventName]!.removeListener(callback);
- }
- this.bookmarksDragManager_.stopObserving();
- }
-
- /** BookmarksDragDelegate */
- getAscendants(bookmarkId: string): string[] {
- const path = this.findPathToId_(bookmarkId);
- return path.map(bookmark => bookmark.id);
- }
-
- /** BookmarksDragDelegate */
- getIndex(bookmark: chrome.bookmarks.BookmarkTreeNode): number {
- const path = this.findPathToId_(bookmark.id);
- const parent = path[path.length - 2];
- if (!parent || !parent.children) {
- return -1;
- }
- return parent.children.findIndex((child) => child.id === bookmark.id);
- }
- /** BookmarksDragDelegate */
- isFolderOpen(bookmark: chrome.bookmarks.BookmarkTreeNode): boolean {
- return this.openFolders_.some(id => bookmark.id === id);
- }
-
- /** BookmarksDragDelegate */
- openFolder(folderId: string) {
- this.changeFolderOpenStatus_(folderId, true);
- }
-
- private addListener_(eventName: string, callback: Function): void {
- this.bookmarksApi_.callbackRouter[eventName]!.addListener(callback);
- this.listeners_.set(eventName, callback);
- }
-
- /**
- * Finds the node within the nested array of folders and returns the path to
- * the node in the tree.
- */
- private findPathToId_(id: string): chrome.bookmarks.BookmarkTreeNode[] {
- const path: chrome.bookmarks.BookmarkTreeNode[] = [];
-
- function findPathByIdInternal_(
- id: string, node: chrome.bookmarks.BookmarkTreeNode) {
- if (node.id === id) {
- path.push(node);
- return true;
- }
-
- if (!node.children) {
- return false;
- }
-
- path.push(node);
- const foundInChildren =
- node.children.some(child => findPathByIdInternal_(id, child));
- if (!foundInChildren) {
- path.pop();
- }
-
- return foundInChildren;
- }
-
- this.folders_.some(folder => findPathByIdInternal_(id, folder));
- return path;
- }
-
- /**
- * Reduces an array of nodes to a string to notify Polymer of changes to the
- * nested array.
- */
- private getPathString_(path: chrome.bookmarks.BookmarkTreeNode[]): string {
- return path.reduce((reducedString, pathItem, index) => {
- if (index === 0) {
- return `folders_.${this.folders_.indexOf(pathItem)}`;
- }
-
- const parent = path[index - 1];
- return `${reducedString}.children.${parent!.children!.indexOf(pathItem)}`;
- }, '');
- }
-
- private onChanged_(id: string, changedInfo: chrome.bookmarks.ChangeInfo) {
- const path = this.findPathToId_(id);
- Object.assign(path[path.length - 1], changedInfo);
-
- const pathString = this.getPathString_(path);
- Object.keys(changedInfo)
- .forEach(key => this.notifyPath(`${pathString}.${key}`));
- }
-
- private onChildrenReordered_(
- id: string, reorderedInfo: chrome.bookmarks.ReorderInfo) {
- const path = this.findPathToId_(id);
- const parent = path[path.length - 1];
- const childById = parent!.children!.reduce((map, node) => {
- map.set(node.id, node);
- return map;
- }, new Map());
- parent!.children = reorderedInfo.childIds.map(id => childById.get(id));
- const pathString = this.getPathString_(path);
- this.notifyPath(`${pathString}.children`);
- }
-
- private onCreated_(node: chrome.bookmarks.BookmarkTreeNode) {
- const pathToParent = this.findPathToId_(node.parentId as string);
- const pathToParentString = this.getPathString_(pathToParent);
- const parent = pathToParent[pathToParent.length - 1];
- if (parent && !parent.children) {
- // Newly created folders in this session may not have an array of
- // children yet, so create an empty one.
- parent.children = [];
- }
- this.splice(`${pathToParentString}.children`, node.index!, 0, node);
- }
-
- private changeFolderOpenStatus_(id: string, open: boolean) {
- const alreadyOpenIndex = this.openFolders_.indexOf(id);
- if (open && alreadyOpenIndex === -1) {
- this.openFolders_.push(id);
- } else if (!open) {
- this.openFolders_.splice(alreadyOpenIndex, 1);
- }
-
- // Assign to a new array so that listeners are triggered.
- this.openFolders_ = [...this.openFolders_];
- window.localStorage[LOCAL_STORAGE_OPEN_FOLDERS_KEY] =
- JSON.stringify(this.openFolders_);
- }
-
- private onFolderOpenChanged_(event: CustomEvent) {
- const {id, open} = event.detail;
- this.changeFolderOpenStatus_(id, open);
- }
-
- private onKeydown_(event: KeyboardEvent) {
- if (['ArrowDown', 'ArrowUp'].includes(event.key)) {
- this.handleArrowKeyNavigation_(event);
- return;
- }
-
- if (!event.ctrlKey && !event.metaKey) {
- return;
- }
-
- event.preventDefault();
- const eventTarget = event.composedPath()[0] as HTMLElement;
- const bookmarkData = getBookmarkFromElement(eventTarget);
- if (!bookmarkData) {
- return;
- }
-
- if (event.key === 'x') {
- this.bookmarksApi_.cutBookmark(bookmarkData.id);
- } else if (event.key === 'c') {
- this.bookmarksApi_.copyBookmark(bookmarkData.id);
- } else if (event.key === 'v') {
- if (isBookmarkFolderElement(eventTarget)) {
- this.bookmarksApi_.pasteToBookmark(bookmarkData.id);
- } else {
- this.bookmarksApi_.pasteToBookmark(
- bookmarkData.parentId!, bookmarkData.id);
- }
- }
- }
-
- private handleArrowKeyNavigation_(event: KeyboardEvent) {
- if (!(this.shadowRoot!.activeElement instanceof BookmarkFolderElement)) {
- // If the key event did not happen within a BookmarkFolderElement, do
- // not do anything.
- return;
- }
-
- // Prevent arrow keys from causing scroll.
- event.preventDefault();
-
- const allFolderElements: BookmarkFolderElement[] =
- Array.from(this.shadowRoot!.querySelectorAll('bookmark-folder'));
-
- const delta = event.key === 'ArrowUp' ? -1 : 1;
- let currentIndex =
- allFolderElements.indexOf(this.shadowRoot!.activeElement);
- let focusHasMoved = false;
- while (!focusHasMoved) {
- focusHasMoved = allFolderElements[currentIndex]!.moveFocus(delta);
- currentIndex = (currentIndex + delta + allFolderElements.length) %
- allFolderElements.length;
- }
- }
-
- private onMoved_(movedInfo: chrome.bookmarks.MoveInfo) {
- // Get old path and remove node from oldParent at oldIndex.
- const oldParentPath = this.findPathToId_(movedInfo.oldParentId);
- const oldParentPathString = this.getPathString_(oldParentPath);
- const oldParent = oldParentPath[oldParentPath.length - 1];
- const movedNode = oldParent!.children![movedInfo.oldIndex];
- Object.assign(
- movedNode, {index: movedInfo.index, parentId: movedInfo.parentId});
- this.splice(`${oldParentPathString}.children`, movedInfo.oldIndex, 1);
-
- // Get new parent's path and add the node to the new parent at index.
- const newParentPath = this.findPathToId_(movedInfo.parentId);
- const newParentPathString = this.getPathString_(newParentPath);
- const newParent = newParentPath[newParentPath.length - 1];
- if (newParent && !newParent.children) {
- newParent.children = [];
- }
- this.splice(
- `${newParentPathString}.children`, movedInfo.index, 0, movedNode);
- }
-
- private onRemoved_(id: string) {
- const oldPath = this.findPathToId_(id);
- const removedNode = oldPath.pop()!;
- const oldParent = oldPath[oldPath.length - 1]!;
- const oldParentPathString = this.getPathString_(oldPath);
- this.splice(
- `${oldParentPathString}.children`,
- oldParent.children!.indexOf(removedNode), 1);
- }
-}
-
-customElements.define(BookmarksListElement.is, BookmarksListElement);
diff --git a/browser/resources/sidebar/bookmarks/tsconfig_base.json b/browser/resources/sidebar/bookmarks/tsconfig_base.json
deleted file mode 100644
index 7ceb2c0b2e52..000000000000
--- a/browser/resources/sidebar/bookmarks/tsconfig_base.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../../../../tools/typescript/tsconfig_base.json",
- "compilerOptions": {
- "allowJs": true,
- "noPropertyAccessFromIndexSignature": false,
- "noUnusedLocals": false,
- "strictPropertyInitialization": false
- }
-}
diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn
index a4a78f48fe44..0d2e8557c637 100644
--- a/browser/ui/BUILD.gn
+++ b/browser/ui/BUILD.gn
@@ -202,6 +202,8 @@ source_set("ui") {
"views/frame/brave_browser_frame.h",
"views/frame/brave_browser_view.cc",
"views/frame/brave_browser_view.h",
+ "views/frame/brave_browser_view_layout.cc",
+ "views/frame/brave_browser_view_layout.h",
"views/frame/brave_opaque_browser_frame_view.cc",
"views/frame/brave_opaque_browser_frame_view.h",
"views/frame/brave_window_frame_graphic.cc",
@@ -212,6 +214,8 @@ source_set("ui") {
"views/omnibox/brave_search_conversion_promotion_view.h",
"views/rounded_separator.cc",
"views/rounded_separator.h",
+ "views/side_panel/brave_side_panel.cc",
+ "views/side_panel/brave_side_panel.h",
"views/tabs/brave_browser_tab_strip_controller.cc",
"views/tabs/brave_browser_tab_strip_controller.h",
"views/tabs/brave_tab.cc",
@@ -416,16 +420,10 @@ source_set("ui") {
if (enable_sidebar) {
deps += [
- "//brave/browser/resources/sidebar:resources",
"//brave/browser/ui/sidebar",
- "//brave/browser/ui/webui/sidebar:mojo_bindings",
"//brave/components/sidebar",
"//chrome/app:generated_resources",
- "//components/bookmarks/browser",
"//components/favicon_base",
- "//mojo/public/cpp/bindings",
- "//ui/base/mojom",
- "//ui/webui",
]
sources += [
@@ -455,14 +453,10 @@ source_set("ui") {
"views/sidebar/sidebar_items_contents_view.h",
"views/sidebar/sidebar_items_scroll_view.cc",
"views/sidebar/sidebar_items_scroll_view.h",
- "views/sidebar/sidebar_panel_webview.cc",
- "views/sidebar/sidebar_panel_webview.h",
"views/sidebar/sidebar_show_options_event_detect_widget.cc",
"views/sidebar/sidebar_show_options_event_detect_widget.h",
- "webui/sidebar/sidebar_bookmarks_page_handler.cc",
- "webui/sidebar/sidebar_bookmarks_page_handler.h",
- "webui/sidebar/sidebar_bookmarks_ui.cc",
- "webui/sidebar/sidebar_bookmarks_ui.h",
+ "views/sidebar/sidebar_side_panel_utils.cc",
+ "views/sidebar/sidebar_side_panel_utils.h",
]
}
diff --git a/browser/ui/sidebar/BUILD.gn b/browser/ui/sidebar/BUILD.gn
index 476f894773b4..baa7183ebea4 100644
--- a/browser/ui/sidebar/BUILD.gn
+++ b/browser/ui/sidebar/BUILD.gn
@@ -16,14 +16,10 @@ source_set("sidebar") {
"sidebar_controller.h",
"sidebar_model.cc",
"sidebar_model.h",
- "sidebar_model_data.cc",
- "sidebar_model_data.h",
"sidebar_service_factory.cc",
"sidebar_service_factory.h",
"sidebar_utils.cc",
"sidebar_utils.h",
- "sidebar_web_contents_delegate.cc",
- "sidebar_web_contents_delegate.h",
]
deps = [
diff --git a/browser/ui/sidebar/sidebar.h b/browser/ui/sidebar/sidebar.h
index 209d3367305a..65f789d67354 100644
--- a/browser/ui/sidebar/sidebar.h
+++ b/browser/ui/sidebar/sidebar.h
@@ -32,13 +32,6 @@ class Sidebar {
SidebarService::ShowSidebarOption show_option) = 0;
// Update current sidebar UI.
virtual void UpdateSidebar() = 0;
- virtual void ShowCustomContextMenu(
- const gfx::Point& point,
- std::unique_ptr menu_model) = 0;
- virtual void HideCustomContextMenu() = 0;
- virtual bool HandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) = 0;
protected:
virtual ~Sidebar() {}
diff --git a/browser/ui/sidebar/sidebar_browsertest.cc b/browser/ui/sidebar/sidebar_browsertest.cc
index 490d25b5809f..8bd61a3445b5 100644
--- a/browser/ui/sidebar/sidebar_browsertest.cc
+++ b/browser/ui/sidebar/sidebar_browsertest.cc
@@ -78,8 +78,8 @@ IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, BasicTest) {
// Check sidebar UI is initalized properly.
EXPECT_TRUE(!!controller()->sidebar());
- // Currently we have 3 default items.
- EXPECT_EQ(3UL, model()->GetAllSidebarItems().size());
+ // Currently we have 4 default items.
+ EXPECT_EQ(4UL, model()->GetAllSidebarItems().size());
// Activate item that opens in panel.
controller()->ActivateItemAt(2);
EXPECT_EQ(2, model()->active_index());
@@ -99,19 +99,9 @@ IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, BasicTest) {
controller()->ActivateItemAt(2);
- // Sidebar items at 2, 3 are opened in panel.
- // Check their webcontents are sidebar webcontents.
- EXPECT_TRUE(model()->IsSidebarWebContents(model()->GetWebContentsAt(2)));
- EXPECT_FALSE(
- model()->IsSidebarWebContents(tab_model()->GetActiveWebContents()));
- EXPECT_EQ(browser(),
- chrome::FindBrowserWithWebContents(model()->GetWebContentsAt(2)));
- EXPECT_EQ(browser(), chrome::FindBrowserWithWebContents(
- tab_model()->GetActiveWebContents()));
-
// Remove Item at index 0 change active index from 3 to 2.
SidebarServiceFactory::GetForProfile(browser()->profile())->RemoveItemAt(0);
- EXPECT_EQ(2UL, model()->GetAllSidebarItems().size());
+ EXPECT_EQ(3UL, model()->GetAllSidebarItems().size());
EXPECT_EQ(1, model()->active_index());
// If current active tab is not NTP, we can add current url to sidebar.
@@ -130,31 +120,31 @@ IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, BasicTest) {
}
IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, WebTypePanelTest) {
- // By default, sidebar has 3 items.
- EXPECT_EQ(3UL, model()->GetAllSidebarItems().size());
- ASSERT_TRUE(
- ui_test_utils::NavigateToURL(browser(), GURL("brave://settings/")));
-
- EXPECT_TRUE(CanAddCurrentActiveTabToSidebar(browser()));
- controller()->AddItemWithCurrentTab();
- // have 4 items.
+ // By default, sidebar has 4 items.
EXPECT_EQ(4UL, model()->GetAllSidebarItems().size());
+ // Add an item
+ ASSERT_TRUE(
+ ui_test_utils::NavigateToURL(browser(), GURL("brave://settings/")));
int current_tab_index = tab_model()->active_index();
EXPECT_EQ(0, current_tab_index);
+ EXPECT_TRUE(CanAddCurrentActiveTabToSidebar(browser()));
+ controller()->AddItemWithCurrentTab();
+ // Verify new size
+ EXPECT_EQ(5UL, model()->GetAllSidebarItems().size());
- // Load NTP in newtab and activate it. (tab index 1)
+ // Load NTP in a new tab and activate it. (tab index 1)
ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL("brave://newtab/"),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
current_tab_index = tab_model()->active_index();
- EXPECT_EQ(1, tab_model()->active_index());
+ EXPECT_EQ(1, current_tab_index);
// Activate sidebar item(brave://settings) and check existing first tab is
// activated.
- auto item = model()->GetAllSidebarItems()[3];
- controller()->ActivateItemAt(3);
+ auto item = model()->GetAllSidebarItems()[4];
+ controller()->ActivateItemAt(4);
EXPECT_EQ(0, tab_model()->active_index());
EXPECT_EQ(tab_model()->GetWebContentsAt(0)->GetVisibleURL(), item.url);
@@ -167,16 +157,6 @@ IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, WebTypePanelTest) {
EXPECT_EQ(2, tab_model()->count());
}
-IN_PROC_BROWSER_TEST_F(SidebarBrowserTest,
- FindBrowserWorksWithoutSidebarController) {
- NavigateParams navigate_params(browser(), GURL("brave://newtab/"),
- ui::PAGE_TRANSITION_TYPED);
- navigate_params.disposition = WindowOpenDisposition::NEW_POPUP;
- ui_test_utils::NavigateToURL(&navigate_params);
- EXPECT_TRUE(chrome::FindBrowserWithWebContents(
- navigate_params.navigated_or_inserted_contents));
-}
-
IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, IterateBuiltInWebTypeTest) {
// Click builtin wallet item and it's loaded at current active tab.
auto item = model()->GetAllSidebarItems()[1];
diff --git a/browser/ui/sidebar/sidebar_controller.cc b/browser/ui/sidebar/sidebar_controller.cc
index 52a9c6630768..e4ee05b1afcd 100644
--- a/browser/ui/sidebar/sidebar_controller.cc
+++ b/browser/ui/sidebar/sidebar_controller.cc
@@ -10,7 +10,6 @@
#include "brave/browser/ui/brave_browser.h"
#include "brave/browser/ui/sidebar/sidebar.h"
#include "brave/browser/ui/sidebar/sidebar_model.h"
-#include "brave/browser/ui/sidebar/sidebar_model_data.h"
#include "brave/browser/ui/sidebar/sidebar_service_factory.h"
#include "brave/browser/ui/sidebar/sidebar_utils.h"
#include "brave/components/sidebar/sidebar_service.h"
@@ -67,13 +66,15 @@ void SidebarController::ActivateItemAt(int index,
DCHECK_GE(index, -1);
if (index == -1) {
sidebar_model_->SetActiveIndex(index);
+ UpdateSidebarVisibility();
return;
}
- const auto item = sidebar_model_->GetAllSidebarItems()[index];
+ const auto& item = sidebar_model_->GetAllSidebarItems()[index];
// Only an item for panel can get activated.
if (item.open_in_panel) {
sidebar_model_->SetActiveIndex(index);
+ UpdateSidebarVisibility();
return;
}
@@ -134,8 +135,6 @@ void SidebarController::LoadAtTab(const GURL& url) {
void SidebarController::OnShowSidebarOptionChanged(
SidebarService::ShowSidebarOption option) {
- // Clear active state whenever sidebar enabled state is changed.
- ActivateItemAt(-1);
UpdateSidebarVisibility();
}
diff --git a/browser/ui/sidebar/sidebar_model.cc b/browser/ui/sidebar/sidebar_model.cc
index 3e12fdb6904b..79388b9996db 100644
--- a/browser/ui/sidebar/sidebar_model.cc
+++ b/browser/ui/sidebar/sidebar_model.cc
@@ -9,8 +9,8 @@
#include
#include "base/logging.h"
+#include "base/ranges/algorithm.h"
#include "base/time/time.h"
-#include "brave/browser/ui/sidebar/sidebar_model_data.h"
#include "brave/browser/ui/sidebar/sidebar_service_factory.h"
#include "brave/components/sidebar/sidebar_item.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
@@ -63,9 +63,11 @@ SidebarModel::~SidebarModel() = default;
void SidebarModel::Init(history::HistoryService* history_service) {
// Start with saved item list.
- for (const auto& item : GetAllSidebarItems())
- AddItem(item, -1, false);
-
+ int index = -1;
+ for (const auto& item : GetAllSidebarItems()) {
+ index++;
+ AddItem(item, index, false);
+ }
sidebar_observed_.Observe(GetSidebarService(profile_));
// Can be null in test.
if (history_service)
@@ -83,18 +85,14 @@ void SidebarModel::RemoveObserver(Observer* observer) {
void SidebarModel::AddItem(const SidebarItem& item,
int index,
bool user_gesture) {
- if (index == -1) {
- data_.push_back(std::make_unique(profile_));
- } else {
- data_.insert(data_.begin() + index,
- std::make_unique(profile_));
- }
+ // Sidebar service should always call with a valid index equal to the
+ // index of the SidebarItem.
+ DCHECK_GE(index, 0);
for (Observer& obs : observers_) {
- // Index starts at zero. If |index| is -1, add as a last item.
- obs.OnItemAdded(item, index == -1 ? data_.size() - 1 : index, user_gesture);
+ obs.OnItemAdded(item, index, user_gesture);
}
- // If active_index_ is not -1, check this addition affetcs active index.
+ // If active_index_ is not -1, check this addition affects active index.
if (active_index_ != -1 && active_index_ >= index)
UpdateActiveIndexAndNotify(index);
@@ -108,32 +106,27 @@ void SidebarModel::OnItemAdded(const SidebarItem& item, int index) {
}
void SidebarModel::OnItemMoved(const SidebarItem& item, int from, int to) {
- // Cache active model data to find its new index after moving.
- SidebarModelData* active_data = nullptr;
- if (active_index_ != -1) {
- active_data = data_[active_index_].get();
- }
-
- std::unique_ptr data = std::move(data_[from]);
- data_.erase(data_.begin() + from);
- data_.insert(data_.begin() + to, std::move(data));
-
for (Observer& obs : observers_)
obs.OnItemMoved(item, from, to);
- if (!active_data)
+ if (active_index_ == -1)
return;
// Find new active items index.
- const int data_size = data_.size();
- for (int i = 0; i < data_size; ++i) {
- if (data_[i].get() == active_data) {
- UpdateActiveIndexAndNotify(i);
- return;
- }
+ const bool active_index_is_unaffected =
+ ((active_index_ > from && active_index_ > to) ||
+ (active_index_ < from && active_index_ < to));
+ if (active_index_is_unaffected) {
+ return;
}
-
- NOTREACHED();
+ int new_active_index = -1;
+ if (active_index_ == from) {
+ new_active_index = to;
+ } else {
+ new_active_index = (to < from) ? active_index_ + 1 : active_index_ - 1;
+ }
+ DCHECK_GE(new_active_index, 0);
+ UpdateActiveIndexAndNotify(new_active_index);
}
void SidebarModel::OnWillRemoveItem(const SidebarItem& item, int index) {
@@ -170,7 +163,6 @@ void SidebarModel::OnURLVisited(history::HistoryService* history_service,
}
void SidebarModel::RemoveItemAt(int index) {
- data_.erase(data_.begin() + index);
for (Observer& obs : observers_)
obs.OnItemRemoved(index);
@@ -184,64 +176,29 @@ void SidebarModel::SetActiveIndex(int index, bool load) {
if (index == active_index_)
return;
- // Don't load url if it's already loaded. If not, new loading is started
- // whenever item is activated.
- // TODO(simonhong): Maybe we should have reload option?
- if (load && index != -1 && !IsLoadedAt(index))
- LoadURLAt(GetAllSidebarItems()[index].url, index);
-
UpdateActiveIndexAndNotify(index);
}
-content::WebContents* SidebarModel::GetWebContentsAt(int index) {
- // Only webcontents is requested for items that opens in panel.
- // Opens in new tab doesn't need to get webcontents here.
- DCHECK(GetAllSidebarItems()[index].open_in_panel);
-
- return data_[index]->GetWebContents();
-}
-
-bool SidebarModel::IsSidebarWebContents(
- const content::WebContents* web_contents) const {
- for (const auto& data : data_) {
- if (data->web_contents() && data->web_contents() == web_contents)
- return true;
- }
-
- return false;
-}
-
-const std::vector SidebarModel::GetAllSidebarItems() const {
+const std::vector& SidebarModel::GetAllSidebarItems() const {
return GetSidebarService(profile_)->items();
}
-bool SidebarModel::IsLoadedAt(int index) const {
- DCHECK(GetAllSidebarItems()[index].open_in_panel);
-
- return data_[index]->IsLoaded();
-}
-
bool SidebarModel::IsSidebarHasAllBuiltiInItems() const {
return GetSidebarService(profile_)->GetHiddenDefaultSidebarItems().empty();
}
int SidebarModel::GetIndexOf(const SidebarItem& item) const {
const auto items = GetAllSidebarItems();
- const auto iter =
- std::find_if(items.begin(), items.end(),
- [item](const auto& i) { return item.url == i.url; });
+ const auto iter = base::ranges::find_if(items, [&item](const auto& i) {
+ return (item.built_in_item_type == i.built_in_item_type &&
+ item.url == i.url);
+ });
if (iter == items.end())
return -1;
return std::distance(items.begin(), iter);
}
-void SidebarModel::LoadURLAt(const GURL& url, int index) {
- DCHECK(GetAllSidebarItems()[index].open_in_panel);
-
- data_[index]->LoadURL(url);
-}
-
void SidebarModel::UpdateActiveIndexAndNotify(int new_active_index) {
if (new_active_index == active_index_)
return;
diff --git a/browser/ui/sidebar/sidebar_model.h b/browser/ui/sidebar/sidebar_model.h
index cc245662cb74..bc79392394dc 100644
--- a/browser/ui/sidebar/sidebar_model.h
+++ b/browser/ui/sidebar/sidebar_model.h
@@ -13,7 +13,6 @@
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
-#include "brave/browser/ui/sidebar/sidebar_model_data.h"
#include "brave/components/sidebar/sidebar_service.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
@@ -44,9 +43,7 @@ class Profile;
namespace sidebar {
-class SidebarModelData;
-
-// Manage sidebar's runtime state.
+// Manage sidebar's runtime state for active index and icons.
// Each browser window has different runtime state.
// Observe SidebarService to get item add/deletion notification.
class SidebarModel : public SidebarService::Observer,
@@ -81,17 +78,11 @@ class SidebarModel : public SidebarService::Observer,
// |false| is used in unit test.
void SetActiveIndex(int index, bool load = true);
// Returns true if webcontents of item at |index| already loaded url.
- bool IsLoadedAt(int index) const;
bool IsSidebarHasAllBuiltiInItems() const;
int GetIndexOf(const SidebarItem& item) const;
- // Don't cache web_contents. It can be deleted during the runtime.
- content::WebContents* GetWebContentsAt(int index);
- // Returns true when |web_contents| is used by sidebar panel.
- bool IsSidebarWebContents(const content::WebContents* web_contents) const;
-
// Don't cache item list. list can be changed during the runtime.
- const std::vector GetAllSidebarItems() const;
+ const std::vector& GetAllSidebarItems() const;
// Return -1 if sidebar panel is not opened.
int active_index() const { return active_index_; }
@@ -115,7 +106,6 @@ class SidebarModel : public SidebarService::Observer,
void AddItem(const SidebarItem& item, int index, bool user_gesture);
void RemoveItemAt(int index);
void UpdateActiveIndexAndNotify(int new_active_index);
- void LoadURLAt(const GURL& url, int index);
// TODO(simonhong): Use separated class for fetching favicon from this model
// class.
@@ -135,7 +125,6 @@ class SidebarModel : public SidebarService::Observer,
Profile* profile_ = nullptr;
std::unique_ptr task_tracker_;
base::ObserverList observers_;
- std::vector> data_;
base::ScopedObservation
sidebar_observed_{this};
base::ScopedObservation
diff --git a/browser/ui/sidebar/sidebar_model_data.cc b/browser/ui/sidebar/sidebar_model_data.cc
deleted file mode 100644
index 5aae474a2a5f..000000000000
--- a/browser/ui/sidebar/sidebar_model_data.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright (c) 2021 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "brave/browser/ui/sidebar/sidebar_model_data.h"
-
-#include
-
-#include "brave/browser/ui/sidebar/sidebar_web_contents_delegate.h"
-#include "chrome/browser/profiles/profile.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/url_constants.h"
-#include "extensions/buildflags/buildflags.h"
-#include "url/gurl.h"
-
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-#include "chrome/browser/extensions/tab_helper.h"
-#include "extensions/browser/view_type_utils.h"
-#include "extensions/common/mojom/view_type.mojom.h"
-#endif
-
-namespace sidebar {
-
-namespace {
-
-void AttachTabHelpersForSidebar(content::WebContents* contents) {
-#if BUILDFLAG(ENABLE_EXTENSIONS)
- extensions::SetViewType(contents, extensions::mojom::ViewType::kTabContents);
- extensions::TabHelper::CreateForWebContents(contents);
-#endif
-}
-
-} // namespace
-
-SidebarModelData::SidebarModelData(Profile* profile) : profile_(profile) {}
-
-SidebarModelData::~SidebarModelData() {
- // Make sure to destroy contents first because contents refers delegate.
- contents_.reset();
- contents_delegate_.reset();
-}
-
-content::WebContents* SidebarModelData::GetWebContents() {
- if (!contents_) {
- content::WebContents::CreateParams params(profile_);
- contents_ = content::WebContents::Create(params);
- contents_delegate_.reset(new SidebarWebContentsDelegate);
- contents_->SetDelegate(contents_delegate_.get());
-
- AttachTabHelpersForSidebar(contents_.get());
- }
-
- return contents_.get();
-}
-
-void SidebarModelData::LoadURL(const GURL& url) {
- // Only internal webui can be loaded in sidebar panel now.
- // Revisit when we want to load any url in panel.
- DCHECK(url.SchemeIs(content::kChromeUIScheme));
- GetWebContents()->GetController().LoadURL(url, content::Referrer(),
- ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
- std::string());
-}
-
-bool SidebarModelData::IsLoaded() const {
- if (!contents_)
- return false;
-
- return !contents_->GetVisibleURL().is_empty();
-}
-
-} // namespace sidebar
diff --git a/browser/ui/sidebar/sidebar_model_data.h b/browser/ui/sidebar/sidebar_model_data.h
deleted file mode 100644
index c36bf2df4c04..000000000000
--- a/browser/ui/sidebar/sidebar_model_data.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (c) 2021 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef BRAVE_BROWSER_UI_SIDEBAR_SIDEBAR_MODEL_DATA_H_
-#define BRAVE_BROWSER_UI_SIDEBAR_SIDEBAR_MODEL_DATA_H_
-
-#include
-
-class GURL;
-class Profile;
-
-namespace content {
-class WebContents;
-} // namespace content
-
-namespace sidebar {
-
-class SidebarWebContentsDelegate;
-
-// SidebarModelData represents sidebar each item's runtime state.
-// Each sidebar item of built in type owns WebContents.
-class SidebarModelData {
- public:
- explicit SidebarModelData(Profile* profile);
- virtual ~SidebarModelData();
-
- SidebarModelData(const SidebarModelData&) = delete;
- SidebarModelData& operator=(const SidebarModelData&) = delete;
-
- content::WebContents* GetWebContents();
-
- // nullptr if GetWebContents() is not called yet.
- content::WebContents* web_contents() const { return contents_.get(); }
-
- void LoadURL(const GURL& url);
- bool IsLoaded() const;
-
- private:
- Profile* profile_ = nullptr;
- std::unique_ptr contents_delegate_;
- std::unique_ptr contents_;
-};
-
-} // namespace sidebar
-
-#endif // BRAVE_BROWSER_UI_SIDEBAR_SIDEBAR_MODEL_DATA_H_
diff --git a/browser/ui/sidebar/sidebar_unittest.cc b/browser/ui/sidebar/sidebar_unittest.cc
index 86c47e941357..6f089c2050c0 100644
--- a/browser/ui/sidebar/sidebar_unittest.cc
+++ b/browser/ui/sidebar/sidebar_unittest.cc
@@ -64,26 +64,25 @@ class SidebarModelTest : public testing::Test, public SidebarModel::Observer {
};
TEST_F(SidebarModelTest, ItemsChangedTest) {
- EXPECT_EQ(0UL, model()->data_.size());
+ auto built_in_items_size =
+ SidebarService::GetDefaultBuiltInItemTypes_ForTesting().size();
+ EXPECT_EQ(built_in_items_size, service()->items().size());
model()->Init(nullptr);
- EXPECT_EQ(service()->items().size(), model()->data_.size());
EXPECT_EQ(-1, model()->active_index());
- // Add one more item to test with 4 items.
+ // Add one more item to test with 5 items.
SidebarItem new_item;
new_item.url = GURL("https://brave.com");
service()->AddItem(new_item);
- EXPECT_EQ(4UL, service()->items().size());
- EXPECT_EQ(4UL, model()->data_.size());
- EXPECT_EQ(service()->items().size(), model()->data_.size());
+ EXPECT_EQ(built_in_items_size + 1, service()->items().size());
// Move item at 1 to at index 2.
// Total size and active index is not changed when currently active index is
// -1.
- const size_t model_size = model()->data_.size();
+ const size_t items_size = service()->items().size();
// Cache data at index 1.
- auto* model_data = model()->data_[1].get();
+ const auto item_data = service()->items()[1];
EXPECT_FALSE(on_item_moved_called_);
EXPECT_FALSE(on_active_index_changed_called_);
@@ -91,9 +90,12 @@ TEST_F(SidebarModelTest, ItemsChangedTest) {
EXPECT_TRUE(on_item_moved_called_);
EXPECT_FALSE(on_active_index_changed_called_);
- EXPECT_EQ(model_data, model()->data_[2].get());
+ EXPECT_EQ(item_data.built_in_item_type,
+ service()->items()[2].built_in_item_type);
+ EXPECT_EQ(item_data.url, service()->items()[2].url);
+ EXPECT_EQ(item_data.title, service()->items()[2].title);
EXPECT_EQ(-1, model()->active_index());
- EXPECT_EQ(model_size, model()->data_.size());
+ EXPECT_EQ(items_size, service()->items().size());
model()->SetActiveIndex(1, false);
EXPECT_EQ(1, model()->active_index());
@@ -140,8 +142,6 @@ TEST(SidebarUtilTest, ConvertURLToBuiltInItemURLTest) {
EXPECT_EQ(GURL(kBraveTalkURL),
ConvertURLToBuiltInItemURL(
GURL("https://talk.brave.com/1Ar1vHfLBWX2sAdi")));
- EXPECT_EQ(GURL(kSidebarBookmarksURL),
- ConvertURLToBuiltInItemURL(GURL(chrome::kChromeUIBookmarksURL)));
EXPECT_EQ(
GURL(kBraveUIWalletPageURL),
ConvertURLToBuiltInItemURL(GURL("chrome://wallet/crypto/onboarding")));
diff --git a/browser/ui/sidebar/sidebar_utils.cc b/browser/ui/sidebar/sidebar_utils.cc
index b414e6785958..b006de984fe1 100644
--- a/browser/ui/sidebar/sidebar_utils.cc
+++ b/browser/ui/sidebar/sidebar_utils.cc
@@ -75,7 +75,7 @@ bool CanUseSidebar(Browser* browser) {
// if sidebar panel already has bookmarks item.
GURL ConvertURLToBuiltInItemURL(const GURL& url) {
if (url == GURL(chrome::kChromeUIBookmarksURL))
- return GURL(kSidebarBookmarksURL);
+ return GURL(chrome::kChromeUIBookmarksSidePanelURL);
if (url.host() == kBraveTalkHost)
return GURL(kBraveTalkURL);
diff --git a/browser/ui/sidebar/sidebar_web_contents_delegate.cc b/browser/ui/sidebar/sidebar_web_contents_delegate.cc
deleted file mode 100644
index e8b88c6dcedd..000000000000
--- a/browser/ui/sidebar/sidebar_web_contents_delegate.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (c) 2021 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "brave/browser/ui/sidebar/sidebar_web_contents_delegate.h"
-
-#include "brave/browser/ui/brave_browser.h"
-#include "brave/browser/ui/sidebar/sidebar.h"
-#include "brave/browser/ui/sidebar/sidebar_controller.h"
-#include "chrome/browser/ui/browser_finder.h"
-
-namespace sidebar {
-
-namespace {
-
-SidebarController* GetSidebarController(content::WebContents* source) {
- auto* brave_browser =
- static_cast(chrome::FindBrowserWithWebContents(source));
- if (!brave_browser)
- return nullptr;
-
- return brave_browser->sidebar_controller();
-}
-
-} // namespace
-
-SidebarWebContentsDelegate::SidebarWebContentsDelegate() = default;
-SidebarWebContentsDelegate::~SidebarWebContentsDelegate() = default;
-
-bool SidebarWebContentsDelegate::HandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) {
- if (auto* sidebar_controller = GetSidebarController(source))
- return sidebar_controller->sidebar()->HandleKeyboardEvent(source, event);
-
- return false;
-}
-
-} // namespace sidebar
diff --git a/browser/ui/sidebar/sidebar_web_contents_delegate.h b/browser/ui/sidebar/sidebar_web_contents_delegate.h
deleted file mode 100644
index 80fa8ecd7d04..000000000000
--- a/browser/ui/sidebar/sidebar_web_contents_delegate.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (c) 2021 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef BRAVE_BROWSER_UI_SIDEBAR_SIDEBAR_WEB_CONTENTS_DELEGATE_H_
-#define BRAVE_BROWSER_UI_SIDEBAR_SIDEBAR_WEB_CONTENTS_DELEGATE_H_
-
-#include "content/public/browser/web_contents_delegate.h"
-
-namespace sidebar {
-
-class SidebarWebContentsDelegate : public content::WebContentsDelegate {
- public:
- SidebarWebContentsDelegate();
- ~SidebarWebContentsDelegate() override;
-
- SidebarWebContentsDelegate(const SidebarWebContentsDelegate&) = delete;
- SidebarWebContentsDelegate& operator=(const SidebarWebContentsDelegate&) =
- delete;
-
- private:
- // content::WebContentsDelegate overrides:
- bool HandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) override;
-};
-
-} // namespace sidebar
-
-#endif // BRAVE_BROWSER_UI_SIDEBAR_SIDEBAR_WEB_CONTENTS_DELEGATE_H_
diff --git a/browser/ui/tabs/brave_tab_strip_model.cc b/browser/ui/tabs/brave_tab_strip_model.cc
index 4624a8314e2e..de47b85f361d 100644
--- a/browser/ui/tabs/brave_tab_strip_model.cc
+++ b/browser/ui/tabs/brave_tab_strip_model.cc
@@ -76,8 +76,3 @@ void BraveTabStripModel::SelectMRUTab(TabRelativeDirection direction,
void BraveTabStripModel::StopMRUCycling() {
mru_cycle_list_.clear();
}
-
-bool BraveTabStripModel::IsReadLaterSupportedForAny(
- const std::vector& indices) {
- return false;
-}
diff --git a/browser/ui/tabs/brave_tab_strip_model.h b/browser/ui/tabs/brave_tab_strip_model.h
index cea573c9ba25..905433605700 100644
--- a/browser/ui/tabs/brave_tab_strip_model.h
+++ b/browser/ui/tabs/brave_tab_strip_model.h
@@ -24,8 +24,6 @@ class BraveTabStripModel : public TabStripModel {
void SelectRelativeTab(TabRelativeDirection direction,
UserGestureDetails detail) override;
- bool IsReadLaterSupportedForAny(const std::vector& indices) override;
-
// Set the next tab when doing a MRU cycling with Ctrl-tab
void SelectMRUTab(
TabRelativeDirection direction,
diff --git a/browser/ui/views/frame/brave_browser_view.cc b/browser/ui/views/frame/brave_browser_view.cc
index 68ffeb143a32..55f68fe4b890 100644
--- a/browser/ui/views/frame/brave_browser_view.cc
+++ b/browser/ui/views/frame/brave_browser_view.cc
@@ -180,11 +180,15 @@ BraveBrowserView::BraveBrowserView(std::unique_ptr browser)
auto brave_contents_container = std::make_unique();
- // Wrap |contents_container_| within our new |brave_contents_container_|.
- // |brave_contents_container_| also contains sidebar.
- auto orignal_contents_container = RemoveChildViewT(contents_container_.get());
+ // Wrap chromium side panel with our sidebar container
+ auto original_side_panel = RemoveChildViewT(right_aligned_side_panel_.get());
sidebar_container_view_ = brave_contents_container->AddChildView(
- std::make_unique(GetBraveBrowser()));
+ std::make_unique(GetBraveBrowser(),
+ side_panel_coordinator(),
+ std::move(original_side_panel)));
+ right_aligned_side_panel_ = sidebar_container_view_->side_panel();
+ // Put sidebar into chromium contents area
+ auto orignal_contents_container = RemoveChildViewT(contents_container_.get());
original_contents_container_ = brave_contents_container->AddChildView(
std::move(orignal_contents_container));
brave_contents_container->SetLayoutManager(
diff --git a/browser/ui/views/frame/brave_browser_view_layout.cc b/browser/ui/views/frame/brave_browser_view_layout.cc
new file mode 100644
index 000000000000..8b77dceb52dd
--- /dev/null
+++ b/browser/ui/views/frame/brave_browser_view_layout.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "brave/browser/ui/views/frame/brave_browser_view_layout.h"
+
+void BraveBrowserViewLayout::LayoutSidePanelView(
+ views::View* side_panel,
+ gfx::Rect& contents_container_bounds) {
+ // We don't want to do any special layout for brave's sidebar (which
+ // is the parent of chromium's side panel). We simply
+ // use flex layout to put it to the side of the content view.
+ return;
+}
diff --git a/browser/ui/views/frame/brave_browser_view_layout.h b/browser/ui/views/frame/brave_browser_view_layout.h
new file mode 100644
index 000000000000..92de4b564632
--- /dev/null
+++ b/browser/ui/views/frame/brave_browser_view_layout.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_BROWSER_VIEW_LAYOUT_H_
+#define BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_BROWSER_VIEW_LAYOUT_H_
+
+#include "chrome/browser/ui/views/frame/browser_view_layout.h"
+
+class BraveBrowserViewLayout : public BrowserViewLayout {
+ public:
+ using BrowserViewLayout::BrowserViewLayout;
+
+ // BrowserViewLayout overrides:
+ void LayoutSidePanelView(views::View* side_panel,
+ gfx::Rect& contents_container_bounds) override;
+};
+
+#endif // BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_BROWSER_VIEW_LAYOUT_H_
diff --git a/browser/ui/views/side_panel/brave_side_panel.cc b/browser/ui/views/side_panel/brave_side_panel.cc
new file mode 100644
index 000000000000..15a0f4aaa5db
--- /dev/null
+++ b/browser/ui/views/side_panel/brave_side_panel.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "brave/browser/ui/views/side_panel/brave_side_panel.h"
+
+#include
+
+#include "base/ranges/algorithm.h"
+#include "chrome/browser/themes/theme_properties.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/theme_provider.h"
+#include "ui/views/border.h"
+#include "ui/views/layout/fill_layout.h"
+
+BraveSidePanel::BraveSidePanel(BrowserView* browser_view) {
+ SetVisible(false);
+ SetLayoutManager(std::make_unique());
+
+ // TODO(pbos): Reconsider if SetPanelWidth() should add borders, if so move
+ // accounting for the border into SetPanelWidth(), otherwise remove this TODO.
+ constexpr int kDefaultWidth = 320;
+ SetPreferredSize(gfx::Size(kDefaultWidth, 1));
+ AddObserver(this);
+}
+
+BraveSidePanel::~BraveSidePanel() {
+ RemoveObserver(this);
+}
+
+void BraveSidePanel::UpdateVisibility() {
+ const bool any_child_visible = base::ranges::any_of(
+ children(), [](const auto* view) { return view->GetVisible(); });
+ SetVisible(any_child_visible);
+}
+
+void BraveSidePanel::UpdateBorder() {
+ if (const ui::ThemeProvider* theme_provider = GetThemeProvider()) {
+ constexpr int kBorderThickness = 1;
+ // Negative top border so panel is flush with main tab content
+ SetBorder(views::CreateSolidSidedBorder(
+ gfx::Insets::TLBR(-1, 0, 0, kBorderThickness),
+ theme_provider->GetColor(
+ ThemeProperties::COLOR_TOOLBAR_CONTENT_AREA_SEPARATOR)));
+ }
+}
+
+void BraveSidePanel::ChildVisibilityChanged(View* child) {
+ UpdateVisibility();
+}
+
+void BraveSidePanel::OnThemeChanged() {
+ View::OnThemeChanged();
+ UpdateBorder();
+}
+
+void BraveSidePanel::OnChildViewAdded(View* observed_view, View* child) {
+ UpdateVisibility();
+}
+
+void BraveSidePanel::OnChildViewRemoved(View* observed_view, View* child) {
+ UpdateVisibility();
+}
+
+BEGIN_METADATA(BraveSidePanel, views::View)
+END_METADATA
diff --git a/browser/ui/views/side_panel/brave_side_panel.h b/browser/ui/views/side_panel/brave_side_panel.h
new file mode 100644
index 000000000000..ed4a1659066e
--- /dev/null
+++ b/browser/ui/views/side_panel/brave_side_panel.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_H_
+#define BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_H_
+
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/view.h"
+#include "ui/views/view_observer.h"
+
+class BrowserView;
+
+// Replacement for chromium's SidePanel which defines a
+// unique inset and border style compared to Brave
+class BraveSidePanel : public views::View, public views::ViewObserver {
+ public:
+ METADATA_HEADER(BraveSidePanel);
+ // Same signature as chromium SidePanel
+ explicit BraveSidePanel(BrowserView* browser_view);
+ BraveSidePanel(const BraveSidePanel&) = delete;
+ BraveSidePanel& operator=(const BraveSidePanel&) = delete;
+ ~BraveSidePanel() override;
+
+ private:
+ void UpdateVisibility();
+ void UpdateBorder();
+
+ // views::View:
+ void ChildVisibilityChanged(View* child) override;
+ void OnThemeChanged() override;
+
+ // views::ViewObserver:
+ void OnChildViewAdded(View* observed_view, View* child) override;
+ void OnChildViewRemoved(View* observed_view, View* child) override;
+};
+
+#endif // BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_H_
diff --git a/browser/ui/views/sidebar/sidebar_container_view.cc b/browser/ui/views/sidebar/sidebar_container_view.cc
index d61f1433b7ba..16678f1ee021 100644
--- a/browser/ui/views/sidebar/sidebar_container_view.cc
+++ b/browser/ui/views/sidebar/sidebar_container_view.cc
@@ -7,20 +7,24 @@
#include
+#include "base/auto_reset.h"
#include "base/bind.h"
#include "brave/browser/themes/theme_properties.h"
#include "brave/browser/ui/brave_browser.h"
#include "brave/browser/ui/sidebar/sidebar_controller.h"
#include "brave/browser/ui/sidebar/sidebar_model.h"
-#include "brave/browser/ui/sidebar/sidebar_model_data.h"
#include "brave/browser/ui/sidebar/sidebar_service_factory.h"
#include "brave/browser/ui/views/frame/brave_browser_view.h"
+#include "brave/browser/ui/views/side_panel/brave_side_panel.h"
#include "brave/browser/ui/views/sidebar/sidebar_control_view.h"
-#include "brave/browser/ui/views/sidebar/sidebar_panel_webview.h"
+#include "brave/browser/ui/views/sidebar/sidebar_side_panel_utils.h"
+#include "brave/components/sidebar/sidebar_item.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents.h"
@@ -42,19 +46,6 @@ sidebar::SidebarService* GetSidebarService(BraveBrowser* browser) {
return sidebar::SidebarServiceFactory::GetForProfile(browser->profile());
}
-size_t GetPreferredPanelWidthForCurrentItem(BraveBrowser* browser) {
- auto* controller = browser->sidebar_controller();
- int active_index = controller->model()->active_index();
- const auto item = GetSidebarService(browser)->items()[active_index];
- // Shortcut type doesn't use panel.
- if (!item.open_in_panel)
- return 0;
-
- constexpr size_t kPanelWidthForBuiltIn = 260;
- constexpr size_t kPanelWidthForNonBuiltIn = 360;
- return IsBuiltInType(item) ? kPanelWidthForBuiltIn : kPanelWidthForNonBuiltIn;
-}
-
} // namespace
class SidebarContainerView::BrowserWindowEventObserver
@@ -80,7 +71,7 @@ class SidebarContainerView::BrowserWindowEventObserver
&window_event_position);
if (!host_->sidebar_control_view_->GetLocalBounds().Contains(
window_event_position) &&
- !host_->ShouldShowSidebar()) {
+ !host_->ShouldForceShowSidebar()) {
host_->StopBrowserWindowEventMonitoring();
host_->ShowSidebar(false, true);
}
@@ -90,11 +81,16 @@ class SidebarContainerView::BrowserWindowEventObserver
SidebarContainerView* host_ = nullptr;
};
-SidebarContainerView::SidebarContainerView(BraveBrowser* browser)
+SidebarContainerView::SidebarContainerView(
+ BraveBrowser* browser,
+ SidePanelCoordinator* side_panel_coordinator,
+ std::unique_ptr side_panel)
: browser_(browser),
+ side_panel_coordinator_(side_panel_coordinator),
browser_window_event_observer_(
std::make_unique(this)) {
SetNotifyEnterExitOnChild(true);
+ side_panel_ = AddChildView(std::move(side_panel));
}
SidebarContainerView::~SidebarContainerView() = default;
@@ -103,84 +99,74 @@ void SidebarContainerView::Init() {
initialized_ = true;
sidebar_model_ = browser_->sidebar_controller()->model();
- observed_.Observe(sidebar_model_);
+ sidebar_model_observation_.Observe(sidebar_model_);
+
+ auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
+ DCHECK(browser_view);
+
+ auto* side_panel_registry =
+ browser_view->side_panel_coordinator()->GetGlobalSidePanelRegistry();
+ panel_registry_observation_.Observe(side_panel_registry);
+
+ for (const auto& entry : side_panel_registry->entries()) {
+ DVLOG(1) << "Observing panel entry in ctor: " << entry->name();
+ panel_entry_observations_.AddObservation(entry.get());
+ }
AddChildViews();
// Hide by default. Visibility will be controlled by show options later.
DoHideSidebar(false);
+ UpdateToolbarButtonVisibility();
}
void SidebarContainerView::SetSidebarShowOption(
sidebar::SidebarService::ShowSidebarOption show_option) {
- if (show_option == ShowSidebarOption::kShowAlways) {
- ShowSidebar(true, false);
- return;
- }
-
- if (show_option == ShowSidebarOption::kShowNever) {
- ShowSidebar(false, false);
- return;
- }
-
- ShowSidebar(false, true);
+ UpdateSidebarVisibility(show_option);
}
void SidebarContainerView::UpdateSidebar() {
sidebar_control_view_->Update();
}
-void SidebarContainerView::ShowCustomContextMenu(
- const gfx::Point& point,
- std::unique_ptr menu_model) {
- if (!sidebar_panel_webview_->GetVisible()) {
- LOG(ERROR) << __func__
- << " sidebar panel UI is loaded at non sidebar panel!";
- return;
- }
-
- sidebar_panel_webview_->ShowCustomContextMenu(point, std::move(menu_model));
+void SidebarContainerView::MenuClosed() {
+ UpdateSidebarVisibility();
}
-void SidebarContainerView::HideCustomContextMenu() {
- if (!sidebar_panel_webview_->GetVisible()) {
- LOG(ERROR) << __func__
- << " sidebar panel UI is loaded at non sidebar panel!";
- return;
+void SidebarContainerView::UpdateBackground() {
+ if (const ui::ThemeProvider* theme_provider = GetThemeProvider()) {
+ // Fill background because panel's color uses alpha value.
+ SetBackground(views::CreateSolidBackground(
+ theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR)));
}
-
- sidebar_panel_webview_->HideCustomContextMenu();
}
-bool SidebarContainerView::HandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) {
- DCHECK(sidebar_panel_webview_->GetVisible());
- return sidebar_panel_webview_->TreatUnHandledKeyboardEvent(source, event);
+void SidebarContainerView::UpdateSidebarVisibility() {
+ const auto show_option = GetSidebarService(browser_)->GetSidebarShowOption();
+ UpdateSidebarVisibility(show_option);
}
-void SidebarContainerView::UpdateBackgroundAndBorder() {
- if (const ui::ThemeProvider* theme_provider = GetThemeProvider()) {
- constexpr int kBorderThickness = 1;
- // Fill background because panel's color uses alpha value.
- SetBackground(views::CreateSolidBackground(
- theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR)));
- if (sidebar_panel_webview_ && sidebar_panel_webview_->GetVisible()) {
- SetBorder(views::CreateSolidSidedBorder(
- gfx::Insets::TLBR(0, 0, 0, kBorderThickness),
- theme_provider->GetColor(
- ThemeProperties::COLOR_TOOLBAR_CONTENT_AREA_SEPARATOR)));
- } else {
- // Don't need right side border when panel is closed.
- SetBorder(nullptr);
- }
+void SidebarContainerView::UpdateSidebarVisibility(
+ sidebar::SidebarService::ShowSidebarOption show_option) {
+ // Always show, don't need to use mouse event detection.
+ if (show_option == ShowSidebarOption::kShowAlways) {
+ ShowSidebar(true, false);
+ return;
+ }
+ // Never show, except if there's a UI operation in progress. Still
+ // don't need to use mouse event detection.
+ if (show_option == ShowSidebarOption::kShowNever) {
+ ShowSidebar(ShouldForceShowSidebar(), false);
+ return;
}
+ // Only show if mouse is hovered or there's a UI operation in progress.
+ ShowSidebar(IsMouseHovered() || ShouldForceShowSidebar(), true);
}
void SidebarContainerView::AddChildViews() {
+ // Insert to index 0 because |side_panel_| will already be at 0 but
+ // we want the controls first.
sidebar_control_view_ =
- AddChildView(std::make_unique(browser_));
- sidebar_panel_webview_ =
- AddChildView(std::make_unique(browser_->profile()));
+ AddChildViewAt(std::make_unique(this, browser_), 0);
}
void SidebarContainerView::Layout() {
@@ -191,10 +177,9 @@ void SidebarContainerView::Layout() {
sidebar_control_view_->GetPreferredSize().width();
sidebar_control_view_->SetBounds(0, 0, control_view_preferred_width,
height());
- if (sidebar_panel_webview_->GetVisible()) {
- sidebar_panel_webview_->SetBounds(
- control_view_preferred_width, 0,
- GetPreferredPanelWidthForCurrentItem(browser_), height());
+ if (side_panel_->GetVisible()) {
+ side_panel_->SetBounds(control_view_preferred_width, 0,
+ side_panel_->GetPreferredSize().width(), height());
}
}
@@ -205,8 +190,8 @@ gfx::Size SidebarContainerView::CalculatePreferredSize() const {
int preferred_width =
sidebar_control_view_->GetPreferredSize().width() + GetInsets().width();
- if (sidebar_panel_webview_->GetVisible())
- preferred_width += GetPreferredPanelWidthForCurrentItem(browser_);
+ if (side_panel_->GetVisible())
+ preferred_width += side_panel_->GetPreferredSize().width();
// height is determined by parent.
return {preferred_width, 0};
}
@@ -214,11 +199,21 @@ gfx::Size SidebarContainerView::CalculatePreferredSize() const {
void SidebarContainerView::OnThemeChanged() {
View::OnThemeChanged();
- UpdateBackgroundAndBorder();
+ UpdateBackground();
}
-bool SidebarContainerView::ShouldShowSidebar() const {
- return sidebar_panel_webview_->GetVisible() ||
+bool SidebarContainerView::ShouldForceShowSidebar() const {
+ // Always show if panel should be visible. It is more reliable to check
+ // whether the active index is a panel item rather than checking if
+ // side_panel_ is visible.
+ bool panel_is_active = false;
+ if (auto active_index = sidebar_model_->active_index(); active_index != -1) {
+ const auto& items = sidebar_model_->GetAllSidebarItems();
+ const auto& active_item = items[active_index];
+ panel_is_active = active_item.open_in_panel;
+ }
+ // Always show if user is reordering or a menu is visible
+ return panel_is_active ||
sidebar_control_view_->IsItemReorderingInProgress() ||
sidebar_control_view_->IsBubbleWidgetVisible();
}
@@ -251,7 +246,7 @@ void SidebarContainerView::OnMouseExited(const ui::MouseEvent& event) {
if (!autohide_sidebar)
return;
- if (ShouldShowSidebar()) {
+ if (ShouldForceShowSidebar()) {
StartBrowserWindowEventMonitoring();
return;
}
@@ -260,26 +255,41 @@ void SidebarContainerView::OnMouseExited(const ui::MouseEvent& event) {
}
void SidebarContainerView::OnActiveIndexChanged(int old_index, int new_index) {
+ DVLOG(1) << "OnActiveIndexChanged: " << old_index << " to " << new_index;
if (new_index == -1) {
- sidebar_panel_webview_->SetVisible(false);
+ // `is_side_panel_event_` is used because `SidePanelCoordinator::Close`
+ // unfortunately calls both the event handler for `OnEntryHidden` as well
+ // as removing the View. Without it, we end up calling
+ // `SidePanelCoordinator::Close` recursively when the event originates from
+ // the SidePanelCoordinator itself (as opposed to out Sidebar buttons). This
+ // would then attempt to remove the entry's panel View twice.
+ // TODO(petemill): Consider reorganising the control between sidebar and
+ // sidepanel so that this is clearer.
+ if (!is_side_panel_event_)
+ side_panel_coordinator_->Close();
GetFocusManager()->ClearFocus();
- } else {
- const auto item = sidebar_model_->GetAllSidebarItems()[new_index];
+ } else if (!is_side_panel_event_) {
+ const auto& item = sidebar_model_->GetAllSidebarItems()[new_index];
if (item.open_in_panel) {
- sidebar_panel_webview_->SetWebContents(
- sidebar_model_->GetWebContentsAt(new_index));
- sidebar_panel_webview_->SetVisible(true);
- // When panel is opened, it will get focused.
- sidebar_panel_webview_->RequestFocus();
+ // Get side panel entry information
+ side_panel_coordinator_->Show(SidePanelIdFromSideBarItem(item));
} else {
- sidebar_panel_webview_->SetVisible(false);
- GetFocusManager()->ClearFocus();
+ side_panel_coordinator_->Close();
}
}
- UpdateBackgroundAndBorder();
InvalidateLayout();
}
+void SidebarContainerView::OnItemAdded(const sidebar::SidebarItem& item,
+ int index,
+ bool user_gesture) {
+ UpdateToolbarButtonVisibility();
+}
+
+void SidebarContainerView::OnItemRemoved(int index) {
+ UpdateToolbarButtonVisibility();
+}
+
SidebarShowOptionsEventDetectWidget*
SidebarContainerView::GetEventDetectWidget() {
if (!show_options_widget_) {
@@ -324,6 +334,17 @@ void SidebarContainerView::DoHideSidebar(bool show_event_detect_widget) {
InvalidateLayout();
}
+void SidebarContainerView::UpdateToolbarButtonVisibility() {
+ // Coordinate sidebar toolbar button visibility based on
+ // whether there are any sibar items with a sidepanel.
+ // This is similar to how chromium's side_panel_coordinator View
+ // also has some control on the toolbar button.
+ auto has_panel_item =
+ GetSidebarService(browser_)->GetDefaultPanelItem().has_value();
+ auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
+ browser_view->toolbar()->side_panel_button()->SetVisible(has_panel_item);
+}
+
void SidebarContainerView::StartBrowserWindowEventMonitoring() {
if (browser_window_event_monitor_)
return;
@@ -337,5 +358,56 @@ void SidebarContainerView::StopBrowserWindowEventMonitoring() {
browser_window_event_monitor_.reset();
}
+void SidebarContainerView::OnEntryShown(SidePanelEntry* entry) {
+ base::AutoReset auto_reset(&is_side_panel_event_, true);
+
+ // Make sure item is selected. We need to observe the SidePanel system
+ // as well as Sidebar as there are other ways than Sidebar for SidePanel
+ // items to be shown and hidden, e.g. toolbar button.
+ DVLOG(1) << "Panel shown: " << entry->name();
+ for (const auto& item : sidebar_model_->GetAllSidebarItems()) {
+ if (!item.open_in_panel) {
+ continue;
+ }
+ if (entry->id() == sidebar::SidePanelIdFromSideBarItem(item)) {
+ auto side_bar_index = sidebar_model_->GetIndexOf(item);
+ auto* controller = browser_->sidebar_controller();
+ controller->ActivateItemAt(side_bar_index);
+ break;
+ }
+ }
+}
+
+void SidebarContainerView::OnEntryHidden(SidePanelEntry* entry) {
+ base::AutoReset auto_reset(&is_side_panel_event_, true);
+ // Make sure item is deselected
+ DVLOG(1) << "Panel hidden: " << entry->name();
+ for (const auto& item : sidebar_model_->GetAllSidebarItems()) {
+ if (!item.open_in_panel) {
+ continue;
+ }
+ if (entry->id() == sidebar::SidePanelIdFromSideBarItem(item)) {
+ auto side_bar_index = sidebar_model_->GetIndexOf(item);
+ auto* controller = browser_->sidebar_controller();
+ if (controller->IsActiveIndex(side_bar_index)) {
+ controller->ActivateItemAt(-1);
+ }
+ break;
+ }
+ }
+}
+
+void SidebarContainerView::OnEntryRegistered(SidePanelEntry* entry) {
+ // Observe when it's shown or hidden
+ DVLOG(1) << "Observing panel entry in registry observer: " << entry->name();
+ panel_entry_observations_.AddObservation(entry);
+}
+
+void SidebarContainerView::OnEntryWillDeregister(SidePanelEntry* entry) {
+ // Stop observing
+ DVLOG(1) << "Unobserving panel entry in registry observer: " << entry->name();
+ panel_entry_observations_.RemoveObservation(entry);
+}
+
BEGIN_METADATA(SidebarContainerView, views::View)
END_METADATA
diff --git a/browser/ui/views/sidebar/sidebar_container_view.h b/browser/ui/views/sidebar/sidebar_container_view.h
index 99174bcdf765..6a32f9b59d7e 100644
--- a/browser/ui/views/sidebar/sidebar_container_view.h
+++ b/browser/ui/views/sidebar/sidebar_container_view.h
@@ -9,12 +9,18 @@
#include
#include "base/memory/raw_ptr.h"
+#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "brave/browser/ui/sidebar/sidebar.h"
#include "brave/browser/ui/sidebar/sidebar_model.h"
+#include "brave/browser/ui/views/side_panel/brave_side_panel.h"
+#include "brave/browser/ui/views/sidebar/sidebar_control_view.h"
#include "brave/browser/ui/views/sidebar/sidebar_show_options_event_detect_widget.h"
#include "brave/components/sidebar/sidebar_service.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_entry_observer.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_registry_observer.h"
#include "ui/events/event_observer.h"
#include "ui/views/view.h"
@@ -27,20 +33,24 @@ class SidebarBrowserTest;
} // namespace sidebar
class BraveBrowser;
-class SidebarControlView;
-class SidebarPanelWebView;
+class SidePanelEntry;
// This view is the parent view of all sidebar ui.
// Thi will include sidebar items button, add button, settings button and panel
// view.
class SidebarContainerView
: public sidebar::Sidebar,
+ public SidebarControlView::Delegate,
public views::View,
public SidebarShowOptionsEventDetectWidget::Delegate,
- public sidebar::SidebarModel::Observer {
+ public sidebar::SidebarModel::Observer,
+ public SidePanelEntryObserver,
+ public SidePanelRegistryObserver {
public:
METADATA_HEADER(SidebarContainerView);
- explicit SidebarContainerView(BraveBrowser* browser);
+ SidebarContainerView(BraveBrowser* browser,
+ SidePanelCoordinator* side_panel_coordinator,
+ std::unique_ptr side_panel);
~SidebarContainerView() override;
SidebarContainerView(const SidebarContainerView&) = delete;
@@ -48,17 +58,15 @@ class SidebarContainerView
void Init();
+ BraveSidePanel* side_panel() { return side_panel_; }
+
// Sidebar overrides:
void SetSidebarShowOption(
sidebar::SidebarService::ShowSidebarOption show_option) override;
void UpdateSidebar() override;
- void ShowCustomContextMenu(
- const gfx::Point& point,
- std::unique_ptr menu_model) override;
- void HideCustomContextMenu() override;
- bool HandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) override;
+
+ // SidebarControlView::Delegate overrides:
+ void MenuClosed() override;
// views::View overrides:
void Layout() override;
@@ -71,7 +79,19 @@ class SidebarContainerView
void ShowSidebar() override;
// sidebar::SidebarModel::Observer overrides:
+ void OnItemAdded(const sidebar::SidebarItem& item,
+ int index,
+ bool user_gesture) override;
void OnActiveIndexChanged(int old_index, int new_index) override;
+ void OnItemRemoved(int index) override;
+
+ // SidePanelEntryObserver:
+ void OnEntryShown(SidePanelEntry* entry) override;
+ void OnEntryHidden(SidePanelEntry* entry) override;
+
+ // SidePanelRegistryObserver:
+ void OnEntryRegistered(SidePanelEntry* entry) override;
+ void OnEntryWillDeregister(SidePanelEntry* entry) override;
private:
friend class sidebar::SidebarBrowserTest;
@@ -79,11 +99,15 @@ class SidebarContainerView
class BrowserWindowEventObserver;
void AddChildViews();
- void UpdateBackgroundAndBorder();
+ void UpdateBackground();
+ void UpdateSidebarVisibility();
+ void UpdateSidebarVisibility(
+ sidebar::SidebarService::ShowSidebarOption show_option);
void ShowOptionsEventDetectWidget(bool show);
void ShowSidebar(bool show_sidebar, bool show_event_detect_widget);
SidebarShowOptionsEventDetectWidget* GetEventDetectWidget();
- bool ShouldShowSidebar() const;
+ bool ShouldForceShowSidebar() const;
+ void UpdateToolbarButtonVisibility();
// On some condition(ex, add item bubble is visible),
// sidebar should not be hidden even if mouse goes out from sidebar ui.
@@ -102,17 +126,23 @@ class SidebarContainerView
void DoHideSidebar(bool show_event_detect_widget);
raw_ptr browser_ = nullptr;
+ raw_ptr side_panel_coordinator_ = nullptr;
+ raw_ptr side_panel_ = nullptr;
raw_ptr sidebar_model_ = nullptr;
- raw_ptr sidebar_panel_webview_ = nullptr;
raw_ptr sidebar_control_view_ = nullptr;
bool initialized_ = false;
+ bool is_side_panel_event_ = false;
base::OneShotTimer sidebar_hide_timer_;
std::unique_ptr browser_window_event_observer_;
std::unique_ptr browser_window_event_monitor_;
std::unique_ptr show_options_widget_;
base::ScopedObservation
- observed_{this};
+ sidebar_model_observation_{this};
+ base::ScopedMultiSourceObservation
+ panel_entry_observations_{this};
+ base::ScopedObservation
+ panel_registry_observation_{this};
};
#endif // BRAVE_BROWSER_UI_VIEWS_SIDEBAR_SIDEBAR_CONTAINER_VIEW_H_
diff --git a/browser/ui/views/sidebar/sidebar_control_view.cc b/browser/ui/views/sidebar/sidebar_control_view.cc
index 0499eabbc63b..b3bb0fda1d11 100644
--- a/browser/ui/views/sidebar/sidebar_control_view.cc
+++ b/browser/ui/views/sidebar/sidebar_control_view.cc
@@ -51,8 +51,9 @@ class ControlViewMenuModel : public ui::SimpleMenuModel {
} // namespace
-SidebarControlView::SidebarControlView(BraveBrowser* browser)
- : browser_(browser) {
+SidebarControlView::SidebarControlView(Delegate* delegate,
+ BraveBrowser* browser)
+ : delegate_(delegate), browser_(browser) {
set_context_menu_controller(this);
AddChildViews();
@@ -170,6 +171,10 @@ bool SidebarControlView::IsCommandIdChecked(int command_id) const {
service->GetSidebarShowOption();
}
+void SidebarControlView::MenuClosed(ui::SimpleMenuModel* source) {
+ delegate_->MenuClosed();
+}
+
std::u16string SidebarControlView::GetTooltipTextFor(
const views::View* view) const {
if (view == sidebar_settings_view_)
diff --git a/browser/ui/views/sidebar/sidebar_control_view.h b/browser/ui/views/sidebar/sidebar_control_view.h
index 843494837ce3..a97e4f08fc8f 100644
--- a/browser/ui/views/sidebar/sidebar_control_view.h
+++ b/browser/ui/views/sidebar/sidebar_control_view.h
@@ -39,7 +39,14 @@ class SidebarControlView : public views::View,
public sidebar::SidebarModel::Observer {
public:
METADATA_HEADER(SidebarControlView);
- explicit SidebarControlView(BraveBrowser* browser);
+ class Delegate {
+ public:
+ virtual void MenuClosed() {}
+
+ protected:
+ ~Delegate() = default;
+ };
+ SidebarControlView(Delegate* delegate, BraveBrowser* browser);
~SidebarControlView() override;
SidebarControlView(const SidebarControlView&) = delete;
@@ -58,6 +65,7 @@ class SidebarControlView : public views::View,
// ui::SimpleMenuModel::Delegate overrides:
void ExecuteCommand(int command_id, int event_flags) override;
bool IsCommandIdChecked(int command_id) const override;
+ void MenuClosed(ui::SimpleMenuModel* source) override;
// SidebarButtonView::Delegate overrides:
std::u16string GetTooltipTextFor(const views::View* view) const override;
@@ -85,6 +93,7 @@ class SidebarControlView : public views::View,
void UpdateSettingsButtonState();
void UpdateBackgroundAndBorder();
+ raw_ptr delegate_ = nullptr;
raw_ptr browser_ = nullptr;
raw_ptr sidebar_items_view_ = nullptr;
raw_ptr sidebar_item_add_view_ = nullptr;
diff --git a/browser/ui/views/sidebar/sidebar_items_contents_view.cc b/browser/ui/views/sidebar/sidebar_items_contents_view.cc
index 4aab171d4c67..d7adcc066826 100644
--- a/browser/ui/views/sidebar/sidebar_items_contents_view.cc
+++ b/browser/ui/views/sidebar/sidebar_items_contents_view.cc
@@ -103,7 +103,7 @@ void SidebarItemsContentsView::Update() {
}
void SidebarItemsContentsView::UpdateAllBuiltInItemsViewState() {
- const auto items = sidebar_model_->GetAllSidebarItems();
+ const auto& items = sidebar_model_->GetAllSidebarItems();
// It's not initialized yet if child view count and items size are different.
if (children().size() != items.size())
return;
@@ -138,7 +138,7 @@ std::u16string SidebarItemsContentsView::GetTooltipTextFor(
if (index == -1)
return std::u16string();
- auto item = sidebar_model_->GetAllSidebarItems()[index];
+ auto& item = sidebar_model_->GetAllSidebarItems()[index];
if (!item.title.empty())
return item.title;
@@ -373,7 +373,7 @@ SidebarItemView* SidebarItemsContentsView::GetItemViewAt(int index) {
}
void SidebarItemsContentsView::UpdateItemViewStateAt(int index, bool active) {
- const auto item = sidebar_model_->GetAllSidebarItems()[index];
+ const auto& item = sidebar_model_->GetAllSidebarItems()[index];
SidebarItemView* item_view = GetItemViewAt(index);
if (item.open_in_panel)
@@ -433,6 +433,10 @@ gfx::ImageSkia SidebarItemsContentsView::GetImageForBuiltInItems(
focused_image_resource = IDR_SIDEBAR_BOOKMARKS_FOCUSED;
normal_image_icon = &kSidebarBookmarksIcon;
break;
+ case sidebar::SidebarItem::BuiltInItemType::kReadingList:
+ focused_image_resource = IDR_SIDEBAR_READING_LIST_FOCUSED;
+ normal_image_icon = &kSidebarReadingListIcon;
+ break;
case sidebar::SidebarItem::BuiltInItemType::kHistory:
focused_image_resource = IDR_SIDEBAR_HISTORY_FOCUSED;
normal_image_icon = &kSidebarHistoryIcon;
diff --git a/browser/ui/views/sidebar/sidebar_panel_webview.cc b/browser/ui/views/sidebar/sidebar_panel_webview.cc
deleted file mode 100644
index e476af654c39..000000000000
--- a/browser/ui/views/sidebar/sidebar_panel_webview.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2022 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "brave/browser/ui/views/sidebar/sidebar_panel_webview.h"
-
-#include
-
-#include "ui/base/metadata/metadata_impl_macros.h"
-#include "ui/base/models/menu_model.h"
-#include "ui/views/controls/menu/menu_runner.h"
-
-SidebarPanelWebView::SidebarPanelWebView(
- content::BrowserContext* browser_context)
- : WebView(browser_context) {
- SetVisible(false);
- set_allow_accelerators(true);
-}
-
-SidebarPanelWebView::~SidebarPanelWebView() = default;
-
-void SidebarPanelWebView::ShowCustomContextMenu(
- const gfx::Point& point,
- std::unique_ptr menu_model) {
- // Show context menu at in screen coordinates.
- gfx::Point screen_point = point;
- ConvertPointToScreen(this, &screen_point);
- context_menu_model_ = std::move(menu_model);
- context_menu_runner_ = std::make_unique(
- context_menu_model_.get(),
- views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
- context_menu_runner_->RunMenuAt(
- GetWidget(), nullptr, gfx::Rect(screen_point, gfx::Size()),
- views::MenuAnchorPosition::kTopLeft, ui::MENU_SOURCE_MOUSE,
- web_contents()->GetContentNativeView());
-}
-
-void SidebarPanelWebView::HideCustomContextMenu() {
- if (context_menu_runner_)
- context_menu_runner_->Cancel();
-}
-
-bool SidebarPanelWebView::TreatUnHandledKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) {
- return unhandled_keyboard_event_handler_.HandleKeyboardEvent(
- event, GetFocusManager());
-}
-
-BEGIN_METADATA(SidebarPanelWebView, views::WebView)
-END_METADATA
diff --git a/browser/ui/views/sidebar/sidebar_panel_webview.h b/browser/ui/views/sidebar/sidebar_panel_webview.h
deleted file mode 100644
index 8a9e403378bd..000000000000
--- a/browser/ui/views/sidebar/sidebar_panel_webview.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright (c) 2022 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef BRAVE_BROWSER_UI_VIEWS_SIDEBAR_SIDEBAR_PANEL_WEBVIEW_H_
-#define BRAVE_BROWSER_UI_VIEWS_SIDEBAR_SIDEBAR_PANEL_WEBVIEW_H_
-
-#include
-
-#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
-#include "ui/views/controls/webview/webview.h"
-
-namespace ui {
-class MenuModel;
-} // namespace ui
-
-namespace views {
-class MenuRunner;
-} // namespace views
-
-class SidebarPanelWebView : public views::WebView {
- public:
- METADATA_HEADER(SidebarPanelWebView);
- explicit SidebarPanelWebView(content::BrowserContext* browser_context);
- ~SidebarPanelWebView() override;
- SidebarPanelWebView(const SidebarPanelWebView&) = delete;
- SidebarPanelWebView& operator=(const SidebarPanelWebView&) = delete;
-
- void ShowCustomContextMenu(const gfx::Point& point,
- std::unique_ptr menu_model);
- void HideCustomContextMenu();
- bool TreatUnHandledKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event);
-
- private:
- std::unique_ptr context_menu_runner_;
- std::unique_ptr context_menu_model_;
- views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
-};
-
-#endif // BRAVE_BROWSER_UI_VIEWS_SIDEBAR_SIDEBAR_PANEL_WEBVIEW_H_
diff --git a/browser/ui/views/sidebar/sidebar_side_panel_utils.cc b/browser/ui/views/sidebar/sidebar_side_panel_utils.cc
new file mode 100644
index 000000000000..e7b81c78790a
--- /dev/null
+++ b/browser/ui/views/sidebar/sidebar_side_panel_utils.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "brave/browser/ui/views/sidebar/sidebar_side_panel_utils.h"
+
+#include "base/logging.h"
+#include "brave/components/sidebar/sidebar_item.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
+
+namespace sidebar {
+
+using BuiltInItemType = SidebarItem::BuiltInItemType;
+
+SidePanelEntry::Id SidePanelIdFromSideBarItem(const SidebarItem& item) {
+ DCHECK(item.open_in_panel);
+ switch (item.built_in_item_type) {
+ case BuiltInItemType::kReadingList:
+ return SidePanelEntry::Id::kReadingList;
+ case BuiltInItemType::kBookmarks:
+ return SidePanelEntry::Id::kBookmarks;
+ default:
+ // Add a new case for any new types which we want to support.
+ NOTREACHED() << "Asked for a panel Id from a sidebar item which should "
+ "not have a panel Id, sending Reading List instead.";
+ return SidePanelEntry::Id::kReadingList;
+ }
+}
+
+} // namespace sidebar
diff --git a/browser/ui/views/sidebar/sidebar_side_panel_utils.h b/browser/ui/views/sidebar/sidebar_side_panel_utils.h
new file mode 100644
index 000000000000..893e17641dbc
--- /dev/null
+++ b/browser/ui/views/sidebar/sidebar_side_panel_utils.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_BROWSER_UI_VIEWS_SIDEBAR_SIDEBAR_SIDE_PANEL_UTILS_H_
+#define BRAVE_BROWSER_UI_VIEWS_SIDEBAR_SIDEBAR_SIDE_PANEL_UTILS_H_
+
+#include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
+
+namespace sidebar {
+
+struct SidebarItem;
+
+SidePanelEntry::Id SidePanelIdFromSideBarItem(const SidebarItem& item);
+
+} // namespace sidebar
+
+#endif // BRAVE_BROWSER_UI_VIEWS_SIDEBAR_SIDEBAR_SIDE_PANEL_UTILS_H_
diff --git a/browser/ui/webui/brave_web_ui_controller_factory.cc b/browser/ui/webui/brave_web_ui_controller_factory.cc
index 82eccea3b3b1..a3d42612ba10 100644
--- a/browser/ui/webui/brave_web_ui_controller_factory.cc
+++ b/browser/ui/webui/brave_web_ui_controller_factory.cc
@@ -23,7 +23,6 @@
#include "brave/components/constants/webui_url_constants.h"
#include "brave/components/ipfs/buildflags/buildflags.h"
#include "brave/components/playlist/buildflags/buildflags.h"
-#include "brave/components/sidebar/buildflags/buildflags.h"
#include "brave/components/tor/buildflags/buildflags.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
@@ -66,11 +65,6 @@
#include "brave/browser/ui/webui/tor_internals_ui.h"
#endif
-#if BUILDFLAG(ENABLE_SIDEBAR)
-#include "brave/browser/ui/webui/sidebar/sidebar_bookmarks_ui.h"
-#include "brave/components/sidebar/constants.h"
-#endif
-
using content::WebUI;
using content::WebUIController;
@@ -145,10 +139,6 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) {
#if BUILDFLAG(ENABLE_TOR)
} else if (host == kTorInternalsHost) {
return new TorInternalsUI(web_ui, url.host());
-#endif
-#if BUILDFLAG(ENABLE_SIDEBAR)
- } else if (host == kSidebarBookmarksHost) {
- return new SidebarBookmarksUI(web_ui);
#endif
} else if (host == kFederatedInternalsHost) {
if (base::FeatureList::IsEnabled(
@@ -169,9 +159,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, const GURL& url) {
(url.host_piece() == kIPFSWebUIHost &&
base::FeatureList::IsEnabled(ipfs::features::kIpfsFeature)) ||
#endif // BUILDFLAG(ENABLE_IPFS)
-#if BUILDFLAG(ENABLE_SIDEBAR)
- url.host_piece() == kSidebarBookmarksHost ||
-#endif
#if !BUILDFLAG(IS_ANDROID)
url.host_piece() == kWalletPanelHost ||
url.host_piece() == kWalletPageHost ||
diff --git a/browser/ui/webui/sidebar/BUILD.gn b/browser/ui/webui/sidebar/BUILD.gn
deleted file mode 100644
index 117cebd22a03..000000000000
--- a/browser/ui/webui/sidebar/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2022 The Brave Authors. All rights reserved.
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-
-mojom("mojo_bindings") {
- sources = [ "sidebar.mojom" ]
- webui_module_path = "/"
- public_deps = [
- "//mojo/public/mojom/base",
- "//ui/base/mojom",
- "//ui/gfx/geometry/mojom",
- "//url/mojom:url_mojom_gurl",
- ]
-}
diff --git a/browser/ui/webui/sidebar/sidebar.mojom b/browser/ui/webui/sidebar/sidebar.mojom
deleted file mode 100644
index cff4cd6423ff..000000000000
--- a/browser/ui/webui/sidebar/sidebar.mojom
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2022 The Brave Authors. All rights reserved.
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this file,
-// You can obtain one at http://mozilla.org/MPL/2.0/.
-
-module sidebar.mojom;
-
-import "ui/base/mojom/window_open_disposition.mojom";
-import "ui/gfx/geometry/mojom/geometry.mojom";
-import "url/mojom/url.mojom";
-
-// Used by the sidebar's bookmarks WebUI page (for the side panel) to bootstrap
-// bidirectional communication.
-interface BookmarksPageHandlerFactory {
- // The WebUI calls this method when the page is first initialized.
- CreateBookmarksPageHandler(pending_receiver handler);
-};
-
-// Browser-side handler for requests from WebUI page.
-interface BookmarksPageHandler {
- // Opens a bookmark by URL and passes the parent folder depth for metrics
- // collection.
- OpenBookmark(url.mojom.Url url, int32 parent_folder_depth,
- ui.mojom.ClickModifiers click_modifiers);
-
- // Opens a context menu for a bookmark node. The id parameter is internally
- // an int64 but gets passed as a string from the chrome.bookmarks Extension
- // API.
- ShowContextMenu(string id, gfx.mojom.Point point);
-};
diff --git a/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.cc b/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.cc
deleted file mode 100644
index 5b3d2babf01a..000000000000
--- a/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Copyright (c) 2022 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "brave/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.h"
-
-#include
-#include
-
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "brave/browser/ui/brave_browser.h"
-#include "brave/browser/ui/sidebar/sidebar.h"
-#include "brave/browser/ui/sidebar/sidebar_controller.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h"
-#include "chrome/browser/ui/bookmarks/bookmark_stats.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/browser/bookmark_node.h"
-#include "components/bookmarks/browser/bookmark_utils.h"
-#include "ui/base/models/simple_menu_model.h"
-#include "ui/base/mojom/window_open_disposition.mojom.h"
-#include "ui/base/window_open_disposition.h"
-#include "url/gurl.h"
-
-namespace {
-
-class BookmarkContextMenu : public ui::SimpleMenuModel,
- public ui::SimpleMenuModel::Delegate,
- public BookmarkContextMenuControllerDelegate {
- public:
- explicit BookmarkContextMenu(Browser* browser,
- sidebar::Sidebar* sidebar,
- const bookmarks::BookmarkNode* bookmark)
- : ui::SimpleMenuModel(this),
- controller_(base::WrapUnique(new BookmarkContextMenuController(
- browser->window()->GetNativeWindow(),
- this,
- browser,
- browser->profile(),
- base::BindRepeating(
- [](content::PageNavigator* navigator) { return navigator; },
- browser),
- // Do we need our own histogram enum?
- BOOKMARK_LAUNCH_LOCATION_SIDE_PANEL_CONTEXT_MENU,
- bookmark->parent(),
- {bookmark}))),
- sidebar_(sidebar) {
- AddItem(IDC_BOOKMARK_BAR_OPEN_ALL);
- AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW);
- AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO);
- AddSeparator(ui::NORMAL_SEPARATOR);
-
- AddItem(bookmark->is_folder() ? IDC_BOOKMARK_BAR_RENAME_FOLDER
- : IDC_BOOKMARK_BAR_EDIT);
- AddSeparator(ui::NORMAL_SEPARATOR);
-
- AddItem(IDC_CUT);
- AddItem(IDC_COPY);
- AddItem(IDC_PASTE);
- AddSeparator(ui::NORMAL_SEPARATOR);
-
- AddItem(IDC_BOOKMARK_BAR_REMOVE);
- AddSeparator(ui::NORMAL_SEPARATOR);
-
- AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK);
- AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER);
- AddSeparator(ui::NORMAL_SEPARATOR);
-
- AddItem(IDC_BOOKMARK_MANAGER);
- }
- ~BookmarkContextMenu() override = default;
-
- void ExecuteCommand(int command_id, int event_flags) override {
- controller_->ExecuteCommand(command_id, event_flags);
- }
-
- bool IsCommandIdEnabled(int command_id) const override {
- return controller_->IsCommandIdEnabled(command_id);
- }
-
- bool IsCommandIdVisible(int command_id) const override {
- return controller_->IsCommandIdVisible(command_id);
- }
-
- // BookmarkContextMenuControllerDelegate:
- void CloseMenu() override { sidebar_->HideCustomContextMenu(); }
-
- private:
- void AddItem(int command_id) {
- ui::SimpleMenuModel::AddItem(
- command_id,
- controller_->menu_model()->GetLabelAt(
- controller_->menu_model()->GetIndexOfCommandId(command_id)));
- }
-
- std::unique_ptr controller_;
- sidebar::Sidebar* sidebar_ = nullptr;
-};
-
-} // namespace
-
-SidebarBookmarksPageHandler::SidebarBookmarksPageHandler(
- mojo::PendingReceiver receiver)
- : receiver_(this, std::move(receiver)) {}
-
-SidebarBookmarksPageHandler::~SidebarBookmarksPageHandler() = default;
-
-void SidebarBookmarksPageHandler::OpenBookmark(
- const GURL& url,
- int32_t parent_folder_depth,
- ui::mojom::ClickModifiersPtr click_modifiers) {
- Browser* browser = chrome::FindLastActive();
- if (!browser)
- return;
-
- WindowOpenDisposition open_location = ui::DispositionFromClick(
- click_modifiers->middle_button, click_modifiers->alt_key,
- click_modifiers->ctrl_key, click_modifiers->meta_key,
- click_modifiers->shift_key);
- content::OpenURLParams params(url, content::Referrer(), open_location,
- ui::PAGE_TRANSITION_AUTO_BOOKMARK, false);
- browser->OpenURL(params);
-}
-
-void SidebarBookmarksPageHandler::ShowContextMenu(const std::string& id_string,
- const gfx::Point& point) {
- int64_t id;
- if (!base::StringToInt64(id_string, &id))
- return;
-
- Browser* browser = chrome::FindLastActive();
- if (!browser)
- return;
-
- bookmarks::BookmarkModel* bookmark_model =
- BookmarkModelFactory::GetForBrowserContext(browser->profile());
- const bookmarks::BookmarkNode* bookmark =
- bookmarks::GetBookmarkNodeByID(bookmark_model, id);
- if (!bookmark)
- return;
-
- auto* sidebar =
- static_cast(browser)->sidebar_controller()->sidebar();
- sidebar->ShowCustomContextMenu(
- point, std::make_unique(browser, sidebar, bookmark));
-}
diff --git a/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.h b/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.h
deleted file mode 100644
index 0acd51ef2cab..000000000000
--- a/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (c) 2022 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef BRAVE_BROWSER_UI_WEBUI_SIDEBAR_SIDEBAR_BOOKMARKS_PAGE_HANDLER_H_
-#define BRAVE_BROWSER_UI_WEBUI_SIDEBAR_SIDEBAR_BOOKMARKS_PAGE_HANDLER_H_
-
-#include
-
-#include "brave/browser/ui/webui/sidebar/sidebar.mojom.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-
-class GURL;
-
-class SidebarBookmarksPageHandler
- : public sidebar::mojom::BookmarksPageHandler {
- public:
- explicit SidebarBookmarksPageHandler(
- mojo::PendingReceiver receiver);
- ~SidebarBookmarksPageHandler() override;
- SidebarBookmarksPageHandler(const SidebarBookmarksPageHandler&) = delete;
- SidebarBookmarksPageHandler& operator=(const SidebarBookmarksPageHandler&) =
- delete;
-
- private:
- // sidebar::mojom::BookmarksPageHandler:
- void OpenBookmark(const GURL& url,
- int32_t parent_folder_depth,
- ui::mojom::ClickModifiersPtr click_modifiers) override;
- void ShowContextMenu(const std::string& id, const gfx::Point& point) override;
-
- mojo::Receiver receiver_;
-};
-
-#endif // BRAVE_BROWSER_UI_WEBUI_SIDEBAR_SIDEBAR_BOOKMARKS_PAGE_HANDLER_H_
diff --git a/browser/ui/webui/sidebar/sidebar_bookmarks_ui.cc b/browser/ui/webui/sidebar/sidebar_bookmarks_ui.cc
deleted file mode 100644
index 4d292a52a6a6..000000000000
--- a/browser/ui/webui/sidebar/sidebar_bookmarks_ui.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2022 The Brave Authors. All rights reserved.
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this file,
-// you can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "brave/browser/ui/webui/sidebar/sidebar_bookmarks_ui.h"
-
-#include
-#include
-
-#include "brave/browser/resources/sidebar/grit/sidebar_resources.h"
-#include "brave/browser/resources/sidebar/grit/sidebar_resources_map.h"
-#include "brave/browser/ui/webui/sidebar/sidebar_bookmarks_page_handler.h"
-#include "brave/components/constants/webui_url_constants.h"
-#include "brave/components/l10n/common/locale_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/favicon_source.h"
-#include "chrome/browser/ui/webui/webui_util.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/bookmarks/common/bookmark_pref_names.h"
-#include "components/favicon_base/favicon_url_parser.h"
-#include "components/prefs/pref_service.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-
-SidebarBookmarksUI::SidebarBookmarksUI(content::WebUI* web_ui)
- : ui::MojoWebUIController(web_ui) {
- content::WebUIDataSource* source =
- content::WebUIDataSource::Create(kSidebarBookmarksHost);
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"bookmarksTitle", IDS_BOOKMARK_MANAGER_TITLE},
- };
- for (const auto& str : kLocalizedStrings) {
- std::u16string l10n_str =
- brave_l10n::GetLocalizedResourceUTF16String(str.id);
- source->AddString(str.name, l10n_str);
- }
-
- Profile* const profile = Profile::FromWebUI(web_ui);
- PrefService* prefs = profile->GetPrefs();
- source->AddBoolean(
- "bookmarksDragAndDropEnabled",
- prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled));
-
- content::URLDataSource::Add(
- profile, std::make_unique(
- profile, chrome::FaviconUrlFormat::kFavicon2));
- webui::SetupWebUIDataSource(
- source, base::make_span(kSidebarResources, kSidebarResourcesSize),
- IDR_SIDEBAR_BOOKMARKS_BOOKMARKS_HTML);
- content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
- source);
-}
-
-SidebarBookmarksUI::~SidebarBookmarksUI() = default;
-
-WEB_UI_CONTROLLER_TYPE_IMPL(SidebarBookmarksUI)
-
-void SidebarBookmarksUI::BindInterface(
- mojo::PendingReceiver
- receiver) {
- bookmarks_page_factory_receiver_.reset();
- bookmarks_page_factory_receiver_.Bind(std::move(receiver));
-}
-
-void SidebarBookmarksUI::CreateBookmarksPageHandler(
- mojo::PendingReceiver receiver) {
- bookmarks_page_handler_ =
- std::make_unique(std::move(receiver));
-}
diff --git a/browser/ui/webui/sidebar/sidebar_bookmarks_ui.h b/browser/ui/webui/sidebar/sidebar_bookmarks_ui.h
deleted file mode 100644
index 95b931c3b37e..000000000000
--- a/browser/ui/webui/sidebar/sidebar_bookmarks_ui.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2022 The Brave Authors. All rights reserved.
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this file,
-// you can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef BRAVE_BROWSER_UI_WEBUI_SIDEBAR_SIDEBAR_BOOKMARKS_UI_H_
-#define BRAVE_BROWSER_UI_WEBUI_SIDEBAR_SIDEBAR_BOOKMARKS_UI_H_
-
-#include
-
-#include "brave/browser/ui/webui/sidebar/sidebar.mojom.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "ui/webui/mojo_web_ui_controller.h"
-
-class SidebarBookmarksPageHandler;
-
-class SidebarBookmarksUI : public ui::MojoWebUIController,
- public sidebar::mojom::BookmarksPageHandlerFactory {
- public:
- explicit SidebarBookmarksUI(content::WebUI* web_ui);
- ~SidebarBookmarksUI() override;
- SidebarBookmarksUI(const SidebarBookmarksUI&) = delete;
- SidebarBookmarksUI& operator=(const SidebarBookmarksUI&) = delete;
-
- void BindInterface(
- mojo::PendingReceiver
- receiver);
-
- private:
- // sidebar::mojom::BookmarksPageHandlerFactory
- void CreateBookmarksPageHandler(
- mojo::PendingReceiver receiver)
- override;
-
- std::unique_ptr bookmarks_page_handler_;
- mojo::Receiver
- bookmarks_page_factory_receiver_{this};
-
- WEB_UI_CONTROLLER_TYPE_DECL();
-};
-
-#endif // BRAVE_BROWSER_UI_WEBUI_SIDEBAR_SIDEBAR_BOOKMARKS_UI_H_
diff --git a/chromium_src/chrome/browser/ui/browser_finder.cc b/chromium_src/chrome/browser/ui/browser_finder.cc
deleted file mode 100644
index c451eff89554..000000000000
--- a/chromium_src/chrome/browser/ui/browser_finder.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2021 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "brave/browser/ui/brave_browser.h"
-#include "brave/components/sidebar/buildflags/buildflags.h"
-#include "chrome/browser/ui/browser_list.h"
-
-#if BUILDFLAG(ENABLE_SIDEBAR)
-#include "brave/browser/ui/sidebar/sidebar_controller.h"
-#include "brave/browser/ui/sidebar/sidebar_model.h"
-#endif
-
-#define FindBrowserWithWebContents FindBrowserWithWebContents_ChromiumImpl
-
-#include "src/chrome/browser/ui/browser_finder.cc"
-
-#undef FindBrowserWithWebContents
-
-namespace chrome {
-
-Browser* FindBrowserWithWebContents(const WebContents* web_contents) {
- DCHECK(web_contents);
-
-#if BUILDFLAG(ENABLE_SIDEBAR)
- for (auto* browser : *BrowserList::GetInstance()) {
- // Use |sidebar_controller| directly, because even if the feature is
- // enabled, SidebarController can be not created for a specific
- // BraveBrowser.
- const auto* sidebar_controller =
- static_cast(browser)->sidebar_controller();
- DCHECK(!sidebar_controller || sidebar_controller->model());
- if (sidebar_controller &&
- sidebar_controller->model()->IsSidebarWebContents(web_contents)) {
- return browser;
- }
- }
-#endif
-
- return FindBrowserWithWebContents_ChromiumImpl(web_contents);
-}
-
-} // namespace chrome
diff --git a/chromium_src/chrome/browser/ui/ui_features.cc b/chromium_src/chrome/browser/ui/ui_features.cc
index 95d4b5b6376f..4d1b859fe757 100644
--- a/chromium_src/chrome/browser/ui/ui_features.cc
+++ b/chromium_src/chrome/browser/ui/ui_features.cc
@@ -5,11 +5,19 @@
#include "src/chrome/browser/ui/ui_features.cc"
+#include "base/feature_list.h"
#include "base/feature_override.h"
namespace features {
-OVERRIDE_FEATURE_DEFAULT_STATES({{kTabHoverCardImages,
- base::FEATURE_DISABLED_BY_DEFAULT}});
+OVERRIDE_FEATURE_DEFAULT_STATES({{
+ {kTabHoverCardImages, base::FEATURE_DISABLED_BY_DEFAULT},
+ // Unified SidePanel actually means that each Side Panel item's WebUI is
+ // a separate page, instead of 1 page that has different functions, e.g.
+ // (reading list and bookmarks). We want this feature immediately because
+ // Brave have its own control for showing Side Panels individually via
+ // Brave's Side Bar.
+ {kUnifiedSidePanel, base::FEATURE_ENABLED_BY_DEFAULT},
+}});
} // namespace features
diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_view.cc b/chromium_src/chrome/browser/ui/views/frame/browser_view.cc
index 86c174d47a74..f41e3fc16bb5 100644
--- a/chromium_src/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chromium_src/chrome/browser/ui/views/frame/browser_view.cc
@@ -3,16 +3,27 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
+// Include the corresponding header first since it defines the same macros and
+// therefore avoid undef before use.
+#include "chrome/browser/ui/views/frame/browser_view.h"
+
+#include "brave/browser/ui/views/frame/brave_browser_view_layout.h"
+#include "brave/browser/ui/views/side_panel/brave_side_panel.h"
#include "brave/browser/ui/views/tabs/brave_browser_tab_strip_controller.h"
#include "brave/browser/ui/views/tabs/brave_tab_strip.h"
#include "brave/browser/ui/views/toolbar/brave_toolbar_view.h"
#include "chrome/browser/ui/views/frame/tab_strip_region_view.h"
+#include "chrome/browser/ui/views/side_panel/side_panel.h"
#define ToolbarView BraveToolbarView
#define BrowserTabStripController BraveBrowserTabStripController
#define TabStrip BraveTabStrip
+#define BrowserViewLayout BraveBrowserViewLayout
+#define SidePanel BraveSidePanel
#include "src/chrome/browser/ui/views/frame/browser_view.cc"
#undef ToolbarView
#undef BrowserTabStripController
#undef TabStrip
+#undef BrowserViewLayout
+#undef SidePanel
diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_view.h b/chromium_src/chrome/browser/ui/views/frame/browser_view.h
index a4ece2950ce5..46c438100b77 100644
--- a/chromium_src/chrome/browser/ui/views/frame/browser_view.h
+++ b/chromium_src/chrome/browser/ui/views/frame/browser_view.h
@@ -7,11 +7,17 @@
#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_H_
#include "brave/browser/ui/brave_browser_window.h"
+#include "brave/browser/ui/views/frame/brave_browser_view_layout.h"
+#include "brave/browser/ui/views/side_panel/brave_side_panel.h"
+#include "chrome/browser/ui/views/side_panel/side_panel.h"
+#include "chrome/browser/ui/views/side_search/side_search_browser_controller.h"
#define BrowserViewLayoutDelegateImpl \
BrowserViewLayoutDelegateImpl; \
friend class BraveBrowserView
#define BrowserWindow BraveBrowserWindow
+#define BrowserViewLayout BraveBrowserViewLayout
+#define SidePanel BraveSidePanel
#define GetContentsLayoutManager \
GetContentsLayoutManager_Unused(); \
virtual ContentsLayoutManager* GetContentsLayoutManager
@@ -23,6 +29,8 @@
#undef BrowserViewLayoutDelegateImpl
#undef BrowserWindow
#undef MaybeShowReadingListInSidePanelIPH
+#undef BrowserViewLayout
+#undef SidePanel
#undef GetContentsLayoutManager
#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_H_
diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_view_layout.h b/chromium_src/chrome/browser/ui/views/frame/browser_view_layout.h
new file mode 100644
index 000000000000..01c64b0040e4
--- /dev/null
+++ b/chromium_src/chrome/browser/ui/views/frame/browser_view_layout.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
+#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
+
+// Make override-able
+#define LayoutSidePanelView virtual LayoutSidePanelView
+#include "src/chrome/browser/ui/views/frame/browser_view_layout.h"
+#undef LayoutSidePanelView
+
+#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
diff --git a/chromium_src/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc b/chromium_src/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
new file mode 100644
index 000000000000..28acca3d55d2
--- /dev/null
+++ b/chromium_src/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "brave/browser/ui/sidebar/sidebar_service_factory.h"
+#include "brave/browser/ui/views/sidebar/sidebar_side_panel_utils.h"
+#include "brave/components/sidebar/sidebar_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace {
+
+absl::optional GetDefaultEntryId(Profile* profile) {
+ auto* service = sidebar::SidebarServiceFactory::GetForProfile(profile);
+ auto panel_item = service->GetDefaultPanelItem();
+ if (panel_item.has_value()) {
+ return SidePanelIdFromSideBarItem(panel_item.value());
+ }
+ return absl::nullopt;
+}
+
+} // namespace
+
+// Brave has its own side panel navigation in the form of the SideBar, so
+// hide the Chromium combobox-style header.
+#define BRAVE_SIDE_PANEL_COORDINATOR_CREATE_HEADER header->SetVisible(false);
+
+// Choose Brave's own default, and exclude items that user has removed
+// from sidebar. If none are enabled, do nothing.
+#define BRAVE_SIDE_PANEL_COORDINATOR_SHOW \
+ if (!entry_id.has_value()) { \
+ entry_id = GetDefaultEntryId(browser_view_->GetProfile()); \
+ if (!entry_id.has_value()) \
+ return; \
+ }
+
+#include "src/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc"
+#undef BRAVE_SIDE_PANEL_COORDINATOR_CREATE_HEADER
+#undef BRAVE_SIDE_PANEL_COORDINATOR_SHOW
diff --git a/chromium_src/chrome/browser/ui/views/side_search/side_search_browser_controller.cc b/chromium_src/chrome/browser/ui/views/side_search/side_search_browser_controller.cc
new file mode 100644
index 000000000000..8620f2c17b25
--- /dev/null
+++ b/chromium_src/chrome/browser/ui/views/side_search/side_search_browser_controller.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+// Include any corresponding headers first that define the same macros and
+// therefore avoid undef before use.
+#include "chrome/browser/ui/views/side_search/side_search_browser_controller.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+
+#include "brave/browser/ui/views/side_panel/brave_side_panel.h"
+#include "chrome/browser/ui/views/side_panel/side_panel.h"
+
+#define SidePanel BraveSidePanel
+#include "src/chrome/browser/ui/views/side_search/side_search_browser_controller.cc"
+#undef SidePanel
diff --git a/chromium_src/chrome/browser/ui/views/side_search/side_search_browser_controller.h b/chromium_src/chrome/browser/ui/views/side_search/side_search_browser_controller.h
new file mode 100644
index 000000000000..ad6b7cc7b0d4
--- /dev/null
+++ b/chromium_src/chrome/browser/ui/views/side_search/side_search_browser_controller.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_
+#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_
+
+#include "brave/browser/ui/views/side_panel/brave_side_panel.h"
+#include "chrome/browser/ui/views/side_panel/side_panel.h"
+
+#define SidePanel BraveSidePanel
+#include "src/chrome/browser/ui/views/side_search/side_search_browser_controller.h"
+#undef SidePanel
+
+#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_
diff --git a/chromium_src/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chromium_src/chrome/browser/ui/views/toolbar/toolbar_view.cc
index f71edc804d2b..29e9a52bf6cc 100644
--- a/chromium_src/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chromium_src/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -18,11 +18,8 @@
AddChildView(std::make_unique(browser_view_)); \
if (false)
-#define BRAVE_TOOLBAR_VIEW_DEACTIVATE_SIDE_PANEL if (false)
-
#include "src/chrome/browser/ui/views/toolbar/toolbar_view.cc"
#undef BRAVE_TOOLBAR_VIEW_INIT
-#undef BRAVE_TOOLBAR_VIEW_DEACTIVATE_SIDE_PANEL
#if BUILDFLAG(ENABLE_EXTENSIONS)
#undef LocationBarView
#endif
diff --git a/chromium_src/components/reading_list/features/reading_list_switches.cc b/chromium_src/components/reading_list/features/reading_list_switches.cc
deleted file mode 100644
index e5433ab0b1f1..000000000000
--- a/chromium_src/components/reading_list/features/reading_list_switches.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (c) 2021 The Brave Authors. All rights reserved.
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "src/components/reading_list/features/reading_list_switches.cc"
-
-#include "base/feature_list.h"
-#include "base/feature_override.h"
-
-namespace reading_list {
-namespace switches {
-
-OVERRIDE_FEATURE_DEFAULT_STATES({{
- {kReadLater, base::FEATURE_DISABLED_BY_DEFAULT},
-}});
-
-} // namespace switches
-} // namespace reading_list
diff --git a/common/extensions/api/_api_features.json b/common/extensions/api/_api_features.json
index 6d9515c5539c..c7b8d9b3bcb0 100644
--- a/common/extensions/api/_api_features.json
+++ b/common/extensions/api/_api_features.json
@@ -26,19 +26,6 @@
"chrome://newtab/*"
]
}],
- "bookmarkManagerPrivate": [{
- "dependencies": ["permission:bookmarkManagerPrivate"],
- "contexts": ["blessed_extension"],
- "default_parent": true
- }, {
- "channel": "stable",
- "contexts": ["webui"],
- "matches": [
- "chrome://bookmarks/*",
- "chrome://read-later.top-chrome/*",
- "chrome://sidebar-bookmarks.top-chrome/*"
- ]
- }],
"bookmarks": [{
"dependencies": ["permission:bookmarks"],
"contexts": ["blessed_extension"],
@@ -48,8 +35,8 @@
"contexts": ["webui"],
"matches": [
"chrome://bookmarks/*",
- "chrome://read-later.top-chrome/*",
- "chrome://sidebar-bookmarks.top-chrome/*"
+ "chrome://bookmarks-side-panel.top-chrome/*",
+ "chrome://read-later.top-chrome/*"
],
"default_parent": true
}, {
diff --git a/components/constants/webui_url_constants.cc b/components/constants/webui_url_constants.cc
index bf9593aaf747..98cb11f1dd71 100644
--- a/components/constants/webui_url_constants.cc
+++ b/components/constants/webui_url_constants.cc
@@ -49,7 +49,6 @@ const char kShieldsPanelURL[] = "chrome://brave-shields.top-chrome";
const char kShieldsPanelHost[] = "brave-shields.top-chrome";
const char kCookieListOptInHost[] = "cookie-list-opt-in.top-chrome";
const char kCookieListOptInURL[] = "chrome://cookie-list-opt-in.top-chrome";
-const char kSidebarBookmarksHost[] = "sidebar-bookmarks.top-chrome";
const char kFederatedInternalsURL[] = "brave://federated-internals";
const char kFederatedInternalsHost[] = "federated-internals";
const char kContentFiltersPath[] = "shields/filters";
diff --git a/components/constants/webui_url_constants.h b/components/constants/webui_url_constants.h
index 178d211ce2ce..17f261b93fb0 100644
--- a/components/constants/webui_url_constants.h
+++ b/components/constants/webui_url_constants.h
@@ -50,7 +50,6 @@ extern const char kShieldsPanelURL[];
extern const char kShieldsPanelHost[];
extern const char kCookieListOptInHost[];
extern const char kCookieListOptInURL[];
-extern const char kSidebarBookmarksHost[];
extern const char kFederatedInternalsURL[];
extern const char kFederatedInternalsHost[];
extern const char kContentFiltersPath[];
diff --git a/components/resources/brave_components_strings.grd b/components/resources/brave_components_strings.grd
index bd1c042b7dbc..473111969f48 100644
--- a/components/resources/brave_components_strings.grd
+++ b/components/resources/brave_components_strings.grd
@@ -368,6 +368,9 @@
History
+
+ Reading List
+
diff --git a/components/sidebar/constants.h b/components/sidebar/constants.h
index 87d3400bf2b4..9791862ad0b0 100644
--- a/components/sidebar/constants.h
+++ b/components/sidebar/constants.h
@@ -14,12 +14,7 @@ constexpr char kSidebarItemBuiltInItemTypeKey[] = "built_in_item_type";
constexpr char kSidebarItemTitleKey[] = "title";
constexpr char kSidebarItemOpenInPanelKey[] = "open_in_panel";
-// TODO(simonhong): Move this to
-// //brave/components/constants/webui_url_constants.h when default builtin items
// list is provided from chrome layer.
-constexpr char kSidebarBookmarksURL[] =
- "chrome://sidebar-bookmarks.top-chrome/";
-
constexpr char kBraveTalkURL[] = "https://talk.brave.com/widget";
constexpr char kBraveTalkHost[] = "talk.brave.com";
diff --git a/components/sidebar/pref_names.h b/components/sidebar/pref_names.h
index de8983151646..08d7355fd2a3 100644
--- a/components/sidebar/pref_names.h
+++ b/components/sidebar/pref_names.h
@@ -9,6 +9,8 @@
namespace sidebar {
constexpr char kSidebarItems[] = "brave.sidebar.sidebar_items";
+constexpr char kSidebarHiddenBuiltInItems[] =
+ "brave.sidebar.hidden_built_in_items";
constexpr char kSidebarShowOption[] = "brave.sidebar.sidebar_show_option";
constexpr char kSidebarItemAddedFeedbackBubbleShowCount[] =
"brave.sidebar.item_added_feedback_bubble_shown_count";
diff --git a/components/sidebar/sidebar_item.cc b/components/sidebar/sidebar_item.cc
index 2300f594d372..7cf35b3c255f 100644
--- a/components/sidebar/sidebar_item.cc
+++ b/components/sidebar/sidebar_item.cc
@@ -8,13 +8,11 @@
namespace sidebar {
// static
-SidebarItem SidebarItem::Create(const GURL& url,
- const std::u16string& title,
+SidebarItem SidebarItem::Create(const std::u16string& title,
Type type,
BuiltInItemType built_in_item_type,
bool open_in_panel) {
SidebarItem item;
- item.url = url;
item.title = title;
item.type = type;
item.built_in_item_type = built_in_item_type;
@@ -22,6 +20,17 @@ SidebarItem SidebarItem::Create(const GURL& url,
return item;
}
+// static
+SidebarItem SidebarItem::Create(const GURL& url,
+ const std::u16string& title,
+ Type type,
+ BuiltInItemType built_in_item_type,
+ bool open_in_panel) {
+ SidebarItem item = Create(title, type, built_in_item_type, open_in_panel);
+ item.url = url;
+ return item;
+}
+
SidebarItem::SidebarItem() = default;
SidebarItem::~SidebarItem() = default;
diff --git a/components/sidebar/sidebar_item.h b/components/sidebar/sidebar_item.h
index 0b7040ca0b1e..44bea398068b 100644
--- a/components/sidebar/sidebar_item.h
+++ b/components/sidebar/sidebar_item.h
@@ -21,9 +21,15 @@ struct SidebarItem {
kBraveTalk,
kWallet,
kBookmarks,
+ kReadingList,
kHistory,
};
+ static SidebarItem Create(const std::u16string& title,
+ Type type,
+ BuiltInItemType built_in_item_type,
+ bool open_in_panel);
+
static SidebarItem Create(const GURL& url,
const std::u16string& title,
Type type,
diff --git a/components/sidebar/sidebar_service.cc b/components/sidebar/sidebar_service.cc
index e83a91f20290..1a05a2ce259b 100644
--- a/components/sidebar/sidebar_service.cc
+++ b/components/sidebar/sidebar_service.cc
@@ -7,22 +7,28 @@
#include
#include
+#include
#include
+#include
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/notreached.h"
+#include "base/ranges/algorithm.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "brave/components/l10n/common/locale_util.h"
#include "brave/components/sidebar/constants.h"
#include "brave/components/sidebar/pref_names.h"
+#include "brave/components/sidebar/sidebar_item.h"
#include "components/grit/brave_components_strings.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
-#include "base/logging.h"
-
using version_info::Channel;
namespace sidebar {
@@ -45,12 +51,19 @@ SidebarItem GetBuiltInItemForType(SidebarItem::BuiltInItemType type) {
SidebarItem::Type::kTypeBuiltIn,
SidebarItem::BuiltInItemType::kWallet, false);
case SidebarItem::BuiltInItemType::kBookmarks:
- return SidebarItem::Create(GURL(kSidebarBookmarksURL),
- brave_l10n::GetLocalizedResourceUTF16String(
+ return SidebarItem::Create(brave_l10n::GetLocalizedResourceUTF16String(
IDS_SIDEBAR_BOOKMARKS_ITEM_TITLE),
SidebarItem::Type::kTypeBuiltIn,
SidebarItem::BuiltInItemType::kBookmarks,
true);
+ case SidebarItem::BuiltInItemType::kReadingList:
+ return SidebarItem::Create(
+ // TODO(petemill): Have these items created under brave/browser
+ // so that we can access common strings, like IDS_READ_LATER_TITLE.
+ brave_l10n::GetLocalizedResourceUTF16String(
+ IDS_SIDEBAR_READING_LIST_ITEM_TITLE),
+ SidebarItem::Type::kTypeBuiltIn,
+ SidebarItem::BuiltInItemType::kReadingList, true);
case SidebarItem::BuiltInItemType::kHistory:
return SidebarItem::Create(GURL("chrome://history/"),
brave_l10n::GetLocalizedResourceUTF16String(
@@ -63,34 +76,22 @@ SidebarItem GetBuiltInItemForType(SidebarItem::BuiltInItemType type) {
return SidebarItem();
}
-SidebarItem::BuiltInItemType GetBuiltInItemTypeForURL(const std::string& url) {
- if (url == "https://together.brave.com/" || url == "https://talk.brave.com/")
- return SidebarItem::BuiltInItemType::kBraveTalk;
-
- if (url == "chrome://wallet/")
- return SidebarItem::BuiltInItemType::kWallet;
-
- if (url == kSidebarBookmarksURL || url == "chrome://bookmarks/")
- return SidebarItem::BuiltInItemType::kBookmarks;
-
- if (url == "chrome://history/")
- return SidebarItem::BuiltInItemType::kHistory;
-
- NOTREACHED();
- return SidebarItem::BuiltInItemType::kNone;
-}
-
-SidebarItem GetBuiltInItemForURL(const std::string& url) {
- return GetBuiltInItemForType(GetBuiltInItemTypeForURL(url));
+const std::vector& GetDefaultBuiltInItemTypes() {
+ // This is the default display order
+ static const base::NoDestructor s_built_in_item_types(
+ std::vector{
+ SidebarItem::BuiltInItemType::kBraveTalk,
+ SidebarItem::BuiltInItemType::kWallet,
+ SidebarItem::BuiltInItemType::kBookmarks,
+ SidebarItem::BuiltInItemType::kReadingList});
+ return *s_built_in_item_types;
}
std::vector GetDefaultSidebarItems() {
std::vector items;
- items.push_back(
- GetBuiltInItemForType(SidebarItem::BuiltInItemType::kBraveTalk));
- items.push_back(GetBuiltInItemForType(SidebarItem::BuiltInItemType::kWallet));
- items.push_back(
- GetBuiltInItemForType(SidebarItem::BuiltInItemType::kBookmarks));
+ for (const auto& item_type : GetDefaultBuiltInItemTypes()) {
+ items.push_back(GetBuiltInItemForType(item_type));
+ }
return items;
}
@@ -100,6 +101,7 @@ std::vector GetDefaultSidebarItems() {
void SidebarService::RegisterProfilePrefs(PrefRegistrySimple* registry,
version_info::Channel channel) {
registry->RegisterListPref(kSidebarItems);
+ registry->RegisterListPref(kSidebarHiddenBuiltInItems);
registry->RegisterIntegerPref(
kSidebarShowOption,
channel == Channel::STABLE
@@ -108,8 +110,16 @@ void SidebarService::RegisterProfilePrefs(PrefRegistrySimple* registry,
registry->RegisterIntegerPref(kSidebarItemAddedFeedbackBubbleShowCount, 0);
}
+// static
+std::vector
+SidebarService::GetDefaultBuiltInItemTypes_ForTesting() {
+ return GetDefaultBuiltInItemTypes();
+}
+
SidebarService::SidebarService(PrefService* prefs) : prefs_(prefs) {
DCHECK(prefs_);
+ MigratePrefSidebarBuiltInItemsToHidden();
+
LoadSidebarItems();
MigrateSidebarShowOptions();
@@ -134,6 +144,97 @@ void SidebarService::MigrateSidebarShowOptions() {
}
}
+void SidebarService::MigratePrefSidebarBuiltInItemsToHidden() {
+ // kSidebarItems pref used to contain built-in items which should be shown.
+ // This was changed to store those in a separate pref which contains
+ // built-in items the user has chosen to hide. However kSidebarItems still
+ // has entries for built-in items so they can be re-ordered.
+ // It only stores built-in items that should be hidden so that new
+ // items will appear, and we can remove old items.
+ auto* built_in_items_to_hide_preference =
+ prefs_->FindPreference(kSidebarHiddenBuiltInItems);
+ if (!built_in_items_to_hide_preference->IsDefaultValue()) {
+ VLOG(1) << "Not migrating built-in items, migration already complete.";
+ return;
+ }
+ auto* preference = prefs_->FindPreference(kSidebarItems);
+ if (preference->IsDefaultValue()) {
+ VLOG(1) << "Not migrating built-in items, pref is still default.";
+ return;
+ }
+ // Only include items that were known prior to this migration
+ std::vector built_in_items_to_hide;
+ built_in_items_to_hide.push_back(
+ GetBuiltInItemForType(SidebarItem::BuiltInItemType::kBraveTalk));
+ built_in_items_to_hide.push_back(
+ GetBuiltInItemForType(SidebarItem::BuiltInItemType::kWallet));
+ built_in_items_to_hide.push_back(
+ GetBuiltInItemForType(SidebarItem::BuiltInItemType::kBookmarks));
+
+ const auto& items = preference->GetValue()->GetList();
+ VLOG(2) << "MigratePrefSidebarBuiltInItemsToHidden: item count is "
+ << items.size();
+
+ // Find built-in items in items pref and keep them visible
+ for (const auto& item : items) {
+ DVLOG(2) << "Found an item: " << item.DebugString();
+ // Verify item is valid
+ if (!item.is_dict() || item.GetDict().empty()) {
+ DVLOG(1) << "Item in prefs was not a valid dict: " << item.DebugString();
+ continue;
+ }
+ // Only care about built-in type
+ SidebarItem::Type type;
+ const auto type_value = item.FindIntKey(kSidebarItemTypeKey);
+ if (!type_value) {
+ VLOG(1) << "Item has no type item";
+ continue;
+ }
+ type = static_cast(*type_value);
+ if (type != SidebarItem::Type::kTypeBuiltIn) {
+ VLOG(2) << "Item is not built-in type";
+ continue;
+ }
+ // Found a built-in item to keep
+ const auto item_id = item.FindIntKey(kSidebarItemBuiltInItemTypeKey);
+ if (!item_id.has_value()) {
+ LOG(ERROR) << "MigratePrefSidebarBuiltInItemsToHidden: A built-in item "
+ "was found in the older pref format without a valid id.";
+ DVLOG(1) << "Pref list item was: " << item.DebugString();
+ }
+ // Remember not to hide this item
+ auto iter = base::ranges::find_if(
+ built_in_items_to_hide, [&item_id](const auto& default_item) {
+ return default_item.built_in_item_type ==
+ static_cast(*item_id);
+ });
+ // It might be an item which is no longer is offered
+ if (iter != built_in_items_to_hide.end()) {
+ built_in_items_to_hide.erase(iter);
+ } else {
+ VLOG(1) << "A built-in item was found in the older pref format which is "
+ "no longer part of the default built-in items, id: "
+ << *item_id;
+ }
+ }
+
+ // Build new pref, if any have been marked for hiding
+ ListPrefUpdate builtin_items_update(prefs_, kSidebarHiddenBuiltInItems);
+ if (built_in_items_to_hide.size()) {
+ for (const auto& item : built_in_items_to_hide) {
+ DCHECK(item.type == SidebarItem::Type::kTypeBuiltIn);
+ const auto value = static_cast(item.built_in_item_type);
+ VLOG(2) << "Marked for hiding built-in item with ID: " << value;
+ base::Value item_type(value);
+ builtin_items_update->Append(std::move(item_type));
+ }
+ } else {
+ // Always store something so that we know migration is done
+ // when pref isn't default value.
+ builtin_items_update->ClearList();
+ }
+}
+
void SidebarService::AddItem(const SidebarItem& item) {
items_.push_back(item);
@@ -176,19 +277,45 @@ void SidebarService::MoveItem(int from, int to) {
}
void SidebarService::UpdateSidebarItemsToPrefStore() {
+ // Store all items in a list pref.
+ // Each item gets an entry. Built in items only need their type, and are
+ // only stored so we preserve their order. Custom items
+ // need all their detail.
+ // We also need to explicitly store which built-in items have been hidden
+ // so that we know which new items the user has been exposed to and which
+ // they've chosen to hide.
ListPrefUpdate update(prefs_, kSidebarItems);
update->ClearList();
+ DVLOG(2) << "Serializing items (count: " << items_.size() << ")";
+ // Serialize each item
for (const auto& item : items_) {
+ DVLOG(2) << "Adding item to pref list: "
+ << static_cast(item.built_in_item_type);
base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetStringKey(kSidebarItemURLKey, item.url.spec());
- dict.SetStringKey(kSidebarItemTitleKey, base::UTF16ToUTF8(item.title));
dict.SetIntKey(kSidebarItemTypeKey, static_cast(item.type));
dict.SetIntKey(kSidebarItemBuiltInItemTypeKey,
static_cast(item.built_in_item_type));
- dict.SetBoolKey(kSidebarItemOpenInPanelKey, item.open_in_panel);
+ if (item.type != SidebarItem::Type::kTypeBuiltIn) {
+ dict.SetStringKey(kSidebarItemURLKey, item.url.spec());
+ dict.SetStringKey(kSidebarItemTitleKey, base::UTF16ToUTF8(item.title));
+ dict.SetBoolKey(kSidebarItemOpenInPanelKey, item.open_in_panel);
+ }
update->Append(std::move(dict));
}
+
+ // Store which built-in items should be hidden
+ ListPrefUpdate hide_builtin_update(prefs_, kSidebarHiddenBuiltInItems);
+ hide_builtin_update->ClearList();
+ // TODO(petemill): If we make any hidden-by-default built-in items,
+ // then this logic needs to change to only consider shown-by-default items,
+ // and perhaps use a dict for each item to store whether built-in item is
+ // chosen to be added or removed.
+ auto hidden_items = GetHiddenDefaultSidebarItems();
+ for (const auto& hidden_item : hidden_items) {
+ base::Value item_type(static_cast(hidden_item.built_in_item_type));
+ hide_builtin_update->Append(std::move(item_type));
+ }
}
void SidebarService::AddObserver(Observer* observer) {
@@ -203,11 +330,11 @@ std::vector SidebarService::GetHiddenDefaultSidebarItems() const {
auto default_items = GetDefaultSidebarItems();
const auto added_default_items = GetDefaultSidebarItemsFromCurrentItems();
for (const auto& added_item : added_default_items) {
- auto iter = std::find_if(default_items.begin(), default_items.end(),
- [added_item](const auto& default_item) {
- return default_item.built_in_item_type ==
- added_item.built_in_item_type;
- });
+ auto iter = base::ranges::find_if(
+ default_items, [&added_item](const auto& default_item) {
+ return default_item.built_in_item_type ==
+ added_item.built_in_item_type;
+ });
default_items.erase(iter);
}
return default_items;
@@ -225,75 +352,134 @@ SidebarService::ShowSidebarOption SidebarService::GetSidebarShowOption() const {
return static_cast(prefs_->GetInteger(kSidebarShowOption));
}
+absl::optional SidebarService::GetDefaultPanelItem() const {
+ static const base::NoDestructor preferred_item_types(
+ std::vector{
+ SidebarItem::BuiltInItemType::kReadingList,
+ SidebarItem::BuiltInItemType::kBookmarks});
+ absl::optional default_item;
+ for (const auto& type : *preferred_item_types) {
+ auto found_item_iter = base::ranges::find_if(
+ items_,
+ [type](SidebarItem item) { return (item.built_in_item_type == type); });
+ if (found_item_iter != items_.end()) {
+ default_item = *found_item_iter;
+ DCHECK_EQ(default_item->open_in_panel, true);
+ break;
+ }
+ }
+ return default_item;
+}
+
void SidebarService::SetSidebarShowOption(ShowSidebarOption show_options) {
DCHECK_NE(ShowSidebarOption::kShowOnClick, show_options);
prefs_->SetInteger(kSidebarShowOption, static_cast(show_options));
}
void SidebarService::LoadSidebarItems() {
- auto* preference = prefs_->FindPreference(kSidebarItems);
- if (preference->IsDefaultValue()) {
- items_ = GetDefaultSidebarItems();
- return;
- }
-
- const auto& items = preference->GetValue()->GetList();
- for (const auto& item : items) {
- SidebarItem::Type type;
- if (const auto value = item.FindIntKey(kSidebarItemTypeKey)) {
- type = static_cast(*value);
- } else {
- continue;
- }
+ auto default_items_to_add = GetDefaultSidebarItems();
- std::string url;
- if (const auto* value = item.FindStringKey(kSidebarItemURLKey)) {
- url = *value;
- } else {
- continue;
- }
-
- // Always use latest properties for built-in type item.
- if (type == SidebarItem::Type::kTypeBuiltIn) {
- SidebarItem built_in_item;
- if (const auto value = item.FindIntKey(kSidebarItemBuiltInItemTypeKey)) {
- built_in_item = GetBuiltInItemForType(
- static_cast(*value));
+ // Pref for custom items and custom order
+ auto* preference = prefs_->FindPreference(kSidebarItems);
+ if (!preference->IsDefaultValue()) {
+ const auto& items = preference->GetValue()->GetList();
+ for (const auto& item : items) {
+ DVLOG(2) << "load: " << item.DebugString();
+ SidebarItem::Type type;
+ if (const auto type_value = item.FindIntKey(kSidebarItemTypeKey)) {
+ type = static_cast(*type_value);
} else {
- // Fallback when built-in item type key is not existed.
- built_in_item = GetBuiltInItemForURL(url);
+ continue;
}
- // Remove blocked item from existing users data.
- if (!IsBlockedBuiltInItem(built_in_item))
- items_.push_back(built_in_item);
- continue;
- }
-
- bool open_in_panel;
- if (const auto value = item.FindBoolKey(kSidebarItemOpenInPanelKey)) {
- open_in_panel = *value;
- } else {
- continue;
+ // Always use latest properties for built-in type item.
+ if (type == SidebarItem::Type::kTypeBuiltIn) {
+ if (const auto value =
+ item.FindIntKey(kSidebarItemBuiltInItemTypeKey)) {
+ auto id = static_cast(*value);
+ auto iter = std::find_if(
+ default_items_to_add.begin(), default_items_to_add.end(),
+ [id](const auto& default_item) {
+ return default_item.built_in_item_type == id;
+ });
+ // It might be an item which is no longer is offered as built-in
+ if (iter == default_items_to_add.end()) {
+ continue;
+ }
+ // Valid built-in item, add it
+ items_.emplace_back(*std::make_move_iterator(iter));
+ default_items_to_add.erase(iter);
+ continue;
+ }
+ }
+ // Deserialize custom item
+ std::string url;
+ if (const auto* value = item.FindStringKey(kSidebarItemURLKey)) {
+ url = *value;
+ } else {
+ continue;
+ }
+ // Open in panel for custom items is not yet supported
+ bool open_in_panel = false;
+ std::string title;
+ if (const auto* value = item.FindStringKey(kSidebarItemTitleKey)) {
+ title = *value;
+ }
+ items_.push_back(SidebarItem::Create(
+ GURL(url), base::UTF8ToUTF16(title), type,
+ SidebarItem::BuiltInItemType::kNone, open_in_panel));
}
+ }
- // Title can be updated later.
- std::string title;
- if (const auto* value = item.FindStringKey(kSidebarItemTitleKey)) {
- title = *value;
+ //
+ // Add built-in items which haven't been shown or hidden.
+ //
+ // Don't consider built-in items that the user has already hidden.
+ auto* hidden_built_in_preference =
+ prefs_->FindPreference(kSidebarHiddenBuiltInItems);
+ if (!hidden_built_in_preference->IsDefaultValue()) {
+ for (const auto& item : hidden_built_in_preference->GetValue()->GetList()) {
+ // Don't show this built-in item
+ const auto id = static_cast(item.GetInt());
+ DVLOG(2) << "hide built-in item with id: " << item.GetInt();
+ auto iter =
+ std::find_if(default_items_to_add.begin(), default_items_to_add.end(),
+ [id](const auto& default_item) {
+ return default_item.built_in_item_type ==
+ static_cast(id);
+ });
+ if (iter != default_items_to_add.end()) {
+ default_items_to_add.erase(iter);
+ } else {
+ DLOG(ERROR) << "Asked to hide an item that was already asked to show. "
+ "This indicates something is wrong with the "
+ "serialization process. Id was: "
+ << item.GetInt();
+ }
}
-
- DCHECK(type != SidebarItem::Type::kTypeBuiltIn);
- items_.push_back(SidebarItem::Create(
- GURL(url), base::UTF8ToUTF16(title), type,
- SidebarItem::BuiltInItemType::kNone, open_in_panel));
}
-}
-// For now, only builtin history item is blocked.
-bool SidebarService::IsBlockedBuiltInItem(const SidebarItem& item) const {
- if (!IsBuiltInType(item))
- return false;
- return item.built_in_item_type == SidebarItem::BuiltInItemType::kHistory;
+ // Add the items the user has never seen (or never persisted).
+ // Get the initial order of items so that we can attempt to
+ // insert at the intended order.
+ auto default_item_types = GetDefaultBuiltInItemTypes();
+ for (const auto& item : default_items_to_add) {
+ const auto& default_item_iter =
+ std::find(default_item_types.begin(), default_item_types.end(),
+ item.built_in_item_type);
+ auto default_index = default_item_iter - default_item_types.begin();
+ // Add at the default index for the first time. For users which haven't
+ // changed any order, or removed items, this will be at the intentional
+ // index. For users who have re-ordered, this will be different but still
+ // acceptable. It will be a minority of cases where it gets inserted in to
+ // the middle of custom items, but that will still work.
+ auto index = std::min(static_cast(default_index),
+ static_cast(items_.size()));
+ VLOG(2) << "Inserting built-in item ("
+ << static_cast(item.built_in_item_type)
+ << " with default index: " << default_index
+ << " at actual index: " << index;
+ items_.insert(items_.begin() + index, std::move(item));
+ }
}
void SidebarService::OnPreferenceChanged(const std::string& pref_name) {
diff --git a/components/sidebar/sidebar_service.h b/components/sidebar/sidebar_service.h
index 359e45321359..9a4446c16dc8 100644
--- a/components/sidebar/sidebar_service.h
+++ b/components/sidebar/sidebar_service.h
@@ -16,6 +16,7 @@
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/version_info/channel.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefRegistrySimple;
class PrefService;
@@ -50,7 +51,7 @@ class SidebarService : public KeyedService {
explicit SidebarService(PrefService* prefs);
~SidebarService() override;
- const std::vector items() const { return items_; }
+ const std::vector& items() const { return items_; }
void AddItem(const SidebarItem& item);
void RemoveItemAt(int index);
@@ -63,18 +64,25 @@ class SidebarService : public KeyedService {
ShowSidebarOption GetSidebarShowOption() const;
void SetSidebarShowOption(ShowSidebarOption show_options);
+ absl::optional GetDefaultPanelItem() const;
+
SidebarService(const SidebarService&) = delete;
SidebarService& operator=(const SidebarService&) = delete;
private:
+ FRIEND_TEST_ALL_PREFIXES(SidebarModelTest, ItemsChangedTest);
FRIEND_TEST_ALL_PREFIXES(SidebarServiceTest, AddRemoveItems);
+ FRIEND_TEST_ALL_PREFIXES(SidebarServiceTest, NewDefaultItemAdded);
+
+ static std::vector
+ GetDefaultBuiltInItemTypes_ForTesting();
void LoadSidebarItems();
void UpdateSidebarItemsToPrefStore();
std::vector GetDefaultSidebarItemsFromCurrentItems() const;
void OnPreferenceChanged(const std::string& pref_name);
- bool IsBlockedBuiltInItem(const SidebarItem& item) const;
void MigrateSidebarShowOptions();
+ void MigratePrefSidebarBuiltInItemsToHidden();
raw_ptr prefs_ = nullptr;
std::vector items_;
diff --git a/components/sidebar/sidebar_service_unittest.cc b/components/sidebar/sidebar_service_unittest.cc
index 7ebb5dc5057b..d65730eec2d5 100644
--- a/components/sidebar/sidebar_service_unittest.cc
+++ b/components/sidebar/sidebar_service_unittest.cc
@@ -3,11 +3,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include
#include
#include
#include "brave/components/sidebar/constants.h"
#include "brave/components/sidebar/pref_names.h"
+#include "brave/components/sidebar/sidebar_item.h"
#include "brave/components/sidebar/sidebar_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
@@ -77,7 +79,7 @@ TEST_F(SidebarServiceTest, AddRemoveItems) {
InitService();
// Check the default items count.
- EXPECT_EQ(3UL, service_->items().size());
+ EXPECT_EQ(4UL, service_->items().size());
EXPECT_EQ(0UL, service_->GetHiddenDefaultSidebarItems().size());
// Cache 1st item to compare after removing.
@@ -89,7 +91,7 @@ TEST_F(SidebarServiceTest, AddRemoveItems) {
EXPECT_EQ(-1, item_index_on_called_);
service_->RemoveItemAt(0);
- EXPECT_EQ(2UL, service_->items().size());
+ EXPECT_EQ(3UL, service_->items().size());
EXPECT_EQ(1UL, service_->GetHiddenDefaultSidebarItems().size());
EXPECT_EQ(0, item_index_on_called_);
EXPECT_TRUE(on_will_remove_item_called_);
@@ -100,8 +102,8 @@ TEST_F(SidebarServiceTest, AddRemoveItems) {
EXPECT_FALSE(on_item_added_called_);
service_->AddItem(item);
// New item will be added at last.
- EXPECT_EQ(2, item_index_on_called_);
- EXPECT_EQ(3UL, service_->items().size());
+ EXPECT_EQ(3, item_index_on_called_);
+ EXPECT_EQ(4UL, service_->items().size());
EXPECT_EQ(0UL, service_->GetHiddenDefaultSidebarItems().size());
EXPECT_TRUE(on_item_added_called_);
ClearState();
@@ -111,10 +113,10 @@ TEST_F(SidebarServiceTest, AddRemoveItems) {
SidebarItem::Type::kTypeWeb, SidebarItem::BuiltInItemType::kNone, true);
EXPECT_TRUE(IsWebType(item2));
service_->AddItem(item2);
- EXPECT_EQ(3, item_index_on_called_);
- EXPECT_EQ(4UL, service_->items().size());
+ EXPECT_EQ(4, item_index_on_called_);
+ EXPECT_EQ(5UL, service_->items().size());
// Default item count is not changed.
- EXPECT_EQ(3UL, service_->GetDefaultSidebarItemsFromCurrentItems().size());
+ EXPECT_EQ(4UL, service_->GetDefaultSidebarItemsFromCurrentItems().size());
}
TEST_F(SidebarServiceTest, MoveItem) {
@@ -125,7 +127,7 @@ TEST_F(SidebarServiceTest, MoveItem) {
SidebarItem new_item;
new_item.url = GURL("https://brave.com");
service_->AddItem(new_item);
- EXPECT_EQ(4UL, service_->items().size());
+ EXPECT_EQ(5UL, service_->items().size());
// Move item at 0 to index 2.
SidebarItem item = service_->items()[0];
@@ -149,10 +151,343 @@ TEST_F(SidebarServiceTest, MoveItem) {
EXPECT_EQ(item.url, service_->items()[1].url);
}
+TEST_F(SidebarServiceTest, MoveItemSavedToPrefs) {
+ SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::DEV);
+ InitService();
+
+ // Add one more item to test with 4 items.
+ SidebarItem new_item;
+ new_item.url = GURL("https://brave.com");
+ service_->AddItem(new_item);
+ EXPECT_EQ(5UL, service_->items().size());
+
+ // Move item at 0 to index 2.
+ SidebarItem item = service_->items()[0];
+ GURL url = item.url;
+ service_->MoveItem(0, 2);
+ EXPECT_TRUE(on_item_moved_called_);
+ service_.reset();
+ InitService();
+ EXPECT_EQ(5UL, service_->items().size());
+ EXPECT_EQ(url, service_->items()[2].url);
+}
+
+TEST_F(SidebarServiceTest, HideBuiltInItem) {
+ SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::DEV);
+ // Have prefs which contain a custom item and hides 1 built-in item
+ {
+ ListPrefUpdate update(&prefs_, sidebar::kSidebarHiddenBuiltInItems);
+ update->ClearList();
+ update->Append(static_cast(SidebarItem::BuiltInItemType::kBookmarks));
+ }
+ {
+ ListPrefUpdate update(&prefs_, sidebar::kSidebarItems);
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringKey(sidebar::kSidebarItemURLKey,
+ "https://custom1.brave.com/");
+ dict.SetStringKey(sidebar::kSidebarItemTitleKey, "Custom Item 1");
+ dict.SetIntKey(sidebar::kSidebarItemTypeKey,
+ static_cast(SidebarItem::Type::kTypeWeb));
+ dict.SetBoolKey(sidebar::kSidebarItemOpenInPanelKey, false);
+ update->Append(std::move(dict));
+ }
+
+ InitService();
+ // None of the items should be the hidden one
+ auto items = service_->items();
+ auto bookmark_iter =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kBookmarks);
+ });
+ EXPECT_EQ(bookmark_iter, items.end());
+ // Check serialization also perists that
+ service_.reset();
+ InitService();
+ items = service_->items();
+ bookmark_iter =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kBookmarks);
+ });
+ EXPECT_EQ(bookmark_iter, items.end());
+}
+
+TEST_F(SidebarServiceTest, NewDefaultItemAdded) {
+ SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::DEV);
+ // Have prefs which contain a custom item and hides 1 built-in item
+ {
+ ListPrefUpdate update(&prefs_, sidebar::kSidebarHiddenBuiltInItems);
+ update->ClearList();
+ update->Append(static_cast(SidebarItem::BuiltInItemType::kBookmarks));
+ }
+ {
+ ListPrefUpdate update(&prefs_, sidebar::kSidebarItems);
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringKey(sidebar::kSidebarItemURLKey,
+ "https://custom1.brave.com/");
+ dict.SetStringKey(sidebar::kSidebarItemTitleKey, "Custom Item 1");
+ dict.SetIntKey(sidebar::kSidebarItemTypeKey,
+ static_cast(SidebarItem::Type::kTypeWeb));
+ dict.SetBoolKey(sidebar::kSidebarItemOpenInPanelKey, false);
+ update->Append(std::move(dict));
+ }
+
+ InitService();
+ // Make sure other default items are present. They are considered not seen yet
+ // since kSidebarItems was not default value and did not contain them.
+ // None of the items should be the hidden one
+ auto items = service_->items();
+ auto bookmark_iter =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kBookmarks);
+ });
+ EXPECT_EQ(bookmark_iter, items.end());
+ // All other default items should be present even though not present
+ // in kSidebarItems pref.
+ std::vector remaining_default_items{
+ SidebarItem::BuiltInItemType::kBraveTalk,
+ SidebarItem::BuiltInItemType::kWallet,
+ SidebarItem::BuiltInItemType::kReadingList,
+ };
+ // Get expected indexes (the custom item will replace the index of the removed
+ // built-in).
+ auto all_default_item_types =
+ SidebarService::GetDefaultBuiltInItemTypes_ForTesting();
+ // There should also be the custom item we added
+ EXPECT_EQ(remaining_default_items.size() + 1, service_->items().size());
+ for (auto built_in_type : remaining_default_items) {
+ auto iter = std::find_if(
+ items.begin(), items.end(), [built_in_type](const auto& item) {
+ return (item.built_in_item_type == built_in_type);
+ });
+ EXPECT_NE(iter, items.end());
+ auto expected_index =
+ std::find(all_default_item_types.begin(), all_default_item_types.end(),
+ built_in_type) -
+ all_default_item_types.begin();
+ auto index = iter - items.begin();
+ EXPECT_EQ(expected_index, index)
+ << "New item with ID " << static_cast(built_in_type)
+ << " was inserted at expected index";
+ }
+}
+
+TEST_F(SidebarServiceTest, MigratePrefSidebarBuiltInItemsSomeHidden) {
+ SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::BETA);
+ // Make prefs already have old-style builtin items before service
+ // initialization.
+ {
+ ListPrefUpdate update(&prefs_, sidebar::kSidebarItems);
+ update->ClearList();
+
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringKey(sidebar::kSidebarItemURLKey,
+ "https://anything.brave.com/");
+ dict.SetStringKey(sidebar::kSidebarItemTitleKey, "Anything");
+ dict.SetIntKey(sidebar::kSidebarItemTypeKey,
+ static_cast(SidebarItem::Type::kTypeBuiltIn));
+ dict.SetIntKey(sidebar::kSidebarItemBuiltInItemTypeKey,
+ static_cast(SidebarItem::BuiltInItemType::kBraveTalk));
+ dict.SetBoolKey(sidebar::kSidebarItemOpenInPanelKey, true);
+ update->Append(std::move(dict));
+ }
+
+ InitService();
+
+ // Verify service has migrated the "include" of kBraveTalk to be the exclude
+ // of all other built-in items that were known prior to this migration and are
+ // still available.
+ auto* preference = prefs_.FindPreference(kSidebarItems);
+ auto* hidden_preference = prefs_.FindPreference(kSidebarHiddenBuiltInItems);
+ EXPECT_EQ(1UL, preference->GetValue()->GetList().size())
+ << "Still contains built-in item in original preference, for ordering "
+ "purposes";
+ EXPECT_EQ(2UL, hidden_preference->GetValue()->GetList().size())
+ << "Migration resulted in hiding the expected number of items";
+ // Verify expected items
+ EXPECT_EQ(2UL, service_->items().size());
+ auto items = service_->items();
+ auto talk_iter =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kBraveTalk);
+ });
+ auto reading_iter =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kReadingList);
+ });
+ EXPECT_NE(talk_iter, items.end());
+ EXPECT_NE(reading_iter, items.end());
+ // Check service has updated built-in item. Previously url was incorrect. This
+ // check is to make sure that we don't re-introduce code which stores the URL
+ // for built-in items.
+ auto talk_item = *talk_iter;
+ EXPECT_EQ(talk_item.url, kBraveTalkURL);
+}
+
+TEST_F(SidebarServiceTest, MigratePrefSidebarBuiltInItemsNoneHidden) {
+ SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::BETA);
+ // Make prefs already have ALL old-style builtin items before service
+ // initialization. This tests that when not adding anything to the new pref
+ // that re-migration will not break anything.
+ // Also add a custom item so that the main items pref is not default value.
+ {
+ ListPrefUpdate update(&prefs_, sidebar::kSidebarItems);
+ update->ClearList();
+
+ std::vector hideable_types{
+ SidebarItem::BuiltInItemType::kBraveTalk,
+ SidebarItem::BuiltInItemType::kWallet,
+ SidebarItem::BuiltInItemType::kBookmarks,
+ };
+
+ for (const auto& built_in_type : hideable_types) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringKey(sidebar::kSidebarItemURLKey,
+ "https://anything.brave.com/");
+ dict.SetStringKey(sidebar::kSidebarItemTitleKey, "Anything");
+ dict.SetIntKey(sidebar::kSidebarItemTypeKey,
+ static_cast(SidebarItem::Type::kTypeBuiltIn));
+ dict.SetIntKey(sidebar::kSidebarItemBuiltInItemTypeKey,
+ static_cast(built_in_type));
+ dict.SetBoolKey(sidebar::kSidebarItemOpenInPanelKey, true);
+ update->Append(std::move(dict));
+ }
+
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringKey(sidebar::kSidebarItemURLKey,
+ "https://custom1.brave.com/");
+ dict.SetStringKey(sidebar::kSidebarItemTitleKey, "Custom Item 1");
+ dict.SetIntKey(sidebar::kSidebarItemTypeKey,
+ static_cast(SidebarItem::Type::kTypeWeb));
+ dict.SetBoolKey(sidebar::kSidebarItemOpenInPanelKey, false);
+ update->Append(std::move(dict));
+ }
+
+ InitService();
+
+ // Verify service has migrated the "include" of kBraveTalk to be the exclude
+ // of all other built-in items that were known prior to this migration and are
+ // still available.
+ auto* preference = prefs_.FindPreference(kSidebarItems);
+ auto* hidden_preference = prefs_.FindPreference(kSidebarHiddenBuiltInItems);
+ EXPECT_EQ(4UL, preference->GetValue()->GetList().size())
+ << "Migration still contains built-in items, for ordering purposes";
+ EXPECT_EQ(0UL, hidden_preference->GetValue()->GetList().size())
+ << "Migration did not result in hiding any built-in items";
+ // kSidebarHiddenBuiltInItems being non-default is how we know migration is
+ // already done.
+ EXPECT_FALSE(hidden_preference->IsDefaultValue());
+ // kSidebarItems should still have custom item
+ EXPECT_FALSE(preference->IsDefaultValue());
+ // Verify expected items = items in pref plus new item (reading list)
+ EXPECT_EQ(5UL, service_->items().size());
+ // Simulate re-launch and check service has still updated items.
+ // This tests re-migration doesn't occur and hide all the hideable built-in
+ // items.
+ service_.reset();
+ InitService();
+ // Prefs still haven't been re-serialized, so don't contain new items
+ EXPECT_EQ(4UL, preference->GetValue()->GetList().size());
+ EXPECT_EQ(0UL, hidden_preference->GetValue()->GetList().size());
+ EXPECT_FALSE(hidden_preference->IsDefaultValue());
+ EXPECT_FALSE(preference->IsDefaultValue());
+ EXPECT_EQ(5UL, service_->items().size());
+
+ // Check again after service updates prefs. Force serialization by performing
+ // a move operation (and move it back).
+ service_->MoveItem(0, 1);
+ service_->MoveItem(0, 1);
+ service_.reset();
+ InitService();
+ // Pref now includes new default items added after migration (ReadingList),
+ // so size has increased by 1.
+ EXPECT_EQ(5UL, preference->GetValue()->GetList().size());
+ EXPECT_EQ(0UL, hidden_preference->GetValue()->GetList().size());
+ EXPECT_FALSE(hidden_preference->IsDefaultValue());
+ EXPECT_FALSE(preference->IsDefaultValue());
+ EXPECT_EQ(5UL, service_->items().size());
+ // Verify that new a new item not contained in prefs was added at correct
+ // index.
+ auto items = service_->items();
+ auto iter = std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kReadingList;
+ });
+ auto index = iter - items.begin();
+ EXPECT_EQ(3, index);
+}
+
+TEST_F(SidebarServiceTest, HidesBuiltInItemsViaPref) {
+ SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::BETA);
+ // Verify default state
+ InitService();
+ auto items = service_->items();
+ auto bookmarks_iter =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kBookmarks);
+ });
+ EXPECT_NE(bookmarks_iter, items.end());
+
+ // Update pref to hide bookmarks item
+ // Make prefs already have old-style builtin items before service
+ // initialization.
+ {
+ ListPrefUpdate update(&prefs_, sidebar::kSidebarHiddenBuiltInItems);
+ update->ClearList();
+ update->Append(static_cast(SidebarItem::BuiltInItemType::kBookmarks));
+ }
+
+ // Verify new state doesn't include bookmarks item
+ InitService();
+ items = service_->items();
+ auto bookmarks_iter_removed =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kBookmarks);
+ });
+ EXPECT_EQ(bookmarks_iter_removed, items.end());
+}
+
+TEST_F(SidebarServiceTest, HidesBuiltInItemsViaService) {
+ SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::BETA);
+ // Verify default state
+ InitService();
+ auto items = service_->items();
+ auto bookmark_item_index = 0u;
+ bool found = false;
+ while (bookmark_item_index < items.size()) {
+ auto item = items[bookmark_item_index];
+ if (item.built_in_item_type == SidebarItem::BuiltInItemType::kBookmarks) {
+ found = true;
+ break;
+ }
+ bookmark_item_index++;
+ }
+ EXPECT_TRUE(found);
+ // Update service to hide bookmarks item
+ service_->RemoveItemAt(bookmark_item_index);
+
+ // Verify new state doesn't include bookmarks item
+ service_.reset();
+ InitService();
+ items = service_->items();
+ auto bookmarks_iter_removed =
+ std::find_if(items.begin(), items.end(), [](const auto& item) {
+ return (item.built_in_item_type ==
+ SidebarItem::BuiltInItemType::kBookmarks);
+ });
+ EXPECT_EQ(bookmarks_iter_removed, items.end());
+}
+
TEST_F(SidebarServiceTest, BuiltInItemUpdateTestWithBuiltInItemTypeKey) {
SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::BETA);
// Make prefs already have builtin items before service initialization.
- // And it has old url.
+ // And it has old url in old pref format (storing built-in items).
{
ListPrefUpdate update(&prefs_, sidebar::kSidebarItems);
update->ClearList();
@@ -172,7 +507,7 @@ TEST_F(SidebarServiceTest, BuiltInItemUpdateTestWithBuiltInItemTypeKey) {
InitService();
// Check service has updated built-in item. Previously url was deprecated.xxx.
- EXPECT_EQ(1UL, service_->items().size());
+ EXPECT_EQ(2UL, service_->items().size());
EXPECT_EQ(GURL(kBraveTalkURL), service_->items()[0].url);
// Simulate re-launch and check service has still updated items.
@@ -182,7 +517,7 @@ TEST_F(SidebarServiceTest, BuiltInItemUpdateTestWithBuiltInItemTypeKey) {
InitService();
// Check service has updated built-in item. Previously url was deprecated.xxx.
- EXPECT_EQ(1UL, service_->items().size());
+ EXPECT_EQ(2UL, service_->items().size());
EXPECT_EQ(GURL(kBraveTalkURL), service_->items()[0].url);
}
@@ -208,42 +543,16 @@ TEST_F(SidebarServiceTest, BuiltInItemDoesntHaveHistoryItem) {
InitService();
// Check service doesn't have history item.
- EXPECT_EQ(0UL, service_->items().size());
-
+ for (const auto& item : service_->items()) {
+ EXPECT_NE(SidebarItem::BuiltInItemType::kHistory, item.built_in_item_type);
+ }
// Make sure history is not included in the not added default items list.
auto not_added_default_items = service_->GetHiddenDefaultSidebarItems();
- EXPECT_EQ(3UL, not_added_default_items.size());
for (const auto& item : not_added_default_items) {
EXPECT_NE(SidebarItem::BuiltInItemType::kHistory, item.built_in_item_type);
}
}
-TEST_F(SidebarServiceTest, BuiltInItemUpdateTestWithoutBuiltInItemTypeKey) {
- SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::STABLE);
- // Prepare built-in item in prefs w/o setting BuiltInItemType.
- // If not stored, service uses url to get proper latest properties.
- {
- ListPrefUpdate update(&prefs_, sidebar::kSidebarItems);
- update->ClearList();
-
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetStringKey(sidebar::kSidebarItemURLKey,
- "https://together.brave.com/");
- dict.SetStringKey(sidebar::kSidebarItemTitleKey, "Brave together");
- dict.SetIntKey(sidebar::kSidebarItemTypeKey,
- static_cast(SidebarItem::Type::kTypeBuiltIn));
- dict.SetBoolKey(sidebar::kSidebarItemOpenInPanelKey, true);
- update->Append(std::move(dict));
- }
-
- InitService();
-
- // Check item type is set properly.
- EXPECT_EQ(1UL, service_->items().size());
- EXPECT_EQ(SidebarItem::BuiltInItemType::kBraveTalk,
- service_->items()[0].built_in_item_type);
-}
-
TEST_F(SidebarServiceTest, SidebarShowOptionsDeprecationTest) {
SidebarService::RegisterProfilePrefs(prefs_.registry(), Channel::STABLE);
// Show on click is deprecated.
diff --git a/patches/chrome-browser-ui-views-side_panel-side_panel_coordinator.cc.patch b/patches/chrome-browser-ui-views-side_panel-side_panel_coordinator.cc.patch
new file mode 100644
index 000000000000..cc8b5ff6c04d
--- /dev/null
+++ b/patches/chrome-browser-ui-views-side_panel-side_panel_coordinator.cc.patch
@@ -0,0 +1,20 @@
+diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
+index 1efe9453a6d271fdb118f39f95630296de13a95e..ef134beaf3bf407580e6fa84a3bbc82f6856984a 100644
+--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
++++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
+@@ -180,6 +180,7 @@ SidePanelCoordinator::~SidePanelCoordinator() {
+ }
+
+ void SidePanelCoordinator::Show(absl::optional entry_id) {
++ BRAVE_SIDE_PANEL_COORDINATOR_SHOW
+ if (!entry_id.has_value())
+ entry_id = GetLastActiveEntryId().value_or(kDefaultEntry);
+
+@@ -419,6 +420,7 @@ std::unique_ptr SidePanelCoordinator::CreateHeader() {
+ ChromeLayoutProvider::Get()->GetDistanceMetric(
+ ChromeDistanceMetric::DISTANCE_SIDE_PANEL_HEADER_VECTOR_ICON_SIZE)));
+
++ BRAVE_SIDE_PANEL_COORDINATOR_CREATE_HEADER
+ return header;
+ }
+
diff --git a/patches/chrome-browser-ui-views-toolbar-toolbar_view.cc.patch b/patches/chrome-browser-ui-views-toolbar-toolbar_view.cc.patch
index 990a3faa4081..b69f9b930e77 100644
--- a/patches/chrome-browser-ui-views-toolbar-toolbar_view.cc.patch
+++ b/patches/chrome-browser-ui-views-toolbar-toolbar_view.cc.patch
@@ -2,15 +2,7 @@ diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui
index 8499344e764b14f52fea1ace029fc4aa6bd5619a..ee822fe7723cb3c17036ef2b7d730b16c8c096fd 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
-@@ -298,6 +298,7 @@ void ToolbarView::Init() {
- }
-
- std::unique_ptr side_panel_button;
-+ BRAVE_TOOLBAR_VIEW_DEACTIVATE_SIDE_PANEL
- if (browser_view_->right_aligned_side_panel()) {
- side_panel_button = std::make_unique(browser_);
- }
-@@ -364,6 +365,7 @@ void ToolbarView::Init() {
+@@ -364,6 +364,7 @@ void ToolbarView::Init() {
} else {
// TODO(crbug.com/932818): Remove this once the
// |kAutofillEnableToolbarStatusChip| is fully launched.
diff --git a/vector_icons/chrome/app/vector_icons/side_panel.icon b/vector_icons/chrome/app/vector_icons/side_panel.icon
new file mode 100644
index 000000000000..1cb8324dabbb
--- /dev/null
+++ b/vector_icons/chrome/app/vector_icons/side_panel.icon
@@ -0,0 +1,23 @@
+// Copyright (c) 2022 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// you can obtain one at http://mozilla.org/MPL/2.0/.
+
+CANVAS_DIMENSIONS, 18,
+FLIPS_IN_RTL,
+MOVE_TO, 18, 15.75f,
+R_CUBIC_TO, 0, 0.83f, -0.67f, 1.5f, -1.5f, 1.5f,
+R_H_LINE_TO, -15,
+R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f,
+V_LINE_TO, 2.25f,
+CUBIC_TO, 0, 1.42f, 0.67f, 0.75f, 1.5f, 0.75f,
+R_H_LINE_TO, 15,
+R_CUBIC_TO, 0.83f, 0, 1.5f, 0.67f, 1.5f, 1.5f,
+R_V_LINE_TO, 13.5f,
+CLOSE,
+MOVE_TO, 5.25f, 2.25f,
+R_V_LINE_TO, 13.5f,
+H_LINE_TO, 16.5f,
+V_LINE_TO, 2.25f,
+H_LINE_TO, 5.25f,
+CLOSE