blob: 8addf08eeaf43bc996f812368b78ed1a75534f63 [file] [log] [blame]
// Copyright 2022 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/side_panel_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/strings/strcat.h"
#include "chrome/browser/companion/core/features.h"
#include "chrome/browser/history_clusters/history_clusters_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/side_panel/bookmarks/bookmarks_side_panel_coordinator.h"
#include "chrome/browser/ui/views/side_panel/feed/feed_side_panel_coordinator.h"
#include "chrome/browser/ui/views/side_panel/history_clusters/history_clusters_side_panel_coordinator.h"
#include "chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.h"
#include "chrome/browser/ui/views/side_panel/reading_list/reading_list_side_panel_coordinator.h"
#include "chrome/browser/ui/views/side_panel/search_companion/search_companion_side_panel_coordinator.h"
#include "chrome/browser/ui/views/side_panel/side_panel_content_proxy.h"
#include "chrome/browser/ui/views/side_panel/side_panel_registry.h"
#include "chrome/browser/ui/views/side_panel/user_note/user_note_ui_coordinator.h"
#include "components/feed/feed_feature_list.h"
#include "components/history_clusters/core/features.h"
#include "components/history_clusters/core/history_clusters_service.h"
#include "components/prefs/pref_service.h"
#include "components/user_notes/user_notes_features.h"
#include "ui/accessibility/accessibility_features.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/ui/views/side_panel/extensions/extension_side_panel_manager.h"
#include "extensions/common/extension_features.h"
#endif
namespace {
std::string GetHistogramNameForId(SidePanelEntry::Id id) {
static constexpr auto id_to_histogram_name_map =
// Note: once provided the histogram name should not be changed since it
// is persisted to logs. When adding a new Id please add actions to
// tools/metrics/actions/actions.xml for "SidePanel.[new id name].Shown"
// since we cannot autogenerate this in actions.xml.
base::MakeFixedFlatMap<SidePanelEntry::Id, const char*>(
{{SidePanelEntry::Id::kReadingList, "ReadingList"},
{SidePanelEntry::Id::kBookmarks, "Bookmarks"},
{SidePanelEntry::Id::kHistoryClusters, "HistoryClusters"},
{SidePanelEntry::Id::kReadAnything, "ReadAnything"},
{SidePanelEntry::Id::kUserNote, "UserNotes"},
{SidePanelEntry::Id::kFeed, "Feed"},
{SidePanelEntry::Id::kSideSearch, "SideSearch"},
{SidePanelEntry::Id::kLens, "Lens"},
{SidePanelEntry::Id::kAssistant, "Assistant"},
{SidePanelEntry::Id::kAboutThisSite, "AboutThisSite"},
{SidePanelEntry::Id::kCustomizeChrome, "CustomizeChrome"},
{SidePanelEntry::Id::kWebView, "WebView"},
{SidePanelEntry::Id::kSearchCompanion, "Companion"},
{SidePanelEntry::Id::kExtension, "Extension"}});
auto* i = id_to_histogram_name_map.find(id);
DCHECK(i != id_to_histogram_name_map.cend());
return {i->second};
}
} // namespace
// static
void SidePanelUtil::PopulateGlobalEntries(Browser* browser,
SidePanelRegistry* global_registry) {
// Add reading list.
ReadingListSidePanelCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(global_registry);
// Add bookmarks.
BookmarksSidePanelCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(global_registry);
// Add history clusters.
if (HistoryClustersSidePanelCoordinator::IsSupported(browser->profile())) {
HistoryClustersSidePanelCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(global_registry);
}
// Add read anything.
if (features::IsReadAnythingEnabled()) {
ReadAnythingCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(global_registry);
}
// Create Search Companion coordinator.
if (base::FeatureList::IsEnabled(companion::features::kSidePanelCompanion) &&
SearchCompanionSidePanelCoordinator::IsSupported(
browser->profile(), /*include_dsp_check=*/false)) {
SearchCompanionSidePanelCoordinator::GetOrCreateForBrowser(browser);
}
// Add user notes.
if (user_notes::IsUserNotesEnabled()) {
UserNoteUICoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(global_registry);
}
// Add feed.
if (base::FeatureList::IsEnabled(feed::kWebUiFeed)) {
feed::FeedSidePanelCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(global_registry);
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
if (base::FeatureList::IsEnabled(
extensions_features::kExtensionSidePanelIntegration)) {
extensions::ExtensionSidePanelManager::GetOrCreateForBrowser(browser);
}
#endif
return;
}
SidePanelContentProxy* SidePanelUtil::GetSidePanelContentProxy(
views::View* content_view) {
if (!content_view->GetProperty(kSidePanelContentProxyKey))
content_view->SetProperty(
kSidePanelContentProxyKey,
std::make_unique<SidePanelContentProxy>(true).release());
return content_view->GetProperty(kSidePanelContentProxyKey);
}
std::unique_ptr<views::View> SidePanelUtil::DeregisterAndReturnView(
SidePanelRegistry* registry,
SidePanelEntry::Key key) {
std::unique_ptr<SidePanelEntry> entry =
registry->DeregisterAndReturnEntry(key);
return entry->CachedView() ? entry->GetContent() : nullptr;
}
void SidePanelUtil::RecordSidePanelOpen(
absl::optional<SidePanelUtil::SidePanelOpenTrigger> trigger) {
base::RecordAction(base::UserMetricsAction("SidePanel.Show"));
if (trigger.has_value())
base::UmaHistogramEnumeration("SidePanel.OpenTrigger", trigger.value());
}
void SidePanelUtil::RecordSidePanelClosed(base::TimeTicks opened_timestamp) {
base::RecordAction(base::UserMetricsAction("SidePanel.Hide"));
base::UmaHistogramLongTimes("SidePanel.OpenDuration",
base::TimeTicks::Now() - opened_timestamp);
}
void SidePanelUtil::RecordSidePanelResizeMetrics(SidePanelEntry::Id id,
int side_panel_contents_width,
int browser_window_width) {
std::string entry_name = GetHistogramNameForId(id);
// Metrics per-id and overall for side panel width after resize.
base::UmaHistogramCounts10000(
base::StrCat({"SidePanel.", entry_name, ".ResizedWidth"}),
side_panel_contents_width);
base::UmaHistogramCounts10000("SidePanel.ResizedWidth",
side_panel_contents_width);
// Metrics per-id and overall for side panel width after resize as a
// percentage of browser width.
int width_percentage = side_panel_contents_width * 100 / browser_window_width;
base::UmaHistogramPercentage(
base::StrCat({"SidePanel.", entry_name, ".ResizedWidthPercentage"}),
width_percentage);
base::UmaHistogramPercentage("SidePanel.ResizedWidthPercentage",
width_percentage);
}
void SidePanelUtil::RecordNewTabButtonClicked(SidePanelEntry::Id id) {
base::RecordComputedAction(base::StrCat(
{"SidePanel.", GetHistogramNameForId(id), ".NewTabButtonClicked"}));
}
void SidePanelUtil::RecordEntryShownMetrics(SidePanelEntry::Id id) {
base::RecordComputedAction(
base::StrCat({"SidePanel.", GetHistogramNameForId(id), ".Shown"}));
}
void SidePanelUtil::RecordEntryHiddenMetrics(SidePanelEntry::Id id,
base::TimeTicks shown_timestamp) {
base::UmaHistogramLongTimes(
base::StrCat({"SidePanel.", GetHistogramNameForId(id), ".ShownDuration"}),
base::TimeTicks::Now() - shown_timestamp);
}
void SidePanelUtil::RecordEntryShowTriggeredMetrics(
Browser* browser,
SidePanelEntry::Id id,
absl::optional<SidePanelUtil::SidePanelOpenTrigger> trigger) {
if (trigger.has_value()) {
base::UmaHistogramEnumeration(
base::StrCat(
{"SidePanel.", GetHistogramNameForId(id), ".ShowTriggered"}),
trigger.value());
}
if (id == SidePanelEntry::Id::kSearchCompanion) {
auto* search_companion_coordinator =
SearchCompanionSidePanelCoordinator::GetOrCreateForBrowser(browser);
search_companion_coordinator->NotifyCompanionOfSidePanelOpenTrigger(
trigger);
}
}