0

[TabRestore] Rewrite BrowserLiveTabContext::AddRestoredTab

AddRestoredTab does not take into account the context for which we are
restoring a tab. This change makes it so we know if the tab being
restored is by itself, or restored alongside other tabs within its
group or window.

This change is necessary to prevent tab duplication for saved groups as
we want SavedTabGroups to be the source of truth for restored groups.

Tab duplication was happening anytime there was a conflict between the
SavedTabGroup and the tab group persisted in TabRestore.

Now we only rely on the SavedTabGroup if we have one.

Change-Id: I6266e63f281832341a2b2cdc96de727f20b22882
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6381720
Reviewed-by: Eshwar Stalin <estalin@chromium.org>
Reviewed-by: Gauthier Ambard <gambard@chromium.org>
Commit-Queue: Darryl James <dljames@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1438261}
This commit is contained in:
dljames
2025-03-26 11:03:50 -07:00
committed by Chromium LUCI CQ
parent c63241596d
commit 624e0e97d3
13 changed files with 88 additions and 66 deletions

@ -75,9 +75,13 @@ class SESSIONS_EXPORT LiveTabContext {
// has been created by TabRestoreService.
// |original_session_type| indicates the type of session entry the tab
// belongs to.
// |restored_from_group_or_window_context| when true indicates if the tab we
// are restoring is part of a window or group which is trying to restore all
// of its tabs.
virtual LiveTab* AddRestoredTab(const tab_restore::Tab& tab,
int tab_index,
bool select,
bool restored_from_group_or_window_context,
tab_restore::Type original_session_type) = 0;
// Note: |tab.platform_data| may be null (e.g., if restoring from last session

@ -71,8 +71,9 @@ void AddSerializedNavigationEntries(
const int delta =
(behavior == AddBehavior::kCurrentAndPreceedingEntries) ? -1 : 1;
int current_index = live_tab->GetCurrentEntryIndex();
if (behavior == AddBehavior::kEntriesFollowingCurrentEntry)
if (behavior == AddBehavior::kEntriesFollowingCurrentEntry) {
++current_index;
}
int added_count = 0;
while (current_index >= 0 && current_index < max_index &&
added_count <= gMaxPersistNavigationCount) {
@ -147,8 +148,9 @@ void TabRestoreServiceHelper::SetHelperObserver(Observer* observer) {
}
TabRestoreServiceHelper::~TabRestoreServiceHelper() {
for (auto& observer : observer_list_)
for (auto& observer : observer_list_) {
observer.TabRestoreServiceDestroyed(tab_restore_service_);
}
base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
this);
}
@ -193,8 +195,9 @@ std::optional<SessionID> TabRestoreServiceHelper::CreateHistoricalTab(
auto local_tab = std::make_unique<Tab>();
PopulateTab(local_tab.get(), index, context, live_tab);
if (local_tab->navigations.empty())
if (local_tab->navigations.empty()) {
return std::nullopt;
}
SessionID id = local_tab->id;
AddEntry(std::move(local_tab), true, true);
@ -472,7 +475,8 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTabOrGroupFromWindow(
restored_tab_browser_id = tab.browser_id;
LiveTab* restored_tab = nullptr;
context = RestoreTab(tab, context, disposition,
sessions::tab_restore::WINDOW, &restored_tab);
sessions::tab_restore::WINDOW, &restored_tab,
/*restored_from_group_or_window_context=*/false);
live_tabs->push_back(restored_tab);
std::optional<tab_groups::TabGroupId> group_id = tab.group;
@ -521,9 +525,9 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTabOrGroupFromWindow(
// Restore the tab.
LiveTab* restored_tab = nullptr;
LiveTabContext* new_context =
RestoreTab(tab, context, disposition, sessions::tab_restore::WINDOW,
&restored_tab);
LiveTabContext* new_context = RestoreTab(
tab, context, disposition, sessions::tab_restore::WINDOW,
&restored_tab, /*restored_from_group_or_window_context=*/true);
if (tab_i != 0) {
// CHECK that the context should be the same except for the first tab.
DCHECK_EQ(new_context, context);
@ -623,8 +627,8 @@ std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById(
}
LiveTab* restored_tab = nullptr;
context =
RestoreTab(tab, context, disposition, entry.type, &restored_tab);
context = RestoreTab(tab, context, disposition, entry.type, &restored_tab,
/*restored_from_group_or_window_context=*/false);
live_tabs.push_back(restored_tab);
context->ShowBrowserWindow();
break;
@ -668,7 +672,8 @@ std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById(
for (const auto& tab : window.tabs) {
const bool select_tab = tab->id == selected_tab_id;
LiveTab* restored_tab = context->AddRestoredTab(
*tab.get(), context->GetTabCount(), select_tab, entry.type);
*tab.get(), context->GetTabCount(), select_tab,
/*restored_from_group_or_window_context=*/true, entry.type);
if (restored_tab) {
client_->OnTabRestored(
@ -730,7 +735,7 @@ std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById(
for (const auto& tab : group.tabs) {
LiveTab* restored_tab = context->AddRestoredTab(
*tab.get(), context->GetTabCount(), group.tabs[0]->id == tab->id,
entry.type);
/*restored_from_group_or_window_context=*/true, entry.type);
live_tabs.push_back(restored_tab);
}
} else {
@ -740,8 +745,9 @@ std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById(
const Tab& tab = *group.tabs[i];
if (tab.id == id) {
LiveTab* restored_tab = nullptr;
context = RestoreTab(tab, context, disposition, entry.type,
&restored_tab);
context =
RestoreTab(tab, context, disposition, entry.type, &restored_tab,
/*restored_from_group_or_window_context=*/false);
live_tabs.push_back(restored_tab);
CHECK(ValidateGroup(group));
group.tabs.erase(group.tabs.begin() + i);
@ -779,13 +785,15 @@ bool TabRestoreServiceHelper::IsRestoring() const {
}
void TabRestoreServiceHelper::NotifyEntriesChanged() {
for (auto& observer : observer_list_)
for (auto& observer : observer_list_) {
observer.TabRestoreServiceChanged(tab_restore_service_);
}
}
void TabRestoreServiceHelper::NotifyLoaded() {
for (auto& observer : observer_list_)
for (auto& observer : observer_list_) {
observer.TabRestoreServiceLoaded(tab_restore_service_);
}
}
void TabRestoreServiceHelper::AddEntry(std::unique_ptr<Entry> entry,
@ -993,7 +1001,8 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTab(
LiveTabContext* context,
WindowOpenDisposition disposition,
sessions::tab_restore::Type session_restore_type,
LiveTab** live_tab) {
LiveTab** live_tab,
bool restored_from_group_or_window_context) {
LiveTab* restored_tab;
if (disposition == WindowOpenDisposition::CURRENT_TAB && context) {
restored_tab = context->ReplaceRestoredTab(tab);
@ -1043,7 +1052,7 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTab(
restored_tab = context->AddRestoredTab(
tab, tab_index,
/*select=*/disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB,
session_restore_type);
restored_from_group_or_window_context, session_restore_type);
}
client_->OnTabRestored(

@ -173,7 +173,8 @@ class SESSIONS_EXPORT TabRestoreServiceHelper
LiveTabContext* context,
WindowOpenDisposition disposition,
sessions::tab_restore::Type session_restore_type,
LiveTab** live_tab);
LiveTab** live_tab,
bool restored_from_group_or_window_context);
// This is a helper function for RestoreEntryById(). Restores a single entry
// from the `window`. The entry to restore is denoted by `id` and can either