Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Side by Side Diff: chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java

Issue 2088443003: Shortcut ctrl+shift+T added on android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: UMA added correctly, nit changes. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.tabmodel; 5 package org.chromium.chrome.browser.tabmodel;
6 6
7 import android.annotation.TargetApi;
8 import android.os.Build;
7 import android.test.suitebuilder.annotation.MediumTest; 9 import android.test.suitebuilder.annotation.MediumTest;
8 10
11 import org.chromium.base.ApplicationStatus;
9 import org.chromium.base.ThreadUtils; 12 import org.chromium.base.ThreadUtils;
10 import org.chromium.base.test.util.FlakyTest; 13 import org.chromium.base.test.util.FlakyTest;
14 import org.chromium.base.test.util.MinAndroidSdkLevel;
11 import org.chromium.base.test.util.Restriction; 15 import org.chromium.base.test.util.Restriction;
16 import org.chromium.base.test.util.UrlUtils;
17 import org.chromium.chrome.browser.ChromeTabbedActivity;
18 import org.chromium.chrome.browser.ChromeTabbedActivity2;
19 import org.chromium.chrome.browser.multiwindow.MultiWindowUtilsTest;
20 import org.chromium.chrome.browser.tab.EmptyTabObserver;
12 import org.chromium.chrome.browser.tab.Tab; 21 import org.chromium.chrome.browser.tab.Tab;
13 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; 22 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
14 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; 23 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
15 import org.chromium.chrome.test.ChromeTabbedActivityTestBase; 24 import org.chromium.chrome.test.ChromeTabbedActivityTestBase;
16 import org.chromium.chrome.test.util.ChromeRestriction; 25 import org.chromium.chrome.test.util.ChromeRestriction;
17 import org.chromium.content.browser.test.util.CallbackHelper; 26 import org.chromium.content.browser.test.util.CallbackHelper;
27 import org.chromium.content.browser.test.util.Criteria;
28 import org.chromium.content.browser.test.util.CriteriaHelper;
18 import org.chromium.content_public.browser.LoadUrlParams; 29 import org.chromium.content_public.browser.LoadUrlParams;
19 30
31 import java.util.concurrent.Callable;
20 import java.util.concurrent.TimeoutException; 32 import java.util.concurrent.TimeoutException;
21 33
22 /** 34 /**
23 * Tests undo and restoring of tabs in a {@link TabModel}. 35 * Tests undo and restoring of tabs in a {@link TabModel}.
24 */ 36 */
25 public class UndoTabModelTest extends ChromeTabbedActivityTestBase { 37 public class UndoTabModelTest extends ChromeTabbedActivityTestBase {
26 private static final Tab[] EMPTY = new Tab[] { }; 38 private static final Tab[] EMPTY = new Tab[] { };
39 private static final String TEST_URL_0 = UrlUtils.encodeHtmlDataUri("<html>t est_url_0.</html>");
40 private static final String TEST_URL_1 = UrlUtils.encodeHtmlDataUri("<html>t est_url_1</html>");
27 41
28 @Override 42 @Override
29 public void startMainActivity() throws InterruptedException { 43 public void startMainActivity() throws InterruptedException {
30 startMainActivityOnBlankPage(); 44 startMainActivityOnBlankPage();
31 } 45 }
32 46
33 private void checkState( 47 private void checkState(
34 final TabModel model, final Tab[] tabsList, final Tab selectedTab, 48 final TabModel model, final Tab[] tabsList, final Tab selectedTab,
35 final Tab[] closingTabs, final Tab[] fullTabsList, 49 final Tab[] closingTabs, final Tab[] fullTabsList,
36 final Tab fullSelectedTab) { 50 final Tab fullSelectedTab) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 private void createTabOnUiThread(final ChromeTabCreator tabCreator) { 82 private void createTabOnUiThread(final ChromeTabCreator tabCreator) {
69 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 83 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
70 @Override 84 @Override
71 public void run() { 85 public void run() {
72 tabCreator.createNewTab(new LoadUrlParams("about:blank"), 86 tabCreator.createNewTab(new LoadUrlParams("about:blank"),
73 TabLaunchType.FROM_CHROME_UI, null); 87 TabLaunchType.FROM_CHROME_UI, null);
74 } 88 }
75 }); 89 });
76 } 90 }
77 91
92 private void createFullyLoadedTabOnUiThread(final ChromeTabbedActivity activ ity,
93 final String url) {
94 final CallbackHelper tabCallbackHelper = new CallbackHelper();
95 final TabLoadedObserver observer = new TabLoadedObserver(tabCallbackHelp er);
96
97 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
98 @Override
99 public void run() {
100 activity.getTabCreator(false).createNewTab(new LoadUrlParams(url ),
101 TabLaunchType.FROM_CHROME_UI, null).addObserver(observer );
102 }
103 });
104
105 // Must wait for the page to be fully loaded.
106 try {
107 tabCallbackHelper.waitForCallback(0);
108 } catch (TimeoutException | InterruptedException e) {
109 fail("Failed to load the tab.");
110 }
111 }
112
78 private void selectTabOnUiThread(final TabModel model, final Tab tab) { 113 private void selectTabOnUiThread(final TabModel model, final Tab tab) {
79 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 114 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
80 @Override 115 @Override
81 public void run() { 116 public void run() {
82 model.setIndex(model.indexOf(tab), TabSelectionType.FROM_USER); 117 model.setIndex(model.indexOf(tab), TabSelectionType.FROM_USER);
83 } 118 }
84 }); 119 });
85 } 120 }
86 121
87 private void closeTabOnUiThread( 122 private void closeTabOnUiThread(
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 }); 349 });
315 350
316 for (int i = 0; i < selector.getModels().size(); i++) { 351 for (int i = 0; i < selector.getModels().size(); i++) {
317 TabList tabs = selector.getModelAt(i).getComprehensiveModel(); 352 TabList tabs = selector.getModelAt(i).getComprehensiveModel();
318 for (int j = 0; j < tabs.getCount(); j++) { 353 for (int j = 0; j < tabs.getCount(); j++) {
319 assertFalse(tabs.isClosurePending(tabs.getTabAt(j).getId())); 354 assertFalse(tabs.isClosurePending(tabs.getTabAt(j).getId()));
320 } 355 }
321 } 356 }
322 } 357 }
323 358
359 private void openMostRecentlyClosedTabOnUiThread(final TabModelSelector sele ctor) {
360 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
361 @Override
362 public void run() {
363 selector.getCurrentModel().openMostRecentlyClosedTab();
364 }
365 });
366 }
367
368 // Helper class that notifies when a page load is finished.
369 private static class TabLoadedObserver extends EmptyTabObserver {
370 private CallbackHelper mLoadedCallback;
371
372 public TabLoadedObserver(CallbackHelper loadCallback) {
373 super();
374 mLoadedCallback = loadCallback;
375 }
376 @Override
377 public void onPageLoadFinished(Tab tab) {
378 mLoadedCallback.notifyCalled();
379 }
380 }
381
382 // Helper class that notifies after the tab is closed, and a tab restore ser vice entry has been
383 // created in tab restore service.
384 private static class TabClosedObserver extends EmptyTabModelObserver {
385 private CallbackHelper mTabClosedCallback;
386
387 public TabClosedObserver(CallbackHelper closedCallback) {
388 mTabClosedCallback = closedCallback;
389 }
390
391 @Override
392 public void didCloseTab(int tabId, boolean incognito) {
393 mTabClosedCallback.notifyCalled();
394 }
395 }
396
324 /** 397 /**
325 * Test undo with a single tab with the following actions/expected states: 398 * Test undo with a single tab with the following actions/expected states:
326 * Action Model List Close List Compr ehensive List 399 * Action Model List Close List Compr ehensive List
327 * 1. Initial State [ 0s ] - [ 0s ] 400 * 1. Initial State [ 0s ] - [ 0s ]
328 * 2. CloseTab(0, allow undo) - [ 0 ] [ 0s ] 401 * 2. CloseTab(0, allow undo) - [ 0 ] [ 0s ]
329 * 3. CancelClose(0) [ 0s ] - [ 0s ] 402 * 3. CancelClose(0) [ 0s ] - [ 0s ]
330 * 4. CloseTab(0, allow undo) - [ 0 ] [ 0s ] 403 * 4. CloseTab(0, allow undo) - [ 0 ] [ 0s ]
331 * 5. CommitClose(0) - - - 404 * 5. CommitClose(0) - - -
332 * 6. CreateTab(0) [ 0s ] - [ 0s ] 405 * 6. CreateTab(0) [ 0s ] - [ 0s ]
333 * 7. CloseTab(0, allow undo) - [ 0 ] [ 0s ] 406 * 7. CloseTab(0, allow undo) - [ 0 ] [ 0s ]
(...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 closeTabOnUiThread(model, tab0, true); 1476 closeTabOnUiThread(model, tab0, true);
1404 checkState(model, new Tab[] { tab1 }, tab1, EMPTY, fullList, tab1); 1477 checkState(model, new Tab[] { tab1 }, tab1, EMPTY, fullList, tab1);
1405 1478
1406 // 3. 1479 // 3.
1407 saveStateOnUiThread(selector); 1480 saveStateOnUiThread(selector);
1408 fullList = new Tab[] { tab1 }; 1481 fullList = new Tab[] { tab1 };
1409 checkState(model, new Tab[] { tab1 }, tab1, EMPTY, fullList, tab1); 1482 checkState(model, new Tab[] { tab1 }, tab1, EMPTY, fullList, tab1);
1410 assertTrue(tab0.isClosing()); 1483 assertTrue(tab0.isClosing());
1411 assertFalse(tab0.isInitialized()); 1484 assertFalse(tab0.isInitialized());
1412 } 1485 }
1486
1487 /**
1488 * Test opening recently closed tabs using the rewound list in Java.
1489 * @throws InterruptedException
1490 */
1491 @MediumTest
1492 public void testOpenRecentlyClosedTab() throws InterruptedException {
1493 TabModelSelector selector = getActivity().getTabModelSelector();
1494 TabModel model = selector.getModel(false);
1495 ChromeTabCreator tabCreator = getActivity().getTabCreator(false);
1496
1497 createTabOnUiThread(tabCreator);
1498
1499 Tab tab0 = model.getTabAt(0);
1500 Tab tab1 = model.getTabAt(1);
1501 Tab[] allTabs = new Tab[]{tab0, tab1};
1502
1503 closeTabOnUiThread(model, tab1, true);
1504 checkState(model, new Tab[]{tab0}, tab0, new Tab[]{tab1}, allTabs, tab0) ;
1505
1506 // Ensure tab recovery, ordering, and reuse of {@link Tab} objects in Ja va.
1507 openMostRecentlyClosedTabOnUiThread(selector);
1508 checkState(model, allTabs, tab0, EMPTY, allTabs, tab0);
1509 }
1510
1511 /**
1512 * Test opening recently closed tab using native tab restore service.
1513 * @throws InterruptedException
1514 */
1515 @MediumTest
1516 public void testOpenRecentlyClosedTabNative() throws InterruptedException {
1517 final TabModelSelector selector = getActivity().getTabModelSelector();
1518 final TabModel model = selector.getModel(false);
1519
1520 // Create new tab and attach observer to listen to loaded event.
1521 // Native can only successfully recover the tab after a page load has fi nished and
1522 // it has navigation history.
1523 createFullyLoadedTabOnUiThread(getActivity(), TEST_URL_0);
1524
1525 // Close the tab, and commit pending closure.
1526 assertEquals(model.getCount(), 2);
1527 closeTabOnUiThread(model, model.getTabAt(1), false);
1528 assertEquals(1, model.getCount());
1529 Tab[] tabs = new Tab[]{model.getTabAt(0)};
1530 checkState(model, tabs, tabs[0], EMPTY, tabs, tabs[0]);
1531
1532 // Recover the page.
1533 openMostRecentlyClosedTabOnUiThread(selector);
1534
1535 assertEquals(2, model.getCount());
1536 tabs = new Tab[]{model.getTabAt(0), model.getTabAt(1)};
1537 assertEquals(TEST_URL_0, tabs[1].getUrl());
1538 checkState(model, tabs, tabs[0], EMPTY, tabs, tabs[0]);
1539 }
1540
1541 /**
1542 * Test opening recently closed tab when we have multiple windows.
1543 * | Action | Result
1544 * 1. Create second window. |
1545 * 2. Open tab in window 1. |
1546 * 3. Open tab in window 2. |
1547 * 4. Close tab in window 1. |
1548 * 5. Close tab in window 2. |
1549 * 6. Restore tab. | Tab restored in window 2.
1550 * 7. Restore tab. | Tab restored in window 1.
1551 * @throws InterruptedException
1552 */
1553 @MediumTest
1554 @MinAndroidSdkLevel(24)
1555 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
1556 public void testOpenRecentlyClosedTabMultiWindow() throws InterruptedExcepti on {
1557 final ChromeTabbedActivity2 secondActivity =
1558 MultiWindowUtilsTest.createSecondChromeTabbedActivity(getActivit y());
1559
1560 // Wait for the second window to be fully initialized.
1561 CriteriaHelper.pollUiThread(new Criteria() {
1562 @Override
1563 public boolean isSatisfied() {
1564 return secondActivity.getTabModelSelector().isTabStateInitialize d();
1565 }
1566 });
1567 // First window context.
1568 final TabModelSelector firstSelector = getActivity().getTabModelSelector ();
1569 final TabModel firstModel = firstSelector.getModel(false);
1570
1571 // Second window context.
1572 final TabModel secondModel = secondActivity.getTabModelSelector().getMod el(false);
1573
1574 // Create tabs.
1575 createFullyLoadedTabOnUiThread(getActivity(), TEST_URL_0);
1576 createFullyLoadedTabOnUiThread(secondActivity, TEST_URL_1);
1577
1578 assertEquals("Unexpected number of tabs in first window.", 2, firstModel .getCount());
1579 assertEquals("Unexpected number of tabs in second window.", 2, secondMod el.getCount());
1580
1581 // Close one tab in the first window.
1582 closeTabOnUiThread(firstModel, firstModel.getTabAt(1), false);
1583 assertEquals("Unexpected number of tabs in first window.", 1, firstModel .getCount());
1584 assertEquals("Unexpected number of tabs in second window.", 2, secondMod el.getCount());
1585
1586 // Close one tab in the second window.
1587 closeTabOnUiThread(secondModel, secondModel.getTabAt(1), false);
1588 assertEquals("Unexpected number of tabs in first window.", 1, firstModel .getCount());
1589 assertEquals("Unexpected number of tabs in second window.", 1, secondMod el.getCount());
1590
1591 // Restore one tab.
1592 openMostRecentlyClosedTabOnUiThread(firstSelector);
1593 assertEquals("Unexpected number of tabs in first window.", 1, firstModel .getCount());
1594 assertEquals("Unexpected number of tabs in second window.", 2, secondMod el.getCount());
1595
1596 // Restore one more tab.
1597 openMostRecentlyClosedTabOnUiThread(firstSelector);
1598
1599 // Check final states of both windows.
1600 Tab firstModelTab = firstModel.getTabAt(0);
Theresa 2016/07/12 17:25:17 nit: move this above line 1582, before any tabs ar
1601 Tab secondModelTab = secondModel.getTabAt(0);
1602 Tab[] firstWindowTabs = new Tab[]{firstModelTab, firstModel.getTabAt(1)} ;
1603 Tab[] secondWindowTabs = new Tab[]{secondModelTab, secondModel.getTabAt( 1)};
1604 checkState(firstModel, firstWindowTabs, firstModelTab, EMPTY, firstWindo wTabs,
1605 firstModelTab);
1606 checkState(secondModel, secondWindowTabs, secondModelTab, EMPTY, secondW indowTabs,
1607 secondModelTab);
1608 assertEquals(TEST_URL_0, firstWindowTabs[1].getUrl());
1609 assertEquals(TEST_URL_1, secondWindowTabs[1].getUrl());
1610
1611 secondActivity.finishAndRemoveTask();
1612 }
1613
1614 /**
1615 * Test restoring closed tab from a closed window.
1616 * | Action | Result
1617 * 1. Create second window. |
1618 * 2. Open tab in window 2. |
1619 * 3. Close tab in window 2. |
1620 * 4. Close second window. |
1621 * 5. Restore tab. | Tab restored in first window.
1622 * @throws InterruptedException
1623 */
1624 @MediumTest
1625 @MinAndroidSdkLevel(24)
1626 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
1627 public void testOpenRecentlyClosedTabMultiWindowFallback() throws Interrupte dException {
1628 final ChromeTabbedActivity2 secondActivity =
1629 MultiWindowUtilsTest.createSecondChromeTabbedActivity(getActivit y());
1630 // Wait for the second window to be fully initialized.
1631 CriteriaHelper.pollUiThread(new Criteria() {
1632 @Override
1633 public boolean isSatisfied() {
1634 return secondActivity.getTabModelSelector().isTabStateInitialize d();
1635 }
1636 });
1637
1638 // First window context.
1639 final TabModelSelector firstSelector = getActivity().getTabModelSelector ();
1640 final TabModel firstModel = firstSelector.getModel(false);
1641
1642 // Second window context.
1643 final TabModel secondModel = secondActivity.getTabModelSelector().getMod el(false);
1644
1645 // Create tab on second window.
1646 createFullyLoadedTabOnUiThread(secondActivity, TEST_URL_1);
1647 assertEquals("Window 2 should have 2 tab.", 2, secondModel.getCount());
1648
1649 // Close tab in second window, wait until tab restore service history is created.
1650 CallbackHelper closedCallback = new CallbackHelper();
1651 secondModel.addObserver(new TabClosedObserver(closedCallback));
1652 closeTabOnUiThread(secondModel, secondModel.getTabAt(1), false);
1653
1654 try {
1655 closedCallback.waitForCallback(0);
1656 } catch (TimeoutException | InterruptedException e) {
1657 fail("Failed to close the tab on the second window.");
1658 }
1659
1660 assertEquals("Window 2 should have 1 tab.", 1, secondModel.getCount());
1661
1662 // Closed the second window. Must wait until it's totally closed.
1663 int numExpectedActivities = ApplicationStatus.getRunningActivities().siz e() - 1;
1664 secondActivity.finishAndRemoveTask();
1665 CriteriaHelper.pollUiThread(Criteria.equals(numExpectedActivities, new C allable<Integer>() {
1666 @Override
1667 public Integer call() {
1668 return ApplicationStatus.getRunningActivities().size();
1669 }
1670 }));
1671 assertEquals("Window 1 should have 1 tab.", 1, firstModel.getCount());
1672
1673 // Restore closed tab from second window. It should be created in first window.
1674 openMostRecentlyClosedTabOnUiThread(firstSelector);
1675 assertEquals("Closed tab in second window should be restored in the firs t window.", 2,
1676 firstModel.getCount());
1677 Tab[] firstWindowTabs = new Tab[]{firstModel.getTabAt(0), firstModel.get TabAt(1)};
1678 checkState(firstModel, firstWindowTabs, firstWindowTabs[0], EMPTY, first WindowTabs,
1679 firstWindowTabs[0]);
1680 assertEquals(TEST_URL_1, firstWindowTabs[1].getUrl());
1681 }
1413 } 1682 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698