chromium/chrome/android/junit/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetricsUnitTest.java

// 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.

package org.chromium.chrome.browser.app.metrics;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.provider.Browser;
import android.speech.RecognizerResultsIntent;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;

import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.ContextUtils;
import org.chromium.base.IntentUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.components.webapps.ShortcutSource;

/** Unit tests for TabbedActivityLaunchCauseMetrics. */
@RunWith(BaseRobolectricTestRunner.class)
public final class TabbedActivityLaunchCauseMetricsUnitTest {
    @Mock private Activity mActivity;

    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

    @Before
    public void setUp() {
        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.CREATED);
    }

    @After
    public void tearDown() {
        LaunchCauseMetrics.resetForTests();
    }

    private static int histogramCountForValue(int value) {
        return RecordHistogram.getHistogramValueCountForTesting(
                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, value);
    }

    @Test
    public void testOpenInBrowserMetrics() throws Throwable {
        int count =
                histogramCountForValue(LaunchCauseMetrics.LaunchCause.OPEN_IN_BROWSER_FROM_MENU);
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("about:blank"));
        intent.putExtra(IntentHandler.EXTRA_FROM_OPEN_IN_BROWSER, true);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        // Tests the case where Chrome is backgrounded either by the intent picker, or by
        // cross-channel Open In Browser.
        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.OPEN_IN_BROWSER_FROM_MENU, launchCause);
        Assert.assertEquals(
                count,
                histogramCountForValue(LaunchCauseMetrics.LaunchCause.OPEN_IN_BROWSER_FROM_MENU));

        // Resume a different ChromeActivity to make it look like we're transitioning between
        // ChromeActivitys.
        ChromeTabbedActivity chromeActivity = new ChromeTabbedActivity();
        ApplicationStatus.onStateChangeForTesting(chromeActivity, ActivityState.CREATED);
        ApplicationStatus.onStateChangeForTesting(chromeActivity, ActivityState.STARTED);
        ApplicationStatus.onStateChangeForTesting(chromeActivity, ActivityState.RESUMED);

        // Ensures we record this metric even when Chrome has already recorded a launch.
        metrics.onReceivedIntent();
        launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.OPEN_IN_BROWSER_FROM_MENU, launchCause);
        Assert.assertEquals(
                count,
                histogramCountForValue(LaunchCauseMetrics.LaunchCause.OPEN_IN_BROWSER_FROM_MENU));

        // Ensures we don't record this metric again without a new Intent having been received.
        launchCause = metrics.recordLaunchCause();
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.OTHER, launchCause);
        Assert.assertEquals(
                count,
                histogramCountForValue(LaunchCauseMetrics.LaunchCause.OPEN_IN_BROWSER_FROM_MENU));

        // Ensures other metrics still aren't recorded when Chrome has already recorded a launch.
        int total =
                RecordHistogram.getHistogramTotalCountForTesting(
                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM);
        intent.putExtra(IntentHandler.EXTRA_FROM_OPEN_IN_BROWSER, false);
        metrics.onReceivedIntent();
        launchCause = metrics.recordLaunchCause();
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.OTHER, launchCause);
        Assert.assertEquals(
                total,
                RecordHistogram.getHistogramTotalCountForTesting(
                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM));
    }

    @Test
    public void testVoiceSearchResultsMetrics() throws Throwable {
        int count =
                histogramCountForValue(
                        LaunchCauseMetrics.LaunchCause.EXTERNAL_SEARCH_ACTION_INTENT);
        Intent intent = new Intent(RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(
                LaunchCauseMetrics.LaunchCause.EXTERNAL_SEARCH_ACTION_INTENT, launchCause);
        Assert.assertEquals(
                count,
                histogramCountForValue(
                        LaunchCauseMetrics.LaunchCause.EXTERNAL_SEARCH_ACTION_INTENT));

        // Ensures we don't record this metric when Chrome has already recorded a launch.
        metrics.onReceivedIntent();
        launchCause = metrics.recordLaunchCause();
        Assert.assertEquals(
                LaunchCauseMetrics.LaunchCause.OTHER, launchCause);
        Assert.assertEquals(
                count,
                histogramCountForValue(
                        LaunchCauseMetrics.LaunchCause.EXTERNAL_SEARCH_ACTION_INTENT));
    }

    @Test
    public void testBringToFrontNotification() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.NOTIFICATION);
        Intent intent =
                IntentHandler.createTrustedBringTabToFrontIntent(
                        1, IntentHandler.BringToFrontSource.NOTIFICATION);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.NOTIFICATION, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.NOTIFICATION));

        // Resume a different ChromeActivity to make it look like we're transitioning between
        // ChromeActivitys.
        ChromeTabbedActivity chromeActivity = new ChromeTabbedActivity();
        ApplicationStatus.onStateChangeForTesting(chromeActivity, ActivityState.CREATED);
        ApplicationStatus.onStateChangeForTesting(chromeActivity, ActivityState.STARTED);
        ApplicationStatus.onStateChangeForTesting(chromeActivity, ActivityState.RESUMED);

        metrics.onReceivedIntent();
        launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.NOTIFICATION, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.NOTIFICATION));
    }

    @Test
    public void testBringToFrontSearch() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.HOME_SCREEN_WIDGET);
        Intent intent =
                IntentHandler.createTrustedBringTabToFrontIntent(
                        1, IntentHandler.BringToFrontSource.SEARCH_ACTIVITY);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.HOME_SCREEN_WIDGET, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.HOME_SCREEN_WIDGET));
    }

    @Test
    public void testBringToFrontActiviteTab() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.NOTIFICATION);
        Intent intent =
                IntentHandler.createTrustedBringTabToFrontIntent(
                        1, IntentHandler.BringToFrontSource.ACTIVATE_TAB);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.NOTIFICATION, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.NOTIFICATION));
    }

    @Test
    public void testExternalViewIntent() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.EXTERNAL_VIEW_INTENT);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.EXTERNAL_VIEW_INTENT, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.EXTERNAL_VIEW_INTENT));
    }

    @Test
    public void testChromeViewIntent() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER_CHROME);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.putExtra(
                Browser.EXTRA_APPLICATION_ID,
                ContextUtils.getApplicationContext().getPackageName());
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.OTHER_CHROME, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER_CHROME));
    }

    @Test
    public void testOtherChromeIntent() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER_CHROME);
        Intent intent = new Intent();
        intent.setPackage(ContextUtils.getApplicationContext().getPackageName());
        intent.putExtra(
                Browser.EXTRA_APPLICATION_ID,
                ContextUtils.getApplicationContext().getPackageName());
        IntentUtils.addTrustedIntentExtras(intent);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.OTHER_CHROME, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER_CHROME));
    }

    @Test
    public void testHomescreenShortcut() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.HOME_SCREEN_SHORTCUT);
        Intent intent =
                ShortcutHelper.createShortcutIntent(
                        "about:blank", "id", ShortcutSource.ADD_TO_HOMESCREEN_SHORTCUT);
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.HOME_SCREEN_SHORTCUT, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.HOME_SCREEN_SHORTCUT));
    }

    @Test
    public void testShareIntent() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.SHARE_INTENT);
        Intent intent = new Intent(Intent.ACTION_SEND, Uri.parse("https://example.com"));
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.SHARE_INTENT, launchCause);
        Assert.assertEquals(
                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.SHARE_INTENT));
    }

    @Test
    public void testNfcViewIntent() throws Throwable {
        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.NFC);
        Intent intent =
                new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED, Uri.parse("https://example.com"));
        Mockito.when(mActivity.getIntent()).thenReturn(intent);

        TabbedActivityLaunchCauseMetrics metrics = new TabbedActivityLaunchCauseMetrics(mActivity);

        metrics.onReceivedIntent();
        int launchCause = metrics.recordLaunchCause();
        ++count;
        Assert.assertEquals(LaunchCauseMetrics.LaunchCause.NFC, launchCause);
        Assert.assertEquals(count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.NFC));
    }
}