// Copyright 2015 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;

import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;

import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.os.Debug;
import android.os.SystemClock;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.FlakyTest;
import org.chromium.base.test.util.Restriction;
import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.compositor.layouts.Layout;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromePhone;
import org.chromium.chrome.browser.compositor.layouts.StaticLayout;
import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeEventFilter.ScrollDirection;
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler;
import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack;
import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
import org.chromium.chrome.browser.tabmodel.TabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
import org.chromium.chrome.browser.tabmodel.TabModelUtils;
import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy;
import org.chromium.chrome.browser.toolbar.ToolbarPhone;
import org.chromium.chrome.test.ChromeTabbedActivityTestBase;
import org.chromium.chrome.test.util.ApplicationTestUtils;
import org.chromium.chrome.test.util.ChromeRestriction;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.MenuUtils;
import org.chromium.chrome.test.util.NewTabPageTestUtils;
import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content.browser.test.util.DOMUtils;
import org.chromium.content.browser.test.util.JavaScriptUtils;
import org.chromium.content.browser.test.util.UiUtils;
import org.chromium.content.common.ContentSwitches;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.net.test.EmbeddedTestServer;

import java.io.File;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * General Tab tests.
 */
public class TabsTest extends ChromeTabbedActivityTestBase {

    private static final String TEST_FILE_PATH =
            "/chrome/test/data/android/tabstest/tabs_test.html";
    private static final String TEST_PAGE_FILE_PATH = "/chrome/test/data/google/google.html";

    private EmbeddedTestServer mTestServer;

    private float mPxToDp = 1.0f;
    private float mTabsViewHeightDp;
    private float mTabsViewWidthDp;

    private boolean mNotifyChangedCalled;

    private static final int SWIPE_TO_RIGHT_DIRECTION = 1;
    private static final int SWIPE_TO_LEFT_DIRECTION = -1;

    private static final long WAIT_RESIZE_TIMEOUT_MS = 3000;

    private static final int STRESSFUL_TAB_COUNT = 100;

    private static final String INITIAL_SIZE_TEST_URL = UrlUtils.encodeHtmlDataUri(
            "<html><head><meta name=\"viewport\" content=\"width=device-width\">"
            + "<script>"
            + "  document.writeln(window.innerWidth + ',' + window.innerHeight);"
            + "</script></head>"
            + "<body>"
            + "</body></html>");

    private static final String RESIZE_TEST_URL = UrlUtils.encodeHtmlDataUri(
            "<html><head><script>"
            + "  var resizeHappened = false;"
            + "  function onResize() {"
            + "    resizeHappened = true;"
            + "    document.getElementById('test').textContent ="
            + "       window.innerWidth + 'x' + window.innerHeight;"
            + "  }"
            + "</script></head>"
            + "<body onresize=\"onResize()\">"
            + "  <div id=\"test\">No resize event has been received yet.</div>"
            + "</body></html>");

    @Override
    protected void tearDown() throws Exception {
        if (mTestServer != null) {
            mTestServer.stopAndDestroyServer();
        }
        super.tearDown();
    }

    /**
     * Verify that spawning a popup from a background tab in a different model works properly.
     * @throws InterruptedException
     * @throws TimeoutException
     */
    @LargeTest
    @Feature({"Navigation"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @CommandLineFlags.Add(ContentSwitches.DISABLE_POPUP_BLOCKING)
    @RetryOnFailure
    public void testSpawnPopupOnBackgroundTab() throws InterruptedException, TimeoutException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        loadUrl(mTestServer.getURL(TEST_FILE_PATH));
        final Tab tab = getActivity().getActivityTab();

        newIncognitoTabFromMenu();

        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                tab.getWebContents().evaluateJavaScriptForTests(
                        "(function() {"
                        + "  window.open('www.google.com');"
                        + "})()",
                        null);
            }
        });

        CriteriaHelper.pollUiThread(Criteria.equals(2, new Callable<Integer>() {
            @Override
            public Integer call() {
                return getActivity().getTabModelSelector().getModel(false).getCount();
            }
        }));
    }

    @MediumTest
    @RetryOnFailure
    public void testAlertDialogDoesNotChangeActiveModel() throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        newIncognitoTabFromMenu();
        loadUrl(mTestServer.getURL(TEST_FILE_PATH));
        final Tab tab = getActivity().getActivityTab();
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                tab.getWebContents().evaluateJavaScriptForTests(
                        "(function() {"
                        + "  alert('hi');"
                        + "})()",
                        null);
            }
        });

        final AtomicReference<JavascriptAppModalDialog> dialog =
                new AtomicReference<>();

        CriteriaHelper.pollInstrumentationThread(new Criteria() {
            @Override
            public boolean isSatisfied() {
                dialog.set(JavascriptAppModalDialog.getCurrentDialogForTest());

                return dialog.get() != null;
            }
        });

        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                dialog.get().onClick(null, DialogInterface.BUTTON_POSITIVE);
            }
        });

        dialog.set(null);

        CriteriaHelper.pollInstrumentationThread(new Criteria() {
            @Override
            public boolean isSatisfied() {
                return JavascriptAppModalDialog.getCurrentDialogForTest() == null;
            }
        });

        assertTrue("Incognito model was not selected",
                getActivity().getTabModelSelector().isIncognitoSelected());
    }

    /**
     * Verify New Tab Open and Close Event not from the context menu.
     * @throws InterruptedException
     *
     * https://crbug.com/490473
     * @LargeTest
     * @Feature({"Android-TabSwitcher"})
     * @Restriction(RESTRICTION_TYPE_PHONE)
     */
    @DisabledTest
    public void testOpenAndCloseNewTabButton() throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        startMainActivityWithURL(mTestServer.getURL(TEST_FILE_PATH));
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                String title = getActivity().getCurrentTabModel().getTabAt(0).getTitle();
                assertEquals("Data file for TabsTest", title);
            }
        });
        final int tabCount = getActivity().getCurrentTabModel().getCount();
        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
                getActivity().getLayoutManager(), true, false);
        View tabSwitcherButton = getActivity().findViewById(R.id.tab_switcher_button);
        assertNotNull("'tab_switcher_button' view is not found", tabSwitcherButton);
        singleClickView(tabSwitcherButton);
        overviewModeWatcher.waitForBehavior();
        overviewModeWatcher = new OverviewModeBehaviorWatcher(
                getActivity().getLayoutManager(), false, true);
        View newTabButton = getActivity().findViewById(R.id.new_tab_button);
        assertNotNull("'new_tab_button' view is not found", newTabButton);
        singleClickView(newTabButton);
        overviewModeWatcher.waitForBehavior();

        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                assertEquals("The tab count is wrong",
                        tabCount + 1, getActivity().getCurrentTabModel().getCount());
            }
        });

        CriteriaHelper.pollUiThread(new Criteria() {
            @Override
            public boolean isSatisfied() {
                Tab tab = getActivity().getCurrentTabModel().getTabAt(1);
                String title = tab.getTitle().toLowerCase(Locale.US);
                String expectedTitle = "new tab";
                return title.startsWith(expectedTitle);
            }
        });

        ChromeTabUtils.closeCurrentTab(getInstrumentation(), getActivity());
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                assertEquals(tabCount, getActivity().getCurrentTabModel().getCount());
            }
        });
    }

    private void assertWaitForKeyboardStatus(final boolean show) throws InterruptedException {
        CriteriaHelper.pollUiThread(new Criteria() {
            @Override
            public boolean isSatisfied() {
                updateFailureReason("expected keyboard show: " + show);
                return show
                        == org.chromium.ui.UiUtils.isKeyboardShowing(
                                   getActivity(), getActivity().getTabsView());
            }
        });
    }

    /**
     * Verify that opening a new tab, switching to an existing tab and closing current tab hide
     * keyboard.
     */
    @LargeTest
    @Restriction(ChromeRestriction.RESTRICTION_TYPE_TABLET)
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testHideKeyboard() throws Exception {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());

        // Open a new tab(The 1st tab) and click node.
        ChromeTabUtils.fullyLoadUrlInNewTab(
                getInstrumentation(), getActivity(), mTestServer.getURL(TEST_FILE_PATH), false);
        assertEquals("Failed to click node.", true,
                DOMUtils.clickNode(
                        this, getActivity().getActivityTab().getContentViewCore(), "input_text"));
        assertWaitForKeyboardStatus(true);

        // Open a new tab(the 2nd tab).
        ChromeTabUtils.fullyLoadUrlInNewTab(
                getInstrumentation(), getActivity(), mTestServer.getURL(TEST_FILE_PATH), false);
        assertWaitForKeyboardStatus(false);

        // Click node in the 2nd tab.
        DOMUtils.clickNode(this, getActivity().getActivityTab().getContentViewCore(), "input_text");
        assertWaitForKeyboardStatus(true);

        // Switch to the 1st tab.
        ChromeTabUtils.switchTabInCurrentTabModel(getActivity(), 1);
        assertWaitForKeyboardStatus(false);

        // Click node in the 1st tab.
        DOMUtils.clickNode(this, getActivity().getActivityTab().getContentViewCore(), "input_text");
        assertWaitForKeyboardStatus(true);

        // Close current tab(the 1st tab).
        ChromeTabUtils.closeCurrentTab(getInstrumentation(), getActivity());
        assertWaitForKeyboardStatus(false);
    }

    /**
     * Verify that opening a new window hides keyboard.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testHideKeyboardWhenOpeningWindow() throws Exception {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        // Open a new tab and click an editable node.
        ChromeTabUtils.fullyLoadUrlInNewTab(
                getInstrumentation(), getActivity(), mTestServer.getURL(TEST_FILE_PATH), false);
        assertEquals("Failed to click textarea.", true,
                DOMUtils.clickNode(
                        this, getActivity().getActivityTab().getContentViewCore(), "textarea"));
        assertWaitForKeyboardStatus(true);

        // Click the button to open a new window.
        assertEquals("Failed to click button.", true,
                DOMUtils.clickNode(
                        this, getActivity().getActivityTab().getContentViewCore(), "button"));
        assertWaitForKeyboardStatus(false);
    }

    /**
     * Verify that opening a new tab and navigating immediately sets a size on the newly created
     * renderer. https://crbug.com/434477.
     * @throws InterruptedException
     * @throws TimeoutException
     */
    @SmallTest
    @RetryOnFailure
    public void testNewTabSetsContentViewSize() throws InterruptedException, TimeoutException {
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        getInstrumentation().waitForIdleSync();

        // Make sure we're on the NTP
        Tab tab = getActivity().getActivityTab();
        NewTabPageTestUtils.waitForNtpLoaded(tab);

        loadUrl(INITIAL_SIZE_TEST_URL);

        final WebContents webContents = tab.getWebContents();
        String innerText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
                webContents, "document.body.innerText").replace("\"", "");

        DisplayMetrics metrics = getActivity().getResources().getDisplayMetrics();

        // For non-integer pixel ratios like the N7v1 (1.333...), the layout system will actually
        // ceil the width.
        int expectedWidth = (int) Math.ceil(metrics.widthPixels / metrics.density);

        String[] nums = innerText.split(",");
        assertTrue(nums.length == 2);
        int innerWidth = Integer.parseInt(nums[0]);
        int innerHeight = Integer.parseInt(nums[1]);

        assertEquals(expectedWidth, innerWidth);

        // Height can be affected by browser controls so just make sure it's non-0.
        assertTrue("innerHeight was not set by page load time", innerHeight > 0);
    }

    static class SimulateClickOnMainThread implements Runnable {
        private final LayoutManagerChrome mLayoutManager;
        private final float mX;
        private final float mY;

        public SimulateClickOnMainThread(LayoutManagerChrome layoutManager, float x, float y) {
            mLayoutManager = layoutManager;
            mX = x;
            mY = y;
        }

        @Override
        public void run() {
            mLayoutManager.simulateClick(mX, mY);
        }
    }

    static class SimulateTabSwipeOnMainThread implements Runnable {
        private final LayoutManagerChrome mLayoutManager;
        private final float mX;
        private final float mY;
        private final float mDeltaX;
        private final float mDeltaY;

        public SimulateTabSwipeOnMainThread(LayoutManagerChrome layoutManager, float x, float y,
                float dX, float dY) {
            mLayoutManager = layoutManager;
            mX = x;
            mY = y;
            mDeltaX = dX;
            mDeltaY = dY;
        }

        @Override
        public void run() {
            mLayoutManager.simulateDrag(mX, mY, mDeltaX, mDeltaY);
        }
    }

    /**
     * Verify that the provided click position closes a tab.
     * @throws InterruptedException
     */
    private void checkCloseTabAtPosition(final float x, final float y)
            throws InterruptedException {
        getActivity();

        int initialTabCount = getActivity().getCurrentTabModel().getCount();
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        getInstrumentation().waitForIdleSync();
        View button = getActivity().findViewById(R.id.tab_switcher_button);
        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
                getActivity().getLayoutManager(), true, false);
        singleClickView(button);
        overviewModeWatcher.waitForBehavior();
        assertTrue("Expected: " + (initialTabCount + 1) + " tab Got: "
                + getActivity().getCurrentTabModel().getCount(),
                (initialTabCount + 1) == getActivity().getCurrentTabModel().getCount());
        getInstrumentation().waitForIdleSync();
        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        ChromeTabUtils.closeTabWithAction(getInstrumentation(), getActivity(), new Runnable() {
            @Override
            public void run() {
                getInstrumentation().runOnMainSync(
                        new SimulateClickOnMainThread(layoutManager, x, y));
            }
        });
        assertTrue("Expected: " + initialTabCount + " tab Got: "
                + getActivity().getCurrentTabModel().getCount(),
                initialTabCount == getActivity().getCurrentTabModel().getCount());
    }

    /**
     * Verify close button works in the TabSwitcher in portrait mode.
     * This code does not handle properly different screen densities.
     * @throws InterruptedException
     */
    @LargeTest
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testTabSwitcherPortraitCloseButton() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        int portraitWidth = Math.min(getActivity().getResources().getDisplayMetrics().widthPixels,
                getActivity().getResources().getDisplayMetrics().heightPixels);
        // Hard-coded coordinates of the close button on the top right of the screen.
        // If the coordinates need to be updated, the easiest is to take a screenshot and measure.
        // Note that starting from the right of the screen should cover any screen size.
        checkCloseTabAtPosition(portraitWidth * mPxToDp - 32, 70);
    }

    /**
     * Verify close button works in the TabSwitcher in landscape mode.
     * This code does not handle properly different screen densities.
     * @throws InterruptedException
     * @Restriction({RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
     * @LargeTest
     * @Feature({"Android-TabSwitcher"})
     */
    @FlakyTest(message = "crbug.com/170179")
    public void testTabSwitcherLandscapeCloseButton() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        // Hard-coded coordinates of the close button on the bottom left of the screen.
        // If the coordinates need to be updated, the easiest is to take a screenshot and measure.
        checkCloseTabAtPosition(31 * mPxToDp, 31 * mPxToDp);
    }

    /**
     * Verify that we can open a large number of tabs without running out of
     * memory. This test waits for the NTP to load before opening the next one.
     * This is a LargeTest but because we're doing it "slowly", we need to further scale
     * the timeout for adb am instrument and the various events.
     */
    /*
     * @EnormousTest
     * @TimeoutScale(10)
     * @Feature({"Android-TabSwitcher"})
     * Bug crbug.com/166208
     */
    @DisabledTest
    public void testOpenManyTabsSlowly() throws InterruptedException {
        int startCount = getActivity().getCurrentTabModel().getCount();
        for (int i = 1; i <= STRESSFUL_TAB_COUNT; ++i) {
            ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
            getInstrumentation().waitForIdleSync();
            assertEquals(startCount + i, getActivity().getCurrentTabModel().getCount());
        }
    }

    /**
     * Verify that we can open a large number of tabs without running out of
     * memory. This test hammers the "new tab" button quickly to stress the app.
     *
     * @LargeTest
     * @TimeoutScale(10)
     * @Feature({"Android-TabSwitcher"})
     *
     */
    @FlakyTest
    public void testOpenManyTabsQuickly() {
        int startCount = getActivity().getCurrentTabModel().getCount();
        for (int i = 1; i <= STRESSFUL_TAB_COUNT; ++i) {
            MenuUtils.invokeCustomMenuActionSync(getInstrumentation(), getActivity(),
                    R.id.new_tab_menu_id);
            assertEquals(startCount + i, getActivity().getCurrentTabModel().getCount());
        }
    }

    /**
     * Verify that we can open a burst of new tabs, even when there are already
     * a large number of tabs open.
     * Bug: crbug.com/180718
     * @EnormousTest
     * @TimeoutScale(30)
     * @Feature({"Navigation"})
     */
    @FlakyTest
    public void testOpenManyTabsInBursts() throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        final int burstSize = 5;
        final String url = mTestServer.getURL(TEST_PAGE_FILE_PATH);
        final int startCount = getActivity().getCurrentTabModel().getCount();
        for (int tabCount = startCount; tabCount < STRESSFUL_TAB_COUNT; tabCount += burstSize)  {
            loadUrlInManyNewTabs(url, burstSize);
            assertEquals(tabCount + burstSize, getActivity().getCurrentTabModel().getCount());
        }
    }

    /**
     * Verify opening 10 tabs at once and that each tab loads when selected.
     */
    /*
     * @EnormousTest
     * @TimeoutScale(30)
     * @Feature({"Navigation"})
     */
    @FlakyTest(message = "crbug.com/223110")
    public void testOpenManyTabsAtOnce10() throws InterruptedException {
        openAndVerifyManyTestTabs(10);
    }

    /**
     * Verify that we can open a large number of tabs all at once and that each
     * tab loads when selected.
     */
    private void openAndVerifyManyTestTabs(final int num) throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        final String url = mTestServer.getURL(TEST_PAGE_FILE_PATH);
        int startCount = getActivity().getCurrentTabModel().getCount();
        loadUrlInManyNewTabs(url, num);
        assertEquals(startCount + num,
                     getActivity().getCurrentTabModel().getCount());
    }

    class ClickOptionButtonOnMainThread implements Runnable {
        @Override
        public void run() {
            // This is equivalent to clickById(R.id.tab_switcher_button) but does not rely on the
            // event pipeline.
            View button = getActivity().findViewById(R.id.tab_switcher_button);
            assertNotNull("Could not find view R.id.tab_switcher_button", button);
            View toolbar = getActivity().findViewById(R.id.toolbar);
            assertNotNull("Could not find view R.id.toolbar", toolbar);
            assertTrue("R.id.toolbar is not a ToolbarPhone", toolbar instanceof ToolbarPhone);
            ((ToolbarPhone) toolbar).onClick(button);
        }
    }

    /**
     * Displays the tabSwitcher mode and wait for it to settle.
     */
    private void showOverviewAndWaitForAnimation() throws InterruptedException {
        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
                getActivity().getLayoutManager(), true, false);
        // For some unknown reasons calling clickById(R.id.tab_switcher_button) sometimes hang.
        // The following is verbose but more reliable.
        getInstrumentation().runOnMainSync(new ClickOptionButtonOnMainThread());
        overviewModeWatcher.waitForBehavior();
    }

    /**
     * Exits the tabSwitcher mode and wait for it to settle.
     */
    private void hideOverviewAndWaitForAnimation() throws InterruptedException {
        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
                getActivity().getLayoutManager(), false, true);
        getInstrumentation().runOnMainSync(new ClickOptionButtonOnMainThread());
        overviewModeWatcher.waitForBehavior();
    }

    /**
     * Opens tabs to populate the model to a given count.
     * @param targetTabCount The desired number of tabs in the model.
     * @param waitToLoad     Whether the tabs need to be fully loaded.
     * @return               The new number of tabs in the model.
     * @throws InterruptedException
     */
    private int openTabs(final int targetTabCount, boolean waitToLoad) throws InterruptedException {
        int tabCount = getActivity().getCurrentTabModel().getCount();
        while (tabCount < targetTabCount) {
            ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
            tabCount++;
            assertEquals("The tab count is wrong",
                    tabCount, getActivity().getCurrentTabModel().getCount());
            Tab tab = TabModelUtils.getCurrentTab(getActivity().getCurrentTabModel());
            while (waitToLoad && tab.isLoading()) {
                Thread.yield();
            }
        }
        return tabCount;
    }

    /**
     * Verifies that when more than 9 tabs are open only at most 8 are drawn. Basically it verifies
     * that the tab culling mechanism works properly.
     */
    /*
       @LargeTest
       @Feature({"Android-TabSwitcher"})
    */
    @DisabledTest(message = "crbug.com/156746")
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    public void testTabsCulling() throws InterruptedException {
        // Open one more tabs than maxTabsDrawn.
        final int maxTabsDrawn = 8;
        int tabCount = openTabs(maxTabsDrawn + 1, false);
        showOverviewAndWaitForAnimation();

        // Check counts.
        LayoutManagerChromePhone layoutManager =
                (LayoutManagerChromePhone) getActivity().getLayoutManager();
        int drawnCount = layoutManager.getOverviewLayout().getLayoutTabsToRender().length;
        int drawnExpected = Math.min(tabCount, maxTabsDrawn);
        assertEquals("The number of drawn tab is wrong", drawnExpected, drawnCount);
    }

    /**
     * Checks the stacked tabs in the stack are visible.
     * @throws InterruptedException
     */
    private void checkTabsStacking() throws InterruptedException {
        final int count = getActivity().getCurrentTabModel().getCount();
        assertEquals("The number of tab in the stack should match the number of tabs in the model",
                count, getLayoutTabInStackCount(false));

        assertTrue("The selected tab should always be visible",
                stackTabIsVisible(false, getActivity().getCurrentTabModel().index()));
        for (int i = 0; i < Stack.MAX_NUMBER_OF_STACKED_TABS_TOP && i < count; i++) {
            assertTrue("The stacked tab " + i + " from the top should always be visible",
                    stackTabIsVisible(false, i));
        }
        for (int i = 0; i < Stack.MAX_NUMBER_OF_STACKED_TABS_BOTTOM && i < count; i++) {
            assertTrue("The stacked tab " + i + " from the bottom should always be visible",
                    stackTabIsVisible(false, count - 1 - i));
        }
    }

    /**
     * Verifies that the tab are actually stacking at the bottom and top of the screen.
     */
    /**
     * @LargeTest
     * @Feature({"Android-TabSwitcher"})
     */
    @FlakyTest(message = "crbug.com/170179")
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    public void testTabsStacking() throws InterruptedException {
        final int count = openTabs(12, false);

        // Selecting the first tab to scroll all the way to the top.
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                TabModelUtils.setIndex(getActivity().getCurrentTabModel(), 0);
            }
        });
        showOverviewAndWaitForAnimation();
        checkTabsStacking();

        // Selecting the last tab to scroll all the way to the bottom.
        hideOverviewAndWaitForAnimation();
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                TabModelUtils.setIndex(getActivity().getCurrentTabModel(), count - 1);
            }
        });
        showOverviewAndWaitForAnimation();
        checkTabsStacking();
    }

    /**
     * @return A stable read of allocated size (native + dalvik) after gc.
     */
    @SuppressFBWarnings("DM_GC")
    private long getStableAllocatedSize() {
        // Measure the equivalent of allocated size native + dalvik in:
        // adb shell dumpsys meminfo | grep chrome -A 20
        int maxTries = 8;
        int tries = 0;
        long threshold = 512; // bytes
        long lastAllocatedSize = Long.MAX_VALUE;
        long currentAllocatedSize = 0;
        while (tries < maxTries && Math.abs(currentAllocatedSize - lastAllocatedSize) > threshold) {
            System.gc();
            try {
                Thread.sleep(1000 + tries * 500); // Memory measurement is not an exact science...
                lastAllocatedSize = currentAllocatedSize;
                currentAllocatedSize = Debug.getNativeHeapAllocatedSize()
                        + Runtime.getRuntime().totalMemory();
                //Log.w("MEMORY_MEASURE", "[" + tries + "/" + maxTries + "]" +
                //        "currentAllocatedSize " + currentAllocatedSize);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tries++;
        }
        assertTrue("Could not have a stable read on native allocated size even after "
                + tries + " gc.", tries < maxTries);
        return currentAllocatedSize;
    }

    /**
     * Verify that switching back and forth to the tabswitcher does not leak memory.
     */
    /**
     * @LargeTest
     * @Feature({"Android-TabSwitcher"})
     */
    @FlakyTest(message = "crbug.com/303319")
    @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE)
    public void testTabSwitcherMemoryLeak() throws InterruptedException {
        openTabs(4, true);

        int maxTries = 10;
        int tries = 0;
        long threshold = 1024; // bytes
        long lastAllocatedSize = 0;
        long currentAllocatedSize = 2 * threshold;
        while (tries < maxTries && (lastAllocatedSize + threshold) < currentAllocatedSize) {
            showOverviewAndWaitForAnimation();

            lastAllocatedSize = currentAllocatedSize;
            currentAllocatedSize = getStableAllocatedSize();
            //Log.w("MEMORY_TEST", "[" + tries + "/" + maxTries + "]" +
            //        "currentAllocatedSize " + currentAllocatedSize);

            hideOverviewAndWaitForAnimation();
            tries++;
        }

        assertTrue("Native heap allocated size keeps increasing even after "
                + tries + " iterations", tries < maxTries);
    }

    /**
     * Verify that switching back and forth stay stable. This test last for at least 8 seconds.
     */
    @LargeTest
    @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE)
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testTabSwitcherStability() throws InterruptedException {
        openTabs(8, true);

        // This is about as fast as you can ever click.
        final long fastestUserInput = 20; // ms
        for (int i = 0; i < 200; i++) {
            // Show overview
            getInstrumentation().runOnMainSync(new ClickOptionButtonOnMainThread());
            Thread.sleep(fastestUserInput);

            // hide overview
            getInstrumentation().runOnMainSync(new ClickOptionButtonOnMainThread());
            Thread.sleep(fastestUserInput);
        }
    }

    @LargeTest
    @Feature({"Android-TabSwitcher"})
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    public void testTabSelectionPortrait() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        checkTabSelection(2, 0, false);

        // Ensure all tabs following the selected tab are off the screen when the animation is
        // complete.
        final int count = getLayoutTabInStackCount(false);
        for (int i = 1; i < count; i++) {
            float y = getLayoutTabInStackXY(false, i)[1];
            assertTrue(
                    String.format(Locale.US,
                            "Tab %d's final draw Y, %f, should exceed the view height, %f.",
                            i, y, mTabsViewHeightDp),
                    y >= mTabsViewHeightDp);
        }
    }

    /**
     * @LargeTest
     * @Feature({"Android-TabSwitcher"})
     */
    @FlakyTest(message = "crbug.com/170179")
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    public void testTabSelectionLandscape() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        checkTabSelection(2, 0, true);

        // Ensure all tabs following the selected tab are off the screen when the animation is
        // complete.
        final int count = getLayoutTabInStackCount(false);
        for (int i = 1; i < count; i++) {
            float x = getLayoutTabInStackXY(false, i)[0];
            assertTrue(
                    String.format(Locale.US,
                            "Tab %d's final draw X, %f, should exceed the view width, %f.",
                            i, x, mTabsViewWidthDp),
                    x >= mTabsViewWidthDp);
        }
    }

    /**
     * Verify that we don't crash and show the overview mode after closing the last tab.
     */
    @SmallTest
    @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE)
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testCloseLastTabFromMain() throws InterruptedException {
        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
                getActivity().getLayoutManager(), true, false);
        ChromeTabUtils.closeCurrentTab(getInstrumentation(), getActivity());
        getInstrumentation().waitForIdleSync();
        overviewModeWatcher.waitForBehavior();
    }

    private LayoutManagerChrome updateTabsViewSize() {
        View tabsView = getActivity().getTabsView();
        mTabsViewHeightDp = tabsView.getHeight() * mPxToDp;
        mTabsViewWidthDp = tabsView.getWidth() * mPxToDp;
        return getActivity().getLayoutManager();
    }

    private Stack getStack(final LayoutManagerChrome layoutManager, boolean isIncognito) {
        assertTrue("getStack must be executed on the ui thread",
                ThreadUtils.runningOnUiThread());
        LayoutManagerChromePhone layoutManagerPhone = (LayoutManagerChromePhone) layoutManager;
        StackLayout layout = (StackLayout) layoutManagerPhone.getOverviewLayout();
        return (layout).getTabStack(isIncognito);
    }

    private int getLayoutTabInStackCount(final boolean isIncognito) {
        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        final int[] count = new int[1];
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                Stack stack = getStack(layoutManager, isIncognito);
                count[0] = stack.getTabs().length;
            }
        });
        return count[0];
    }

    private boolean stackTabIsVisible(final boolean isIncognito, final int index) {
        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        final boolean[] isVisible = new boolean[1];
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                Stack stack = getStack(layoutManager, isIncognito);
                isVisible[0] = (stack.getTabs())[index].getLayoutTab().isVisible();
            }
        });
        return isVisible[0];
    }

    private float[] getLayoutTabInStackXY(final boolean isIncognito, final int index) {
        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        final float[] xy = new float[2];
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                Stack stack = getStack(layoutManager, isIncognito);
                xy[0] = (stack.getTabs())[index].getLayoutTab().getX();
                xy[1] = (stack.getTabs())[index].getLayoutTab().getY();
            }
        });
        return xy;
    }

    private float[] getStackTabClickTarget(final int tabIndexToSelect, final boolean isIncognito,
            final boolean isLandscape) {
        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        final float[] target = new float[2];
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                Stack stack = getStack(layoutManager, isIncognito);
                StackTab[] tabs = stack.getTabs();
                // The position of the click is expressed from the top left corner of the content.
                // The aim is to find an offset that is inside the content but not on the close
                // button.  For this, we calculate the center of the visible tab area.
                LayoutTab layoutTab = tabs[tabIndexToSelect].getLayoutTab();
                LayoutTab nextLayoutTab = (tabIndexToSelect + 1) < tabs.length
                        ? tabs[tabIndexToSelect + 1].getLayoutTab() : null;

                float tabOffsetX = layoutTab.getX();
                float tabOffsetY = layoutTab.getY();
                float tabRightX, tabBottomY;
                if (isLandscape) {
                    tabRightX = nextLayoutTab != null
                            ? nextLayoutTab.getX()
                            : tabOffsetX + layoutTab.getScaledContentWidth();
                    tabBottomY = tabOffsetY + layoutTab.getScaledContentHeight();
                } else {
                    tabRightX = tabOffsetX + layoutTab.getScaledContentWidth();
                    tabBottomY = nextLayoutTab != null
                            ? nextLayoutTab.getY()
                            : tabOffsetY + layoutTab.getScaledContentHeight();
                }
                tabRightX = Math.min(tabRightX, mTabsViewWidthDp);
                tabBottomY = Math.min(tabBottomY, mTabsViewHeightDp);

                target[0] = (tabOffsetX + tabRightX) / 2.0f;
                target[1] = (tabOffsetY + tabBottomY) / 2.0f;
            }
        });
        return target;
    }

    private void checkTabSelection(int additionalTabsToOpen, int tabIndexToSelect,
            boolean isLandscape) throws InterruptedException {
        for (int i = 0; i < additionalTabsToOpen; i++) {
            ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        }
        assertEquals("Number of open tabs does not match",
                additionalTabsToOpen + 1 , getActivity().getCurrentTabModel().getCount());
        showOverviewAndWaitForAnimation();

        float[] coordinates = getStackTabClickTarget(tabIndexToSelect, false, isLandscape);
        float clickX = coordinates[0];
        float clickY = coordinates[1];

        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
                getActivity().getLayoutManager(), false, true);

        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        getInstrumentation().runOnMainSync(new SimulateClickOnMainThread(layoutManager,
                (int) clickX, (int) clickY));
        overviewModeWatcher.waitForBehavior();

        // Make sure we did not accidentally close a tab.
        assertEquals("Number of open tabs does not match",
                additionalTabsToOpen + 1 , getActivity().getCurrentTabModel().getCount());
    }

    public void swipeToCloseTab(final int tabIndexToClose, final boolean isLandscape,
            final boolean isIncognito, final int swipeDirection) throws InterruptedException {
        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        float[] coordinates = getStackTabClickTarget(tabIndexToClose, isIncognito, isLandscape);
        final float clickX = coordinates[0];
        final float clickY = coordinates[1];
        Log.v("ChromeTest", String.format("clickX %f clickY %f", clickX, clickY));

        ChromeTabUtils.closeTabWithAction(getInstrumentation(), getActivity(), new Runnable() {
            @Override
            public void run() {
                if (isLandscape) {
                    getInstrumentation().runOnMainSync(new SimulateTabSwipeOnMainThread(
                            layoutManager, clickX, clickY, 0, swipeDirection * mTabsViewWidthDp));
                } else {
                    getInstrumentation().runOnMainSync(new SimulateTabSwipeOnMainThread(
                            layoutManager, clickX, clickY, swipeDirection * mTabsViewHeightDp, 0));
                }
            }
        });

        CriteriaHelper.pollUiThread(new Criteria("Did not finish animation") {
            @Override
            public boolean isSatisfied() {
                Layout layout = getActivity().getLayoutManager().getActiveLayout();
                return !layout.isLayoutAnimating();
            }
        });
    }

    private void swipeToCloseNTabs(int number, boolean isLandscape, boolean isIncognito,
            int swipeDirection)
            throws InterruptedException {

        for (int i = number - 1; i >= 0; i--) {
            swipeToCloseTab(i, isLandscape, isIncognito, swipeDirection);
        }
    }

    /**
     * Test closing few tabs by swiping them in Overview portrait mode.
     */
    @MediumTest
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @Feature({"Android-TabSwitcher", "Main"})
    @RetryOnFailure
    public void testCloseTabPortrait() throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        startMainActivityWithURL(mTestServer.getURL("/chrome/test/data/android/test.html"));

        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        int tabCount = getActivity().getCurrentTabModel().getCount();
        ChromeTabUtils.newTabsFromMenu(getInstrumentation(), getActivity(), 3);
        assertEquals("wrong count after new tabs", tabCount + 3,
                getActivity().getCurrentTabModel().getCount());

        showOverviewAndWaitForAnimation();
        swipeToCloseNTabs(3, false, false, SWIPE_TO_LEFT_DIRECTION);

        assertEquals("Wrong tab counts after closing a few of them",
                tabCount, getActivity().getCurrentTabModel().getCount());
    }

    /**
     * Test closing few tabs by swiping them in Overview landscape mode.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher", "Main"})
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @RetryOnFailure
    public void testCloseTabLandscape() throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        startMainActivityWithURL(mTestServer.getURL("/chrome/test/data/android/test.html"));

        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        int tabCount = getActivity().getCurrentTabModel().getCount();
        ChromeTabUtils.newTabsFromMenu(getInstrumentation(), getActivity(), 3);
        assertEquals("wrong count after new tabs", tabCount + 3,
                getActivity().getCurrentTabModel().getCount());

        showOverviewAndWaitForAnimation();
        swipeToCloseTab(0, true, false, SWIPE_TO_LEFT_DIRECTION);
        swipeToCloseTab(0, true, false, SWIPE_TO_LEFT_DIRECTION);
        swipeToCloseTab(0, true, false, SWIPE_TO_LEFT_DIRECTION);

        assertEquals("Wrong tab counts after closing a few of them",
                tabCount, getActivity().getCurrentTabModel().getCount());
    }

    /**
     * Test close Incognito tab by swiping in Overview Portrait mode.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @RetryOnFailure
    public void testCloseIncognitoTabPortrait() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        newIncognitoTabsFromMenu(2);

        showOverviewAndWaitForAnimation();
        UiUtils.settleDownUI(getInstrumentation());
        swipeToCloseNTabs(2, false, true, SWIPE_TO_LEFT_DIRECTION);
    }

    /**
     * Test close 5 Incognito tabs by swiping in Overview Portrait mode.
     */
    @Feature({"Android-TabSwitcher"})
    @MediumTest
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @RetryOnFailure
    public void testCloseFiveIncognitoTabPortrait() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        newIncognitoTabsFromMenu(5);

        showOverviewAndWaitForAnimation();
        UiUtils.settleDownUI(getInstrumentation());
        swipeToCloseNTabs(5, false, true, SWIPE_TO_LEFT_DIRECTION);
    }

    /**
     * Simple swipe gesture should not close tabs when two Tabstacks are open in Overview mode.
     * Test in Portrait Mode.
     */
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    public void testSwitchTabStackWithoutClosingTabsInPortrait() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        newIncognitoTabFromMenu();
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());

        showOverviewAndWaitForAnimation();
        UiUtils.settleDownUI(getInstrumentation());
        final int normalTabCount = getLayoutTabInStackCount(false);
        final int incognitoTabCount = getLayoutTabInStackCount(true);

        LayoutManagerChrome layoutManager = updateTabsViewSize();

        // Swipe to Incognito Tabs.
        getInstrumentation().runOnMainSync(new SimulateTabSwipeOnMainThread(layoutManager,
                mTabsViewWidthDp - 20 , mTabsViewHeightDp / 2 ,
                SWIPE_TO_LEFT_DIRECTION * mTabsViewWidthDp, 0));
        UiUtils.settleDownUI(getInstrumentation());
        assertTrue("Tabs Stack should have been changed to incognito.",
                getActivity().getCurrentTabModel().isIncognito());
        assertEquals("Normal tabs count should be unchanged while switching to incognito tabs.",
                normalTabCount, getLayoutTabInStackCount(false));

        // Swipe to regular Tabs.
        getInstrumentation().runOnMainSync(new SimulateTabSwipeOnMainThread(layoutManager,
                20, mTabsViewHeightDp / 2,
                SWIPE_TO_RIGHT_DIRECTION * mTabsViewWidthDp, 0));
        UiUtils.settleDownUI(getInstrumentation());
        assertEquals("Incognito tabs count should be unchanged while switching back to normal "
                + "tab stack.", incognitoTabCount, getLayoutTabInStackCount(true));
        assertFalse("Tabs Stack should have been changed to regular tabs.",
                getActivity().getCurrentTabModel().isIncognito());
        assertEquals("Normal tabs count should be unchanged while switching back to normal tabs.",
                normalTabCount, getLayoutTabInStackCount(false));
    }

    /**
     * Simple swipe gesture should not close tabs when two Tabstacks are open in Overview mode.
     * Test in Landscape Mode.
     */
    /*
        @MediumTest
        @Feature({"Android-TabSwitcher"})
     */
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @DisabledTest(message = "crbug.com/157259")
    public void testSwitchTabStackWithoutClosingTabsInLandscape() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        newIncognitoTabFromMenu();
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());

        showOverviewAndWaitForAnimation();
        UiUtils.settleDownUI(getInstrumentation());
        final int normalTabCount = getLayoutTabInStackCount(false);
        final int incognitoTabCount = getLayoutTabInStackCount(true);

        LayoutManagerChrome layoutManager = updateTabsViewSize();

        // Swipe to Incognito Tabs.
        getInstrumentation().runOnMainSync(new SimulateTabSwipeOnMainThread(layoutManager,
                mTabsViewWidthDp / 2 , mTabsViewHeightDp - 20 ,
                0, SWIPE_TO_LEFT_DIRECTION * mTabsViewWidthDp));
        UiUtils.settleDownUI(getInstrumentation());
        assertTrue("Tabs Stack should have been changed to incognito.",
                getActivity().getCurrentTabModel().isIncognito());
        assertEquals("Normal tabs count should be unchanged while switching to incognito tabs.",
                normalTabCount, getLayoutTabInStackCount(false));

        // Swipe to regular Tabs.
        getInstrumentation().runOnMainSync(new SimulateTabSwipeOnMainThread(layoutManager,
                mTabsViewWidthDp / 2, 20,
                0, SWIPE_TO_RIGHT_DIRECTION * mTabsViewWidthDp));
        UiUtils.settleDownUI(getInstrumentation());
        assertEquals("Incognito tabs count should be unchanged while switching back to normal "
                + "tab stack.", incognitoTabCount, getLayoutTabInStackCount(true));
        assertFalse("Tabs Stack should have been changed to regular tabs.",
                getActivity().getCurrentTabModel().isIncognito());
        assertEquals("Normal tabs count should be unchanged while switching back to normal tabs.",
                normalTabCount, getLayoutTabInStackCount(false));
    }

    /**
     * Test close Incognito tab by swiping in Overview Landscape mode.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @RetryOnFailure
    public void testCloseIncognitoTabLandscape() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        newIncognitoTabFromMenu();

        showOverviewAndWaitForAnimation();
        UiUtils.settleDownUI(getInstrumentation());
        swipeToCloseTab(0, true, true, SWIPE_TO_LEFT_DIRECTION);
    }

    /**
     * Test close 5 Incognito tabs by swiping in Overview Landscape mode.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @RetryOnFailure
    public void testCloseFiveIncognitoTabLandscape() throws InterruptedException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        newIncognitoTabsFromMenu(5);

        showOverviewAndWaitForAnimation();
        UiUtils.settleDownUI(getInstrumentation());
        swipeToCloseNTabs(5, true, true, SWIPE_TO_LEFT_DIRECTION);
    }

    /**
     * Test that we can safely close a tab during a fling (http://b/issue?id=5364043)
     */
    @SmallTest
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testCloseTabDuringFling() throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        loadUrlInNewTab(mTestServer.getURL(
                "/chrome/test/data/android/tabstest/text_page.html"));
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                ContentViewCore view = getActivity().getActivityTab().getContentViewCore();
                view.flingViewport(SystemClock.uptimeMillis(), 0, -2000);
            }
        });
        ChromeTabUtils.closeCurrentTab(getInstrumentation(), getActivity());
    }

    /**
     * Flaky on instrumentation-yakju-clankium-ics. See https://crbug.com/431296.
     * @Restriction(RESTRICTION_TYPE_PHONE)
     * @MediumTest
     * @Feature({"Android-TabSwitcher"})
     */
    @FlakyTest
    public void testQuickSwitchBetweenTabAndSwitcherMode() throws InterruptedException {
        mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
        final String[] urls = {
                mTestServer.getURL("/chrome/test/data/android/navigate/one.html"),
                mTestServer.getURL("/chrome/test/data/android/navigate/two.html"),
                mTestServer.getURL("/chrome/test/data/android/navigate/three.html")};

        for (String url : urls) {
            loadUrlInNewTab(url);
        }

        int lastUrlIndex = urls.length - 1;

        View button = getActivity().findViewById(R.id.tab_switcher_button);
        assertNotNull("Could not find 'tab_switcher_button'", button);

        for (int i = 0; i < 15; i++) {
            singleClickView(button);
            // Switch back to the tab view from the tab-switcher mode.
            singleClickView(button);

            assertEquals("URL mismatch after switching back to the tab from tab-switch mode",
                    urls[lastUrlIndex], getActivity().getActivityTab().getUrl());
        }
    }

    /**
     * Open an incognito tab from menu and verify its property.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testOpenIncognitoTab() throws InterruptedException {
        newIncognitoTabFromMenu();

        assertTrue("Current Tab should be an incognito tab.",
                getActivity().getActivityTab().isIncognito());
    }

    /**
     * Test NewTab button on the browser toolbar.
     * Restricted to phones due crbug.com/429671.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE)
    @RetryOnFailure
    public void testNewTabButton() throws InterruptedException {
        MenuUtils.invokeCustomMenuActionSync(getInstrumentation(), getActivity(),
                R.id.close_all_tabs_menu_id);
        UiUtils.settleDownUI(getInstrumentation());

        CriteriaHelper.pollInstrumentationThread(new Criteria("Should be in overview mode") {
            @Override
            public boolean isSatisfied() {
                return getActivity().isInOverviewMode();
            }
        });

        int initialTabCount = getActivity().getCurrentTabModel().getCount();
        assertEquals("Tab count is expected to be 0 after closing all the tabs",
                0, initialTabCount);

        ChromeTabUtils.clickNewTabButton(this, this);

        int newTabCount = getActivity().getCurrentTabModel().getCount();
        assertEquals("Tab count is expected to be 1 after clicking Newtab button",
                1, newTabCount);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testToolbarSwipeOnlyTab() throws InterruptedException {
        final TabModel tabModel = getActivity().getTabModelSelector().getModel(false);

        assertEquals("Incorrect starting index", 0, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.RIGHT, 0, false);
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.LEFT, 0, false);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testToolbarSwipePrevTab() throws InterruptedException {
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        UiUtils.settleDownUI(getInstrumentation());

        final TabModel tabModel = getActivity().getTabModelSelector().getModel(false);

        assertEquals("Incorrect starting index", 1, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.RIGHT, 0, true);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testToolbarSwipeNextTab() throws InterruptedException {
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        ChromeTabUtils.switchTabInCurrentTabModel(getActivity(), 0);
        UiUtils.settleDownUI(getInstrumentation());

        final TabModel tabModel = getActivity().getTabModelSelector().getModel(false);

        assertEquals("Incorrect starting index", 0, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.LEFT, 1, true);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testToolbarSwipePrevTabNone() throws InterruptedException {
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        ChromeTabUtils.switchTabInCurrentTabModel(getActivity(), 0);
        UiUtils.settleDownUI(getInstrumentation());

        final TabModel tabModel = getActivity().getTabModelSelector().getModel(false);

        assertEquals("Incorrect starting index", 0, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.RIGHT, 0, false);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testToolbarSwipeNextTabNone() throws InterruptedException {
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        UiUtils.settleDownUI(getInstrumentation());

        final TabModel tabModel = getActivity().getTabModelSelector().getModel(false);

        assertEquals("Incorrect starting index", 1, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.LEFT, 1, false);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testToolbarSwipeNextThenPrevTab() throws InterruptedException {
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        ChromeTabUtils.switchTabInCurrentTabModel(getActivity(), 0);
        UiUtils.settleDownUI(getInstrumentation());

        final TabModel tabModel = getActivity().getTabModelSelector().getModel(false);

        assertEquals("Incorrect starting index", 0, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.LEFT, 1, true);

        assertEquals("Incorrect starting index", 1, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.RIGHT, 0, true);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testToolbarSwipeNextThenPrevTabIncognito() throws InterruptedException {
        newIncognitoTabFromMenu();
        newIncognitoTabFromMenu();
        ChromeTabUtils.switchTabInCurrentTabModel(getActivity(), 0);
        UiUtils.settleDownUI(getInstrumentation());

        final TabModel tabModel = getActivity().getTabModelSelector().getModel(true);

        assertEquals("Incorrect starting index", 0, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.LEFT, 1, true);

        assertEquals("Incorrect starting index", 1, tabModel.index());
        runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.RIGHT, 0, true);
    }

    private void runToolbarSideSwipeTestOnCurrentModel(ScrollDirection direction, int finalIndex,
            boolean expectsSelection) throws InterruptedException {
        final CallbackHelper selectCallback = new CallbackHelper();
        final int id = getActivity().getCurrentTabModel().getTabAt(finalIndex).getId();
        final TabModelObserver observer = new EmptyTabModelObserver() {
            @Override
            public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
                if (tab.getId() == id) selectCallback.notifyCalled();
            }
        };

        if (expectsSelection) {
            ThreadUtils.runOnUiThreadBlocking(new Runnable() {
                @Override
                public void run() {
                    TabModelSelector selector = getActivity().getTabModelSelector();
                    for (TabModel tabModel : selector.getModels()) {
                        tabModel.addObserver(observer);
                    }
                }
            });
        }

        performToolbarSideSwipe(direction);
        waitForStaticLayout();
        assertEquals("Index after toolbar side swipe is incorrect", finalIndex,
                getActivity().getCurrentTabModel().index());

        if (expectsSelection) {
            try {
                selectCallback.waitForCallback(0);
            } catch (TimeoutException e) {
                fail("Tab selected event was never received");
            }
            ThreadUtils.runOnUiThreadBlocking(new Runnable() {
                @Override
                public void run() {
                    TabModelSelector selector = getActivity().getTabModelSelector();
                    for (TabModel tabModel : selector.getModels()) {
                        tabModel.removeObserver(observer);
                    }
                }
            });
        }
    }


    private void performToolbarSideSwipe(ScrollDirection direction) {
        assertTrue("Unexpected direction for side swipe " + direction,
                direction == ScrollDirection.LEFT || direction == ScrollDirection.RIGHT);
        final View toolbar = getActivity().findViewById(R.id.toolbar);
        int[] toolbarPos = new int[2];
        toolbar.getLocationOnScreen(toolbarPos);
        final int width = toolbar.getWidth();
        final int height = toolbar.getHeight();

        final int fromX = toolbarPos[0] + width / 2;
        final int toX = toolbarPos[0] + (direction == ScrollDirection.LEFT ? 0 : width);
        final int y = toolbarPos[1] + height / 2;
        final int stepCount = 10;

        long downTime = SystemClock.uptimeMillis();
        dragStart(fromX, y, downTime);
        dragTo(fromX, toX, y, y, stepCount, downTime);
        dragEnd(toX, y, downTime);
    }

    private void waitForStaticLayout() throws InterruptedException {
        CriteriaHelper.pollUiThread(
                new Criteria("Static Layout never selected after side swipe") {
                    @Override
                    public boolean isSatisfied() {
                        CompositorViewHolder compositorViewHolder = (CompositorViewHolder)
                                getActivity().findViewById(R.id.compositor_view_holder);
                        LayoutManager layoutManager = compositorViewHolder.getLayoutManager();

                        return layoutManager.getActiveLayout() instanceof StaticLayout;
                    }
                });
    }

    /**
     * Test that swipes and tab transitions are not causing URL bar to be focused.
     */
    @MediumTest
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testOSKIsNotShownDuringSwipe() throws InterruptedException {
        final View urlBar = getActivity().findViewById(R.id.url_bar);
        final LayoutManagerChrome layoutManager = updateTabsViewSize();
        final EdgeSwipeHandler edgeSwipeHandler = layoutManager.getTopSwipeHandler();

        UiUtils.settleDownUI(getInstrumentation());
        getInstrumentation().runOnMainSync(
                new Runnable() {
                    @Override
                    public void run() {
                        urlBar.requestFocus();
                    }
                });
        UiUtils.settleDownUI(getInstrumentation());

        getInstrumentation().runOnMainSync(
                new Runnable() {
                    @Override
                    public void run() {
                        urlBar.clearFocus();
                    }
                });
        UiUtils.settleDownUI(getInstrumentation());
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        UiUtils.settleDownUI(getInstrumentation());

        assertFalse("Keyboard somehow got shown",
                org.chromium.ui.UiUtils.isKeyboardShowing(getActivity(), urlBar));

        ThreadUtils.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                edgeSwipeHandler.swipeStarted(ScrollDirection.RIGHT, 0, 0);
                float swipeXChange = mTabsViewWidthDp / 2.f;
                edgeSwipeHandler.swipeUpdated(
                        swipeXChange, 0.f, swipeXChange, 0.f, swipeXChange, 0.f);
            }
        });

        CriteriaHelper.pollUiThread(
                new Criteria("Layout still requesting Tab Android view be attached") {
                    @Override
                    public boolean isSatisfied() {
                        LayoutManager driver = getActivity().getLayoutManager();
                        return !driver.getActiveLayout().shouldDisplayContentOverlay();
                    }
                });

        ThreadUtils.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                assertFalse("Keyboard should be hidden while swiping",
                        org.chromium.ui.UiUtils.isKeyboardShowing(getActivity(), urlBar));
                edgeSwipeHandler.swipeFinished();
            }
        });

        CriteriaHelper.pollUiThread(
                new Criteria("Layout not requesting Tab Android view be attached") {
                    @Override
                    public boolean isSatisfied() {
                        LayoutManager driver = getActivity().getLayoutManager();
                        return driver.getActiveLayout().shouldDisplayContentOverlay();
                    }
                });

        assertFalse("Keyboard should not be shown",
                org.chromium.ui.UiUtils.isKeyboardShowing(getActivity(), urlBar));
    }

    /**
     * Test that orientation changes cause the live tab reflow.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
    @RetryOnFailure
    public void testOrientationChangeCausesLiveTabReflowInNormalView()
            throws InterruptedException, TimeoutException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        loadUrl(RESIZE_TEST_URL);
        final WebContents webContents =
                getActivity().getActivityTab().getWebContents();

        JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents,
                                                          "resizeHappened = false;");
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        UiUtils.settleDownUI(getInstrumentation());
        assertEquals("onresize event wasn't received by the tab (normal view)",
                "true",
                JavaScriptUtils.executeJavaScriptAndWaitForResult(
                        webContents, "resizeHappened",
                        WAIT_RESIZE_TIMEOUT_MS, TimeUnit.MILLISECONDS));
    }

    /**
     * Test that orientation changes cause the live tab reflow.
     */
    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @Restriction({ChromeRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
    public void testOrientationChangeCausesLiveTabReflowInTabSwitcher()
            throws InterruptedException, TimeoutException {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
        loadUrl(RESIZE_TEST_URL);
        final WebContents webContents =
                        getActivity().getActivityTab().getWebContents();

        showOverviewAndWaitForAnimation();
        JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents,
                                                          "resizeHappened = false;");
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        UiUtils.settleDownUI(getInstrumentation());
        assertEquals("onresize event wasn't received by the live tab (tabswitcher, to Landscape)",
                "true",
                JavaScriptUtils.executeJavaScriptAndWaitForResult(
                        webContents, "resizeHappened",
                        WAIT_RESIZE_TIMEOUT_MS, TimeUnit.MILLISECONDS));

        JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents,
                                                          "resizeHappened = false;");
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        UiUtils.settleDownUI(getInstrumentation());
        assertEquals("onresize event wasn't received by the live tab (tabswitcher, to Portrait)",
                "true",
                JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents,
                        "resizeHappened", WAIT_RESIZE_TIMEOUT_MS, TimeUnit.MILLISECONDS));
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testLastClosedUndoableTabGetsHidden() {
        final TabModel model = getActivity().getTabModelSelector().getCurrentModel();
        final Tab tab = TabModelUtils.getCurrentTab(model);

        assertEquals("Too many tabs at startup", 1, model.getCount());

        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                model.closeTab(tab, false, false, true);
            }
        });

        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                assertTrue("Tab close is not undoable", model.isClosurePending(tab.getId()));
                assertTrue("Tab was not hidden", tab.isHidden());
            }
        });
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testLastClosedTabTriggersNotifyChangedCall() {
        final TabModel model = getActivity().getTabModelSelector().getCurrentModel();
        final Tab tab = TabModelUtils.getCurrentTab(model);
        final TabModelSelector selector = getActivity().getTabModelSelector();
        mNotifyChangedCalled = false;

        selector.addObserver(new EmptyTabModelSelectorObserver() {
            @Override
            public void onChange() {
                mNotifyChangedCalled = true;
            }
        });

        assertEquals("Too many tabs at startup", 1, model.getCount());

        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                model.closeTab(tab, false, false, true);
            }
        });

        assertTrue("notifyChanged() was not called", mNotifyChangedCalled);
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testTabsAreDestroyedOnModelDestruction() throws InterruptedException {
        startMainActivityOnBlankPage();
        final TabModelSelectorImpl selector =
                (TabModelSelectorImpl) getActivity().getTabModelSelector();
        final Tab tab = getActivity().getActivityTab();

        final AtomicBoolean webContentsDestroyCalled = new AtomicBoolean();

        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
            public void run() {
                @SuppressWarnings("unused") // Avoid GC of observer
                WebContentsObserver observer = new WebContentsObserver(tab.getWebContents()) {
                            @Override
                            public void destroy() {
                                super.destroy();
                                webContentsDestroyCalled.set(true);
                            }
                        };

                assertNotNull("No initial tab at startup", tab);
                assertNotNull("Tab does not have a web contents", tab.getWebContents());
                assertTrue("Tab is destroyed", tab.isInitialized());

                selector.destroy();

                assertNull("Tab still has a web contents", tab.getWebContents());
                assertFalse("Tab was not destroyed", tab.isInitialized());
            }
        });

        assertTrue("WebContentsObserver was never destroyed", webContentsDestroyCalled.get());
    }

    @MediumTest
    @Feature({"Android-TabSwitcher"})
    @RetryOnFailure
    public void testIncognitoTabsNotRestoredAfterSwipe() throws Exception {
        newIncognitoTabFromMenu();

        File tabStateDir = TabbedModeTabPersistencePolicy.getOrCreateTabbedModeStateDirectory();
        TabModel normalModel = getActivity().getTabModelSelector().getModel(false);
        TabModel incognitoModel = getActivity().getTabModelSelector().getModel(true);
        File normalTabFile = new File(tabStateDir,
                TabState.getTabStateFilename(
                        normalModel.getTabAt(normalModel.getCount() - 1).getId(), false));
        File incognitoTabFile = new File(tabStateDir,
                TabState.getTabStateFilename(incognitoModel.getTabAt(0).getId(), true));

        assertFileExists(normalTabFile, true);
        assertFileExists(incognitoTabFile, true);

        // Although we're destroying the activity, the Application will still live on since its in
        // the same process as this test.
        ApplicationTestUtils.finishActivity(getActivity());

        // Activity will be started without a savedInstanceState.
        startMainActivityOnBlankPage();
        assertFileExists(normalTabFile, true);
        assertFileExists(incognitoTabFile, false);
    }

    @Override
    public void startMainActivity() throws InterruptedException {
        float dpToPx = getInstrumentation().getContext().getResources().getDisplayMetrics().density;
        mPxToDp = 1.0f / dpToPx;

        // Exclude the tests that can launch directly to a page other than the NTP.
        if (getName().equals("testOpenAndCloseNewTabButton")
                || getName().equals("testSwitchToTabThatDoesNotHaveThumbnail")
                || getName().equals("testCloseTabPortrait")
                || getName().equals("testCloseTabLandscape")
                || getName().equals("testTabsAreDestroyedOnModelDestruction")) {
            return;
        }
        startMainActivityFromLauncher();
    }

    private void assertFileExists(final File fileToCheck, final boolean expected)
            throws InterruptedException {
        CriteriaHelper.pollInstrumentationThread(
                    Criteria.equals(expected, new Callable<Boolean>() {
                        @Override
                        public Boolean call() {
                            return fileToCheck.exists();
                        }
                    }));
    }
}
