chromium/chrome/browser/apps/link_capturing/metrics/intent_handling_metrics.cc

// 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/link_capturing/metrics/intent_handling_metrics.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_constants.h"
#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_IN_MIGRATION();
          return IntentPickerAction::kInvalid;
      }
    case apps::IntentPickerCloseReason::PREFERRED_APP_FOUND:
      // For the HTTP/HTTPS Intent Picker, preferred app metrics are recorded
      // separately in RecordPreferredAppLinkClickMetrics.
      NOTREACHED_IN_MIGRATION();
      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_IN_MIGRATION();
      return Platform::CHROME;
  }
}

}  // 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::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::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);
  }
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

}  // namespace apps