// Copyright 2017 The Chromium Authors. All rights reserved.
// 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.vr;

import static org.chromium.chrome.browser.vr.XrTestFramework.NATIVE_URLS_OF_INTEREST;
import static org.chromium.chrome.browser.vr.XrTestFramework.PAGE_LOAD_TIMEOUT_S;
import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_LONG_MS;
import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE;

import android.graphics.PointF;
import android.graphics.RectF;
import android.os.SystemClock;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.PaymentRequestObserverForTest;
import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityVrTestRule;
import org.chromium.chrome.browser.vr.util.NativeUiUtils;
import org.chromium.chrome.browser.vr.util.RenderTestUtils;
import org.chromium.chrome.browser.vr.util.VrBrowserTransitionUtils;
import org.chromium.chrome.browser.vr.util.VrShellDelegateUtils;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.RenderTestRule;

import java.io.IOException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * End-to-end tests for native UI presentation in VR Browser mode.
 */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
public class VrBrowserNativeUiTest {
    // We explicitly instantiate a rule here instead of using parameterization since this class
    // only ever runs in ChromeTabbedActivity.
    @Rule
    public ChromeTabbedActivityVrTestRule mVrTestRule = new ChromeTabbedActivityVrTestRule();

    @Rule
    public RenderTestRule mRenderTestRule =
            new RenderTestRule("components/test/data/vr_browser_ui/render_tests");

    private VrBrowserTestFramework mVrBrowserTestFramework;

    private static final String TEST_PAGE_2D_URL =
            VrBrowserTestFramework.getFileUrlForHtmlTestFile("test_navigation_2d_page");

    @Before
    public void setUp() throws Exception {
        mVrBrowserTestFramework = new VrBrowserTestFramework(mVrTestRule);
        VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
    }

    /**
     * Tests that URLs are not shown for native UI.
     */
    @Test
    @MediumTest
    public void testUrlOnNativeUi()
            throws IllegalArgumentException, InterruptedException, TimeoutException {
        for (String url : NATIVE_URLS_OF_INTEREST) {
            mVrTestRule.loadUrl(url, PAGE_LOAD_TIMEOUT_S);
            Assert.assertFalse("URL is being shown for native page " + url,
                    TestVrShellDelegate.isDisplayingUrlForTesting());
        }
    }

    /**
     * Tests that URLs are shown for non-native UI.
     */
    @Test
    @MediumTest
    public void testUrlOnNonNativeUi()
            throws IllegalArgumentException, InterruptedException, TimeoutException {
        mVrTestRule.loadUrl(TEST_PAGE_2D_URL, PAGE_LOAD_TIMEOUT_S);
        Assert.assertTrue("URL is not being show for non-native page",
                TestVrShellDelegate.isDisplayingUrlForTesting());
    }

    /**
     * Tests that the Payment Request API is supressed in the VR Browser and its native UI does not
     * show. Automation of a manual test from https://crbug.com/862162.
     */
    @Test
    @MediumTest
    public void testPaymentRequest() throws InterruptedException {
        // We can't request payment on file:// URLs, so use a local server.
        mVrBrowserTestFramework.loadUrlAndAwaitInitialization(
                mVrBrowserTestFramework.getEmbeddedServerUrlForHtmlTestFile("test_payment_request"),
                PAGE_LOAD_TIMEOUT_S);
        // Set up an observer so we'll know if the payment request is shown.
        AtomicBoolean requestShown = new AtomicBoolean(false);
        PaymentRequestObserverForTest observer = new PaymentRequestObserverForTest() {
            @Override
            public void onPaymentRequestReadyForInput(PaymentRequestUI ui) {
                requestShown.set(true);
            }
            @Override
            public void onPaymentRequestReadyToPay(PaymentRequestUI ui) {}
            @Override
            public void onPaymentRequestSelectionChecked(PaymentRequestUI ui) {}
            @Override
            public void onPaymentRequestResultReady(PaymentRequestUI ui) {}
        };
        PaymentRequestUI.setPaymentRequestObserverForTest(observer);
        // Request payment and wait for the promise to auto-reject.
        mVrBrowserTestFramework.executeStepAndWait("stepRequestPayment()");
        // Ensure that the native UI wasn't shown even though the request was rejected.
        // Need to sleep for a bit in order to allow the UI to show if it's going to.
        SystemClock.sleep(1000);
        Assert.assertFalse("Native Payment Request UI was shown", requestShown.get());
        // Ensure we weren't somehow kicked out of VR from this.
        Assert.assertTrue("Payment request caused VR exit",
                VrShellDelegateUtils.getDelegateInstance().isVrEntryComplete());
        mVrBrowserTestFramework.endTest();
    }

    /**
     * Tests that the current URL is automatically populated when opening up the omnibox text
     * entry mode.
     */
    @Test
    @MediumTest
    public void testOmniboxContainsCurrentUrl() throws InterruptedException {
        // This is a really roundabout way of checking the automatically populated text in the
        // omnibox without having to add yet more native plumbing to read the current text.
        // The idea is that by deleting the last four characters, we should be left with just
        // "chrome://", so we can then input another chrome:// URL based off that. The only way
        // the second navigation will complete successfully is if the omnibox had "chrome://gpu/"
        // when we opened it.
        NativeUiUtils.enableMockedKeyboard();
        mVrTestRule.loadUrl("chrome://gpu/");
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        // Click near the righthand side of the text input field so the cursor is at the end instead
        // of selecting the existing text.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(0.4f, 0.0f));
        // Delete "gpu/".
        for (int i = 0; i < 4; ++i) {
            NativeUiUtils.inputBackspace();
        }
        // Wait for suggestions to change so that our navigation succeeds.
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputString("version/"); });
        NativeUiUtils.inputEnter();
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), "chrome://version/");
    }

    /**
     * Tests that the the omnibox automatically scrolls the text when it is longer than the box
     * can fit.
     */
    @Test
    @MediumTest
    public void testOmniboxTextScrolls() throws InterruptedException {
        // This is a roundabout way of checking that the text scrolls. By inputting a long string,
        // clicking near the beginning and deleting a character, we can check that the text scrolled
        // by checking whether a character at the beginning of the string was deleted or not - if
        // the text scrolled, then a character later in the string should have been deleted.
        NativeUiUtils.enableMockedKeyboard();
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        String expectedString = "chrome://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        NativeUiUtils.inputString(expectedString + "a");
        // Click near the lefthand side of the input field to place the cursor near the beginning
        // of the visible part of the string.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(-0.45f, 0.0f));
        // We expect this to delete an "a" instead of anything in "chrome://". Do so and wait for
        // the suggestions to appear.
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputBackspace(); });
        NativeUiUtils.inputEnter();
        // Navigating automatically appends a "/".
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), expectedString + "/");
    }

    /**
     * Tests that the omnibox automatically clears any text that gets input but not committed.
     */
    @Test
    @MediumTest
    public void testOmniboxClearsUncommittedText() throws InterruptedException {
        // Similar to testOmniboxContainsCurrentUrl, we check that the uncommitted text is not
        // present the second time we open the omnibox by deleting a number of characters from
        // the expected text and entering additional text.
        NativeUiUtils.enableMockedKeyboard();
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        // Input text and close the omnibox without committing.
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputString("chrome://version/"); });
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.OMNIBOX_CLOSE_BUTTON, new PointF());
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        // Click near the righthand side of the text input field so the cursor is at the end instead
        // of selecting the existing text.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(0.4f, 0.0f));
        // Delete "about:blank".
        for (int i = 0; i < 11; ++i) {
            NativeUiUtils.inputBackspace();
        }
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visibile */,
                () -> { NativeUiUtils.inputString("chrome://version/"); });
        NativeUiUtils.inputEnter();
        // This should only succeed if the original "chrome://version/" we input is not present -
        // if it is, we'll end up navigating to "chromechrome://version/".
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), "chrome://version/");
    }

    /**
     * Tests that omnibox autocompletion is functional.
     */
    @Test
    @MediumTest
    public void testOmniboxAutocompletion() throws InterruptedException {
        // At least with chrome:// URLs, autocompletion only kicks in when there's one valid option
        // left. So, test that:
        // 1. Autocompletion works if only one option is available.
        // 2. Autocompletion updates successfully if additional characters are added.
        // 3. Autocompletion doesn't work if multiple options are available.
        // 4. Autocompletion cancels if a non-matching character is input.
        NativeUiUtils.enableMockedKeyboard();
        // Test that autocompletion works with only one option left.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        // This should autocomplete to "chrome://version".
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputString("chrome://v"); });
        NativeUiUtils.inputEnter();
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), "chrome://version/");
        // Navigate away from chrome://version/ so waitForTabPageLoaded doesn't no-op the next time.
        mVrTestRule.loadUrl("about:blank");

        // Test that autocompletion updates successfully when entering more text.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputString("chrome://v"); });
        NativeUiUtils.inputString("e");
        // Since suggestions are already visible, we need to wait for suggestions to update via
        // a glorified sleep instead of waiting for suggestions to appear.
        NativeUiUtils.waitNumFrames(NativeUiUtils.NUM_FRAMES_FOR_SUGGESTION_UPDATE);
        NativeUiUtils.inputEnter();
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), "chrome://version/");

        // Test that autocompletion doesn't work with more than one option available.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        // This could be either "chrome://net-export" or "chrome://net-internals", so it shouldn't
        // autocomplete to anything.
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputString("chrome://net-"); });
        NativeUiUtils.inputEnter();
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), "chrome://net-/");

        // Test that autocompletion cancels if a non-matching character is input.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        // This should autocomplete to "chrome://version".
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputString("chrome://v"); });
        NativeUiUtils.inputString("a");
        NativeUiUtils.waitNumFrames(NativeUiUtils.NUM_FRAMES_FOR_SUGGESTION_UPDATE);
        NativeUiUtils.inputEnter();
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), "chrome://va/");
    }

    /**
     * Tests that the keyboard appears when clicking on the URL bar.
     * Also contains a regression test for https://crbug.com/874671 where inputting text into the
     * URL bar would cause a browser crash.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testKeyboardAppearsOnUrlBarClick()
            throws InterruptedException, TimeoutException, IOException {
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        // For whatever reason, the laser has a lot of random noise (not visible to an actual user)
        // when the keyboard is present on certain OS/hardware configurations (currently known to
        // happen on Pixel XL w/ N). So, allow pixels to differ by a small amount without failing.
        mRenderTestRule.setPixelDiffThreshold(5);
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "keyboard_visible_browser_ui", mRenderTestRule);
        // Regression test for https://crbug.com/874671
        // We need to use the VrCore-side emulated controller because the keyboard isn't a UI
        // element, meaning we can't specify it as a click target for the Chrome-side controller.
        NativeUiUtils.revertToRealInput();
        // Point at the keyboard and click an arbitrary key
        EmulatedVrController controller = new EmulatedVrController(mVrTestRule.getActivity());
        controller.recenterView();
        controller.moveControllerInstant(0.0f, -0.259f, -0.996f, -0.0f);
        // Spam clicks to ensure we're getting one in.
        for (int i = 0; i < 5; i++) {
            controller.performControllerClick();
        }
    }

    /**
     * Tests that the overflow menu appears when the overflow menu button is clicked.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testOverflowMenuAppears()
            throws InterruptedException, TimeoutException, IOException {
        // TODO(https://crbug.com/930840): Remove this when the weird gradient behavior is fixed.
        mRenderTestRule.setPixelDiffThreshold(2);
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.OVERFLOW_MENU, new PointF());
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "overflow_menu_visible_browser_ui", mRenderTestRule);
    }

    /**
     * Tests that the page info popup appears when the security token in the URL bar is clicked.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testPageInfoAppearsOnSecurityTokenClick()
            throws InterruptedException, TimeoutException, IOException {
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.PAGE_INFO_BUTTON, new PointF());
        // Workaround for https://crbug.com/893291, where the text doesn't actually show up until a
        // bit after the element is drawn.
        SystemClock.sleep(1000);
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "page_info_visible_browser_ui", mRenderTestRule);
    }

    /**
     * Tests that data URLs have the data portion of the URL emphasized like in 2D browsing.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testDataUrlEmphasis() throws InterruptedException, IOException {
        NativeUiUtils.enableMockedInput();
        mVrTestRule.loadUrl("data:,Hello%2C%20World!", PAGE_LOAD_TIMEOUT_S);
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "data_url_emphasis_browser_ui", mRenderTestRule);
    }

    /**
     * Tests that file URLs have the entire URL emphasized like in 2D browsing.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testFileUrlEmphasis() throws InterruptedException, IOException {
        NativeUiUtils.enableMockedInput();
        mVrTestRule.loadUrl(VrBrowserTestFramework.getFileUrlForHtmlTestFile("2d_permission_page"),
                PAGE_LOAD_TIMEOUT_S);
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "file_url_emphasis_browser_ui", mRenderTestRule);
    }

    /**
     * Tests that the reposition bar does not appear if the keyboard is open.
     */
    @Test
    @MediumTest
    @Feature({"Browser", "RenderTest"})
    public void testRepositionBarDoesNotAppearWithKeyboardOpen()
            throws InterruptedException, TimeoutException, IOException {
        // Use the mock keyboard so it doesn't show, reducing the chance of flakes due to AA.
        NativeUiUtils.enableMockedKeyboard();
        mVrTestRule.loadUrl(
                VrBrowserTestFramework.getFileUrlForHtmlTestFile("generic_text_entry_page"),
                PAGE_LOAD_TIMEOUT_S);
        NativeUiUtils.clickContentNode(
                "textfield", new PointF(), 1 /* numClicks */, mVrBrowserTestFramework);
        NativeUiUtils.waitForUiQuiescence();
        NativeUiUtils.hoverElement(UserFriendlyElementName.CONTENT_QUAD, new PointF(0.0f, 0.55f));
        NativeUiUtils.waitForUiQuiescence();
        // Due to the way the repositioner works, the reposition bar is technically always visible
        // in the element hierarchy, so we can't just assert that it's invisible. Instead, we have
        // to resort to pixel diffing.
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "reposition_bar_keyboard_open", mRenderTestRule);
    }

    /*
     * Tests that hovering over various elements in the URL bar looks as expected.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testUrlBarHovering() throws InterruptedException, TimeoutException, IOException {
        testUrlBarHoveringImpl(false);
    }

    /**
     * Tests that hovering over various elements in the URL bar looks as expected while in Incognito
     * mode.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testUrlBarHoveringIncognito()
            throws InterruptedException, TimeoutException, IOException {
        mVrBrowserTestFramework.openIncognitoTab("about:blank");
        testUrlBarHoveringImpl(true);
    }

    private void testUrlBarHoveringImpl(boolean incognito)
            throws InterruptedException, TimeoutException, IOException {
        // Back button hovering doesn't do anything unless the back button is actually active. so
        // navigate to do that.
        mVrTestRule.loadUrl("chrome://version/", PAGE_LOAD_TIMEOUT_S);
        // Back button.
        NativeUiUtils.hoverElement(UserFriendlyElementName.BACK_BUTTON, new PointF());
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                generateRenderTestIdentifier("back_button_hover", incognito), mRenderTestRule);
        // Security icon.
        NativeUiUtils.hoverElement(UserFriendlyElementName.PAGE_INFO_BUTTON, new PointF());
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                generateRenderTestIdentifier("security_icon_hover", incognito), mRenderTestRule);
        // URL bar.
        NativeUiUtils.hoverElement(UserFriendlyElementName.URL, new PointF());
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                generateRenderTestIdentifier("url_bar_hover", incognito), mRenderTestRule);
        // Overflow menu.
        NativeUiUtils.hoverElement(UserFriendlyElementName.OVERFLOW_MENU, new PointF());
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                generateRenderTestIdentifier("overflow_menu_hover", incognito), mRenderTestRule);
    }

    /**
     * Tests that hovering over various elements in the overflow menu looks as expected.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testOverflowMenuHovering()
            throws InterruptedException, TimeoutException, IOException {
        testOverflowMenuHoveringImpl(false);
    }

    /**
     * Tests that hovering over various elements in the overflow menu looks as expected while in
     * Incognito mode.
     */
    @Test
    @LargeTest
    @Feature({"Browser", "RenderTest"})
    public void testOverflowMenuHoveringIncognito()
            throws InterruptedException, TimeoutException, IOException {
        mVrBrowserTestFramework.openIncognitoTab("about:blank");
        testOverflowMenuHoveringImpl(true);
    }

    private void testOverflowMenuHoveringImpl(boolean incognito)
            throws InterruptedException, TimeoutException, IOException {
        // TODO(https://crbug.com/930840): Remove this when the weird gradient behavior is fixed.
        mRenderTestRule.setPixelDiffThreshold(2);
        // The forward button only has a hover state if the button is actually active, so navigate
        // a bit.
        mVrTestRule.loadUrl("chrome://version/", PAGE_LOAD_TIMEOUT_S);
        VrBrowserTransitionUtils.navigateBack();
        ChromeTabUtils.waitForTabPageLoaded(
                mVrTestRule.getActivity().getActivityTab(), "about:blank");
        // Make the overflow menu appear.
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.RELOAD_BUTTON, true /* visible */, () -> {
                    NativeUiUtils.clickElement(UserFriendlyElementName.OVERFLOW_MENU, new PointF());
                });
        // Reload button.
        NativeUiUtils.hoverElement(UserFriendlyElementName.RELOAD_BUTTON, new PointF());
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                generateRenderTestIdentifier("reload_button_hover", incognito), mRenderTestRule);
        // Forward Button.
        NativeUiUtils.hoverElement(UserFriendlyElementName.FORWARD_BUTTON, new PointF());
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                generateRenderTestIdentifier("forward_button_hover", incognito), mRenderTestRule);
        // New Incognito tab button/close Incognito tabs button.
        if (incognito) {
            NativeUiUtils.hoverElement(UserFriendlyElementName.CLOSE_INCOGNITO_TABS, new PointF());
            NativeUiUtils.waitForUiQuiescence();
            RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                    generateRenderTestIdentifier("close_incognito_tabs_hover", incognito),
                    mRenderTestRule);
        } else {
            NativeUiUtils.hoverElement(UserFriendlyElementName.NEW_INCOGNITO_TAB, new PointF());
            NativeUiUtils.waitForUiQuiescence();
            RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                    generateRenderTestIdentifier("new_incognito_tab_hover", incognito),
                    mRenderTestRule);
        }
    }

    private String generateRenderTestIdentifier(String name, boolean incognito) {
        return name + (incognito ? "_incognito" : "") + "_browser_ui";
    }

    /**
     * Tests that highlighting suggestions looks correct and that clicking just outside of the
     * suggestion doesn't trigger its onclick. Regression test for https://crbug.com/799593.
     */
    @Test
    @MediumTest
    @Feature({"Browser", "RenderTest"})
    public void testSuggestionHovering()
            throws InterruptedException, TimeoutException, IOException {
        // Input some text to get suggestions.
        NativeUiUtils.enableMockedKeyboard();
        NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
        NativeUiUtils.performActionAndWaitForVisibilityStatus(
                UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
                () -> { NativeUiUtils.inputString("chrome://"); });

        // We need to crop the image before comparing to avoid the blinking cursor in the omnibox.
        // So, crop roughly around the suggestion box. This tends to chop off the bottom half of
        // the bottom suggestion on larger devices, but that's preferable to accidentally getting
        // the omnibox in the image, and should still be sufficient to catch the intended issues
        // (hover states, clicks actually registering).
        final RectF cropBounds = new RectF(0.1f, 0.4f, 0.6f, 0.625f);

        // There should be three suggestions, so hover the top then the middle one to ensure that
        // the hover effect properly moves between the two.
        NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, 0.3f));
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "suggestion_hovering_top", cropBounds, mRenderTestRule);
        NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF());
        NativeUiUtils.waitForUiQuiescence();
        RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "suggestion_hovering_middle", cropBounds, mRenderTestRule);

        // Ensure that the hover effect disappears when slightly to the right of the suggestion and
        // that clicking doesn't do anything.
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.51f, 0.0f));
        RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "suggestion_clicking_right", cropBounds, mRenderTestRule);
        // Again on the left side.
        NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF());
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.SUGGESTION_BOX, new PointF(-0.51f, 0.0f));
        RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "suggestion_clicking_left", cropBounds, mRenderTestRule);
        // Again above the top suggestion.
        NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, 0.3f));
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, 0.51f));
        RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "suggestion_clicking_top", cropBounds, mRenderTestRule);
        // Again below the bottom suggestion.
        NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, -0.3f));
        // For some reason, we have to aim slightly more offset than in other directions in order
        // to not actually hit the suggestion (probably due to the way we calculate where to click
        // not taking into account where the controller is, so hit testing can produce a slightly
        // different result).
        NativeUiUtils.clickElementAndWaitForUiQuiescence(
                UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, -0.55f));
        RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
                "suggestion_clicking_bottom", cropBounds, mRenderTestRule);
    }
}
