blob: 933ca51ccd4bcc25e831dd97fc0133748546fb2c [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 "base/time/time.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/browser_window/public/browser_window_features.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/companion/companion_utils.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_coordinator.h"
#include "chrome/browser/ui/views/side_panel/side_panel_registry.h"
#include "chrome/browser/ui/views/side_panel/side_panel_ui.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"
#include "ui/actions/actions.h"
#include "chrome/browser/ui/views/side_panel/extensions/extension_side_panel_manager.h"
#include "extensions/common/extension_features.h"
DEFINE_UI_CLASS_PROPERTY_TYPE(SidePanelContentState)
DEFINE_UI_CLASS_PROPERTY_KEY(std::underlying_type_t<SidePanelContentState>,
kSidePanelContentStateKey,
std::underlying_type_t<SidePanelContentState>(
SidePanelContentState::kReadyToShow))
// static
void SidePanelUtil::PopulateGlobalEntries(Browser* browser,
SidePanelRegistry* window_registry) {
// Add reading list.
ReadingListSidePanelCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(window_registry);
// Add bookmarks.
BookmarksSidePanelCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(window_registry);
// Add history clusters.
if (HistoryClustersSidePanelCoordinator::IsSupported(browser->profile())) {
HistoryClustersSidePanelCoordinator::GetOrCreateForBrowser(browser)
->CreateAndRegisterEntry(window_registry);
}
// Create Search Companion coordinator.
// Disable runtime checks so that coordinator can monitor the runtime changes
// in the availability of companion.
if (companion::IsCompanionFeatureEnabled() &&
SearchCompanionSidePanelCoordinator::IsSupported(
browser->profile(),
/*include_runtime_checks=*/false)) {
SearchCompanionSidePanelCoordinator::GetOrCreateForBrowser(browser);
}
if (base::FeatureList::IsEnabled(
extensions_features::kExtensionSidePanelIntegration)) {
extensions::ExtensionSidePanelManager::CreateForBrowser(browser,
window_registry);
}
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(
std::optional<SidePanelUtil::SidePanelOpenTrigger> trigger) {
base::RecordAction(base::UserMetricsAction("SidePanel.Show"));
if (trigger.has_value()) {
base::UmaHistogramEnumeration("SidePanel.OpenTrigger", trigger.value());
}
}
void SidePanelUtil::RecordSidePanelShowOrChangeEntryTrigger(
std::optional<SidePanelUtil::SidePanelOpenTrigger> trigger) {
if (trigger.has_value()) {
base::UmaHistogramEnumeration("SidePanel.OpenOrChangeEntryTrigger",
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 = SidePanelEntryIdToHistogramName(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.", SidePanelEntryIdToHistogramName(id),
".NewTabButtonClicked"}));
}
void SidePanelUtil::RecordEntryShownMetrics(
SidePanelEntry::Id id,
base::TimeTicks load_started_timestamp) {
base::RecordComputedAction(base::StrCat(
{"SidePanel.", SidePanelEntryIdToHistogramName(id), ".Shown"}));
if (load_started_timestamp != base::TimeTicks()) {
base::UmaHistogramLongTimes(
base::StrCat({"SidePanel.", SidePanelEntryIdToHistogramName(id),
".TimeFromEntryTriggerToShown"}),
base::TimeTicks::Now() - load_started_timestamp);
}
}
void SidePanelUtil::RecordEntryHiddenMetrics(SidePanelEntry::Id id,
base::TimeTicks shown_timestamp) {
base::UmaHistogramLongTimes(
base::StrCat({"SidePanel.", SidePanelEntryIdToHistogramName(id),
".ShownDuration"}),
base::TimeTicks::Now() - shown_timestamp);
}
void SidePanelUtil::RecordEntryShowTriggeredMetrics(
Browser* browser,
SidePanelEntry::Id id,
std::optional<SidePanelUtil::SidePanelOpenTrigger> trigger) {
if (trigger.has_value()) {
base::UmaHistogramEnumeration(
base::StrCat({"SidePanel.", SidePanelEntryIdToHistogramName(id),
".ShowTriggered"}),
trigger.value());
}
if (id == SidePanelEntry::Id::kSearchCompanion) {
auto* search_companion_coordinator =
SearchCompanionSidePanelCoordinator::GetOrCreateForBrowser(browser);
search_companion_coordinator->NotifyCompanionOfSidePanelOpenTrigger(
trigger);
}
}
void SidePanelUtil::RecordComboboxShown() {
base::UmaHistogramBoolean("SidePanel.ComboboxMenuShown", true);
}
void SidePanelUtil::RecordPinnedButtonClicked(SidePanelEntry::Id id,
bool is_pinned) {
base::RecordComputedAction(base::StrCat(
{"SidePanel.", SidePanelEntryIdToHistogramName(id), ".",
is_pinned ? "Pinned" : "Unpinned", ".BySidePanelHeaderButton"}));
}
void SidePanelUtil::RecordSidePanelAnimationMetrics(
base::TimeDelta largest_step_time) {
base::UmaHistogramTimes("SidePanel.TimeOfLongestAnimationStep",
largest_step_time);
}