This change allows a couple of more places to be migrated to `BrowserWindowInterface`. Chromium changes: https://chromium.googlesource.com/chromium/src/+/e8d0df41d25900497716dd3a4b070c6436fa1a97 commit e8d0df41d25900497716dd3a4b070c6436fa1a97 Author: Kun Wang <kunwang@microsoft.com> Date: Wed Apr 15 23:35:39 2026 -0700 [bedrock] Migrate FindLastActiveWithProfile Step 1 Bug: 494010890 Change-Id: Ie0385deeda2e2f28baf75a810ada0becf5807c78 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7753884 Reviewed-by: Thomas Lukaszewicz <tluk@chromium.org> Reviewed-by: Qikai Zhong <qikaizhong@microsoft.com> Commit-Queue: Kun Wang <kunwang@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1615659}
233 lines
8.6 KiB
C++
233 lines
8.6 KiB
C++
// Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
|
|
|
|
// Based on Chromium code subject to the following license:
|
|
// Copyright 2021 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "brave/browser/ui/commander/entity_match.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "base/check.h"
|
|
#include "brave/browser/ui/commander/fuzzy_finder.h"
|
|
#include "chrome/browser/ui/browser.h"
|
|
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
|
|
#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
|
|
#include "chrome/browser/ui/tab_ui_helper.h"
|
|
#include "chrome/browser/ui/tabs/tab_group_model.h"
|
|
#include "chrome/browser/ui/tabs/tab_utils.h"
|
|
#include "chrome/grit/generated_resources.h"
|
|
#include "components/sessions/content/session_tab_helper.h"
|
|
#include "components/tabs/public/tab_group.h"
|
|
#include "ui/base/l10n/l10n_util.h"
|
|
#include "ui/gfx/text_elider.h"
|
|
|
|
namespace commander {
|
|
|
|
namespace {
|
|
// TODO(lgrey): Just guessing for now! Not even sure if we need a max width,
|
|
// but right now, the code that does "<title> and x other tabs" wants a max.
|
|
double constexpr kMaxTitleWidth = 1000;
|
|
|
|
// TODO(crbug.com/418774949) Move to TabGroupFeatures for desktop.
|
|
std::u16string GetContentString(const BrowserWindowInterface* browser,
|
|
const TabGroup& group) {
|
|
constexpr size_t kContextMenuTabTitleMaxLength = 30;
|
|
std::u16string format_string = l10n_util::GetPluralStringFUTF16(
|
|
IDS_TAB_CXMENU_PLACEHOLDER_GROUP_TITLE, group.tab_count() - 1);
|
|
|
|
std::u16string short_title;
|
|
gfx::ElideString(
|
|
TabUIHelper::From(browser->GetTabStripModel()->GetActiveTab())
|
|
->GetTitle(),
|
|
kContextMenuTabTitleMaxLength, &short_title);
|
|
return base::ReplaceStringPlaceholders(format_string, short_title, nullptr);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
WindowMatch::WindowMatch(BrowserWindowInterface* browser,
|
|
const std::u16string& title,
|
|
double score)
|
|
: browser(browser), title(title), score(score) {}
|
|
WindowMatch::~WindowMatch() = default;
|
|
WindowMatch::WindowMatch(WindowMatch&& other) = default;
|
|
WindowMatch& WindowMatch::operator=(WindowMatch&& other) = default;
|
|
|
|
std::unique_ptr<CommandItem> WindowMatch::ToCommandItem() const {
|
|
auto item = std::make_unique<CommandItem>(title, score, matched_ranges);
|
|
item->entity_type = CommandItem::Entity::kWindow;
|
|
return item;
|
|
}
|
|
|
|
GroupMatch::GroupMatch(tab_groups::TabGroupId group,
|
|
const std::u16string& title,
|
|
double score)
|
|
: group(group), title(title), score(score) {}
|
|
GroupMatch::~GroupMatch() = default;
|
|
GroupMatch::GroupMatch(GroupMatch&& other) = default;
|
|
GroupMatch& GroupMatch::operator=(GroupMatch&& other) = default;
|
|
|
|
std::unique_ptr<CommandItem> GroupMatch::ToCommandItem() const {
|
|
auto item = std::make_unique<CommandItem>(title, score, matched_ranges);
|
|
item->entity_type = CommandItem::Entity::kGroup;
|
|
return item;
|
|
}
|
|
|
|
TabMatch::TabMatch(int index,
|
|
int session_id,
|
|
const std::u16string& title,
|
|
double score)
|
|
: index(index), session_id(session_id), title(title), score(score) {}
|
|
TabMatch::~TabMatch() = default;
|
|
TabMatch::TabMatch(TabMatch&& other) = default;
|
|
TabMatch& TabMatch::operator=(TabMatch&& other) = default;
|
|
|
|
std::unique_ptr<CommandItem> TabMatch::ToCommandItem() const {
|
|
auto item = std::make_unique<CommandItem>(title, score, matched_ranges);
|
|
item->entity_type = CommandItem::Entity::kTab;
|
|
return item;
|
|
}
|
|
|
|
TabSearchOptions::TabSearchOptions() = default;
|
|
TabSearchOptions::~TabSearchOptions() = default;
|
|
|
|
std::vector<TabMatch> TabsMatchingInput(const BrowserWindowInterface* browser,
|
|
const std::u16string& input,
|
|
const TabSearchOptions& options) {
|
|
DCHECK(browser);
|
|
DCHECK(!(options.only_pinned && options.only_unpinned));
|
|
DCHECK(!(options.only_audible && options.only_muted));
|
|
DCHECK(!options.exclude_tab_group.has_value() ||
|
|
options.exclude_tab_group != options.only_tab_group);
|
|
double ordering_score = 1.0;
|
|
std::vector<TabMatch> results;
|
|
FuzzyFinder finder(input);
|
|
std::vector<gfx::Range> ranges;
|
|
const TabStripModel* tab_strip_model = browser->GetTabStripModel();
|
|
for (int i = 0; i < tab_strip_model->count(); ++i) {
|
|
if (tab_strip_model->IsTabPinned(i) ? options.only_unpinned
|
|
: options.only_pinned) {
|
|
continue;
|
|
}
|
|
content::WebContents* contents = tab_strip_model->GetWebContentsAt(i);
|
|
if (options.only_audible && !contents->IsCurrentlyAudible()) {
|
|
continue;
|
|
}
|
|
if (options.only_muted && !contents->IsAudioMuted()) {
|
|
continue;
|
|
}
|
|
auto group = tab_strip_model->GetTabGroupForTab(i);
|
|
if (options.only_tab_group.has_value() && options.only_tab_group != group) {
|
|
continue;
|
|
}
|
|
if (options.exclude_tab_group.has_value() &&
|
|
options.exclude_tab_group == group) {
|
|
continue;
|
|
}
|
|
|
|
auto title = contents->GetTitle();
|
|
if (input.empty()) {
|
|
TabMatch match(i, sessions::SessionTabHelper::IdForTab(contents).id(),
|
|
title, ordering_score);
|
|
results.push_back(std::move(match));
|
|
ordering_score *= .95;
|
|
} else {
|
|
double score = finder.Find(title, ranges);
|
|
if (score > 0) {
|
|
TabMatch match(i, sessions::SessionTabHelper::IdForTab(contents).id(),
|
|
title, score);
|
|
match.matched_ranges = ranges;
|
|
results.push_back(std::move(match));
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
std::vector<WindowMatch> WindowsMatchingInput(
|
|
const BrowserWindowInterface* browser_to_exclude,
|
|
const std::u16string& input,
|
|
bool match_profile) {
|
|
std::vector<WindowMatch> results;
|
|
double mru_score = .95;
|
|
FuzzyFinder finder(input);
|
|
std::vector<gfx::Range> ranges;
|
|
// TODO(https://github.com/brave/brave-browser/issues/49807): This code as a
|
|
// whole needs to be revisited with regards the use of `Browser*`.
|
|
ForEachCurrentBrowserWindowInterfaceOrderedByActivation(
|
|
[&](BrowserWindowInterface* browser_window_interface) {
|
|
Browser* browser =
|
|
browser_window_interface->GetBrowserForMigrationOnly();
|
|
if (browser == browser_to_exclude || !browser->is_type_normal()) {
|
|
return true; // continue iterating
|
|
}
|
|
if (match_profile &&
|
|
browser->profile() != browser_to_exclude->GetProfile()) {
|
|
return true; // continue iterating
|
|
}
|
|
std::u16string title =
|
|
browser->GetWindowTitleForMaxWidth(kMaxTitleWidth);
|
|
if (input.empty()) {
|
|
WindowMatch match(browser, title, mru_score);
|
|
results.push_back(std::move(match));
|
|
mru_score *= .95;
|
|
} else {
|
|
double score = finder.Find(title, ranges);
|
|
if (score > 0) {
|
|
WindowMatch match(browser, std::move(title), score);
|
|
match.matched_ranges = ranges;
|
|
results.push_back(std::move(match));
|
|
}
|
|
}
|
|
return true; // continue iterating
|
|
});
|
|
|
|
return results;
|
|
}
|
|
|
|
std::vector<GroupMatch> GroupsMatchingInput(
|
|
const BrowserWindowInterface* browser,
|
|
const std::u16string& input,
|
|
std::optional<tab_groups::TabGroupId> group_to_exclude) {
|
|
DCHECK(browser);
|
|
std::vector<GroupMatch> results;
|
|
FuzzyFinder finder(input);
|
|
std::vector<gfx::Range> ranges;
|
|
TabGroupModel* model = browser->GetTabStripModel()->group_model();
|
|
if (!model) {
|
|
return results;
|
|
}
|
|
// For empty input, use this to preserve TabGroupModel's ordering, which is
|
|
// arbitrary but still helpful to keep consistent across calls and surfaces.
|
|
double ordering_score = .95;
|
|
for (const tab_groups::TabGroupId& group_id : model->ListTabGroups()) {
|
|
if (group_to_exclude == group_id) {
|
|
continue;
|
|
}
|
|
TabGroup* group = model->GetTabGroup(group_id);
|
|
const std::u16string& group_title = group->visual_data()->title();
|
|
const std::u16string& title =
|
|
group_title.empty() ? GetContentString(browser, *group) : group_title;
|
|
if (input.empty()) {
|
|
GroupMatch match(group_id, title, ordering_score);
|
|
results.push_back(std::move(match));
|
|
ordering_score *= .95;
|
|
} else {
|
|
double score = finder.Find(title, ranges);
|
|
if (score > 0) {
|
|
GroupMatch match(group_id, title, score);
|
|
match.matched_ranges = ranges;
|
|
results.push_back(std::move(match));
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
} // namespace commander
|