Files
brave-core/browser/ui/sidebar/sidebar_controller.cc
Claudio DeSouza b9b1ce9657 [cr149] browser_navigator now in its own directory
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}
2026-05-22 16:57:32 -04:00

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(&params);
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(&params);
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(&params);
}
}
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