Chromium Code Reviews| Index: chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java |
| diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java |
| index 450008e09e7430010450826c8935ed3bfbc5039d..23971eab4636c7f332c507b1eef93e02d27aa46e 100644 |
| --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java |
| +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java |
| @@ -4,19 +4,33 @@ |
| package org.chromium.chrome.browser.tabmodel; |
| +import android.annotation.TargetApi; |
| +import android.app.Activity; |
| +import android.content.Intent; |
| +import android.os.Build; |
| import android.test.suitebuilder.annotation.MediumTest; |
| +import org.chromium.base.ApplicationStatus; |
| import org.chromium.base.ThreadUtils; |
| import org.chromium.base.test.util.FlakyTest; |
| import org.chromium.base.test.util.Restriction; |
| +import org.chromium.base.test.util.UrlUtils; |
| +import org.chromium.chrome.browser.ChromeTabbedActivity; |
| +import org.chromium.chrome.browser.ChromeTabbedActivity2; |
| +import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; |
| +import org.chromium.chrome.browser.tab.EmptyTabObserver; |
| import org.chromium.chrome.browser.tab.Tab; |
| import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
| import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; |
| import org.chromium.chrome.test.ChromeTabbedActivityTestBase; |
| import org.chromium.chrome.test.util.ChromeRestriction; |
| import org.chromium.content.browser.test.util.CallbackHelper; |
| +import org.chromium.content.browser.test.util.Criteria; |
| +import org.chromium.content.browser.test.util.CriteriaHelper; |
| import org.chromium.content_public.browser.LoadUrlParams; |
| +import java.lang.ref.WeakReference; |
| +import java.util.concurrent.Callable; |
| import java.util.concurrent.TimeoutException; |
| /** |
| @@ -24,6 +38,7 @@ import java.util.concurrent.TimeoutException; |
| */ |
| public class UndoTabModelTest extends ChromeTabbedActivityTestBase { |
| private static final Tab[] EMPTY = new Tab[] { }; |
| + private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>poit.</html>"); |
| @Override |
| public void startMainActivity() throws InterruptedException { |
| @@ -321,6 +336,64 @@ public class UndoTabModelTest extends ChromeTabbedActivityTestBase { |
| } |
| } |
| + private void openRecentlyClosedTabOnUiThread(final TabModelSelector selector) { |
|
Theresa
2016/06/30 20:50:25
nit: openMostRecentlyClosedTabOnUiThread?
Sorry
xingliu
2016/07/01 00:30:38
Done.
|
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| + @Override |
| + public void run() { |
| + ((TabModelSelectorImpl) selector).getCurrentModel().openRecentlyClosedTab(); |
| + } |
| + }); |
| + } |
| + |
| + // Helper class that notifies when a page load is finished. |
| + private class TestTabObserver extends EmptyTabObserver { |
|
Theresa
2016/06/30 20:50:24
findbugs says that this should be a static inner c
xingliu
2016/07/01 00:30:38
Done.
|
| + private CallbackHelper mCallbackHelper; |
| + public TestTabObserver(CallbackHelper callbackHelper) { |
| + super(); |
| + mCallbackHelper = callbackHelper; |
| + } |
| + @Override |
| + public void onPageLoadFinished(Tab tab) { |
| + mCallbackHelper.notifyCalled(); |
| + } |
| + } |
| + |
| + private ChromeTabbedActivity2 createSecondChromeTabbedActivity() throws InterruptedException { |
|
Theresa
2016/06/30 20:50:24
This is just a copy-paste from MultiWindowUtilsTes
xingliu
2016/07/01 00:30:38
Done.
|
| + int numExpectedActivities = ApplicationStatus.getRunningActivities().size() + 1; |
| + |
| + // Find second window activity class. |
| + ChromeTabbedActivity activity = getActivity(); |
| + Class<? extends Activity> secondActivityClass = |
| + MultiWindowUtils.getInstance().getOpenInOtherWindowActivity(activity); |
| + assertEquals("ChromeTabbedActivity2 should be used as the 'open in other window' activity.", |
| + ChromeTabbedActivity2.class, secondActivityClass); |
| + |
| + // Create an intent and start the second ChromeTabbedActivity. |
| + Intent intent = new Intent(activity.getIntent()); |
| + intent.setClass(activity, secondActivityClass); |
| + activity.startActivity(intent); |
| + |
| + // Wait for ChromeTabbedActivity2 to be created. |
| + CriteriaHelper.pollUiThread(Criteria.equals(numExpectedActivities, new Callable<Integer>() { |
| + @Override |
| + public Integer call() { |
| + return ApplicationStatus.getRunningActivities().size(); |
| + } |
| + })); |
| + |
| + // Find and return the second ChromeTabbedActivity. |
| + ChromeTabbedActivity2 returnActivity = null; |
| + for (WeakReference<Activity> reference : ApplicationStatus.getRunningActivities()) { |
| + Activity runningActivity = reference.get(); |
| + if (runningActivity == null) continue; |
| + if (runningActivity.getClass().equals(ChromeTabbedActivity2.class)) { |
| + returnActivity = (ChromeTabbedActivity2) runningActivity; |
| + } |
| + } |
| + assertTrue(returnActivity != null); |
| + return returnActivity; |
| + } |
| + |
| /** |
| * Test undo with a single tab with the following actions/expected states: |
| * Action Model List Close List Comprehensive List |
| @@ -1410,4 +1483,142 @@ public class UndoTabModelTest extends ChromeTabbedActivityTestBase { |
| assertTrue(tab0.isClosing()); |
| assertFalse(tab0.isInitialized()); |
| } |
| + |
| + /** |
| + * Test open recently closed tab using the rewound list in java. |
|
Theresa
2016/06/30 20:50:25
nit: "Test opening recently closed tabs using the
xingliu
2016/07/01 00:30:38
Done.
|
| + * Open recently closed tab first uses rewind list in java, then try to use |
| + * native tab_restore_service if nothing in rewind list. |
| + * @throws InterruptedException |
| + */ |
| + @MediumTest |
| + public void testOpenRecentlyClosedTab() throws InterruptedException { |
| + TabModelSelector selector = getActivity().getTabModelSelector(); |
| + TabModel model = selector.getModel(false); |
| + ChromeTabCreator tabCreator = getActivity().getTabCreator(false); |
| + |
| + createTabOnUiThread(tabCreator); |
| + |
| + Tab tab0 = model.getTabAt(0); |
| + Tab tab1 = model.getTabAt(1); |
| + Tab[] allTabs = new Tab[]{tab0, tab1}; |
| + |
| + closeTabOnUiThread(model, tab1, true); |
| + checkState(model, new Tab[]{tab0}, tab0, new Tab[]{tab1}, allTabs, tab0); |
| + |
| + // Ensure tab recovery, ordering, and reuse of {@link Tab} objects in java. |
| + openRecentlyClosedTabOnUiThread(selector); |
| + checkState(model, allTabs, tab0, EMPTY, allTabs, tab0); |
| + } |
| + |
| + /** |
| + * Test open recently closed tab which uses native code from tab restore service. |
|
Theresa
2016/06/30 20:50:24
nit: "Test opening recently closed tabs using the
|
| + * Open recently closed tab first use rewind list in java, then try to use |
| + * native tab_restore_service if nothing in rewind list. |
| + * @throws InterruptedException |
| + */ |
| + @MediumTest |
| + public void testOpenRecentlyClosedTabNative() throws InterruptedException { |
| + final TabModelSelector selector = getActivity().getTabModelSelector(); |
| + final TabModel model = selector.getModel(false); |
| + final ChromeTabCreator tabCreator = getActivity().getTabCreator(false); |
| + final CallbackHelper tabCallbackHelper = new CallbackHelper(); |
| + final TestTabObserver observer = new TestTabObserver(tabCallbackHelper); |
| + |
| + // Create new tab and attach observer to listen to loaded event. |
|
Theresa
2016/06/30 20:50:24
nit: "... to listen for page load finished events.
xingliu
2016/07/01 00:30:38
Done.
|
| + // We need to wait the page to be fully loaded, then it has navigation |
| + // history, then native code can successfully recover the page. |
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| + @Override |
| + public void run() { |
| + tabCreator.createNewTab(new LoadUrlParams(TEST_URL), |
| + TabLaunchType.FROM_CHROME_UI, null).addObserver(observer); |
| + } |
| + }); |
| + |
| + // Wait for the page to be fully loaded. |
| + try { |
| + tabCallbackHelper.waitForCallback(0); |
| + } catch (TimeoutException e) { |
| + fail(); |
|
Theresa
2016/06/30 20:50:25
Let's add an error message to the failure to help
xingliu
2016/07/01 00:30:38
Done.
|
| + } |
| + |
| + // Close the tab, and commit pending closure. |
| + assertEquals(model.getCount(), 2); |
| + closeTabOnUiThread(model, model.getTabAt(1), false); |
| + assertEquals(1, model.getCount()); |
| + |
| + // Recover the page. |
| + openRecentlyClosedTabOnUiThread(selector); |
| + |
| + assertEquals(2, model.getCount()); |
| + Tab newTab = model.getTabAt(1); |
| + assertEquals(TEST_URL, newTab.getUrl()); |
| + assertTrue(TabModelUtils.getCurrentTab(model) == newTab); |
|
Theresa
2016/06/30 20:50:25
This line is covered by checkState()
xingliu
2016/07/01 00:30:38
Done.
|
| + Tab[] tabs = new Tab[]{model.getTabAt(0), newTab}; |
| + checkState(model, tabs, newTab, EMPTY, tabs, newTab); |
| + } |
| + |
| + /** |
| + * Test open recently closed tab when we have multiple window. |
|
Theresa
2016/06/30 20:50:25
nit: "Test opening recently closed tabs when we ha
|
| + * Open recently closed tab first use rewind list in java, then try to use |
| + * native tab_restore_service if nothing in rewind list. |
| + * @throws InterruptedException |
| + */ |
| + @MediumTest |
| + @TargetApi(Build.VERSION_CODES.LOLLIPOP) |
| + public void testOpenRecentlyClosedTabMultiWindow() throws InterruptedException { |
|
Theresa
2016/06/30 20:50:24
Thank you for adding this!
|
| + ChromeTabbedActivity2 secondWindow = createSecondChromeTabbedActivity(); |
| + |
| + // first window context. |
|
Theresa
2016/06/30 20:50:24
nit: s/first/First
xingliu
2016/07/01 00:30:38
Done.
|
| + final TabModelSelector selector = getActivity().getTabModelSelector(); |
| + final TabModel model = selector.getModel(false); |
| + final ChromeTabCreator tabCreator = getActivity().getTabCreator(false); |
| + final CallbackHelper tabCallbackHelper = new CallbackHelper(); |
| + final TestTabObserver observer = new TestTabObserver(tabCallbackHelper); |
| + |
| + // second window context. |
|
Theresa
2016/06/30 20:50:24
nit: s/second/Second
xingliu
2016/07/01 00:30:38
Done.
|
| + final TabModelSelector secondSelector = secondWindow.getTabModelSelector(); |
| + final TabModel secondModel = secondSelector.getModel(false); |
| + |
| + // Expected to one tab in first window and 0 tabs on second window. |
|
Theresa
2016/06/30 20:50:24
nit: "Assert the first window has 1 tab and the se
xingliu
2016/07/01 00:30:38
Done.
|
| + assertEquals(model.getCount(), 1); |
|
Theresa
2016/06/30 20:50:24
nit: include an error message and put the expected
xingliu
2016/07/01 00:30:38
Done.
|
| + assertEquals(0, secondModel.getCount()); |
|
Theresa
2016/06/30 20:50:24
nit: use an error message like "Unexpected number
xingliu
2016/07/01 00:30:38
Done.
|
| + |
| + // TODO(xingliu): Another test case to create tab on second window, |
| + // currently hit exception while do stuff in second window. |
|
Theresa
2016/06/30 20:50:24
What exception are you seeing? We may need to limi
|
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| + @Override |
| + public void run() { |
| + tabCreator.createNewTab(new LoadUrlParams(TEST_URL), |
| + TabLaunchType.FROM_CHROME_UI, null).addObserver(observer); |
| + } |
| + }); |
| + |
| + // Must wait for the page to be fully loaded. |
| + try { |
| + tabCallbackHelper.waitForCallback(0); |
| + } catch (TimeoutException e) { |
| + fail(); |
| + } |
| + assertEquals(2, model.getCount()); |
| + assertEquals(0, secondModel.getCount()); |
| + |
| + closeTabOnUiThread(model, model.getTabAt(1), false); |
| + assertEquals(1, model.getCount()); |
| + assertEquals(0, secondModel.getCount()); |
| + |
| + // Recover the page. |
| + openRecentlyClosedTabOnUiThread(selector); |
| + assertEquals(2, model.getCount()); |
| + assertEquals(0, secondModel.getCount()); |
| + |
| + Tab[] firstWindowTabs = new Tab[]{model.getTabAt(0), model.getTabAt(1)}; |
| + |
| + checkState(model, firstWindowTabs, model.getTabAt(1), EMPTY, firstWindowTabs, |
| + model.getTabAt(1)); |
| + checkState(secondModel, EMPTY, null, EMPTY, EMPTY, null); |
| + |
| + // Close the second window. |
| + secondWindow.finishAndRemoveTask(); |
| + } |
| } |