| Index: chrome/test/android/javatests_staging/src/org/chromium/chrome/test/ChromeTabbedActivityTestBase.java
 | 
| diff --git a/chrome/test/android/javatests_staging/src/org/chromium/chrome/test/ChromeTabbedActivityTestBase.java b/chrome/test/android/javatests_staging/src/org/chromium/chrome/test/ChromeTabbedActivityTestBase.java
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..3ada648808cac1dffe152e4057a8d598ebc66819
 | 
| --- /dev/null
 | 
| +++ b/chrome/test/android/javatests_staging/src/org/chromium/chrome/test/ChromeTabbedActivityTestBase.java
 | 
| @@ -0,0 +1,137 @@
 | 
| +// 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;
 | 
| +
 | 
| +import android.app.Activity;
 | 
| +import android.app.Instrumentation;
 | 
| +import android.content.Intent;
 | 
| +import android.text.TextUtils;
 | 
| +import android.util.Log;
 | 
| +import android.view.View;
 | 
| +
 | 
| +import org.chromium.base.test.util.CommandLineFlags;
 | 
| +import org.chromium.chrome.browser.ChromeSwitches;
 | 
| +import org.chromium.chrome.browser.ChromeTabbedActivity;
 | 
| +import org.chromium.chrome.browser.EmptyTabObserver;
 | 
| +import org.chromium.chrome.browser.Tab;
 | 
| +import org.chromium.chrome.browser.tab.ChromeTab;
 | 
| +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.TabModelUtils;
 | 
| +import org.chromium.content.browser.test.util.CallbackHelper;
 | 
| +import org.chromium.content.browser.test.util.TestTouchUtils;
 | 
| +
 | 
| +import java.util.concurrent.TimeoutException;
 | 
| +
 | 
| +/**
 | 
| + * The base class of the ChromeTabbedActivity specific tests. It provides the common methods
 | 
| + * to access the ChromeTabbedActivity UI.
 | 
| + */
 | 
| +@CommandLineFlags.Add(ChromeSwitches.DISABLE_DOCUMENT_MODE)
 | 
| +public abstract class ChromeTabbedActivityTestBase extends
 | 
| +        ChromeActivityTestCaseBase<ChromeTabbedActivity> {
 | 
| +    private static final String TAG = "ChromeTabbedActivityTestBase";
 | 
| +
 | 
| +    public ChromeTabbedActivityTestBase() {
 | 
| +        super(ChromeTabbedActivity.class);
 | 
| +    }
 | 
| +
 | 
| +    /**
 | 
| +     * Load a url in multiple new tabs in parallel. Each {@link ChromeTab} will pretend to be
 | 
| +     * created from a link.
 | 
| +     *
 | 
| +     * @param url The url of the page to load.
 | 
| +     * @param numTabs The number of tabs to open.
 | 
| +     */
 | 
| +    public void loadUrlInManyNewTabs(final String url, final int numTabs)
 | 
| +            throws InterruptedException {
 | 
| +        final CallbackHelper[] pageLoadedCallbacks = new CallbackHelper[numTabs];
 | 
| +        final int[] tabIds = new int[numTabs];
 | 
| +        for (int i = 0; i < numTabs; ++i) {
 | 
| +            final int index = i;
 | 
| +            getInstrumentation().runOnMainSync(new Runnable() {
 | 
| +                @Override
 | 
| +                public void run() {
 | 
| +                    Tab currentTab = getActivity().getCurrentTabCreator().launchUrl(
 | 
| +                            url, TabLaunchType.FROM_LINK);
 | 
| +                    final CallbackHelper pageLoadCallback = new CallbackHelper();
 | 
| +                    pageLoadedCallbacks[index] = pageLoadCallback;
 | 
| +                    currentTab.addObserver(new EmptyTabObserver() {
 | 
| +                        @Override
 | 
| +                        public void onPageLoadFinished(Tab tab) {
 | 
| +                            pageLoadCallback.notifyCalled();
 | 
| +                            tab.removeObserver(this);
 | 
| +                        }
 | 
| +                    });
 | 
| +                    tabIds[index] = currentTab.getId();
 | 
| +                }
 | 
| +            });
 | 
| +        }
 | 
| +        //  When opening many tabs some may be frozen due to memory pressure and won't send
 | 
| +        //  PAGE_LOAD_FINISHED events. Iterate over the newly opened tabs and wait for each to load.
 | 
| +        for (int i = 0; i < numTabs; ++i) {
 | 
| +            final TabModel tabModel = getActivity().getCurrentTabModel();
 | 
| +            final Tab tab = TabModelUtils.getTabById(tabModel, tabIds[i]);
 | 
| +            getInstrumentation().runOnMainSync(new Runnable() {
 | 
| +                @Override
 | 
| +                public void run() {
 | 
| +                    TabModelUtils.setIndex(tabModel, tabModel.indexOf(tab));
 | 
| +                }
 | 
| +            });
 | 
| +            try {
 | 
| +                pageLoadedCallbacks[i].waitForCallback(0);
 | 
| +            } catch (TimeoutException e) {
 | 
| +                fail(String.format("PAGE_LOAD_FINISHED was not received for tabId=%d", tabIds[i]));
 | 
| +            }
 | 
| +        }
 | 
| +    }
 | 
| +
 | 
| +    @Override
 | 
| +    protected void startActivityCompletely(Intent intent) {
 | 
| +        Instrumentation.ActivityMonitor monitor = getInstrumentation().addMonitor(
 | 
| +                ChromeTabbedActivity.class.getName(), null, false);
 | 
| +        Activity activity = getInstrumentation().startActivitySync(intent);
 | 
| +        assertNotNull("Main activity did not start", activity);
 | 
| +        ChromeTabbedActivity tabbedActivity = (ChromeTabbedActivity)
 | 
| +                monitor.waitForActivityWithTimeout(ACTIVITY_START_TIMEOUT_MS);
 | 
| +        assertNotNull("ChromeTabbedActivity did not start", tabbedActivity);
 | 
| +        setActivity(tabbedActivity);
 | 
| +        Log.d(TAG, "startActivityCompletely <<");
 | 
| +    }
 | 
| +
 | 
| +    /**
 | 
| +     * Long presses the view, selects an item from the context menu, and
 | 
| +     * asserts that a new tab is opened and is incognito iff expectIncognito is true.
 | 
| +     * @param view The View to long press.
 | 
| +     * @param contextMenuItemId The context menu item to select on the view.
 | 
| +     * @param expectIncognito Whether the opened tab is expected to be incognito.
 | 
| +     * @param expectedUrl The expected url for the new tab.
 | 
| +     */
 | 
| +    protected void invokeContextMenuAndOpenInANewTab(View view, int contextMenuItemId,
 | 
| +            boolean expectIncognito, final String expectedUrl) throws InterruptedException {
 | 
| +        final CallbackHelper createdCallback = new CallbackHelper();
 | 
| +        final TabModel tabModel = getActivity().getTabModelSelector().getModel(expectIncognito);
 | 
| +        tabModel.addObserver(new EmptyTabModelObserver() {
 | 
| +            @Override
 | 
| +            public void didAddTab(Tab tab, TabLaunchType type) {
 | 
| +                if (TextUtils.equals(expectedUrl, tab.getUrl())) {
 | 
| +                    createdCallback.notifyCalled();
 | 
| +                    tabModel.removeObserver(this);
 | 
| +                }
 | 
| +            }
 | 
| +        });
 | 
| +
 | 
| +        TestTouchUtils.longClickView(getInstrumentation(), view);
 | 
| +        assertTrue(getInstrumentation().invokeContextMenuAction(getActivity(),
 | 
| +                contextMenuItemId, 0));
 | 
| +
 | 
| +        try {
 | 
| +            createdCallback.waitForCallback(0);
 | 
| +        } catch (TimeoutException e) {
 | 
| +            fail("Never received tab creation event");
 | 
| +        }
 | 
| +    }
 | 
| +}
 | 
| 
 |