chromium/chrome/browser/apps/link_capturing/metrics/intent_handling_metrics_unittest.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/metrics/histogram_macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/apps/link_capturing/intent_picker_info.h"
#include "chrome/test/base/testing_profile.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/components/arc/arc_prefs.h"
#include "ash/components/arc/metrics/arc_metrics_service.h"
#include "ash/components/arc/metrics/stability_metrics_manager.h"
#include "ash/components/arc/session/arc_service_manager.h"
#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
#include "ui/display/test/test_screen.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

namespace apps {

TEST(IntentHandlingMetricsTest, TestRecordIntentPickerMetrics) {
  struct TestCase {
    PickerEntryType entry_type;
    IntentPickerCloseReason close_reason;
    bool should_persist;

    IntentHandlingMetrics::IntentPickerAction expected_action;
    IntentHandlingMetrics::Platform expected_platform;
  };

  const TestCase kTestCases[]{
      // Open in ARC:
      {PickerEntryType::kArc, IntentPickerCloseReason::OPEN_APP, true,
       IntentHandlingMetrics::IntentPickerAction::kArcAppSelectedAndPreferred,
       IntentHandlingMetrics::Platform::ARC},

      {PickerEntryType::kArc, IntentPickerCloseReason::OPEN_APP, false,
       IntentHandlingMetrics::IntentPickerAction::kArcAppSelected,
       IntentHandlingMetrics::Platform::ARC},

      // Open in PWA:
      {PickerEntryType::kWeb, IntentPickerCloseReason::OPEN_APP, true,
       IntentHandlingMetrics::IntentPickerAction::kPwaSelectedAndPreferred,
       IntentHandlingMetrics::Platform::PWA},

      {PickerEntryType::kWeb, IntentPickerCloseReason::OPEN_APP, false,
       IntentHandlingMetrics::IntentPickerAction::kPwaSelected,
       IntentHandlingMetrics::Platform::PWA},

      // Stay in Chrome:
      {PickerEntryType::kWeb, IntentPickerCloseReason::STAY_IN_CHROME, true,
       IntentHandlingMetrics::IntentPickerAction::kChromeSelectedAndPreferred,
       IntentHandlingMetrics::Platform::CHROME},

      {PickerEntryType::kWeb, IntentPickerCloseReason::STAY_IN_CHROME, false,
       IntentHandlingMetrics::IntentPickerAction::kChromeSelected,
       IntentHandlingMetrics::Platform::CHROME},

      // Dismiss/error:
      {PickerEntryType::kWeb, IntentPickerCloseReason::DIALOG_DEACTIVATED, true,
       IntentHandlingMetrics::IntentPickerAction::kDialogDeactivated,
       IntentHandlingMetrics::Platform::CHROME},

      {PickerEntryType::kWeb, IntentPickerCloseReason::ERROR_AFTER_PICKER, true,
       IntentHandlingMetrics::IntentPickerAction::kError,
       IntentHandlingMetrics::Platform::CHROME},
  };

  for (const auto& test : kTestCases) {
    base::HistogramTester histogram_tester;

    IntentHandlingMetrics::RecordIntentPickerMetrics(
        test.entry_type, test.close_reason, test.should_persist);

    histogram_tester.ExpectBucketCount("ChromeOS.Intents.IntentPickerAction",
                                       test.expected_action, 1);
    histogram_tester.ExpectBucketCount(
        "ChromeOS.Apps.IntentPickerDestinationPlatform", test.expected_platform,
        1);
  }
}

TEST(IntentHandlingMetricsTest, TestRecordPreferredAppLinkClickMetrics) {
  base::HistogramTester histogram_tester;

  IntentHandlingMetrics::RecordPreferredAppLinkClickMetrics(
      IntentHandlingMetrics::Platform::ARC);

  histogram_tester.ExpectBucketCount(
      "ChromeOS.Apps.IntentPickerDestinationPlatform",
      IntentHandlingMetrics::Platform::ARC, 1);
}

TEST(IntentHandlingMetricsTest, TestRecordLinkCapturingEntryPointShown) {
  base::HistogramTester histogram_tester;
  IntentHandlingMetrics test;

  std::vector<apps::IntentPickerAppInfo> app_info = {
      {apps::PickerEntryType::kDevice, ui::ImageModel(), "test", "test"}};

  // Link capturing entry point shown for unknown app type.
  test.RecordLinkCapturingEntryPointShown(app_info);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.ArcApp",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 0);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.WebApp",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 0);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 1);

  // Prepare the app info for next testcase.
  app_info = {{apps::PickerEntryType::kWeb, ui::ImageModel(), "test", "test"}};

  // Link capturing entry point shown for web app type.
  test.RecordLinkCapturingEntryPointShown(app_info);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.ArcApp",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 0);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.WebApp",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 1);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 2);

  // Prepare the app info for next testcase.
  app_info = {{apps::PickerEntryType::kArc, ui::ImageModel(), "test", "test"},
              {apps::PickerEntryType::kWeb, ui::ImageModel(), "test", "test"},
              {apps::PickerEntryType::kWeb, ui::ImageModel(), "test", "test"}};

  // Link capturing entry point shown for 2 web apps and 1 ARC app.
  test.RecordLinkCapturingEntryPointShown(app_info);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.ArcApp",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 1);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.WebApp",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 2);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2",
      IntentHandlingMetrics::LinkCapturingEvent::kEntryPointShown, 3);
}

TEST(IntentHandlingMetricsTest, TestRecordLinkCapturingEvent) {
  base::HistogramTester histogram_tester;
  IntentHandlingMetrics test;

  // ARC app captures a link.
  test.RecordLinkCapturingEvent(
      PickerEntryType::kArc,
      IntentHandlingMetrics::LinkCapturingEvent::kAppOpened);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.ArcApp",
      IntentHandlingMetrics::LinkCapturingEvent::kAppOpened, 1);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.WebApp",
      IntentHandlingMetrics::LinkCapturingEvent::kAppOpened, 0);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2",
      IntentHandlingMetrics::LinkCapturingEvent::kAppOpened, 1);

  // Link capturing settings changed for web app.
  test.RecordLinkCapturingEvent(
      PickerEntryType::kWeb,
      IntentHandlingMetrics::LinkCapturingEvent::kSettingsChanged);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.ArcApp",
      IntentHandlingMetrics::LinkCapturingEvent::kSettingsChanged, 0);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2.WebApp",
      IntentHandlingMetrics::LinkCapturingEvent::kSettingsChanged, 1);
  histogram_tester.ExpectBucketCount(
      "ChromeOS.Intents.LinkCapturingEvent2",
      IntentHandlingMetrics::LinkCapturingEvent::kSettingsChanged, 1);
}

#if BUILDFLAG(IS_CHROMEOS_ASH)

// A fixture class that sets up arc::ArcMetricsService.
class IntentHandlingMetricsTestWithMetricsService : public testing::Test {
 protected:
  IntentHandlingMetricsTestWithMetricsService() = default;
  IntentHandlingMetricsTestWithMetricsService(
      const IntentHandlingMetricsTestWithMetricsService&) = delete;
  IntentHandlingMetricsTestWithMetricsService& operator=(
      const IntentHandlingMetricsTestWithMetricsService&) = delete;
  ~IntentHandlingMetricsTestWithMetricsService() override = default;

  void SetUp() override {
    arc::prefs::RegisterLocalStatePrefs(local_state_.registry());
    arc::StabilityMetricsManager::Initialize(&local_state_);
    arc::ArcMetricsService::GetForBrowserContextForTesting(profile());
  }

  Profile* profile() { return &profile_; }

 private:
  content::BrowserTaskEnvironment task_environment_;
  display::test::TestScreen test_screen_{/*create_display=*/true,
                                         /*register_screen=*/true};
  arc::ArcServiceManager arc_service_manager_;
  TestingPrefServiceSimple local_state_;
  TestingProfile profile_;
};

TEST_F(IntentHandlingMetricsTestWithMetricsService,
       TestRecordExternalProtocolUserInteractionMetrics) {
  struct TestCase {
    PickerEntryType entry_type;
    IntentPickerCloseReason close_reason;
    bool should_persist;

    IntentHandlingMetrics::PickerAction expected_action;
    bool expected_link_click;
  };

  const TestCase kTestCases[]{
      // Arc apps:
      {PickerEntryType::kArc, IntentPickerCloseReason::OPEN_APP,
       /*should_persist=*/true,
       IntentHandlingMetrics::PickerAction::ARC_APP_PREFERRED_PRESSED,
       /*expected_link_click=*/true},

      {PickerEntryType::kArc, IntentPickerCloseReason::OPEN_APP,
       /*should_persist=*/false,
       IntentHandlingMetrics::PickerAction::ARC_APP_PRESSED,
       /*expected_link_click=*/true},

      {PickerEntryType::kArc, IntentPickerCloseReason::PREFERRED_APP_FOUND,
       /*should_persist=*/false,
       IntentHandlingMetrics::PickerAction::PREFERRED_ARC_ACTIVITY_FOUND,
       /*expected_link_click=*/true},

      // Device:
      {PickerEntryType::kDevice, IntentPickerCloseReason::OPEN_APP,
       /*should_persist=*/false,
       IntentHandlingMetrics::PickerAction::DEVICE_PRESSED,
       /*expected_link_click=*/false},

      // Dismiss:
      {PickerEntryType::kArc, IntentPickerCloseReason::DIALOG_DEACTIVATED,
       /*should_persist=*/false,
       IntentHandlingMetrics::PickerAction::DIALOG_DEACTIVATED,
       /*expected_link_click=*/false},
  };

  for (const auto& test : kTestCases) {
    base::HistogramTester histogram_tester;

    IntentHandlingMetrics::RecordExternalProtocolUserInteractionMetrics(
        profile(), test.entry_type, test.close_reason, test.should_persist);

    histogram_tester.ExpectBucketCount(
        "Arc.UserInteraction", arc::UserInteractionType::APP_STARTED_FROM_LINK,
        test.expected_link_click);
  }
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

}  // namespace apps