blob: f70a53f2bf7559784add6a557c3c0ab971e95c5c [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_sharing_utils.h"
#include <vector>
#include "base/containers/contains.h"
#include "base/no_destructor.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.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/common/webui_url_constants.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"
#include "url/url_constants.h"
namespace glic {
bool IsBrowserValidForSharingInProfile(
BrowserWindowInterface* browser_interface,
Profile* profile) {
return browser_interface && profile &&
browser_interface->GetProfile() == profile &&
!profile->IsOffTheRecord();
}
bool IsTabValidForSharing(content::WebContents* web_contents) {
// We allow allow blank pages to avoid flicker during transitions.
static const base::NoDestructor<std::vector<GURL>> kUrlAllowList{
{GURL(), GURL(url::kAboutBlankURL),
GURL(chrome::kChromeUINewTabPageThirdPartyURL),
GURL(chrome::kChromeUINewTabPageURL), GURL(chrome::kChromeUINewTabURL),
GURL(chrome::kChromeUIWhatsNewURL)}};
if (!web_contents) {
return false;
}
const GURL& url = web_contents->GetLastCommittedURL();
return url.SchemeIsHTTPOrHTTPS() || url.SchemeIsFile() ||
base::Contains(*kUrlAllowList, url);
}
GlicActiveTabForProfileTracker::GlicActiveTabForProfileTracker(Profile* profile)
: active_tab_changed_callback_list_(), profile_(profile) {
BrowserList::AddObserver(this);
// If we already have an active browser, set up active tab subscription.
UpdateActiveTabSubscription(
GetLastActiveBrowserWindowInterfaceWithAnyProfile());
// Trigger an update now, even though we have no subscribers, so that
// GetActiveTab works correctly.
UpdateActiveTab();
}
GlicActiveTabForProfileTracker::~GlicActiveTabForProfileTracker() {
BrowserList::RemoveObserver(this);
}
bool GlicActiveTabForProfileTracker::IsBrowserActiveForProfile(
BrowserWindowInterface* browser) {
return browser && browser->GetProfile() == profile_ && browser->IsActive();
}
void GlicActiveTabForProfileTracker::UpdateActiveTabSubscription(
BrowserWindowInterface* browser) {
if (IsBrowserActiveForProfile(browser)) {
active_tab_subscription_ = browser->RegisterActiveTabDidChange(
base::BindRepeating(&GlicActiveTabForProfileTracker::OnActiveTabChanged,
base::Unretained(this)));
} else {
active_tab_subscription_ = {};
}
}
void GlicActiveTabForProfileTracker::OnBrowserSetLastActive(Browser* browser) {
UpdateActiveTabSubscription(browser);
UpdateActiveTab();
}
void GlicActiveTabForProfileTracker::OnBrowserNoLongerActive(Browser* browser) {
active_tab_subscription_ = {};
UpdateActiveTab();
}
void GlicActiveTabForProfileTracker::OnActiveTabChanged(
BrowserWindowInterface* browser) {
UpdateActiveTab();
}
void GlicActiveTabForProfileTracker::UpdateActiveTab() {
tabs::TabInterface* active_tab = nullptr;
BrowserWindowInterface* const browser =
GetLastActiveBrowserWindowInterfaceWithAnyProfile();
if (IsBrowserActiveForProfile(browser)) {
active_tab = browser->GetActiveTabInterface();
}
if (last_notified_tab_.WasInvalidated() ||
last_notified_tab_.get() != active_tab) {
last_notified_tab_ = active_tab ? active_tab->GetWeakPtr()
: base::WeakPtr<tabs::TabInterface>();
NotifyActiveTabChanged(last_notified_tab_.get());
}
}
base::CallbackListSubscription
GlicActiveTabForProfileTracker::AddActiveTabChangedCallback(
base::RepeatingCallback<void(tabs::TabInterface*)> callback) {
return active_tab_changed_callback_list_.Add(std::move(callback));
}
tabs::TabInterface* GlicActiveTabForProfileTracker::GetActiveTab() const {
return last_notified_tab_.get();
}
void GlicActiveTabForProfileTracker::NotifyActiveTabChanged(
tabs::TabInterface* active_tab) {
active_tab_changed_callback_list_.Notify(active_tab);
}
} // namespace glic