blob: c344704f94f285da26b6e6b5bc9522aba560c0f6 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/scanner/scanner_metrics.h"
#include "ash/app_list/app_list_model_provider.h"
#include "ash/app_list/app_list_public_test_util.h"
#include "ash/app_list/model/search/search_box_model.h"
#include "ash/app_list/views/app_list_bubble_view.h"
#include "ash/app_list/views/app_list_view.h"
#include "ash/app_list/views/search_box_view.h"
#include "ash/capture_mode/capture_mode_test_util.h"
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/capture_mode/capture_mode_api.h"
#include "ash/public/cpp/scanner/scanner_delegate.h"
#include "ash/scanner/fake_scanner_profile_scoped_delegate.h"
#include "ash/scanner/scanner_controller.h"
#include "ash/shelf/home_button.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_navigation_widget.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "chromeos/ash/components/specialized_features/feature_access_checker.h"
#include "scanner_metrics.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/types/event_type.h"
namespace ash {
namespace {
using enum ScannerFeatureUserState;
using ::testing::Return;
class ScannerMetricsParameterisedTest
: public AshTestBase,
public testing::WithParamInterface<ScannerFeatureUserState> {};
INSTANTIATE_TEST_SUITE_P(
/* no prefix */,
ScannerMetricsParameterisedTest,
testing::ValuesIn<ScannerFeatureUserState>({
kConsentDisclaimerAccepted,
kConsentDisclaimerRejected,
kSunfishScreenEnteredViaShortcut,
kDeprecatedSunfishScreenInitialScreenCaptureSentToScannerServer,
kScreenCaptureModeScannerButtonShown,
kDeprecatedScreenCaptureModeInitialScreenCaptureSentToScannerServer,
kNoActionsDetected,
kNewCalendarEventActionDetected,
kNewCalendarEventActionFinishedSuccessfully,
kNewCalendarEventActionPopulationFailed,
kNewContactActionDetected,
kNewContactActionFinishedSuccessfully,
kNewContactActionPopulationFailed,
kNewGoogleSheetActionDetected,
kNewGoogleSheetActionFinishedSuccessfully,
kNewGoogleSheetActionPopulationFailed,
kNewGoogleDocActionDetected,
kNewGoogleDocActionFinishedSuccessfully,
kNewGoogleDocActionPopulationFailed,
kCopyToClipboardActionDetected,
kCopyToClipboardActionFinishedSuccessfully,
kCopyToClipboardActionPopulationFailed,
kNewCalendarEventPopulatedActionExecutionFailed,
kNewContactPopulatedActionExecutionFailed,
kNewGoogleSheetPopulatedActionExecutionFailed,
kNewGoogleDocPopulatedActionExecutionFailed,
kCopyToClipboardPopulatedActionExecutionFailed,
kCanShowUiReturnedFalse,
kCanShowUiReturnedTrueWithoutConsent,
kCanShowUiReturnedTrueWithConsent,
kCanShowUiReturnedFalseDueToNoShellInstance,
kCanShowUiReturnedFalseDueToNoControllerOnShell,
kCanShowUiReturnedFalseDueToEnterprisePolicy,
kCanShowUiReturnedFalseDueToNoProfileScopedDelegate,
kCanShowUiReturnedFalseDueToSettingsToggle,
kCanShowUiReturnedFalseDueToFeatureFlag,
kCanShowUiReturnedFalseDueToFeatureManagement,
kCanShowUiReturnedFalseDueToSecretKey,
kCanShowUiReturnedFalseDueToAccountCapabilities,
kCanShowUiReturnedFalseDueToCountry,
kCanShowUiReturnedFalseDueToKioskMode,
kLauncherShownWithoutSunfishSessionButton,
kLauncherShownWithSunfishSessionButton,
kSunfishSessionImageCapturedAndActionsNotFetched,
kSunfishSessionImageCapturedAndActionsFetchStarted,
kSmartActionsButtonImageCapturedAndActionsNotFetched,
kSmartActionsButtonImageCapturedAndActionsFetchStarted,
kSmartActionsButtonNotShownDueToFeatureChecks,
kSmartActionsButtonNotShownDueToTextDetectionCancelled,
kSmartActionsButtonNotShownDueToNoTextDetected,
kSmartActionsButtonNotShownDueToCanShowUiFalse,
kSmartActionsButtonNotShownDueToOffline,
}));
TEST_P(ScannerMetricsParameterisedTest, Record) {
base::HistogramTester histogram_tester;
RecordScannerFeatureUserState(GetParam());
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState", GetParam(),
1);
}
TEST(ScannerMetricsNoFixtureTest, LauncherShownWithoutSunfishSessionButton) {
base::HistogramTester histogram_tester;
RecordSunfishSessionButtonVisibilityOnLauncherShown(/*is_visible=*/false);
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kLauncherShownWithoutSunfishSessionButton,
1);
}
TEST(ScannerMetricsNoFixtureTest, LauncherShownWithSunfishSessionButton) {
base::HistogramTester histogram_tester;
RecordSunfishSessionButtonVisibilityOnLauncherShown(/*is_visible=*/true);
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kLauncherShownWithSunfishSessionButton, 1);
}
class ScannerMetricsTest : public AshTestBase {
public:
ScannerMetricsTest() {
// Disable Sunfish so we can control `IsSunfishAllowedAndEnabled`.
scoped_feature_list_.InitWithFeatures(
/*enabled_features=*/{features::kScannerUpdate},
/*disabled_features=*/{features::kSunfishFeature});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(ScannerMetricsTest, ClamshellLauncherShownWithoutSunfishSessionButton) {
base::HistogramTester histogram_tester;
ScannerController* scanner_controller = Shell::Get()->scanner_controller();
ASSERT_TRUE(scanner_controller);
auto* delegate = static_cast<FakeScannerProfileScopedDelegate*>(
scanner_controller->delegate_for_testing()->GetProfileScopedDelegate());
ON_CALL(*delegate, CheckFeatureAccess)
.WillByDefault(Return(specialized_features::FeatureAccessFailureSet{
specialized_features::FeatureAccessFailure::kDisabledInSettings}));
ASSERT_FALSE(CanShowSunfishOrScannerUi());
// Open the app list by clicking on the home button.
LeftClickOn(GetPrimaryShelf()->navigation_widget()->GetHomeButton());
AppListBubbleView* bubble_view = GetAppListBubbleView();
ASSERT_TRUE(bubble_view);
views::ImageButton* sunfish_button =
bubble_view->search_box_view()->sunfish_button();
ASSERT_TRUE(sunfish_button);
ASSERT_FALSE(sunfish_button->GetVisible());
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kLauncherShownWithoutSunfishSessionButton,
1);
}
TEST_F(ScannerMetricsTest, ClamshellLauncherShownWithSunfishSessionButton) {
base::HistogramTester histogram_tester;
ScannerController* scanner_controller = Shell::Get()->scanner_controller();
ASSERT_TRUE(scanner_controller);
auto* delegate = static_cast<FakeScannerProfileScopedDelegate*>(
scanner_controller->delegate_for_testing()->GetProfileScopedDelegate());
ON_CALL(*delegate, CheckFeatureAccess)
.WillByDefault(Return(specialized_features::FeatureAccessFailureSet{}));
ASSERT_TRUE(CanShowSunfishOrScannerUi());
// Open the app list by clicking on the home button.
LeftClickOn(GetPrimaryShelf()->navigation_widget()->GetHomeButton());
AppListBubbleView* bubble_view = GetAppListBubbleView();
ASSERT_TRUE(bubble_view);
views::ImageButton* sunfish_button =
bubble_view->search_box_view()->sunfish_button();
ASSERT_TRUE(sunfish_button);
ASSERT_TRUE(sunfish_button->GetVisible());
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kLauncherShownWithSunfishSessionButton, 1);
}
TEST_F(ScannerMetricsTest, ClamshellLauncherButtonClicked) {
base::HistogramTester histogram_tester;
ScannerController* scanner_controller = Shell::Get()->scanner_controller();
ASSERT_TRUE(scanner_controller);
auto* delegate = static_cast<FakeScannerProfileScopedDelegate*>(
scanner_controller->delegate_for_testing()->GetProfileScopedDelegate());
ON_CALL(*delegate, CheckFeatureAccess)
.WillByDefault(Return(specialized_features::FeatureAccessFailureSet{}));
ASSERT_TRUE(CanShowSunfishOrScannerUi());
// Open the app list by clicking on the home button.
LeftClickOn(GetPrimaryShelf()->navigation_widget()->GetHomeButton());
AppListBubbleView* bubble_view = GetAppListBubbleView();
ASSERT_TRUE(bubble_view);
views::ImageButton* sunfish_button =
bubble_view->search_box_view()->sunfish_button();
ASSERT_TRUE(sunfish_button);
ASSERT_TRUE(sunfish_button->GetVisible());
LeftClickOn(sunfish_button);
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kSunfishSessionStartedFromLauncherButton,
1);
}
TEST_F(ScannerMetricsTest, TabletLauncherShownWithoutSunfishSessionButton) {
base::HistogramTester histogram_tester;
ScannerController* scanner_controller = Shell::Get()->scanner_controller();
ASSERT_TRUE(scanner_controller);
auto* delegate = static_cast<FakeScannerProfileScopedDelegate*>(
scanner_controller->delegate_for_testing()->GetProfileScopedDelegate());
ON_CALL(*delegate, CheckFeatureAccess)
.WillByDefault(Return(specialized_features::FeatureAccessFailureSet{
specialized_features::FeatureAccessFailure::kDisabledInSettings}));
ASSERT_FALSE(CanShowSunfishOrScannerUi());
// The app list should be open by default when we enter tablet mode.
SwitchToTabletMode();
AppListView* app_list_view = GetAppListView();
ASSERT_TRUE(app_list_view);
views::ImageButton* sunfish_button =
app_list_view->search_box_view()->sunfish_button();
ASSERT_TRUE(sunfish_button);
ASSERT_FALSE(sunfish_button->GetVisible());
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kLauncherShownWithoutSunfishSessionButton,
1);
}
TEST_F(ScannerMetricsTest, TabletLauncherShownWithSunfishSessionButton) {
base::HistogramTester histogram_tester;
ScannerController* scanner_controller = Shell::Get()->scanner_controller();
ASSERT_TRUE(scanner_controller);
auto* delegate = static_cast<FakeScannerProfileScopedDelegate*>(
scanner_controller->delegate_for_testing()->GetProfileScopedDelegate());
ON_CALL(*delegate, CheckFeatureAccess)
.WillByDefault(Return(specialized_features::FeatureAccessFailureSet{}));
ASSERT_TRUE(CanShowSunfishOrScannerUi());
// The app list should be open by default when we enter tablet mode.
SwitchToTabletMode();
AppListView* app_list_view = GetAppListView();
ASSERT_TRUE(app_list_view);
views::ImageButton* sunfish_button =
app_list_view->search_box_view()->sunfish_button();
ASSERT_TRUE(sunfish_button);
ASSERT_TRUE(sunfish_button->GetVisible());
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kLauncherShownWithSunfishSessionButton, 1);
}
TEST_F(ScannerMetricsTest, TabletLauncherButtonClicked) {
base::HistogramTester histogram_tester;
ScannerController* scanner_controller = Shell::Get()->scanner_controller();
ASSERT_TRUE(scanner_controller);
auto* delegate = static_cast<FakeScannerProfileScopedDelegate*>(
scanner_controller->delegate_for_testing()->GetProfileScopedDelegate());
ON_CALL(*delegate, CheckFeatureAccess)
.WillByDefault(Return(specialized_features::FeatureAccessFailureSet{}));
ASSERT_TRUE(CanShowSunfishOrScannerUi());
// The app list should be open by default when we enter tablet mode.
SwitchToTabletMode();
AppListView* app_list_view = GetAppListView();
ASSERT_TRUE(app_list_view);
views::ImageButton* sunfish_button =
app_list_view->search_box_view()->sunfish_button();
ASSERT_TRUE(sunfish_button);
ASSERT_TRUE(sunfish_button->GetVisible());
LeftClickOn(sunfish_button);
histogram_tester.ExpectBucketCount("Ash.ScannerFeature.UserState",
kSunfishSessionStartedFromLauncherButton,
1);
}
TEST_F(ScannerMetricsTest, HomeButtonLongPress) {
base::HistogramTester histogram_tester;
ScannerController* scanner_controller = Shell::Get()->scanner_controller();
ASSERT_TRUE(scanner_controller);
auto* delegate = static_cast<FakeScannerProfileScopedDelegate*>(
scanner_controller->delegate_for_testing()->GetProfileScopedDelegate());
ON_CALL(*delegate, CheckFeatureAccess)
.WillByDefault(Return(specialized_features::FeatureAccessFailureSet{}));
ASSERT_TRUE(CanShowSunfishOrScannerUi());
HomeButton* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
ui::GestureEvent long_press(
0, 0, ui::EF_NONE, base::TimeTicks(),
ui::GestureEventDetails(ui::EventType::kGestureLongPress));
home_button->OnGestureEvent(&long_press);
histogram_tester.ExpectBucketCount(
"Ash.ScannerFeature.UserState",
kSunfishSessionStartedFromHomeButtonLongPress, 1);
}
} // namespace
} // namespace ash