blob: a99b0fa37b2b25ef248c8edc0ec3a8806752bd9f [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/glic/host/context/glic_delegating_sharing_manager.h"
#include "base/callback_list.h"
namespace glic {
GlicDelegatingSharingManager::GlicDelegatingSharingManager() = default;
GlicDelegatingSharingManager::~GlicDelegatingSharingManager() = default;
base::CallbackListSubscription
GlicDelegatingSharingManager::AddFocusedTabChangedCallback(
FocusedTabChangedCallback callback) {
return focused_tab_changed_callback_list_.Add(std::move(callback));
}
base::CallbackListSubscription
GlicDelegatingSharingManager::AddTabPinningStatusChangedCallback(
TabPinningStatusChangedCallback callback) {
return tab_pinning_status_changed_callback_list_.Add(std::move(callback));
}
FocusedTabData GlicDelegatingSharingManager::GetFocusedTabData() {
return sharing_manager_delegate_
? sharing_manager_delegate_->GetFocusedTabData()
: FocusedTabData(std::string("no focusable tab"), nullptr);
}
bool GlicDelegatingSharingManager::PinTabs(
base::span<const tabs::TabHandle> tab_handles) {
return sharing_manager_delegate_
? sharing_manager_delegate_->PinTabs(tab_handles)
: false;
}
bool GlicDelegatingSharingManager::UnpinTabs(
base::span<const tabs::TabHandle> tab_handles) {
return sharing_manager_delegate_
? sharing_manager_delegate_->UnpinTabs(tab_handles)
: false;
}
void GlicDelegatingSharingManager::UnpinAllTabs() {
if (sharing_manager_delegate_) {
sharing_manager_delegate_->UnpinAllTabs();
}
}
int32_t GlicDelegatingSharingManager::GetMaxPinnedTabs() const {
return sharing_manager_delegate_
? sharing_manager_delegate_->GetMaxPinnedTabs()
: 0;
}
int32_t GlicDelegatingSharingManager::GetNumPinnedTabs() const {
return sharing_manager_delegate_
? sharing_manager_delegate_->GetNumPinnedTabs()
: 0;
}
bool GlicDelegatingSharingManager::IsTabPinned(
tabs::TabHandle tab_handle) const {
return sharing_manager_delegate_
? sharing_manager_delegate_->IsTabPinned(tab_handle)
: false;
}
base::CallbackListSubscription
GlicDelegatingSharingManager::AddFocusedBrowserChangedCallback(
FocusedBrowserChangedCallback callback) {
return focused_browser_changed_callback_list_.Add(std::move(callback));
}
BrowserWindowInterface* GlicDelegatingSharingManager::GetFocusedBrowser()
const {
return sharing_manager_delegate_
? sharing_manager_delegate_->GetFocusedBrowser()
: nullptr;
}
GlicFocusedBrowserManagerInterface&
GlicDelegatingSharingManager::focused_browser_manager() {
// Exposing this directly would break delegation strategy.
// TODO(b:444463509): remove direct manager access from the interface.
NOTREACHED();
}
base::CallbackListSubscription
GlicDelegatingSharingManager::AddFocusedTabDataChangedCallback(
FocusedTabDataChangedCallback callback) {
return focused_tab_data_changed_callback_list_.Add(std::move(callback));
}
base::CallbackListSubscription
GlicDelegatingSharingManager::AddPinnedTabsChangedCallback(
PinnedTabsChangedCallback callback) {
return pinned_tabs_changed_callback_list_.Add(std::move(callback));
}
base::CallbackListSubscription
GlicDelegatingSharingManager::AddPinnedTabDataChangedCallback(
PinnedTabDataChangedCallback callback) {
return pinned_tab_data_changed_callback_list_.Add(std::move(callback));
}
int32_t GlicDelegatingSharingManager::SetMaxPinnedTabs(
uint32_t max_pinned_tabs) {
return sharing_manager_delegate_
? sharing_manager_delegate_->SetMaxPinnedTabs(max_pinned_tabs)
: 0;
}
void GlicDelegatingSharingManager::GetContextFromTab(
tabs::TabHandle tab_handle,
const mojom::GetTabContextOptions& options,
base::OnceCallback<void(GlicGetContextResult)> callback) {
if (!sharing_manager_delegate_) {
std::move(callback).Run(base::unexpected(
GlicGetContextError{GlicGetContextFromTabError::kPageContextNotEligible,
"tab not eligible"}));
return;
}
sharing_manager_delegate_->GetContextFromTab(tab_handle, options,
std::move(callback));
}
void GlicDelegatingSharingManager::GetContextForActorFromTab(
tabs::TabHandle tab_handle,
const mojom::GetTabContextOptions& options,
base::OnceCallback<void(GlicGetContextResult)> callback) {
if (!sharing_manager_delegate_) {
std::move(callback).Run(base::unexpected(
GlicGetContextError{GlicGetContextFromTabError::kPageContextNotEligible,
"tab not eligible"}));
return;
}
sharing_manager_delegate_->GetContextForActorFromTab(tab_handle, options,
std::move(callback));
}
std::vector<content::WebContents*> GlicDelegatingSharingManager::GetPinnedTabs()
const {
return sharing_manager_delegate_ ? sharing_manager_delegate_->GetPinnedTabs()
: std::vector<content::WebContents*>{};
}
void GlicDelegatingSharingManager::SubscribeToPinCandidates(
mojom::GetPinCandidatesOptionsPtr options,
mojo::PendingRemote<mojom::PinCandidatesObserver> observer) {
// TODO(b:444463509): support dynamic subscription streaming for handling
// per-instance sharing manager delegation (e.g. attach/detach).
NOTREACHED();
}
base::WeakPtr<GlicSharingManager> GlicDelegatingSharingManager::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
void GlicDelegatingSharingManager::SetDelegate(
base::WeakPtr<GlicSharingManager> sharing_manager_delegate) {
// Do nothing if the delegate hasn't changed.
if (!sharing_manager_delegate_.WasInvalidated() &&
sharing_manager_delegate.get() == sharing_manager_delegate_.get()) {
return;
}
// Grab currently pinned tabs before swapping delegate so we can fire pinned
// status updates on them.
auto old_pinned_tabs = GetPinnedTabs();
sharing_manager_delegate_ = sharing_manager_delegate;
RefreshDelegateSubscriptions();
ForceNotify(old_pinned_tabs);
}
void GlicDelegatingSharingManager::OnFocusedTabChangedCallback(
const FocusedTabData& focused_tab_data) {
focused_tab_changed_callback_list_.Notify(focused_tab_data);
}
void GlicDelegatingSharingManager::OnFocusedTabDataChangedCallback(
const mojom::TabData* focused_tab_data) {
focused_tab_data_changed_callback_list_.Notify(focused_tab_data);
}
void GlicDelegatingSharingManager::OnFocusedBrowserChangedCallback(
BrowserWindowInterface* browser_window) {
focused_browser_changed_callback_list_.Notify(browser_window);
}
void GlicDelegatingSharingManager::OnTabPinningStatusChangedCallback(
tabs::TabInterface* tab,
bool pinned) {
tab_pinning_status_changed_callback_list_.Notify(tab, pinned);
}
void GlicDelegatingSharingManager::OnPinnedTabsChangedCallback(
const std::vector<content::WebContents*>& pinned_tabs) {
pinned_tabs_changed_callback_list_.Notify(pinned_tabs);
}
void GlicDelegatingSharingManager::OnPinnedTabDataChangedCallback(
const TabDataChange& tab_data_change) {
pinned_tab_data_changed_callback_list_.Notify(tab_data_change);
}
void GlicDelegatingSharingManager::ResetDelegateSubscriptions() {
focused_tab_changed_callback_ = {};
focused_tab_data_changed_callback_ = {};
focused_browser_changed_callback_ = {};
tab_pinning_status_changed_callback_ = {};
pinned_tabs_changed_callback_ = {};
pinned_tab_data_changed_callback_ = {};
}
void GlicDelegatingSharingManager::RefreshDelegateSubscriptions() {
if (!sharing_manager_delegate_) {
ResetDelegateSubscriptions();
return;
}
focused_tab_changed_callback_ =
sharing_manager_delegate_->AddFocusedTabChangedCallback(
base::BindRepeating(
&GlicDelegatingSharingManager::OnFocusedTabChangedCallback,
base::Unretained(this)));
focused_tab_data_changed_callback_ =
sharing_manager_delegate_->AddFocusedTabDataChangedCallback(
base::BindRepeating(
&GlicDelegatingSharingManager::OnFocusedTabDataChangedCallback,
base::Unretained(this)));
focused_browser_changed_callback_ =
sharing_manager_delegate_->AddFocusedBrowserChangedCallback(
base::BindRepeating(
&GlicDelegatingSharingManager::OnFocusedBrowserChangedCallback,
base::Unretained(this)));
tab_pinning_status_changed_callback_ =
sharing_manager_delegate_->AddTabPinningStatusChangedCallback(
base::BindRepeating(
&GlicDelegatingSharingManager::OnTabPinningStatusChangedCallback,
base::Unretained(this)));
pinned_tabs_changed_callback_ =
sharing_manager_delegate_->AddPinnedTabsChangedCallback(
base::BindRepeating(
&GlicDelegatingSharingManager::OnPinnedTabsChangedCallback,
base::Unretained(this)));
pinned_tab_data_changed_callback_ =
sharing_manager_delegate_->AddPinnedTabDataChangedCallback(
base::BindRepeating(
&GlicDelegatingSharingManager::OnPinnedTabDataChangedCallback,
base::Unretained(this)));
}
void GlicDelegatingSharingManager::ForceNotify(
const std::vector<content::WebContents*>& old_pinned_tabs) {
for (auto* tab : old_pinned_tabs) {
tab_pinning_status_changed_callback_list_.Notify(
tabs::TabInterface::GetFromContents(tab), false);
}
for (auto* tab : GetPinnedTabs()) {
tab_pinning_status_changed_callback_list_.Notify(
tabs::TabInterface::GetFromContents(tab), true);
}
// Note: in the case where delegate is now null, we still want to fire these
// (with empty arguments).
focused_tab_changed_callback_list_.Notify(GetFocusedTabData());
focused_browser_changed_callback_list_.Notify(GetFocusedBrowser());
pinned_tabs_changed_callback_list_.Notify(GetPinnedTabs());
}
} // namespace glic