blob: fae716604681f928f501f9579036bfdb5c3868fe [file] [log] [blame]
// Copyright 2023 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/ui/views/side_panel/search_companion/search_companion_side_panel_coordinator.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/side_panel/companion/companion_tab_helper.h"
#include "chrome/browser/ui/side_panel/companion/companion_utils.h"
#include "chrome/browser/ui/side_panel/side_panel_enums.h"
#include "chrome/browser/ui/side_panel/side_panel_ui.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
#include "chrome/browser/ui/views/side_panel/side_panel_registry.h"
#include "chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/vector_icons/vector_icons.h"
SearchCompanionSidePanelCoordinator::SearchCompanionSidePanelCoordinator(
Browser* browser)
: BrowserUserData<SearchCompanionSidePanelCoordinator>(*browser),
browser_(browser),
// TODO(b/269331995): Localize menu item label.
name_(l10n_util::GetStringUTF16(IDS_SIDE_PANEL_COMPANION_TITLE)),
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
icon_(vector_icons::kGoogleSuperGIcon),
disabled_icon_(vector_icons::kGoogleGLogoMonochromeIcon),
#else
icon_(vector_icons::kSearchIcon),
disabled_icon_(vector_icons::kSearchIcon),
#endif
pref_service_(browser->profile()->GetPrefs()) {
if (auto* template_url_service =
TemplateURLServiceFactory::GetForProfile(browser->profile())) {
template_url_service_observation_.Observe(template_url_service);
}
// Only start observing tab changes if google is the default search provider.
dsp_is_google_ = search::DefaultSearchProviderIsGoogle(browser_->profile());
csc_enabled_via_policy_ =
companion::IsCompanionFeatureEnabledByPolicy(pref_service_);
if (DoCompanionRuntimeChecksPass()) {
browser_->tab_strip_model()->AddObserver(this);
CreateAndRegisterEntriesForExistingWebContents(browser_->tab_strip_model());
}
pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
pref_change_registrar_->Init(pref_service_);
pref_change_registrar_->Add(
prefs::kGoogleSearchSidePanelEnabled,
base::BindRepeating(
&SearchCompanionSidePanelCoordinator::OnPolicyPrefChanged,
base::Unretained(this)));
}
SearchCompanionSidePanelCoordinator::~SearchCompanionSidePanelCoordinator() =
default;
// static
bool SearchCompanionSidePanelCoordinator::IsSupported(
Profile* profile,
bool include_runtime_checks) {
if (profile->IsIncognitoProfile() || profile->IsGuestSession()) {
return false;
}
if (include_runtime_checks) {
if (!search::DefaultSearchProviderIsGoogle(profile) ||
!companion::IsCompanionFeatureEnabledByPolicy(profile->GetPrefs())) {
return false;
}
}
return true;
}
bool SearchCompanionSidePanelCoordinator::Show(
SidePanelOpenTrigger side_panel_open_trigger) {
SidePanelUI::GetSidePanelUIForBrowser(&GetBrowser())
->Show(SidePanelEntry::Id::kSearchCompanion, side_panel_open_trigger);
return true;
}
BrowserView* SearchCompanionSidePanelCoordinator::GetBrowserView() const {
return BrowserView::GetBrowserViewForBrowser(&GetBrowser());
}
std::u16string SearchCompanionSidePanelCoordinator::GetTooltipForToolbarButton()
const {
return l10n_util::GetStringUTF16(IDS_SIDE_PANEL_COMPANION_TOOLBAR_TOOLTIP);
}
void SearchCompanionSidePanelCoordinator::NotifyCompanionOfSidePanelOpenTrigger(
absl::optional<SidePanelOpenTrigger> side_panel_open_trigger) {
auto* companion_tab_helper = companion::CompanionTabHelper::FromWebContents(
browser_->tab_strip_model()->GetActiveWebContents());
companion_tab_helper->SetMostRecentSidePanelOpenTrigger(
side_panel_open_trigger);
}
void SearchCompanionSidePanelCoordinator::OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) {
if (change.type() == TabStripModelChange::Type::kInserted) {
for (const auto& inserted_tab : change.GetInsert()->contents) {
companion::CompanionTabHelper::FromWebContents(inserted_tab.contents)
->CreateAndRegisterEntry();
}
}
if (selection.active_tab_changed()) {
MaybeUpdateCompanionEnabledState();
}
}
void SearchCompanionSidePanelCoordinator::TabChangedAt(
content::WebContents* contents,
int index,
TabChangeType change_type) {
MaybeUpdateCompanionEnabledState();
}
void SearchCompanionSidePanelCoordinator::
CreateAndRegisterEntriesForExistingWebContents(
TabStripModel* tab_strip_model) {
for (int index = 0; index < tab_strip_model->GetTabCount(); index++) {
companion::CompanionTabHelper::FromWebContents(
tab_strip_model->GetWebContentsAt(index))
->CreateAndRegisterEntry();
}
}
void SearchCompanionSidePanelCoordinator::
DeregisterEntriesForExistingWebContents(TabStripModel* tab_strip_model) {
for (int index = 0; index < tab_strip_model->GetTabCount(); index++) {
companion::CompanionTabHelper::FromWebContents(
tab_strip_model->GetWebContentsAt(index))
->DeregisterEntry();
}
}
void SearchCompanionSidePanelCoordinator::OnTemplateURLServiceChanged() {
bool was_csc_enabled = DoCompanionRuntimeChecksPass();
dsp_is_google_ = search::DefaultSearchProviderIsGoogle(browser_->profile());
if (was_csc_enabled == DoCompanionRuntimeChecksPass()) {
return;
}
UpdateCompanionAvailabilityInSidePanel();
}
void SearchCompanionSidePanelCoordinator::
UpdateCompanionAvailabilityInSidePanel() {
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
if (!browser_view) {
return;
}
SidePanelToolbarContainer* container =
browser_view->toolbar()->side_panel_container();
// Update existence of companion entry points based on changes.
if (DoCompanionRuntimeChecksPass()) {
container->AddPinnedEntryButtonFor(SidePanelEntry::Id::kSearchCompanion,
name(), icon());
browser_->tab_strip_model()->AddObserver(this);
CreateAndRegisterEntriesForExistingWebContents(browser_->tab_strip_model());
} else {
container->RemovePinnedEntryButtonFor(SidePanelEntry::Id::kSearchCompanion);
browser_->tab_strip_model()->RemoveObserver(this);
DeregisterEntriesForExistingWebContents(browser_->tab_strip_model());
}
}
void SearchCompanionSidePanelCoordinator::MaybeUpdateCompanionEnabledState() {
bool enabled = companion::IsCompanionAvailableForCurrentActiveTab(browser_);
MaybeUpdatePinnedButtonEnabledState(enabled);
MaybeUpdateComboboxEntryEnabledState(enabled);
}
void SearchCompanionSidePanelCoordinator::MaybeUpdatePinnedButtonEnabledState(
bool enabled) {
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
if (!browser_view) {
return;
}
SidePanelToolbarContainer* container =
browser_view->toolbar()->side_panel_container();
if (container && container->IsPinned(SidePanelEntry::Id::kSearchCompanion)) {
ToolbarButton& button =
container->GetPinnedButtonForId(SidePanelEntry::Id::kSearchCompanion);
button.SetEnabled(enabled);
button.SetVectorIcon(enabled ? icon() : disabled_icon());
}
}
void SearchCompanionSidePanelCoordinator::MaybeUpdateComboboxEntryEnabledState(
bool enabled) {
auto* registry = SidePanelRegistry::Get(
browser_->tab_strip_model()->GetActiveWebContents());
if (!registry) {
return;
}
auto* entry = registry->GetEntryForKey(
SidePanelEntry::Key(SidePanelEntry::Id::kSearchCompanion));
if (!entry) {
return;
}
entry->ResetIcon(ui::ImageModel::FromVectorIcon(
(enabled ? icon() : disabled_icon()), ui::kColorIcon,
/*icon_size=*/16));
}
void SearchCompanionSidePanelCoordinator::OnTemplateURLServiceShuttingDown() {
template_url_service_observation_.Reset();
}
void SearchCompanionSidePanelCoordinator::OnPolicyPrefChanged() {
if (!pref_service_) {
return;
}
bool was_csc_enabled = DoCompanionRuntimeChecksPass();
csc_enabled_via_policy_ =
companion::IsCompanionFeatureEnabledByPolicy(pref_service_);
if (was_csc_enabled == DoCompanionRuntimeChecksPass()) {
return;
}
UpdateCompanionAvailabilityInSidePanel();
}
bool SearchCompanionSidePanelCoordinator::DoCompanionRuntimeChecksPass() const {
return dsp_is_google_ && csc_enabled_via_policy_;
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(SearchCompanionSidePanelCoordinator);