chromium/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java

// Copyright 2019 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.homepage;

import android.content.Intent;
import android.view.View;

import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;

import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;

import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.ThreadUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Criteria;
import org.chromium.base.test.util.CriteriaHelper;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.homepage.settings.HomepageMetricsEnums.HomepageLocationType;
import org.chromium.chrome.browser.homepage.settings.HomepageSettings;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
import org.chromium.chrome.browser.toolbar.ToolbarManager;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.browser.TabLoadObserver;
import org.chromium.components.policy.test.annotations.Policies;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.url.GURL;

/**
 * Integration test for {@link HomepagePolicyManager}. Checking if enabling HomepageLocation policy
 * will reflect the expected behaviors for {@link HomepageSettings} and home button.
 */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Policies.Add({
    @Policies.Item(key = "HomepageLocation", string = HomepagePolicyIntegrationTest.TEST_URL)
})
public class HomepagePolicyIntegrationTest {
    public static final String TEST_URL = "http://127.0.0.1:8000/foo.html";
    public static final String GOOGLE_HTML = "/chrome/test/data/android/google.html";

    private static final String METRICS_HOMEPAGE_LOCATION_TYPE = "Settings.Homepage.LocationType";

    private EmbeddedTestServer mTestServer;

    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
    public SettingsActivityTestRule<HomepageSettings> mSettingsActivityTestRule =
            new SettingsActivityTestRule<>(HomepageSettings.class);

    // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish
    // CTA won't work.
    @Rule
    public final RuleChain mRuleChain =
            RuleChain.outerRule(mActivityTestRule).around(mSettingsActivityTestRule);

    @Rule public HomepageTestRule mHomepageTestRule = new HomepageTestRule();

    @Before
    public void setUp() {
        // Give some user pref setting, simulate user that have their customized preference.
        // Use shared preference manager, not to change the order object created in tests.
        mHomepageTestRule.useCustomizedHomepageForTest(GOOGLE_HTML);

        mActivityTestRule.startMainActivityFromLauncher();

        mTestServer =
                EmbeddedTestServer.createAndStartServer(
                        InstrumentationRegistry.getInstrumentation().getContext());
    }

    @Test
    @MediumTest
    @Feature({"Homepage"})
    public void testStartUpPage() {
        ThreadUtils.runOnUiThreadBlocking(
                () ->
                        Assert.assertTrue(
                                "HomepageLocation Policy should be enforced",
                                HomepagePolicyManager.isHomepageManagedByPolicy()));

        // The first time when the page starts, the homepage is fetched from shared preference
        // So the homepage policy is not enforced yet at this point.
        // Instead, we verify the shared preference to see if right policy URL were stored.
        String homepageGurlSerialized =
                ChromeSharedPreferences.getInstance()
                        .readString(ChromePreferenceKeys.HOMEPAGE_LOCATION_POLICY_GURL, "");
        GURL homepageGurl = GURL.deserialize(homepageGurlSerialized);
        Assert.assertEquals(
                "URL stored in shared preference should be the same as policy setting",
                TEST_URL,
                homepageGurl.getSpec());

        // METRICS_HOMEPAGE_LOCATION_TYPE is recorded once in deferred start up tasks.
        Assert.assertEquals(
                "Settings.Homepage.LocationType should record POLICY_OTHER once.",
                1,
                RecordHistogram.getHistogramValueCountForTesting(
                        METRICS_HOMEPAGE_LOCATION_TYPE, HomepageLocationType.POLICY_OTHER));

        // Start the page again. This time, the homepage should be set to what policy is.
        destroyAndRestartActivity();

        Assert.assertEquals(
                "Start up homepage should be the same as the policy setting",
                TEST_URL,
                ChromeTabUtils.getUrlStringOnUiThread(
                        mActivityTestRule.getActivity().getActivityTab()));
    }

    @Test
    @MediumTest
    @Feature({"Homepage"})
    public void testHomeButton() throws Exception {
        String anotherUrl = mTestServer.getURL(GOOGLE_HTML);
        new TabLoadObserver(mActivityTestRule.getActivity().getActivityTab())
                .fullyLoadUrl(anotherUrl);

        Assert.assertNotEquals(
                "Did not switch to a different URL",
                TEST_URL,
                ChromeTabUtils.getUrlStringOnUiThread(
                        mActivityTestRule.getActivity().getActivityTab()));

        CriteriaHelper.pollUiThread(
                () -> {
                    ToolbarManager toolbarManager =
                            mActivityTestRule.getActivity().getToolbarManager();
                    Criteria.checkThat(toolbarManager, Matchers.notNullValue());

                    View homeButton =
                            mActivityTestRule.getActivity().findViewById(R.id.home_button);
                    Criteria.checkThat(homeButton, Matchers.notNullValue());
                    Criteria.checkThat(
                            "Home Button should be visible",
                            homeButton.getVisibility(),
                            Matchers.is(View.VISIBLE));
                    homeButton.performLongClick();

                    Criteria.checkThat(
                            "Home button long click should not generate menu.",
                            toolbarManager.getHomeButtonCoordinatorForTesting().getMenuForTesting(),
                            Matchers.nullValue());
                });

        ChromeTabUtils.waitForTabPageLoaded(
                mActivityTestRule.getActivity().getActivityTab(),
                TEST_URL,
                () -> {
                    View homeButton =
                            mActivityTestRule.getActivity().findViewById(R.id.home_button);
                    TouchCommon.singleClickView(homeButton);
                });

        Assert.assertEquals(
                "After clicking HomeButton, URL should be back to Homepage",
                TEST_URL,
                ChromeTabUtils.getUrlStringOnUiThread(
                        mActivityTestRule.getActivity().getActivityTab()));
    }

    private void destroyAndRestartActivity() {
        ChromeTabbedActivity activity = mActivityTestRule.getActivity();

        // Create an intent to launch a new ChromeTabbedActivity.
        Intent intent = new Intent();
        intent.setClass(activity, ChromeTabbedActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        // Close all tabs so the new activity will create another initial tab with current homepage.
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    activity.getTabModelSelector().closeAllTabs();
                });

        activity.finish();
        CriteriaHelper.pollUiThread(
                () -> {
                    Criteria.checkThat(
                            ApplicationStatus.getStateForActivity(activity),
                            Matchers.is(ActivityState.DESTROYED));
                });

        // Start a new ChromeActivity.
        mActivityTestRule.startActivityCompletely(intent);
        Assert.assertEquals(
                "Start up page is not homepage",
                getHomepageUrlOnUiThread(),
                ChromeTabUtils.getUrlStringOnUiThread(
                        mActivityTestRule.getActivity().getActivityTab()));
    }

    private String getHomepageUrlOnUiThread() {
        return ThreadUtils.runOnUiThreadBlocking(
                () -> HomepageManager.getInstance().getHomepageGurl().getSpec());
    }
}