blob: 8a46930c892a1655088cb4841b3adee7a83ad1b2 [file] [log] [blame]
// Copyright 2020 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/apps/intent_helper/metrics/intent_handling_metrics.h"
#include "ash/components/arc/metrics/arc_metrics_constants.h"
#include "base/containers/contains.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/components/arc/metrics/arc_metrics_service.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
namespace {
const char kLinkCapturingHistogram[] = "ChromeOS.Intents.LinkCapturingEvent2";
const char kLinkCapturingHistogramWeb[] =
"ChromeOS.Intents.LinkCapturingEvent2.WebApp";
const char kLinkCapturingHistogramArc[] =
"ChromeOS.Intents.LinkCapturingEvent2.ArcApp";
using PickerAction = apps::IntentHandlingMetrics::PickerAction;
using IntentPickerAction = apps::IntentHandlingMetrics::IntentPickerAction;
using Platform = apps::IntentHandlingMetrics::Platform;
void RecordDestinationPlatformMetric(
apps::IntentHandlingMetrics::Platform platform) {
UMA_HISTOGRAM_ENUMERATION("ChromeOS.Apps.IntentPickerDestinationPlatform",
platform);
}
IntentPickerAction GetIntentPickerAction(
apps::PickerEntryType entry_type,
apps::IntentPickerCloseReason close_reason,
bool should_persist) {
switch (close_reason) {
case apps::IntentPickerCloseReason::ERROR_BEFORE_PICKER:
case apps::IntentPickerCloseReason::ERROR_AFTER_PICKER:
return IntentPickerAction::kError;
case apps::IntentPickerCloseReason::DIALOG_DEACTIVATED:
return IntentPickerAction::kDialogDeactivated;
case apps::IntentPickerCloseReason::STAY_IN_CHROME:
return should_persist ? IntentPickerAction::kChromeSelectedAndPreferred
: IntentPickerAction::kChromeSelected;
case apps::IntentPickerCloseReason::OPEN_APP:
switch (entry_type) {
case apps::PickerEntryType::kArc:
return should_persist
? IntentPickerAction::kArcAppSelectedAndPreferred
: IntentPickerAction::kArcAppSelected;
case apps::PickerEntryType::kWeb:
return should_persist ? IntentPickerAction::kPwaSelectedAndPreferred
: IntentPickerAction::kPwaSelected;
case apps::PickerEntryType::kDevice:
case apps::PickerEntryType::kMacOs:
case apps::PickerEntryType::kUnknown:
NOTREACHED();
return IntentPickerAction::kInvalid;
}
case apps::IntentPickerCloseReason::PREFERRED_APP_FOUND:
// For the HTTP/HTTPS Intent Picker, preferred app metrics are recorded
// separately in RecordPreferredAppLinkClickMetrics.
NOTREACHED();
return IntentPickerAction::kInvalid;
}
}
Platform GetIntentPickerDestinationPlatform(IntentPickerAction action) {
switch (action) {
case IntentPickerAction::kArcAppSelected:
case IntentPickerAction::kArcAppSelectedAndPreferred:
return Platform::ARC;
case IntentPickerAction::kPwaSelected:
case IntentPickerAction::kPwaSelectedAndPreferred:
return Platform::PWA;
case IntentPickerAction::kChromeSelected:
case IntentPickerAction::kChromeSelectedAndPreferred:
case IntentPickerAction::kDialogDeactivated:
case IntentPickerAction::kError:
return Platform::CHROME;
case IntentPickerAction::kInvalid:
NOTREACHED();
return Platform::CHROME;
}
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Converts the provided |entry_type|, |close_reason| and |should_persist|
// boolean to a PickerAction value for recording in UMA.
PickerAction GetExternalProtocolPickerAction(
apps::PickerEntryType entry_type,
apps::IntentPickerCloseReason close_reason,
bool should_persist) {
switch (close_reason) {
case apps::IntentPickerCloseReason::ERROR_BEFORE_PICKER:
return PickerAction::ERROR_BEFORE_PICKER;
case apps::IntentPickerCloseReason::ERROR_AFTER_PICKER:
return PickerAction::ERROR_AFTER_PICKER;
case apps::IntentPickerCloseReason::DIALOG_DEACTIVATED:
return PickerAction::DIALOG_DEACTIVATED;
case apps::IntentPickerCloseReason::PREFERRED_APP_FOUND:
switch (entry_type) {
case apps::PickerEntryType::kUnknown:
return PickerAction::PREFERRED_CHROME_BROWSER_FOUND;
case apps::PickerEntryType::kArc:
return PickerAction::PREFERRED_ARC_ACTIVITY_FOUND;
case apps::PickerEntryType::kWeb:
return PickerAction::PREFERRED_PWA_FOUND;
case apps::PickerEntryType::kDevice:
case apps::PickerEntryType::kMacOs:
NOTREACHED();
return PickerAction::INVALID;
}
case apps::IntentPickerCloseReason::STAY_IN_CHROME:
return should_persist ? PickerAction::CHROME_PREFERRED_PRESSED
: PickerAction::CHROME_PRESSED;
case apps::IntentPickerCloseReason::OPEN_APP:
switch (entry_type) {
case apps::PickerEntryType::kUnknown:
NOTREACHED();
return PickerAction::INVALID;
case apps::PickerEntryType::kArc:
return should_persist ? PickerAction::ARC_APP_PREFERRED_PRESSED
: PickerAction::ARC_APP_PRESSED;
case apps::PickerEntryType::kWeb:
return should_persist ? PickerAction::PWA_APP_PREFERRED_PRESSED
: PickerAction::PWA_APP_PRESSED;
case apps::PickerEntryType::kDevice:
return PickerAction::DEVICE_PRESSED;
case apps::PickerEntryType::kMacOs:
return PickerAction::MAC_OS_APP_PRESSED;
}
}
NOTREACHED();
return PickerAction::INVALID;
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
} // namespace
namespace apps {
IntentHandlingMetrics::IntentHandlingMetrics() = default;
void IntentHandlingMetrics::RecordIntentPickerMetrics(
PickerEntryType entry_type,
IntentPickerCloseReason close_reason,
bool should_persist) {
IntentPickerAction action =
GetIntentPickerAction(entry_type, close_reason, should_persist);
UMA_HISTOGRAM_ENUMERATION("ChromeOS.Intents.IntentPickerAction", action);
Platform platform = GetIntentPickerDestinationPlatform(action);
RecordDestinationPlatformMetric(platform);
}
void IntentHandlingMetrics::RecordPreferredAppLinkClickMetrics(
Platform platform) {
RecordDestinationPlatformMetric(platform);
}
void IntentHandlingMetrics::RecordIntentPickerIconEvent(
IntentPickerIconEvent event) {
UMA_HISTOGRAM_ENUMERATION("ChromeOS.Intents.IntentPickerIconEvent", event);
}
void IntentHandlingMetrics::RecordLinkCapturingEvent(PickerEntryType app_type,
LinkCapturingEvent event) {
switch (app_type) {
case PickerEntryType::kWeb:
base::UmaHistogramEnumeration(kLinkCapturingHistogramWeb, event);
break;
case PickerEntryType::kArc:
base::UmaHistogramEnumeration(kLinkCapturingHistogramArc, event);
break;
case PickerEntryType::kUnknown:
case PickerEntryType::kDevice:
case PickerEntryType::kMacOs:
// These cases do not represent entering an app and should not record
// any histograms.
return;
}
base::UmaHistogramEnumeration(kLinkCapturingHistogram, event);
}
void IntentHandlingMetrics::RecordLinkCapturingEntryPointShown(
const std::vector<IntentPickerAppInfo>& app_infos) {
if (base::Contains(app_infos, PickerEntryType::kWeb,
&IntentPickerAppInfo::type)) {
base::UmaHistogramEnumeration(kLinkCapturingHistogramWeb,
LinkCapturingEvent::kEntryPointShown);
}
if (base::Contains(app_infos, PickerEntryType::kArc,
&IntentPickerAppInfo::type)) {
base::UmaHistogramEnumeration(kLinkCapturingHistogramArc,
LinkCapturingEvent::kEntryPointShown);
}
base::UmaHistogramEnumeration(kLinkCapturingHistogram,
LinkCapturingEvent::kEntryPointShown);
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
void IntentHandlingMetrics::RecordExternalProtocolMetrics(
arc::Scheme scheme,
PickerEntryType entry_type,
bool accepted,
bool persisted) {
arc::ProtocolAction action =
arc::GetProtocolAction(scheme, entry_type, accepted, persisted);
if (accepted) {
UMA_HISTOGRAM_ENUMERATION("ChromeOS.Apps.ExternalProtocolDialog.Accepted",
action);
} else {
UMA_HISTOGRAM_ENUMERATION("ChromeOS.Apps.ExternalProtocolDialog.Rejected",
action);
}
}
void IntentHandlingMetrics::RecordExternalProtocolUserInteractionMetrics(
content::BrowserContext* context,
PickerEntryType entry_type,
IntentPickerCloseReason close_reason,
bool should_persist) {
if (entry_type == PickerEntryType::kArc &&
(close_reason == IntentPickerCloseReason::PREFERRED_APP_FOUND ||
close_reason == IntentPickerCloseReason::OPEN_APP)) {
arc::ArcMetricsService::RecordArcUserInteraction(
context, arc::UserInteractionType::APP_STARTED_FROM_LINK);
}
// TODO(crbug.com/985233) For now External Protocol Dialog is only querying
// ARC apps, so there's no need to record a destination platform.
PickerAction action =
GetExternalProtocolPickerAction(entry_type, close_reason, should_persist);
UMA_HISTOGRAM_ENUMERATION("ChromeOS.Apps.ExternalProtocolDialog", action);
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
void IntentHandlingMetrics::RecordOpenBrowserMetrics(AppType type) {
UMA_HISTOGRAM_ENUMERATION("ChromeOS.Apps.OpenBrowser", type);
}
} // namespace apps