This is just a replacement for `BrowserWindowInterface`. Chromium changes: https://chromium.googlesource.com/chromium/src/+/6fdf39dcf2a19ea7debd7f96d1668f4631cfabb0 commit 6fdf39dcf2a19ea7debd7f96d1668f4631cfabb0 Author: Kun Wang <kunwang@microsoft.com> Date: Sun Mar 29 13:12:54 2026 -0700 [bedrock] Migrate Browser parameters to BrowserWindowInterface Part 2 Migrate ~30 functions to take BrowserWindowInterface* instead of Browser*. Functions needing Browser*-specific APIs use GetBrowserForMigrationOnly() as an incremental workaround. Also migrates lens::IsRegionSearchEnabled/IsInProgressiveWebApp and ScreenshotCapturedBubbleController::Capture to BrowserWindowInterface*. Bug: 494376650 Change-Id: If121f69b70804171718563074abc5341e0b1a03b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7699547 Reviewed-by: Tom Lukaszewicz <tluk@chromium.org> Reviewed-by: Qikai Zhong <qikaizhong@microsoft.com> Commit-Queue: Tom Lukaszewicz <tluk@chromium.org> Cr-Commit-Position: refs/heads/main@{#1606828}
1258 lines
38 KiB
C++
1258 lines
38 KiB
C++
/* Copyright (c) 2019 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/browser_commands.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
#include <numeric>
|
|
#include <stack>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "base/check.h"
|
|
#include "base/check_op.h"
|
|
#include "base/feature_list.h"
|
|
#include "base/functional/callback_helpers.h"
|
|
#include "base/i18n/file_util_icu.h"
|
|
#include "base/i18n/time_formatting.h"
|
|
#include "base/logging.h"
|
|
#include "base/memory/scoped_refptr.h"
|
|
#include "base/notreached.h"
|
|
#include "base/path_service.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "brave/app/brave_command_ids.h"
|
|
#include "brave/browser/brave_shields/brave_shields_tab_helper.h"
|
|
#include "brave/browser/debounce/debounce_service_factory.h"
|
|
#include "brave/browser/ui/bookmark/brave_bookmark_prefs.h"
|
|
#include "brave/browser/ui/brave_browser.h"
|
|
#include "brave/browser/ui/sidebar/sidebar_service_factory.h"
|
|
#include "brave/browser/ui/tabs/brave_tab_prefs.h"
|
|
#include "brave/browser/ui/tabs/brave_tab_strip_model.h"
|
|
#include "brave/browser/ui/views/frame/vertical_tabs/vertical_tab_strip_region_view.h"
|
|
#include "brave/browser/ui/views/frame/vertical_tabs/vertical_tab_strip_widget_delegate_view.h"
|
|
#include "brave/browser/ui/views/tabs/vertical_tab_utils.h"
|
|
#include "brave/browser/url_sanitizer/url_sanitizer_service_factory.h"
|
|
#include "brave/components/brave_vpn/common/buildflags/buildflags.h"
|
|
#include "brave/components/constants/pref_names.h"
|
|
#include "brave/components/containers/buildflags/buildflags.h"
|
|
#include "brave/components/debounce/core/browser/debounce_service.h"
|
|
#include "brave/components/query_filter/utils.h"
|
|
#include "brave/components/sidebar/browser/sidebar_service.h"
|
|
#include "brave/components/speedreader/common/buildflags/buildflags.h"
|
|
#include "brave/components/tor/buildflags/buildflags.h"
|
|
#include "brave/components/url_sanitizer/core/browser/url_sanitizer_service.h"
|
|
#include "chrome/browser/bookmarks/bookmark_html_writer.h"
|
|
#include "chrome/browser/browser_process.h"
|
|
#include "chrome/browser/profiles/profile.h"
|
|
#include "chrome/browser/profiles/profile_manager.h"
|
|
#include "chrome/browser/profiles/profile_metrics.h"
|
|
#include "chrome/browser/profiles/profile_window.h"
|
|
#include "chrome/browser/ui/browser.h"
|
|
#include "chrome/browser/ui/browser_commands.h"
|
|
#include "chrome/browser/ui/browser_navigator.h"
|
|
#include "chrome/browser/ui/browser_navigator_params.h"
|
|
#include "chrome/browser/ui/browser_tabstrip.h"
|
|
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
|
|
#include "chrome/browser/ui/browser_window/public/global_browser_collection.h"
|
|
#include "chrome/browser/ui/profiles/profile_picker.h"
|
|
#include "chrome/browser/ui/tabs/features.h"
|
|
#include "chrome/browser/ui/tabs/tab_enums.h"
|
|
#include "chrome/browser/ui/tabs/tab_group_model.h"
|
|
#include "chrome/browser/ui/tabs/tab_model.h"
|
|
#include "chrome/browser/ui/tabs/tab_muted_utils.h"
|
|
#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
|
#include "chrome/browser/ui/tabs/tab_utils.h"
|
|
#include "chrome/browser/ui/ui_features.h"
|
|
#include "chrome/common/channel_info.h"
|
|
#include "chrome/common/chrome_paths.h"
|
|
#include "chrome/common/pref_names.h"
|
|
#include "chrome/common/webui_url_constants.h"
|
|
#include "chrome/grit/generated_resources.h"
|
|
#include "components/split_tabs/split_tab_visual_data.h"
|
|
#include "components/tab_groups/tab_group_visual_data.h"
|
|
#include "components/tabs/public/tab_group.h"
|
|
#include "content/public/browser/browser_thread.h"
|
|
#include "content/public/browser/page_navigator.h"
|
|
#include "content/public/browser/web_contents.h"
|
|
#include "ui/base/clipboard/clipboard_buffer.h"
|
|
#include "ui/base/clipboard/scoped_clipboard_writer.h"
|
|
#include "ui/base/window_open_disposition.h"
|
|
#include "ui/shell_dialogs/select_file_dialog.h"
|
|
#include "ui/shell_dialogs/select_file_policy.h"
|
|
#include "ui/shell_dialogs/selected_file_info.h"
|
|
#include "url/origin.h"
|
|
|
|
#if defined(TOOLKIT_VIEWS)
|
|
#include "brave/browser/ui/views/frame/brave_browser_view.h"
|
|
#include "chrome/browser/ui/side_panel/side_panel_entry.h"
|
|
#include "chrome/browser/ui/side_panel/side_panel_entry_id.h"
|
|
#include "chrome/browser/ui/side_panel/side_panel_enums.h"
|
|
#include "chrome/browser/ui/side_panel/side_panel_ui.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_SPEEDREADER)
|
|
#include "brave/browser/speedreader/speedreader_service_factory.h"
|
|
#include "brave/browser/ui/speedreader/speedreader_tab_helper.h"
|
|
#include "brave/components/speedreader/speedreader_service.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_TOR)
|
|
#include "brave/browser/tor/tor_profile_manager.h"
|
|
#include "brave/browser/tor/tor_profile_service_factory.h"
|
|
#include "brave/components/tor/tor_profile_service.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
|
#include "brave/browser/brave_vpn/brave_vpn_service_factory.h"
|
|
#include "brave/browser/ui/brave_vpn/brave_vpn_controller.h"
|
|
#include "brave/components/brave_vpn/browser/brave_vpn_service.h"
|
|
#include "brave/components/brave_vpn/common/brave_vpn_constants.h"
|
|
#include "brave/components/brave_vpn/common/brave_vpn_utils.h"
|
|
#include "brave/components/brave_vpn/common/pref_names.h"
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
#include "brave/browser/brave_vpn/win/storage_utils.h"
|
|
#include "brave/browser/brave_vpn/win/wireguard_utils_win.h"
|
|
#endif // BUILDFLAG(ENABLE_BRAVE_VPN)
|
|
|
|
#endif // BUILDFLAG(ENABLE_BRAVE_VPN)
|
|
|
|
#if BUILDFLAG(ENABLE_COMMANDER)
|
|
#include "brave/browser/ui/commander/commander_service.h"
|
|
#include "brave/browser/ui/commander/commander_service_factory.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_CONTAINERS)
|
|
#include "brave/browser/ui/tabs/public/brave_tab_features.h"
|
|
#include "brave/browser/ui/views/page_action/partitioned_storage_page_action_controller.h"
|
|
#include "brave/components/containers/content/browser/storage_partition_utils.h"
|
|
#include "brave/components/containers/core/mojom/containers.mojom.h"
|
|
#include "components/tabs/public/tab_interface.h"
|
|
#if defined(TOOLKIT_VIEWS)
|
|
#include "chrome/browser/ui/views/frame/browser_view.h"
|
|
#endif
|
|
#endif
|
|
|
|
using content::WebContents;
|
|
|
|
namespace brave {
|
|
|
|
namespace {
|
|
|
|
bool CanTakeTabs(const Browser* from, const Browser* to) {
|
|
return from != to && from->type() == Browser::TYPE_NORMAL &&
|
|
!from->IsAttemptingToCloseBrowser() && !from->is_delete_scheduled() &&
|
|
to->profile() == from->profile();
|
|
}
|
|
|
|
std::vector<int> GetSelectedIndices(Browser* browser) {
|
|
auto* model = browser->tab_strip_model();
|
|
const auto& selection = model->selection_model().GetListSelectionModel();
|
|
auto indices = std::vector<int>(selection.selected_indices().begin(),
|
|
selection.selected_indices().end());
|
|
CHECK(!indices.empty())
|
|
<< "Returning empty indices could case infinite recursion";
|
|
return indices;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
/**
|
|
* @note This function creates a default filename like
|
|
* `bookmarks_2025_12_15.html`, for example, if the date is December 15, 2025.
|
|
*
|
|
* @note This function mimics the behavior of a function with the same name in
|
|
* the Chromium source code.
|
|
*
|
|
* @see
|
|
* https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc;l=205-222?q=IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME
|
|
*/
|
|
base::FilePath GetDefaultFilepathForBookmarkExport() {
|
|
std::string bookmarks_yyyy_MM_dd = l10n_util::GetStringFUTF8(
|
|
IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME,
|
|
base::UTF8ToUTF16(base::UnlocalizedTimeFormatWithPattern(
|
|
base::Time::Now(), "yyyy_MM_dd")));
|
|
|
|
base::FilePath path = base::FilePath::FromUTF8Unsafe(bookmarks_yyyy_MM_dd);
|
|
base::FilePath::StringType path_str = path.value();
|
|
base::i18n::ReplaceIllegalCharactersInPath(&path_str, '_');
|
|
base::FilePath default_path;
|
|
base::PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path);
|
|
return default_path.Append(base::FilePath(path_str));
|
|
}
|
|
|
|
/**
|
|
* @class BookmarksExportListener
|
|
* @brief A listener class for handling bookmark export file selection.
|
|
*
|
|
* This class is responsible for showing a file dialog to the user for selecting
|
|
* the location to save exported bookmarks.
|
|
*
|
|
* @note The lifetime of this class is tied to the FileSelected dialog. It will
|
|
* be automatically deleted when the dialog is closed, a file is selected, or
|
|
* the dialog is cancelled.
|
|
*/
|
|
class BookmarksExportListener : public ui::SelectFileDialog::Listener {
|
|
public:
|
|
explicit BookmarksExportListener(Profile* profile)
|
|
: profile_(profile),
|
|
file_selector_(ui::SelectFileDialog::Create(this, nullptr)) {}
|
|
void FileSelected(const ui::SelectedFileInfo& file, int index) override {
|
|
bookmark_html_writer::WriteBookmarks(profile_, file.file_path,
|
|
base::DoNothing());
|
|
file_selector_->ListenerDestroyed();
|
|
delete this;
|
|
}
|
|
void FileSelectionCanceled() override {
|
|
file_selector_->ListenerDestroyed();
|
|
delete this;
|
|
}
|
|
void ShowFileDialog(Browser* browser) {
|
|
ui::SelectFileDialog::FileTypeInfo file_types;
|
|
|
|
// Only show HTML files in the file dialog.
|
|
file_types.extensions.push_back({FILE_PATH_LITERAL("html")});
|
|
file_selector_->SelectFile(
|
|
ui::SelectFileDialog::SELECT_SAVEAS_FILE,
|
|
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_MENU_EXPORT),
|
|
GetDefaultFilepathForBookmarkExport(), &file_types, 1,
|
|
FILE_PATH_LITERAL("html"), browser->window()->GetNativeWindow(),
|
|
nullptr);
|
|
}
|
|
|
|
private:
|
|
raw_ptr<Profile> profile_;
|
|
scoped_refptr<ui::SelectFileDialog> file_selector_;
|
|
};
|
|
|
|
#if BUILDFLAG(ENABLE_TOR)
|
|
void NewOffTheRecordWindowTor(Browser* browser) {
|
|
CHECK(browser);
|
|
NewOffTheRecordWindowTor(browser->profile());
|
|
}
|
|
|
|
void NewOffTheRecordWindowTor(Profile* profile) {
|
|
CHECK(profile);
|
|
if (profile->IsTor()) {
|
|
chrome::OpenEmptyWindow(profile);
|
|
return;
|
|
}
|
|
|
|
TorProfileManager::SwitchToTorProfile(profile);
|
|
}
|
|
|
|
void NewTorConnectionForSite(BrowserWindowInterface* browser) {
|
|
Profile* profile = browser->GetProfile();
|
|
DCHECK(profile);
|
|
tor::TorProfileService* service =
|
|
TorProfileServiceFactory::GetForContext(profile);
|
|
DCHECK(service);
|
|
WebContents* current_tab =
|
|
browser->GetTabStripModel()->GetActiveWebContents();
|
|
if (!current_tab) {
|
|
return;
|
|
}
|
|
service->SetNewTorCircuit(current_tab);
|
|
}
|
|
#endif
|
|
|
|
void MaybeDistillAndShowSpeedreaderBubble(Browser* browser) {
|
|
#if BUILDFLAG(ENABLE_SPEEDREADER)
|
|
WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
|
|
if (!contents) {
|
|
return;
|
|
}
|
|
if (auto* tab_helper =
|
|
speedreader::SpeedreaderTabHelper::FromWebContents(contents)) {
|
|
tab_helper->ProcessIconClick();
|
|
}
|
|
#endif // BUILDFLAG(ENABLE_SPEEDREADER)
|
|
}
|
|
|
|
void ShowBraveVPNBubble(Browser* browser) {
|
|
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
|
browser->GetFeatures().brave_vpn_controller()->ShowBraveVPNBubble();
|
|
#endif
|
|
}
|
|
|
|
void ToggleBraveVPNTrayIcon() {
|
|
#if BUILDFLAG(ENABLE_BRAVE_VPN) && BUILDFLAG(IS_WIN)
|
|
brave_vpn::EnableVPNTrayIcon(!brave_vpn::IsVPNTrayIconEnabled());
|
|
if (brave_vpn::IsVPNTrayIconEnabled()) {
|
|
brave_vpn::wireguard::ShowBraveVpnStatusTrayIcon();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ToggleBraveVPNButton(Browser* browser) {
|
|
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
|
auto* prefs = browser->profile()->GetPrefs();
|
|
const bool show = prefs->GetBoolean(brave_vpn::prefs::kBraveVPNShowButton);
|
|
prefs->SetBoolean(brave_vpn::prefs::kBraveVPNShowButton, !show);
|
|
#endif
|
|
}
|
|
|
|
void OpenBraveVPNUrls(Browser* browser, int command_id) {
|
|
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
|
brave_vpn::BraveVpnService* vpn_service =
|
|
brave_vpn::BraveVpnServiceFactory::GetForProfile(browser->profile());
|
|
CHECK(vpn_service);
|
|
std::string target_url;
|
|
switch (command_id) {
|
|
case IDC_SEND_BRAVE_VPN_FEEDBACK:
|
|
target_url = brave_vpn::kFeedbackUrl;
|
|
break;
|
|
case IDC_ABOUT_BRAVE_VPN:
|
|
target_url = brave_vpn::kAboutUrl;
|
|
break;
|
|
case IDC_MANAGE_BRAVE_VPN_PLAN:
|
|
target_url =
|
|
brave_vpn::GetManageUrl(vpn_service->GetCurrentEnvironment());
|
|
break;
|
|
default:
|
|
NOTREACHED() << "This should only be called with one of the above VPN "
|
|
"commands. (was "
|
|
<< command_id << ")";
|
|
}
|
|
|
|
chrome::AddTabAt(browser, GURL(target_url), -1, true);
|
|
#endif
|
|
}
|
|
|
|
void ToggleAIChat(Browser* browser) {
|
|
#if defined(TOOLKIT_VIEWS)
|
|
SidePanelUI* side_panel_ui = browser->GetFeatures().side_panel_ui();
|
|
side_panel_ui->Toggle(SidePanelEntry::Key(SidePanelEntryId::kChatUI),
|
|
SidePanelOpenTrigger::kToolbarButton);
|
|
#endif
|
|
}
|
|
|
|
#if BUILDFLAG(ENABLE_BRAVE_WALLET)
|
|
void ShowWalletBubble(Browser* browser) {
|
|
#if defined(TOOLKIT_VIEWS)
|
|
static_cast<BraveBrowserView*>(browser->window())->CreateWalletBubble();
|
|
#endif
|
|
}
|
|
|
|
void ShowApproveWalletBubble(Browser* browser) {
|
|
#if defined(TOOLKIT_VIEWS)
|
|
static_cast<BraveBrowserView*>(browser->window())
|
|
->CreateApproveWalletBubble();
|
|
#endif
|
|
}
|
|
|
|
void CloseWalletBubble(Browser* browser) {
|
|
#if defined(TOOLKIT_VIEWS)
|
|
static_cast<BraveBrowserView*>(browser->window())->CloseWalletBubble();
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void CopySanitizedURL(Browser* browser, const GURL& url) {
|
|
if (!browser || !browser->profile()) {
|
|
return;
|
|
}
|
|
GURL sanitized_url = brave::URLSanitizerServiceFactory::GetForBrowserContext(
|
|
browser->profile())
|
|
->SanitizeURL(url);
|
|
|
|
ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste);
|
|
scw.WriteText(base::UTF8ToUTF16(sanitized_url.spec()));
|
|
}
|
|
|
|
// Copies an url cleared through:
|
|
// - Debouncer (potentially debouncing many levels)
|
|
// - Query filter
|
|
// - URLSanitizerService
|
|
void CopyLinkWithStrictCleaning(Browser* browser, const GURL& url) {
|
|
if (!browser || !browser->profile()) {
|
|
return;
|
|
}
|
|
DCHECK(url.SchemeIsHTTPOrHTTPS());
|
|
GURL final_url;
|
|
// Apply debounce rules.
|
|
auto* debounce_service =
|
|
debounce::DebounceServiceFactory::GetForBrowserContext(
|
|
browser->profile());
|
|
if (debounce_service && !debounce_service->Debounce(url, &final_url)) {
|
|
VLOG(1) << "Unable to apply debounce rules";
|
|
final_url = url;
|
|
}
|
|
// Apply query filters.
|
|
auto filtered_url = query_filter::ApplyQueryFilter(final_url);
|
|
if (filtered_url.has_value()) {
|
|
final_url = filtered_url.value();
|
|
}
|
|
// Sanitize url.
|
|
final_url = brave::URLSanitizerServiceFactory::GetForBrowserContext(
|
|
browser->profile())
|
|
->SanitizeURL(final_url);
|
|
|
|
ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste);
|
|
scw.WriteText(base::UTF8ToUTF16(final_url.spec()));
|
|
}
|
|
|
|
void ToggleWindowTitleVisibilityForVerticalTabs(Browser* browser) {
|
|
auto* prefs = browser->profile()->GetOriginalProfile()->GetPrefs();
|
|
prefs->SetBoolean(
|
|
brave_tabs::kVerticalTabsShowTitleOnWindow,
|
|
!prefs->GetBoolean(brave_tabs::kVerticalTabsShowTitleOnWindow));
|
|
}
|
|
|
|
void ToggleVerticalTabStrip(Browser* browser) {
|
|
if (!tabs::utils::IsVerticalTabToggleEnabled(browser)) {
|
|
return;
|
|
}
|
|
|
|
auto* profile = browser->profile()->GetOriginalProfile();
|
|
auto* prefs = profile->GetPrefs();
|
|
const bool was_using_vertical_tab_strip =
|
|
prefs->GetBoolean(brave_tabs::kVerticalTabsEnabled);
|
|
prefs->SetBoolean(brave_tabs::kVerticalTabsEnabled,
|
|
!was_using_vertical_tab_strip);
|
|
}
|
|
|
|
void ToggleVerticalTabStripFloatingMode(Browser* browser) {
|
|
auto* prefs = browser->profile()->GetOriginalProfile()->GetPrefs();
|
|
prefs->SetBoolean(
|
|
brave_tabs::kVerticalTabsFloatingEnabled,
|
|
!prefs->GetBoolean(brave_tabs::kVerticalTabsFloatingEnabled));
|
|
}
|
|
|
|
void ToggleVerticalTabStripExpanded(Browser* browser) {
|
|
auto* prefs = browser->profile()->GetPrefs();
|
|
bool expanded_state_per_window =
|
|
prefs->GetBoolean(brave_tabs::kVerticalTabsExpandedStatePerWindow);
|
|
// Toggle preference if all tabs share the same state (derived from prefs)
|
|
if (!expanded_state_per_window) {
|
|
prefs->SetBoolean(brave_tabs::kVerticalTabsCollapsed,
|
|
!prefs->GetBoolean(brave_tabs::kVerticalTabsCollapsed));
|
|
return;
|
|
}
|
|
// Otherwise, retrieve current vertical tab strip region view
|
|
auto* browser_view = static_cast<BraveBrowserView*>(browser->window());
|
|
if (!browser_view) {
|
|
return;
|
|
}
|
|
auto* vtsr_view = browser_view->vertical_tab_strip_widget_delegate_view()
|
|
->vertical_tab_strip_region_view();
|
|
if (!vtsr_view) {
|
|
return;
|
|
}
|
|
// toggle state for only this vtsr view
|
|
vtsr_view->ToggleState();
|
|
}
|
|
|
|
void ToggleActiveTabAudioMute(Browser* browser) {
|
|
WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
|
|
if (!contents) {
|
|
return;
|
|
}
|
|
|
|
bool mute_tab = !contents->IsAudioMuted();
|
|
SetTabAudioMuted(contents, mute_tab, TabMutedReason::kAudioIndicator,
|
|
std::string());
|
|
}
|
|
|
|
void ToggleSidebarPosition(Browser* browser) {
|
|
auto* prefs = browser->profile()->GetPrefs();
|
|
prefs->SetBoolean(prefs::kSidePanelHorizontalAlignment,
|
|
!prefs->GetBoolean(prefs::kSidePanelHorizontalAlignment));
|
|
}
|
|
|
|
void ToggleSidebar(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
if (auto* brave_browser_window =
|
|
BraveBrowserWindow::From(browser->window())) {
|
|
brave_browser_window->ToggleSidebar();
|
|
}
|
|
}
|
|
|
|
bool HasSelectedURL(Browser* browser) {
|
|
if (!browser) {
|
|
return false;
|
|
}
|
|
auto* brave_browser_window = BraveBrowserWindow::From(browser->window());
|
|
return brave_browser_window && brave_browser_window->HasSelectedURL();
|
|
}
|
|
|
|
void CleanAndCopySelectedURL(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
auto* brave_browser_window = BraveBrowserWindow::From(browser->window());
|
|
if (brave_browser_window) {
|
|
brave_browser_window->CleanAndCopySelectedURL();
|
|
}
|
|
}
|
|
|
|
void ToggleShieldsEnabled(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
auto* contents = browser->tab_strip_model()->GetActiveWebContents();
|
|
if (!contents) {
|
|
return;
|
|
}
|
|
auto* shields =
|
|
brave_shields::BraveShieldsTabHelper::FromWebContents(contents);
|
|
if (!shields) {
|
|
return;
|
|
}
|
|
|
|
shields->SetBraveShieldsEnabled(!shields->GetBraveShieldsEnabled());
|
|
}
|
|
|
|
void ToggleJavascriptEnabled(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
auto* contents = browser->tab_strip_model()->GetActiveWebContents();
|
|
if (!contents) {
|
|
return;
|
|
}
|
|
auto* shields =
|
|
brave_shields::BraveShieldsTabHelper::FromWebContents(contents);
|
|
if (!shields) {
|
|
return;
|
|
}
|
|
|
|
shields->SetIsNoScriptEnabled(!shields->GetNoScriptEnabled());
|
|
}
|
|
|
|
#if BUILDFLAG(ENABLE_COMMANDER)
|
|
void ToggleCommander(Browser* browser) {
|
|
if (auto* commander_service =
|
|
commander::CommanderServiceFactory::GetForBrowserContext(
|
|
browser->profile())) {
|
|
commander_service->Toggle();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_PLAYLIST_WEBUI)
|
|
void ShowPlaylistBubble(Browser* browser) {
|
|
BraveBrowserWindow::From(browser->window())->ShowPlaylistBubble();
|
|
}
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_BRAVE_WAYBACK_MACHINE)
|
|
void ShowWaybackMachineBubble(Browser* browser) {
|
|
BraveBrowserWindow::From(browser->window())->ShowWaybackMachineBubble();
|
|
}
|
|
#endif
|
|
|
|
void GroupTabsOnCurrentOrigin(Browser* browser) {
|
|
auto url =
|
|
browser->tab_strip_model()->GetActiveWebContents()->GetVisibleURL();
|
|
auto origin = url::Origin::Create(url);
|
|
|
|
std::vector<int> group_indices;
|
|
for (int index = 0; index < browser->tab_strip_model()->count(); ++index) {
|
|
auto* tab = browser->tab_strip_model()->GetWebContentsAt(index);
|
|
auto tab_origin = url::Origin::Create(tab->GetVisibleURL());
|
|
if (origin.IsSameOriginWith(tab_origin)) {
|
|
group_indices.push_back(index);
|
|
}
|
|
}
|
|
auto group_id = browser->tab_strip_model()->AddToNewGroup(group_indices);
|
|
auto* group =
|
|
browser->tab_strip_model()->group_model()->GetTabGroup(group_id);
|
|
|
|
auto data = *group->visual_data();
|
|
data.SetTitle(base::UTF8ToUTF16(origin.host()));
|
|
group->SetVisualData(data);
|
|
}
|
|
|
|
void MoveGroupToNewWindow(Browser* browser) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto current_group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
if (!current_group_id.has_value()) {
|
|
return;
|
|
}
|
|
|
|
tsm->delegate()->MoveGroupToNewWindow(current_group_id.value());
|
|
}
|
|
|
|
bool IsInGroup(Browser* browser) {
|
|
if (!browser) {
|
|
return false;
|
|
}
|
|
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto current_group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
return current_group_id.has_value();
|
|
}
|
|
|
|
bool HasUngroupedTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return false;
|
|
}
|
|
|
|
auto* tsm = browser->tab_strip_model();
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
if (!tsm->GetTabGroupForTab(i)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void GroupUngroupedTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
auto* tsm = browser->tab_strip_model();
|
|
std::vector<int> group_indices;
|
|
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
if (tsm->GetTabGroupForTab(i)) {
|
|
continue;
|
|
}
|
|
group_indices.push_back(i);
|
|
}
|
|
|
|
if (group_indices.empty()) {
|
|
return;
|
|
}
|
|
|
|
tsm->AddToNewGroup(group_indices);
|
|
}
|
|
|
|
void UngroupCurrentGroup(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
auto* tsm = browser->tab_strip_model();
|
|
|
|
auto group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
if (!group_id) {
|
|
return;
|
|
}
|
|
|
|
auto* group = tsm->group_model()->GetTabGroup(group_id.value());
|
|
std::vector<int> indices(group->tab_count());
|
|
tabs::TabInterface* first_tab = group->GetFirstTab();
|
|
DCHECK(first_tab);
|
|
std::iota(indices.begin(), indices.end(), tsm->GetIndexOfTab(first_tab));
|
|
tsm->RemoveFromGroup(indices);
|
|
}
|
|
|
|
void RemoveTabFromGroup(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
auto* tsm = browser->tab_strip_model();
|
|
tsm->RemoveFromGroup({tsm->active_index()});
|
|
}
|
|
|
|
void NameGroup(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
if (!group_id) {
|
|
return;
|
|
}
|
|
|
|
tsm->OpenTabGroupEditor(*group_id);
|
|
}
|
|
|
|
void NewTabInGroup(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
if (!group_id) {
|
|
return;
|
|
}
|
|
|
|
const auto tabs = tsm->group_model()->GetTabGroup(*group_id)->ListTabs();
|
|
tsm->delegate()->AddTabAt(GURL(), tabs.end(), true, *group_id);
|
|
}
|
|
|
|
bool CanUngroupAllTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return false;
|
|
}
|
|
auto* tsm = browser->tab_strip_model();
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
if (tsm->GetTabGroupForTab(i)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void UngroupAllTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
std::vector<int> indices(browser->tab_strip_model()->count());
|
|
std::iota(indices.begin(), indices.end(), 0);
|
|
browser->tab_strip_model()->RemoveFromGroup(indices);
|
|
}
|
|
|
|
void ToggleGroupExpanded(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
if (!group_id) {
|
|
return;
|
|
}
|
|
|
|
auto* group = tsm->group_model()->GetTabGroup(*group_id);
|
|
auto* vd = group->visual_data();
|
|
tab_groups::TabGroupVisualData vd_update(vd->title(), vd->color(),
|
|
!vd->is_collapsed());
|
|
group->SetVisualData(vd_update);
|
|
}
|
|
|
|
void CloseUngroupedTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
auto* tsm = static_cast<BraveTabStripModel*>(browser->tab_strip_model());
|
|
CHECK(tsm);
|
|
|
|
std::vector<int> indices;
|
|
|
|
for (int i = tsm->count() - 1; i >= 0; --i) {
|
|
if (!tsm->GetTabGroupForTab(i)) {
|
|
indices.push_back(i);
|
|
}
|
|
}
|
|
|
|
for (const auto& index : indices) {
|
|
tsm->CloseWebContentsAt(index,
|
|
TabCloseTypes::CLOSE_USER_GESTURE |
|
|
TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB);
|
|
}
|
|
}
|
|
|
|
void CloseTabsNotInCurrentGroup(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
auto* tsm = static_cast<BraveTabStripModel*>(browser->tab_strip_model());
|
|
CHECK(tsm);
|
|
|
|
auto group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
if (!group_id) {
|
|
return;
|
|
}
|
|
|
|
std::vector<int> indices;
|
|
for (int i = tsm->count() - 1; i >= 0; --i) {
|
|
if (tsm->GetTabGroupForTab(i) != *group_id) {
|
|
indices.push_back(i);
|
|
}
|
|
}
|
|
|
|
for (const auto& index : indices) {
|
|
tsm->CloseWebContentsAt(index,
|
|
TabCloseTypes::CLOSE_USER_GESTURE |
|
|
TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB);
|
|
}
|
|
}
|
|
|
|
void CloseGroup(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto group_id = tsm->GetTabGroupForTab(tsm->active_index());
|
|
if (!group_id) {
|
|
return;
|
|
}
|
|
tsm->CloseAllTabsInGroup(*group_id);
|
|
}
|
|
|
|
bool CanBringAllTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return false;
|
|
}
|
|
|
|
bool result = false;
|
|
GlobalBrowserCollection::GetInstance()->ForEach(
|
|
[browser, &result](BrowserWindowInterface* from) {
|
|
result = CanTakeTabs(from->GetBrowserForMigrationOnly(), browser);
|
|
return !result;
|
|
});
|
|
return result;
|
|
}
|
|
|
|
void BringAllTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
// Find all browsers with the same profile
|
|
std::vector<Browser*> browsers;
|
|
GlobalBrowserCollection::GetInstance()->ForEach(
|
|
[&browsers, browser](BrowserWindowInterface* from) {
|
|
auto* from_deprecated = from->GetBrowserForMigrationOnly();
|
|
if (CanTakeTabs(from_deprecated, browser)) {
|
|
browsers.push_back(from_deprecated);
|
|
}
|
|
return true;
|
|
});
|
|
|
|
// Detach all tabs from other browsers
|
|
std::stack<std::unique_ptr<tabs::TabModel>> detached_pinned_tabs;
|
|
std::stack<std::unique_ptr<tabs::TabModel>> detached_unpinned_tabs;
|
|
|
|
const bool shared_pinned_tab_enabled =
|
|
base::FeatureList::IsEnabled(tabs::kBraveSharedPinnedTabs) &&
|
|
browser->profile()->GetPrefs()->GetBoolean(brave_tabs::kSharedPinnedTab);
|
|
|
|
base::flat_set<Browser*> browsers_to_close;
|
|
std::ranges::for_each(browsers, [&detached_pinned_tabs,
|
|
&detached_unpinned_tabs, &browsers_to_close,
|
|
shared_pinned_tab_enabled](auto* other) {
|
|
static_cast<BraveBrowser*>(other)
|
|
->set_ignore_enable_closing_last_tab_pref();
|
|
|
|
auto* tab_strip_model = other->tab_strip_model();
|
|
const int pinned_tab_count = tab_strip_model->IndexOfFirstNonPinnedTab();
|
|
for (int i = tab_strip_model->count() - 1; i >= 0; --i) {
|
|
const bool is_pinned = i < pinned_tab_count;
|
|
if (is_pinned && shared_pinned_tab_enabled) {
|
|
// SharedPinnedTabService is responsible for synchronizing pinned
|
|
// tabs, thus we shouldn't manually detach and attach tabs here.
|
|
// Meanwhile, the tab strips don't get empty when they have dummy
|
|
// contents, we should close the browsers manually.
|
|
browsers_to_close.insert(other);
|
|
continue;
|
|
}
|
|
|
|
auto tab = tab_strip_model->DetachTabAtForInsertion(i);
|
|
if (is_pinned) {
|
|
detached_pinned_tabs.push(std::move(tab));
|
|
} else {
|
|
detached_unpinned_tabs.push(std::move(tab));
|
|
}
|
|
}
|
|
});
|
|
|
|
// Insert pinned tabs
|
|
auto* tab_strip_model = browser->tab_strip_model();
|
|
while (!detached_pinned_tabs.empty()) {
|
|
tab_strip_model->InsertDetachedTabAt(
|
|
tab_strip_model->IndexOfFirstNonPinnedTab(),
|
|
std::move(detached_pinned_tabs.top()), AddTabTypes::ADD_PINNED);
|
|
detached_pinned_tabs.pop();
|
|
}
|
|
|
|
// Insert unpinned tabs
|
|
while (!detached_unpinned_tabs.empty()) {
|
|
tab_strip_model->InsertDetachedTabAt(
|
|
tab_strip_model->count(), std::move(detached_unpinned_tabs.top()),
|
|
AddTabTypes::ADD_NONE);
|
|
detached_unpinned_tabs.pop();
|
|
}
|
|
|
|
if (shared_pinned_tab_enabled) {
|
|
std::ranges::for_each(browsers_to_close,
|
|
[](auto* other) { other->window()->Close(); });
|
|
}
|
|
}
|
|
|
|
bool HasDuplicateTabs(Browser* browser) {
|
|
if (!browser) {
|
|
return false;
|
|
}
|
|
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto* active_web_contents = tsm->GetActiveWebContents();
|
|
if (!active_web_contents) {
|
|
return false;
|
|
}
|
|
|
|
auto url = active_web_contents->GetVisibleURL();
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
// Don't check the active tab.
|
|
if (tsm->active_index() == i) {
|
|
continue;
|
|
}
|
|
|
|
auto* tab = tsm->GetWebContentsAt(i);
|
|
if (tab->GetVisibleURL() == url) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CloseDuplicateTabs(Browser* browser) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
auto url = tsm->GetActiveWebContents()->GetVisibleURL();
|
|
|
|
for (int i = tsm->count() - 1; i >= 0; --i) {
|
|
// Don't close the active tab.
|
|
if (tsm->active_index() == i) {
|
|
continue;
|
|
}
|
|
|
|
auto* tab = tsm->GetWebContentsAt(i);
|
|
if (tab->GetVisibleURL() == url) {
|
|
tab->Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CanCloseTabsToLeft(Browser* browser) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
const auto& selection = tsm->selection_model();
|
|
if (selection.empty()) {
|
|
return false;
|
|
}
|
|
|
|
int left_selected =
|
|
*(selection.GetListSelectionModel().selected_indices().begin());
|
|
return left_selected > 0;
|
|
}
|
|
|
|
void CloseTabsToLeft(Browser* browser) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
const auto& selection = tsm->selection_model();
|
|
if (selection.empty()) {
|
|
return;
|
|
}
|
|
|
|
int left_selected =
|
|
*(selection.GetListSelectionModel().selected_indices().begin());
|
|
for (int i = left_selected - 1; i >= 0; --i) {
|
|
tsm->CloseWebContentsAt(i, TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB |
|
|
TabCloseTypes::CLOSE_USER_GESTURE);
|
|
}
|
|
}
|
|
|
|
bool CanCloseUnpinnedTabs(Browser* browser) {
|
|
auto first_unpinned_index =
|
|
browser->tab_strip_model()->IndexOfFirstNonPinnedTab();
|
|
return first_unpinned_index < browser->tab_strip_model()->count();
|
|
}
|
|
|
|
void CloseUnpinnedTabs(Browser* browser) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
DCHECK(CanCloseUnpinnedTabs(browser));
|
|
|
|
for (int i = tsm->count() - 1; i >= tsm->IndexOfFirstNonPinnedTab(); --i) {
|
|
tsm->CloseWebContentsAt(i, TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB |
|
|
TabCloseTypes::CLOSE_USER_GESTURE);
|
|
}
|
|
}
|
|
|
|
void AddAllTabsToNewGroup(Browser* browser) {
|
|
std::vector<int> indices(browser->tab_strip_model()->count());
|
|
std::iota(indices.begin(), indices.end(), 0);
|
|
browser->tab_strip_model()->AddToNewGroup(indices);
|
|
}
|
|
|
|
bool CanMuteAllTabs(Browser* browser, bool exclude_active) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
if (exclude_active && tsm->active_index() == i) {
|
|
continue;
|
|
}
|
|
|
|
auto* contents = tsm->GetWebContentsAt(i);
|
|
if (contents->IsCurrentlyAudible()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void MuteAllTabs(Browser* browser, bool exclude_active) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
if (exclude_active && tsm->active_index() == i) {
|
|
continue;
|
|
}
|
|
|
|
auto* contents = tsm->GetWebContentsAt(i);
|
|
if (contents->IsCurrentlyAudible()) {
|
|
contents->SetAudioMuted(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CanUnmuteAllTabs(Browser* browser) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
auto* contents = tsm->GetWebContentsAt(i);
|
|
if (contents->IsAudioMuted()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void UnmuteAllTabs(Browser* browser) {
|
|
auto* tsm = browser->tab_strip_model();
|
|
for (int i = 0; i < tsm->count(); ++i) {
|
|
auto* contents = tsm->GetWebContentsAt(i);
|
|
if (contents->IsAudioMuted()) {
|
|
contents->SetAudioMuted(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScrollTabToTop(Browser* browser) {
|
|
auto* contents = browser->tab_strip_model()->GetActiveWebContents();
|
|
contents->ScrollToTopOfDocument();
|
|
}
|
|
|
|
void ScrollTabToBottom(Browser* browser) {
|
|
auto* contents = browser->tab_strip_model()->GetActiveWebContents();
|
|
contents->ScrollToBottomOfDocument();
|
|
}
|
|
|
|
void ExportAllBookmarks(Browser* browser) {
|
|
(new BookmarksExportListener(browser->profile()))->ShowFileDialog(browser);
|
|
}
|
|
|
|
void ToggleAllBookmarksButtonVisibility(Browser* browser) {
|
|
auto* prefs = browser->profile()->GetPrefs();
|
|
prefs->SetBoolean(
|
|
brave::bookmarks::prefs::kShowAllBookmarksButton,
|
|
!prefs->GetBoolean(brave::bookmarks::prefs::kShowAllBookmarksButton));
|
|
}
|
|
|
|
bool CanOpenNewSplitTabsWithSideBySide(Browser* browser) {
|
|
auto* tab_strip_model = browser->tab_strip_model();
|
|
auto active_index = tab_strip_model->active_index();
|
|
if (active_index == TabStripModel::kNoTab) {
|
|
return false;
|
|
}
|
|
|
|
return !tab_strip_model->GetSplitForTab(active_index).has_value();
|
|
}
|
|
|
|
bool CanSplitTabsWithSideBySide(Browser* browser) {
|
|
auto* tab_strip_model = browser->tab_strip_model();
|
|
if (tab_strip_model->empty()) {
|
|
return false;
|
|
}
|
|
|
|
auto selected_indices = GetSelectedIndices(browser);
|
|
if (selected_indices.size() != 2) {
|
|
return false;
|
|
}
|
|
|
|
return std::ranges::none_of(selected_indices, [&](auto index) {
|
|
return tab_strip_model->GetSplitForTab(index).has_value();
|
|
});
|
|
}
|
|
|
|
bool IsSplitTabs(Browser* browser) {
|
|
auto* tab_strip_model = browser->tab_strip_model();
|
|
if (tab_strip_model->empty()) {
|
|
return false;
|
|
}
|
|
|
|
auto selected_indices = GetSelectedIndices(browser);
|
|
return std::ranges::any_of(selected_indices, [&](auto index) {
|
|
return tab_strip_model->GetSplitForTab(index).has_value();
|
|
});
|
|
}
|
|
|
|
void SplitTabsWithSideBySide(Browser* browser,
|
|
split_tabs::SplitTabCreatedSource source) {
|
|
CHECK(brave::CanSplitTabsWithSideBySide(browser));
|
|
|
|
auto selected_indices = GetSelectedIndices(browser);
|
|
CHECK(selected_indices.size() == 2);
|
|
auto* tab_strip_model = browser->tab_strip_model();
|
|
const auto active_index = tab_strip_model->active_index();
|
|
CHECK_NE(TabStripModel::kNoTab, active_index);
|
|
// selected indices must have active tab index.
|
|
CHECK(active_index == selected_indices[0] ||
|
|
active_index == selected_indices[1]);
|
|
const int non_active_index_from_selected_indices =
|
|
active_index == selected_indices[0] ? selected_indices[1]
|
|
: selected_indices[0];
|
|
tab_strip_model->AddToNewSplit(
|
|
{non_active_index_from_selected_indices},
|
|
split_tabs::SplitTabVisualData(split_tabs::SplitTabLayout::kVertical),
|
|
source);
|
|
}
|
|
|
|
void RemoveSplitWithSideBySide(Browser* browser) {
|
|
auto selected_indices = GetSelectedIndices(browser);
|
|
auto* tab_strip_model = browser->tab_strip_model();
|
|
for (auto index : selected_indices) {
|
|
if (auto split_id = tab_strip_model->GetSplitForTab(index)) {
|
|
tab_strip_model->RemoveSplit(*split_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SwapTabsInSplitWithSideBySide(Browser* browser) {
|
|
auto* tab_strip_model = browser->tab_strip_model();
|
|
auto active_index = tab_strip_model->active_index();
|
|
CHECK_NE(TabStripModel::kNoTab, active_index);
|
|
|
|
auto split_id = tab_strip_model->GetSplitForTab(active_index);
|
|
CHECK(split_id.has_value());
|
|
tab_strip_model->ReverseTabsInSplit(*split_id);
|
|
}
|
|
|
|
void ForcePasteInBrowser(Browser* browser) {
|
|
CHECK(browser);
|
|
auto* contents = browser->tab_strip_model()->GetActiveWebContents();
|
|
if (!contents) {
|
|
return;
|
|
}
|
|
ForcePasteInWebContents(contents);
|
|
}
|
|
|
|
void ForcePasteInWebContents(content::WebContents* web_contents) {
|
|
CHECK(web_contents);
|
|
|
|
// Check the WebContents is focused.
|
|
auto* frame = web_contents->GetFocusedFrame();
|
|
if (!frame) {
|
|
return;
|
|
}
|
|
|
|
std::u16string result;
|
|
std::optional<ui::DataTransferEndpoint> data = ui::DataTransferEndpoint(
|
|
frame->GetMainFrame()->GetLastCommittedURL(),
|
|
ui::DataTransferEndpointOptions{
|
|
.notify_if_restricted = true,
|
|
.off_the_record = frame->GetBrowserContext()->IsOffTheRecord()});
|
|
|
|
ui::Clipboard::GetForCurrentThread()->ReadText(
|
|
ui::ClipboardBuffer::kCopyPaste, data,
|
|
base::BindOnce(
|
|
[](base::WeakPtr<content::WebContents> web_contents,
|
|
std::u16string result) {
|
|
// If there's no text in the clipboard don't do anything.
|
|
if (!web_contents || result.empty()) {
|
|
return;
|
|
}
|
|
|
|
// Replace works just like Paste, but it doesn't trigger onpaste
|
|
// handlers
|
|
web_contents->Replace(result);
|
|
},
|
|
web_contents->GetWeakPtr()));
|
|
}
|
|
|
|
#if BUILDFLAG(ENABLE_CONTAINERS)
|
|
void OpenTabUrlInContainer(BrowserWindowInterface* browser_window,
|
|
const tabs::TabHandle& tab,
|
|
const containers::mojom::ContainerPtr& container) {
|
|
const auto* tab_ptr = tab.Get();
|
|
if (!tab_ptr) {
|
|
LOG(ERROR) << "Tab is not valid";
|
|
return;
|
|
}
|
|
|
|
const GURL& url = tab_ptr->GetContents()->GetLastCommittedURL();
|
|
OpenUrlInContainer(browser_window, url, container);
|
|
}
|
|
|
|
void OpenUrlInContainer(BrowserWindowInterface* browser_window,
|
|
const GURL& url,
|
|
const containers::mojom::ContainerPtr& container) {
|
|
if (!url.is_valid()) {
|
|
LOG(ERROR) << "Url is not valid";
|
|
return;
|
|
}
|
|
|
|
CHECK(container);
|
|
|
|
NavigateParams params(browser_window, url, ui::PAGE_TRANSITION_LINK);
|
|
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
|
params.storage_partition_config = content::StoragePartitionConfig::Create(
|
|
browser_window->GetProfile(),
|
|
containers::kContainersStoragePartitionDomain, container->id,
|
|
browser_window->GetProfile()->IsOffTheRecord());
|
|
|
|
Navigate(¶ms);
|
|
}
|
|
|
|
void OpenTabUrlWithoutContainer(BrowserWindowInterface* browser_window,
|
|
const tabs::TabHandle& tab) {
|
|
const auto* tab_ptr = tab.Get();
|
|
if (!tab_ptr) {
|
|
LOG(ERROR) << "Tab is not valid";
|
|
return;
|
|
}
|
|
|
|
const GURL& url = tab_ptr->GetContents()->GetLastCommittedURL();
|
|
OpenUrlWithoutContainer(browser_window, url);
|
|
}
|
|
|
|
void OpenUrlWithoutContainer(BrowserWindowInterface* browser_window,
|
|
const GURL& url) {
|
|
if (!url.is_valid()) {
|
|
LOG(ERROR) << "Url is not valid";
|
|
return;
|
|
}
|
|
|
|
NavigateParams params(browser_window, url, ui::PAGE_TRANSITION_LINK);
|
|
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
|
Navigate(¶ms);
|
|
}
|
|
|
|
void OpenContainerMenuOnPageActionView(BrowserWindowInterface* browser_window,
|
|
actions::ActionItem* item) {
|
|
if (!browser_window) {
|
|
DVLOG(1) << "Browser window is not valid";
|
|
return;
|
|
}
|
|
|
|
#if !defined(TOOLKIT_VIEWS)
|
|
return;
|
|
#else
|
|
BrowserView* const browser_view =
|
|
BrowserView::GetBrowserViewForBrowser(browser_window);
|
|
if (!browser_view || !browser_view->toolbar_button_provider()) {
|
|
DVLOG(1) << "Browser view or toolbar button provider is not valid";
|
|
return;
|
|
}
|
|
|
|
tabs::TabInterface* tab = browser_window->GetActiveTabInterface();
|
|
if (!tab) {
|
|
DVLOG(1) << "Tab is not valid";
|
|
return;
|
|
}
|
|
|
|
tabs::BraveTabFeatures* brave_tab_features =
|
|
tabs::BraveTabFeatures::FromTabFeatures(tab->GetTabFeatures());
|
|
CHECK(brave_tab_features);
|
|
|
|
page_actions::PartitionedStoragePageActionController* const controller =
|
|
brave_tab_features->partitioned_storage_page_action_controller();
|
|
CHECK(controller);
|
|
controller->ExecuteAction(browser_view->toolbar_button_provider(), item);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
} // namespace brave
|