| Index: chrome/test/android/javatests_staging/src/org/chromium/chrome/test/util/ChromeTabUtils.java
|
| diff --git a/chrome/test/android/javatests_staging/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests_staging/src/org/chromium/chrome/test/util/ChromeTabUtils.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e64dafd40b562a4ebffab05a2c3630eca01d23ae
|
| --- /dev/null
|
| +++ b/chrome/test/android/javatests_staging/src/org/chromium/chrome/test/util/ChromeTabUtils.java
|
| @@ -0,0 +1,405 @@
|
| +// 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.test.util;
|
| +
|
| +import android.app.Instrumentation;
|
| +import android.test.InstrumentationTestCase;
|
| +import android.text.TextUtils;
|
| +import android.util.Log;
|
| +
|
| +import com.google.android.apps.chrome.R;
|
| +
|
| +import junit.framework.Assert;
|
| +
|
| +import org.chromium.base.ThreadUtils;
|
| +import org.chromium.chrome.browser.ChromeActivity;
|
| +import org.chromium.chrome.browser.ChromeTabbedActivity;
|
| +import org.chromium.chrome.browser.EmptyTabObserver;
|
| +import org.chromium.chrome.browser.Tab;
|
| +import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton;
|
| +import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelper;
|
| +import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
|
| +import org.chromium.chrome.browser.tabmodel.TabModel;
|
| +import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
|
| +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.TabModelUtils;
|
| +import org.chromium.chrome.test.ChromeTabbedActivityTestBase;
|
| +import org.chromium.content.browser.test.util.CallbackHelper;
|
| +import org.chromium.ui.base.DeviceFormFactor;
|
| +
|
| +import java.util.concurrent.Callable;
|
| +import java.util.concurrent.TimeUnit;
|
| +import java.util.concurrent.TimeoutException;
|
| +
|
| +/**
|
| + * A utility class that contains methods generic to all Tabs tests.
|
| + */
|
| +public class ChromeTabUtils {
|
| + private static final String TAG = "ChromeTabUtils";
|
| +
|
| + /**
|
| + * Waits for the given tab to finish loading it's current page.
|
| + *
|
| + * @param tab The tab to wait for the page loading to be complete.
|
| + * @param url The URL that will be waited to load for. Pass in null if loading the
|
| + * current page is sufficient.
|
| + */
|
| + public static void waitForTabPageLoaded(final Tab tab, final String url)
|
| + throws InterruptedException {
|
| + Assert.assertFalse(ThreadUtils.runningOnUiThread());
|
| +
|
| + final boolean checkUrl = url != null;
|
| +
|
| + final CallbackHelper loadedCallback = new CallbackHelper();
|
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + if (!tab.isLoading()
|
| + && (!checkUrl || TextUtils.equals(tab.getUrl(), url))
|
| + && !tab.getWebContents().isLoadingToDifferentDocument()) {
|
| + loadedCallback.notifyCalled();
|
| + return;
|
| + }
|
| +
|
| + tab.addObserver(new EmptyTabObserver() {
|
| + @Override
|
| + public void onPageLoadFinished(Tab tab) {
|
| + if (!checkUrl || TextUtils.equals(tab.getUrl(), url)) {
|
| + loadedCallback.notifyCalled();
|
| + tab.removeObserver(this);
|
| + }
|
| + }
|
| + });
|
| + }
|
| + });
|
| +
|
| + try {
|
| + loadedCallback.waitForCallback(0);
|
| + } catch (TimeoutException e) {
|
| + Assert.fail("Failed to load URL: " + url + ", final URL: " + tab.getUrl());
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Waits for the given tab to finish loading it's current page.
|
| + *
|
| + * @param tab The tab to wait for the page loading to be complete.
|
| + * @param loadTrigger The trigger action that will result in a page load finished event
|
| + * to be fired (not run on the UI thread by default).
|
| + */
|
| + public static void waitForTabPageLoaded(final Tab tab, Runnable loadTrigger)
|
| + throws InterruptedException {
|
| + waitForTabPageLoaded(tab, loadTrigger, CallbackHelper.WAIT_TIMEOUT_SECONDS);
|
| + }
|
| +
|
| + /**
|
| + * Waits for the given tab to finish loading it's current page.
|
| + *
|
| + * @param tab The tab to wait for the page loading to be complete.
|
| + * @param loadTrigger The trigger action that will result in a page load finished event
|
| + * to be fired (not run on the UI thread by default).
|
| + * @param secondsToWait The number of seconds to wait for the page to be loaded.
|
| + */
|
| + public static void waitForTabPageLoaded(
|
| + final Tab tab, Runnable loadTrigger, long secondsToWait)
|
| + throws InterruptedException {
|
| + final CallbackHelper loadedCallback = new CallbackHelper();
|
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + tab.addObserver(new EmptyTabObserver() {
|
| + @Override
|
| + public void onPageLoadFinished(Tab tab) {
|
| + loadedCallback.notifyCalled();
|
| + tab.removeObserver(this);
|
| + }
|
| + });
|
| + }
|
| + });
|
| + loadTrigger.run();
|
| + try {
|
| + loadedCallback.waitForCallback(0, 1, secondsToWait, TimeUnit.SECONDS);
|
| + } catch (TimeoutException e) {
|
| + Assert.fail("Page did not load. Tab information at time of failure --"
|
| + + " url: " + tab.getUrl()
|
| + + ", load progress: " + tab.getProgress()
|
| + + ", is loading: " + Boolean.toString(tab.isLoading()));
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Waits for the given tab to start loading it's current page.
|
| + *
|
| + * @param tab The tab to wait for the page loading to be started.
|
| + * @param loadTrigger The trigger action that will result in a page load started event
|
| + * to be fired (not run on the UI thread by default).
|
| + * @param secondsToWait The number of seconds to wait for the page to be load to be started.
|
| + */
|
| + public static void waitForTabPageLoadStart(
|
| + final Tab tab, Runnable loadTrigger, long secondsToWait)
|
| + throws InterruptedException {
|
| + final CallbackHelper startedCallback = new CallbackHelper();
|
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + tab.addObserver(new EmptyTabObserver() {
|
| + @Override
|
| + public void onPageLoadStarted(Tab tab) {
|
| + startedCallback.notifyCalled();
|
| + tab.removeObserver(this);
|
| + }
|
| + });
|
| + }
|
| + });
|
| + loadTrigger.run();
|
| + try {
|
| + startedCallback.waitForCallback(0, 1, secondsToWait, TimeUnit.SECONDS);
|
| + } catch (TimeoutException e) {
|
| + Assert.fail("Page did not start loading. Tab information at time of failure --"
|
| + + " url: " + tab.getUrl()
|
| + + ", load progress: " + tab.getProgress()
|
| + + ", is loading: " + Boolean.toString(tab.isLoading()));
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Switch to the given TabIndex in the current tabModel.
|
| + * @param tabIndex
|
| + */
|
| + public static void switchTabInCurrentTabModel(final ChromeActivity activity,
|
| + final int tabIndex) {
|
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + TabModelUtils.setIndex(activity.getCurrentTabModel(), tabIndex);
|
| + }
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * Simulates a click to the normal (not incognito) new tab button.
|
| + * <p>
|
| + * Does not wait for the tab to be loaded.
|
| + */
|
| + public static void clickNewTabButton(InstrumentationTestCase test,
|
| + ChromeTabbedActivityTestBase base) throws InterruptedException {
|
| + final TabModel normalTabModel = base.getActivity().getTabModelSelector().getModel(false);
|
| + final CallbackHelper createdCallback = new CallbackHelper();
|
| + normalTabModel.addObserver(
|
| + new EmptyTabModelObserver() {
|
| + @Override
|
| + public void didAddTab(Tab tab, TabLaunchType type) {
|
| + createdCallback.notifyCalled();
|
| + normalTabModel.removeObserver(this);
|
| + }
|
| + });
|
| + // Tablet and phone have different new tab buttons; click the right one.
|
| + if (DeviceFormFactor.isTablet(base.getActivity())) {
|
| + StripLayoutHelper strip =
|
| + TabStripUtils.getStripLayoutHelper(base.getActivity(), false /* incognito */);
|
| + CompositorButton newTabButton = strip.getNewTabButton();
|
| + TabStripUtils.clickCompositorButton(newTabButton, base);
|
| + test.getInstrumentation().waitForIdleSync();
|
| + } else {
|
| + base.singleClickView(base.getActivity().findViewById(R.id.new_tab_button));
|
| + }
|
| +
|
| + try {
|
| + createdCallback.waitForCallback(0);
|
| + } catch (TimeoutException e) {
|
| + Assert.fail("Never received tab creation event");
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * New a tab by invoking the 'New Tab' menu item.
|
| + * <p>
|
| + * Returns when the tab has been created and has finished navigating.
|
| + */
|
| + public static void newTabFromMenu(Instrumentation instrumentation,
|
| + final ChromeTabbedActivity activity)
|
| + throws InterruptedException {
|
| + final CallbackHelper createdCallback = new CallbackHelper();
|
| + final CallbackHelper selectedCallback = new CallbackHelper();
|
| +
|
| + TabModel tabModel = activity.getTabModelSelector().getModel(false);
|
| + TabModelObserver observer = new EmptyTabModelObserver() {
|
| + @Override
|
| + public void didAddTab(Tab tab, TabLaunchType type) {
|
| + createdCallback.notifyCalled();
|
| + }
|
| +
|
| + @Override
|
| + public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
|
| + selectedCallback.notifyCalled();
|
| + }
|
| + };
|
| + tabModel.addObserver(observer);
|
| +
|
| + MenuUtils.invokeCustomMenuActionSync(instrumentation, activity,
|
| + R.id.new_tab_menu_id);
|
| +
|
| + try {
|
| + createdCallback.waitForCallback(0);
|
| + } catch (TimeoutException ex) {
|
| + Assert.fail("Never received tab created event");
|
| + }
|
| + try {
|
| + selectedCallback.waitForCallback(0);
|
| + } catch (TimeoutException ex) {
|
| + Assert.fail("Never received tab selected event");
|
| + }
|
| + tabModel.removeObserver(observer);
|
| +
|
| + Tab tab = activity.getActivityTab();
|
| + waitForTabPageLoaded(tab, (String) null);
|
| + Assert.assertTrue("NTP never fully loaded.",
|
| + NewTabPageTestUtils.waitForNtpLoaded(tab));
|
| + instrumentation.waitForIdleSync();
|
| + Log.d(TAG, "newTabFromMenu <<");
|
| + }
|
| +
|
| + /**
|
| + * New multiple tabs by invoking the 'new' menu item n times.
|
| + * @param n The number of tabs you want to create.
|
| + */
|
| + public static void newTabsFromMenu(Instrumentation instrumentation,
|
| + ChromeTabbedActivity activity, int n)
|
| + throws InterruptedException {
|
| + while (n > 0) {
|
| + newTabFromMenu(instrumentation, activity);
|
| + --n;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Ensure that at least some given number of tabs are open.
|
| + */
|
| + public static void ensureNumOpenTabs(Instrumentation instrumentation,
|
| + ChromeTabbedActivity activity, int newCount)
|
| + throws InterruptedException {
|
| + int curCount = getNumOpenTabs(activity);
|
| + if (curCount < newCount) {
|
| + newTabsFromMenu(instrumentation, activity, newCount - curCount);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Fetch the number of tabs open in the current model.
|
| + */
|
| + public static int getNumOpenTabs(final ChromeActivity activity) {
|
| + return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer>() {
|
| + @Override
|
| + public Integer call() throws Exception {
|
| + return activity.getCurrentTabModel().getCount();
|
| + }
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * Closes the current tab through TabModelSelector.
|
| + * <p>
|
| + * Returns after the tab has been closed.
|
| + */
|
| + public static void closeCurrentTab(final Instrumentation instrumentation,
|
| + final ChromeTabbedActivity activity)
|
| + throws InterruptedException {
|
| + closeTabWithAction(instrumentation, activity, new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + instrumentation.runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + TabModelUtils.closeCurrentTab(activity.getCurrentTabModel());
|
| + }
|
| + });
|
| + }
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * Closes a tab with the given action and waits for a tab closure to be observed.
|
| + */
|
| + public static void closeTabWithAction(Instrumentation instrumentation,
|
| + final ChromeTabbedActivity activity, Runnable action) throws InterruptedException {
|
| + final CallbackHelper closeCallback = new CallbackHelper();
|
| + final TabModelObserver observer = new EmptyTabModelObserver() {
|
| + @Override
|
| + public void willCloseTab(Tab tab, boolean animate) {
|
| + closeCallback.notifyCalled();
|
| + }
|
| + };
|
| + instrumentation.runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + TabModelSelector selector = activity.getTabModelSelector();
|
| + for (TabModel tabModel : selector.getModels()) {
|
| + tabModel.addObserver(observer);
|
| + }
|
| + }
|
| + });
|
| +
|
| + action.run();
|
| +
|
| + try {
|
| + closeCallback.waitForCallback(0);
|
| + } catch (TimeoutException e) {
|
| + Assert.fail("Tab closed event was never received");
|
| + }
|
| + instrumentation.runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + TabModelSelector selector = activity.getTabModelSelector();
|
| + for (TabModel tabModel : selector.getModels()) {
|
| + tabModel.removeObserver(observer);
|
| + }
|
| + }
|
| + });
|
| + instrumentation.waitForIdleSync();
|
| + Log.d(TAG, "closeTabWithAction <<");
|
| + }
|
| +
|
| + /**
|
| + * Selects a tab with the given action and waits for the selection event to be observed.
|
| + */
|
| + public static void selectTabWithAction(Instrumentation instrumentation,
|
| + final ChromeTabbedActivity activity, Runnable action) throws InterruptedException {
|
| + final CallbackHelper selectCallback = new CallbackHelper();
|
| + final TabModelObserver observer = new EmptyTabModelObserver() {
|
| + @Override
|
| + public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
|
| + selectCallback.notifyCalled();
|
| + }
|
| + };
|
| + instrumentation.runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + TabModelSelector selector = activity.getTabModelSelector();
|
| + for (TabModel tabModel : selector.getModels()) {
|
| + tabModel.addObserver(observer);
|
| + }
|
| + }
|
| + });
|
| +
|
| + action.run();
|
| +
|
| + try {
|
| + selectCallback.waitForCallback(0);
|
| + } catch (TimeoutException e) {
|
| + Assert.fail("Tab selected event was never received");
|
| + }
|
| + instrumentation.runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + TabModelSelector selector = activity.getTabModelSelector();
|
| + for (TabModel tabModel : selector.getModels()) {
|
| + tabModel.removeObserver(observer);
|
| + }
|
| + }
|
| + });
|
| + }
|
| +}
|
|
|