Chromium changes: https://chromium.googlesource.com/chromium/src/+/815c5cff075fb58c5ec93d967479af57312a5894 commit 815c5cff075fb58c5ec93d967479af57312a5894 Author: Foromo Daniel Soromou <koretadaniel@chromium.org> Date: Thu Apr 30 18:38:51 2026 -0700 Move browser_navigator files to a subdirectory Move the `browser_navigator*` files from `chrome/browser/ui/` to a new `chrome/browser/ui/navigator/` subdirectory to better organize the codebase. Update all corresponding include paths across the repository to reflect the new file locations. Bypass-Check-License: This is a file rename only. Bug: none Change-Id: I512c4119e212966e84001924ab2eb2e501a490d7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7801797 Reviewed-by: Darryl James <dljames@chromium.org> Reviewed-by: Dana Fried <dfried@chromium.org> Commit-Queue: Foromo Daniel Soromou <koretadaniel@chromium.org> Reviewed-by: Ashley Prasad <ashleydp@google.com> Reviewed-by: Hidehiko Abe <hidehiko@chromium.org> SLSA-Policy-Verified: SLSA Policy Verification Service <devtools-gerritcodereview-exitgate@google.com> Cr-Commit-Position: refs/heads/main@{#1623653}
315 lines
10 KiB
C++
315 lines
10 KiB
C++
/* 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_controller.h"
|
|
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
#include "base/check.h"
|
|
#include "base/check_op.h"
|
|
#include "brave/browser/ui/sidebar/buildflags/buildflags.h"
|
|
#include "brave/browser/ui/sidebar/sidebar.h"
|
|
#include "brave/browser/ui/sidebar/sidebar_model.h"
|
|
#include "brave/browser/ui/sidebar/sidebar_service_factory.h"
|
|
#include "brave/browser/ui/sidebar/sidebar_utils.h"
|
|
#include "brave/browser/ui/sidebar/sidebar_web_panel_controller.h"
|
|
#include "brave/components/ai_chat/core/common/buildflags/buildflags.h"
|
|
#include "brave/components/sidebar/browser/pref_names.h"
|
|
#include "brave/components/sidebar/browser/sidebar_service.h"
|
|
#include "brave/components/sidebar/common/features.h"
|
|
#include "chrome/browser/history/history_service_factory.h"
|
|
#include "chrome/browser/profiles/profile.h"
|
|
#include "chrome/browser/ui/browser.h"
|
|
#include "chrome/browser/ui/browser_finder.h"
|
|
#include "chrome/browser/ui/browser_tabstrip.h"
|
|
#include "chrome/browser/ui/browser_window.h"
|
|
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
|
|
#include "chrome/browser/ui/browser_window/public/profile_browser_collection.h"
|
|
#include "chrome/browser/ui/navigator/browser_navigator.h"
|
|
#include "chrome/browser/ui/navigator/browser_navigator_params.h"
|
|
#include "chrome/browser/ui/navigator/browser_navigator_params_utils.h"
|
|
#include "chrome/browser/ui/side_panel/side_panel_entry_id.h"
|
|
#include "chrome/browser/ui/side_panel/side_panel_ui.h"
|
|
#include "chrome/browser/ui/singleton_tabs.h"
|
|
#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
|
#include "components/prefs/pref_service.h"
|
|
|
|
namespace sidebar {
|
|
|
|
namespace {
|
|
|
|
SidebarService* GetSidebarService(Profile* profile) {
|
|
return SidebarServiceFactory::GetForProfile(profile);
|
|
}
|
|
|
|
std::vector<int> GetAllExistingTabIndexForHost(TabStripModel* tab_strip_model,
|
|
std::string_view host) {
|
|
const int tab_count = tab_strip_model->count();
|
|
std::vector<int> all_index;
|
|
for (int i = 0; i < tab_count; ++i) {
|
|
content::WebContents* tab = tab_strip_model->GetWebContentsAt(i);
|
|
if (tab->GetVisibleURL().host() == host)
|
|
all_index.push_back(i);
|
|
}
|
|
|
|
return all_index;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
SidebarController::SidebarController(Browser* browser, Profile* profile)
|
|
: tab_strip_model_(browser->tab_strip_model()),
|
|
profile_(profile),
|
|
browser_(browser),
|
|
sidebar_model_(new SidebarModel(profile_)) {
|
|
sidebar_service_observed_.Observe(GetSidebarService(profile_));
|
|
}
|
|
|
|
SidebarController::~SidebarController() = default;
|
|
|
|
bool SidebarController::IsActiveIndex(std::optional<size_t> index) const {
|
|
return sidebar_model_->active_index() == index;
|
|
}
|
|
|
|
bool SidebarController::DoesBrowserHaveOpenedTabForItem(
|
|
const SidebarItem& item) const {
|
|
// This method is only for builtin item's icon state updating.
|
|
DCHECK(item.is_built_in_type());
|
|
DCHECK(!item.open_in_panel);
|
|
|
|
bool result = false;
|
|
ProfileBrowserCollection::GetForProfile(profile_)->ForEach(
|
|
[&item, &result](BrowserWindowInterface* browser) {
|
|
const auto all_index = GetAllExistingTabIndexForHost(
|
|
browser->GetTabStripModel(), item.url.host());
|
|
if (!all_index.empty()) {
|
|
result = true;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
void SidebarController::TearDownPreBrowserWindowDestruction() {
|
|
web_panel_controller_.reset();
|
|
sidebar_service_observed_.Reset();
|
|
sidebar_ = nullptr;
|
|
}
|
|
|
|
void SidebarController::ActivateItemAt(std::optional<size_t> index,
|
|
WindowOpenDisposition disposition) {
|
|
// disengaged means there is no active item.
|
|
if (!index) {
|
|
sidebar_model_->SetActiveIndex(index);
|
|
return;
|
|
}
|
|
|
|
DCHECK_LT(index.value(), sidebar_model_->GetAllSidebarItems().size());
|
|
|
|
const auto& item = sidebar_model_->GetAllSidebarItems()[*index];
|
|
|
|
if (sidebar::IsWebPanelFeatureEnabled() && item.is_web_panel_type()) {
|
|
// TODO(https://github.com/brave/brave-browser/issues/33533): web panel item
|
|
// also should be activated.
|
|
GetWebPanelController()->ToggleWebPanel(item);
|
|
return;
|
|
}
|
|
|
|
// Only an item for panel can get activated.
|
|
if (!item.is_web_type() && item.open_in_panel) {
|
|
sidebar_model_->SetActiveIndex(index);
|
|
|
|
#if BUILDFLAG(ENABLE_AI_CHAT)
|
|
if (sidebar::features::kOpenOneShotLeoPanel.Get() &&
|
|
item.built_in_item_type == SidebarItem::BuiltInItemType::kChatUI) {
|
|
// Prevent one-time Leo panel open.
|
|
profile_->GetPrefs()->SetBoolean(kLeoPanelOneShotOpen, true);
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if (disposition != WindowOpenDisposition::CURRENT_TAB) {
|
|
DCHECK_NE(WindowOpenDisposition::UNKNOWN, disposition);
|
|
NavigateParams params(profile_, item.url,
|
|
ui::PAGE_TRANSITION_AUTO_BOOKMARK);
|
|
params.disposition = disposition;
|
|
params.browser = browser_;
|
|
Navigate(¶ms);
|
|
return;
|
|
}
|
|
|
|
// Iterate whenever builtin shortcut type item icon clicks.
|
|
if (item.is_built_in_type()) {
|
|
IterateOrLoadAtActiveTab(item.url);
|
|
return;
|
|
}
|
|
|
|
LoadAtTab(item.url);
|
|
}
|
|
|
|
void SidebarController::ActivatePanelItem(
|
|
SidebarItem::BuiltInItemType panel_item) {
|
|
// For panel item activation, SidePanelUI is the single source of truth.
|
|
auto* side_panel_ui = side_panel_ui_for_testing_
|
|
? side_panel_ui_for_testing_.get()
|
|
: browser_->GetFeatures().side_panel_ui();
|
|
CHECK(side_panel_ui);
|
|
if (panel_item == SidebarItem::BuiltInItemType::kNone) {
|
|
side_panel_ui->Close();
|
|
return;
|
|
}
|
|
|
|
#if BUILDFLAG(ENABLE_SIDEBAR_V2)
|
|
// Suppress opening animation when we have active item.
|
|
// When opening another panel while other panel is visible,
|
|
// we don't need to open new panel with animation.
|
|
const bool suppress_animations = sidebar_model_->active_index().has_value();
|
|
side_panel_ui->Show(sidebar::SidePanelIdFromSideBarItemType(panel_item),
|
|
/*open_trigger*/ std::nullopt, suppress_animations);
|
|
#else
|
|
side_panel_ui->Show(sidebar::SidePanelIdFromSideBarItemType(panel_item));
|
|
#endif
|
|
}
|
|
|
|
void SidebarController::DeactivateCurrentPanel() {
|
|
ActivatePanelItem(SidebarItem::BuiltInItemType::kNone);
|
|
}
|
|
|
|
void SidebarController::ToggleSidebarPinning() {
|
|
sidebar_pinned_ = !sidebar_pinned_;
|
|
sidebar_->UpdateSidebarVisibility();
|
|
}
|
|
|
|
bool SidebarController::ActiveTabFromOtherBrowsersForHost(const GURL& url) {
|
|
bool found = false;
|
|
ProfileBrowserCollection::GetForProfile(profile_)->ForEach(
|
|
[this, &found, &url](BrowserWindowInterface* browser) {
|
|
// Skip current browser. we are here because current active browser
|
|
// doesn't have a tab that loads |url|.
|
|
if (browser == browser_) {
|
|
return true;
|
|
}
|
|
|
|
const auto all_index = GetAllExistingTabIndexForHost(
|
|
browser->GetTabStripModel(), url.host());
|
|
if (all_index.empty()) {
|
|
return true;
|
|
}
|
|
|
|
// Pick first tab for simplicity.
|
|
browser->GetTabStripModel()->ActivateTabAt(all_index[0]);
|
|
browser->GetBrowserForMigrationOnly()->window()->Activate();
|
|
found = true;
|
|
return false;
|
|
});
|
|
|
|
return found;
|
|
}
|
|
|
|
void SidebarController::IterateOrLoadAtActiveTab(const GURL& url) {
|
|
// Get target tab index
|
|
const auto all_index =
|
|
GetAllExistingTabIndexForHost(tab_strip_model_, url.host());
|
|
if (all_index.empty()) {
|
|
if (ActiveTabFromOtherBrowsersForHost(url))
|
|
return;
|
|
|
|
// Load at current active tab if there is no tab that loaded |url|.
|
|
auto params = GetSingletonTabNavigateParams(browser_, url);
|
|
params.disposition = WindowOpenDisposition::CURRENT_TAB;
|
|
Navigate(¶ms);
|
|
return;
|
|
}
|
|
|
|
const int active_index = tab_strip_model_->active_index();
|
|
for (const auto i : all_index) {
|
|
if (i > active_index) {
|
|
tab_strip_model_->ActivateTabAt(i);
|
|
return;
|
|
}
|
|
}
|
|
|
|
tab_strip_model_->ActivateTabAt(all_index[0]);
|
|
}
|
|
|
|
void SidebarController::LoadAtTab(const GURL& url) {
|
|
auto params = GetSingletonTabNavigateParams(browser_, url);
|
|
int tab_index = GetIndexOfExistingTabMatchingURL(browser_, params);
|
|
// If browser has a tab that already loaded |item.url|, just activate it.
|
|
if (tab_index >= 0) {
|
|
tab_strip_model_->ActivateTabAt(tab_index);
|
|
} else {
|
|
// Load on current tab.
|
|
params.disposition = WindowOpenDisposition::CURRENT_TAB;
|
|
Navigate(¶ms);
|
|
}
|
|
}
|
|
|
|
void SidebarController::OnShowSidebarOptionChanged(
|
|
SidebarService::ShowSidebarOption option) {
|
|
CHECK(sidebar_);
|
|
sidebar_pinned_ = false;
|
|
sidebar_->SetSidebarShowOption(option);
|
|
}
|
|
|
|
void SidebarController::AddItemWithCurrentTab() {
|
|
if (!sidebar::CanAddCurrentActiveTabToSidebar(browser_)) {
|
|
return;
|
|
}
|
|
|
|
auto* active_contents = tab_strip_model_->GetActiveWebContents();
|
|
DCHECK(active_contents);
|
|
const GURL url = active_contents->GetVisibleURL();
|
|
const std::u16string title = active_contents->GetTitle();
|
|
GetSidebarService(profile_)->AddItem(SidebarItem::Create(
|
|
url, title, SidebarItem::Type::kTypeWeb,
|
|
SidebarItem::BuiltInItemType::kNone, IsWebPanelFeatureEnabled()));
|
|
}
|
|
|
|
void SidebarController::UpdateActiveItemState(
|
|
std::optional<SidebarItem::BuiltInItemType> active_panel_item) {
|
|
if (!active_panel_item) {
|
|
ActivateItemAt(std::nullopt);
|
|
return;
|
|
}
|
|
|
|
if (auto index = sidebar_model_->GetIndexOf(*active_panel_item)) {
|
|
ActivateItemAt(*index);
|
|
}
|
|
}
|
|
|
|
void SidebarController::SetSidebar(Sidebar* sidebar) {
|
|
DCHECK(!sidebar_);
|
|
// |sidebar| can be null in unit test.
|
|
if (!sidebar)
|
|
return;
|
|
sidebar_ = sidebar;
|
|
|
|
sidebar_model_->Init(HistoryServiceFactory::GetForProfile(
|
|
profile_, ServiceAccessType::EXPLICIT_ACCESS));
|
|
}
|
|
|
|
SidebarWebPanelController* SidebarController::GetWebPanelController() {
|
|
CHECK(IsWebPanelFeatureEnabled());
|
|
|
|
// It's too early or late to get web panel controller.
|
|
if (!sidebar_) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (!web_panel_controller_) {
|
|
web_panel_controller_ =
|
|
std::make_unique<SidebarWebPanelController>(browser_->GetBrowserView());
|
|
}
|
|
|
|
return web_panel_controller_.get();
|
|
}
|
|
|
|
} // namespace sidebar
|