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

Unified Diff: chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelImplTest.java

Issue 802343003: Upstream DocumentTabModelImpl and related classes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moved package, added OWNERS Created 6 years 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 side-by-side diff with in-line comments
Download patch
Index: chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelImplTest.java
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..348fc1ca14f343266ef69cff4a7e0f8df0c91687
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelImplTest.java
@@ -0,0 +1,434 @@
+// Copyright 2014 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.tabmodel.document;
+
+import android.os.Build;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArrayMap;
+
+import org.chromium.base.CommandLine;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.AdvancedMockContext;
+import org.chromium.base.test.util.MinAndroidSdkLevel;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelUtils;
+import org.chromium.chrome.test.util.browser.tabmodel.document.MockActivityDelegate;
+import org.chromium.chrome.test.util.browser.tabmodel.document.MockStorageDelegate;
+import org.chromium.chrome.test.util.browser.tabmodel.document.MockTabDelegate;
+import org.chromium.chrome.test.util.browser.tabmodel.document.TestInitializationObserver;
+import org.chromium.content.browser.test.NativeLibraryTestBase;
+
+import java.util.Map;
+
+/**
+ * Tests the functionality of the DocumentTabModel.
+ */
+@MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
+public class DocumentTabModelImplTest extends NativeLibraryTestBase {
+ private static final String MODEL_STATE_WITH_1010_1011 = "CgUgACjyBwoFIAEo8wc=";
+
+ private static final String TAB_STATE_1010_ERFWORLD_RETARGETABLE =
+ "AAABSVhnsswAAAFkYAEAAAAAAAABAAAAAAAAAFABAABMAQAAAAAAACcAAABodHRwOi8vd3d3LmVyZndvcmxkLm"
+ + "NvbS9lcmZfc3RyZWFtL3ZpZXcAAAAAAMQAAADAAAAAFQAAAAAAAABOAAAAaAB0AHQAcAA6AC8ALwB3AHcAdw"
+ + "AuAGUAcgBmAHcAbwByAGwAZAAuAGMAbwBtAC8AZQByAGYAXwBzAHQAcgBlAGEAbQAvAHYAaQBlAHcAAAD///"
+ + "//AAAAAAAAAAD/////AAAAAAgAAAAAAAAAAAAAAM2oGVWBBgUAzqgZVYEGBQDPqBlVgQYFAAEAAAAIAAAAAA"
+ + "AAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAAAAAACAAAAAAAAAAAAQAAACcAAABodHRwOi8vd3"
+ + "d3LmVyZndvcmxkLmNvbS9lcmZfc3RyZWFtL3ZpZXcAAAAAAOrxn50XZS4AAAAAAMgAAAD/////AAAAAAACAA"
+ + "AAAAAAAAAA";
+
+ private static final String TAB_STATE_1011_REDDIT =
+ "AAABSVhw+HkAAAJkYAIAAAAAAAACAAAAAQAAACABAAAcAQAAAAAAABcAAABjaHJvbWUtbmF0aXZlOi8vbmV3"
+ + "dGFiLwAHAAAATgBlAHcAIAB0AGEAYgAAAKQAAACgAAAAFQAAAAAAAAAuAAAAYwBoAHIAbwBtAGUALQBuAGEA"
+ + "dABpAHYAZQA6AC8ALwBuAGUAdwB0AGEAYgAvAAAA/////wAAAAAAAAAA/////wAAAAAIAAAAAAAAAAAA8D9M"
+ + "Bk15gQYFAE0GTXmBBgUATgZNeYEGBQABAAAACAAAAAAAAAAAAPC/CAAAAAAAAAAAAPC/AAAAAAAAAAD/////"
+ + "AAAAAAYAAAAAAAAAAAAAAAEAAAAXAAAAY2hyb21lLW5hdGl2ZTovL25ld3RhYi8AAAAAAN5f08EXZS4AAAAA"
+ + "AAAAAAAsAQAAKAEAAAEAAAAfAAAAaHR0cDovL3d3dy5yZWRkaXQuY29tL3IvYW5kcm9pZAAAAAAAtAAAALAA"
+ + "AAAVAAAAAAAAAD4AAABoAHQAdABwADoALwAvAHcAdwB3AC4AcgBlAGQAZABpAHQALgBjAG8AbQAvAHIALwBh"
+ + "AG4AZAByAG8AaQBkAAAA/////wAAAAAAAAAA/////wAAAAAIAAAAAAAAAAAAAABPBk15gQYFAFAGTXmBBgUA"
+ + "TgZNeYEGBQABAAAACAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAAEAAAIAAAAAAAAA"
+ + "AAEAAAAbAAAAaHR0cDovL3JlZGRpdC5jb20vci9hbmRyb2lkAAAAAAAB65zCF2UuAAAAAADIAAAA/////wAA"
+ + "AAAAAgAAAAAAAAAAAA==";
+
+ private static class CloseRunnable implements Runnable {
+ final DocumentTabModel mTabModel;
+ final int mIndex;
+ boolean mSucceeded;
+
+ public CloseRunnable(DocumentTabModel model, int index) {
+ mTabModel = model;
+ mIndex = index;
+ }
+
+ @Override
+ public void run() {
+ mSucceeded = mTabModel.closeTabAt(mIndex);
+ }
+
+ static boolean closeTabAt(DocumentTabModel model, int index) throws Exception {
+ CloseRunnable runnable = new CloseRunnable(model, index);
+ ThreadUtils.runOnUiThreadBlocking(runnable);
+ return runnable.mSucceeded;
+ }
+ }
+
+ private MockActivityDelegate mActivityDelegate;
+ private MockStorageDelegate mStorageDelegate;
+ private MockTabDelegate mTabDelegate;
+ private DocumentTabModel mTabModel;
+ private AdvancedMockContext mContext;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ CommandLine.init(null);
+ loadNativeLibraryAndInitBrowserProcess();
+
+ mActivityDelegate =
+ new MockActivityDelegate("DocumentActivity", "IncognitoDocumentActivity");
+ mTabDelegate = new MockTabDelegate();
+ mContext = new AdvancedMockContext(getInstrumentation().getTargetContext());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mStorageDelegate.ensureDirectoryDestroyed();
+
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ if (mTabModel.isNativeInitialized()) mTabModel.destroy();
+ }
+ });
+
+ super.tearDown();
+ }
+
+ private void setupDocumentTabModel() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ mTabModel = new DocumentTabModelImpl(
+ mActivityDelegate, mStorageDelegate, mTabDelegate, false, 1010, mContext);
+ mTabModel.startTabStateLoad();
+ }
+ });
+ }
+
+ private void initializeNativeTabModel() throws Exception {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ mTabModel.initializeNative();
+ }
+ });
+ TestInitializationObserver.waitUntilState(
+ mTabModel, DocumentTabModelImpl.STATE_DESERIALIZE_END);
+ }
+
+ @SmallTest
+ public void testBasic() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+ mStorageDelegate.setTaskFileBytesFromEncodedString(MODEL_STATE_WITH_1010_1011);
+ mStorageDelegate.addEncodedTabState(1010, TAB_STATE_1010_ERFWORLD_RETARGETABLE);
+ mStorageDelegate.addEncodedTabState(1011, TAB_STATE_1011_REDDIT);
+
+ setupDocumentTabModel();
+
+ // Confirm the data from the task file is restored correctly.
+ assertEquals(2, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1011, mTabModel.getTabAt(1).getId());
+ assertEquals("http://erfworld.com", mTabModel.getInitialUrlForDocument(1010));
+ assertEquals("http://reddit.com/r/android", mTabModel.getInitialUrlForDocument(1011));
+ assertEquals(true, mTabModel.isRetargetable(1010));
+ assertEquals(false, mTabModel.isRetargetable(1011));
+
+ // State of the tabs.
+ assertTrue(mTabModel.isTabStateReady(1010));
+ assertNotNull(mTabModel.getTabStateForDocument(1010));
+ assertNull(mTabModel.getCurrentUrlForDocument(1010));
+ assertNull(mTabModel.getCurrentUrlForDocument(1011));
+
+ // Wait until the tab states are loaded.
+ TestInitializationObserver.waitUntilState(
+ mTabModel, DocumentTabModelImpl.STATE_LOAD_TAB_STATE_BG_END);
+ assertNotNull(mTabModel.getTabStateForDocument(1011));
+
+ // Load the native library, wait until the states are deserialized, then check their values.
+ initializeNativeTabModel();
+ assertEquals("http://www.erfworld.com/erf_stream/view",
+ mTabModel.getCurrentUrlForDocument(1010));
+ assertEquals("http://www.reddit.com/r/android", mTabModel.getCurrentUrlForDocument(1011));
+ }
+
+ @SmallTest
+ public void testIncognitoIgnored() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+ mActivityDelegate.addTask(true, 1012, "http://incognito.com/ignored");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+ mStorageDelegate.setTaskFileBytesFromEncodedString(MODEL_STATE_WITH_1010_1011);
+ mStorageDelegate.addEncodedTabState(1010, TAB_STATE_1010_ERFWORLD_RETARGETABLE);
+ mStorageDelegate.addEncodedTabState(1011, TAB_STATE_1011_REDDIT);
+
+ setupDocumentTabModel();
+
+ // Confirm the data from the task file is restored correctly.
+ assertEquals(2, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1011, mTabModel.getTabAt(1).getId());
+ assertEquals("http://erfworld.com", mTabModel.getInitialUrlForDocument(1010));
+ assertEquals("http://reddit.com/r/android", mTabModel.getInitialUrlForDocument(1011));
+ assertEquals(true, mTabModel.isRetargetable(1010));
+ assertEquals(false, mTabModel.isRetargetable(1011));
+
+ // State of the tabs.
+ assertTrue(mTabModel.isTabStateReady(1010));
+ assertNotNull(mTabModel.getTabStateForDocument(1010));
+ assertNull(mTabModel.getCurrentUrlForDocument(1010));
+ assertNull(mTabModel.getCurrentUrlForDocument(1011));
+
+ // Wait until the tab states are loaded.
+ TestInitializationObserver.waitUntilState(
+ mTabModel, DocumentTabModelImpl.STATE_LOAD_TAB_STATE_BG_END);
+ assertNotNull(mTabModel.getTabStateForDocument(1011));
+
+ // Load the native library, wait until the states are deserialized, then check their values.
+ initializeNativeTabModel();
+ assertEquals("http://www.erfworld.com/erf_stream/view",
+ mTabModel.getCurrentUrlForDocument(1010));
+ assertEquals("http://www.reddit.com/r/android", mTabModel.getCurrentUrlForDocument(1011));
+ }
+
+ /**
+ * Tasks found in Android's Recents and not in the DocumentTabModel's task file should be
+ * added to the DocumentTabModel.
+ */
+ @SmallTest
+ public void testMissingTaskAddedAndUnretargetable() throws Exception {
+ mActivityDelegate.addTask(false, 1012, "http://digg.com");
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+ mStorageDelegate.setTaskFileBytesFromEncodedString(MODEL_STATE_WITH_1010_1011);
+
+ setupDocumentTabModel();
+
+ assertEquals(3, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1011, mTabModel.getTabAt(1).getId());
+ assertEquals(1012, mTabModel.getTabAt(2).getId());
+
+ assertEquals("http://erfworld.com", mTabModel.getInitialUrlForDocument(1010));
+ assertEquals("http://reddit.com/r/android", mTabModel.getInitialUrlForDocument(1011));
+ assertEquals("http://digg.com", mTabModel.getInitialUrlForDocument(1012));
+
+ assertEquals(true, mTabModel.isRetargetable(1010));
+ assertEquals(false, mTabModel.isRetargetable(1011));
+ assertEquals(false, mTabModel.isRetargetable(1012));
+ }
+
+ /**
+ * If a TabState file is missing, we won't be able to get a current URL for it but should still
+ * get notification that the TabState was loaded.
+ */
+ @SmallTest
+ public void testMissingTabState() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+ mStorageDelegate.setTaskFileBytesFromEncodedString(MODEL_STATE_WITH_1010_1011);
+ mStorageDelegate.addEncodedTabState(1011, TAB_STATE_1011_REDDIT);
+
+ setupDocumentTabModel();
+
+ assertEquals(2, mTabModel.getCount());
+ assertTrue(mTabModel.isTabStateReady(1010));
+ assertNull(mTabModel.getTabStateForDocument(1010));
+
+ assertNull(mTabModel.getCurrentUrlForDocument(1010));
+ assertNull(mTabModel.getCurrentUrlForDocument(1011));
+
+ // After the DocumentTabModel has progressed far enough, confirm that the other available
+ // TabState has been loaded.
+ TestInitializationObserver.waitUntilState(
+ mTabModel, DocumentTabModelImpl.STATE_LOAD_TAB_STATE_BG_END);
+ assertTrue(mTabModel.isTabStateReady(1010));
+ assertTrue(mTabModel.isTabStateReady(1011));
+
+ assertNull(mTabModel.getTabStateForDocument(1010));
+ assertNotNull(mTabModel.getTabStateForDocument(1011));
+
+ // Load the native library, wait until the states are deserialized, then check their values.
+ initializeNativeTabModel();
+ assertNull(null, mTabModel.getCurrentUrlForDocument(1010));
+ assertEquals("http://www.reddit.com/r/android", mTabModel.getCurrentUrlForDocument(1011));
+ }
+
+ @SmallTest
+ public void testTasksSwipedAwayBeforeTabModelCreation() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+ mStorageDelegate.setTaskFileBytesFromEncodedString(MODEL_STATE_WITH_1010_1011);
+ setupDocumentTabModel();
+
+ assertEquals(1, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals("http://erfworld.com", mTabModel.getInitialUrlForDocument(1010));
+ }
+
+ /**
+ * Tasks swiped away in Android's Recents should be reflected as closed tabs in the
+ * DocumentTabModel.
+ */
+ @SmallTest
+ public void testTasksSwipedAwayAfterTabModelCreation() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+ mStorageDelegate.setTaskFileBytesFromEncodedString(MODEL_STATE_WITH_1010_1011);
+
+ setupDocumentTabModel();
+ assertEquals(2, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1011, mTabModel.getTabAt(1).getId());
+
+ mActivityDelegate.removeTask(false, 1010);
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ mTabModel.updateRecentlyClosed();
+ }
+ });
+ assertEquals(1, mTabModel.getCount());
+ assertEquals(1011, mTabModel.getTabAt(0).getId());
+ }
+
+ /**
+ * DocumentTabModel#closeAllTabs() should remove all the tabs from the TabModel.
+ */
+ @SmallTest
+ public void testCloseAllTabs() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+ mStorageDelegate.setTaskFileBytesFromEncodedString(MODEL_STATE_WITH_1010_1011);
+
+ setupDocumentTabModel();
+ assertEquals(2, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1011, mTabModel.getTabAt(1).getId());
+
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ mTabModel.closeAllTabs();
+ }
+ });
+ assertEquals(0, mTabModel.getCount());
+ }
+
+ /**
+ * DocumentTabModel#closeTabAt() should close a tab and slide the other ones in to fill the gap.
+ * This test also relies on the DocumentTabModel adding tasks it finds in Android's Recents to
+ * pad out the test.
+ */
+ @SmallTest
+ public void testCloseTabAt() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+ mActivityDelegate.addTask(false, 1012, "http://digg.com");
+ mActivityDelegate.addTask(false, 1013, "http://slashdot.org");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+
+ setupDocumentTabModel();
+ assertEquals(4, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1011, mTabModel.getTabAt(1).getId());
+ assertEquals(1012, mTabModel.getTabAt(2).getId());
+ assertEquals(1013, mTabModel.getTabAt(3).getId());
+
+ assertTrue(CloseRunnable.closeTabAt(mTabModel, 1));
+ assertEquals(3, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1012, mTabModel.getTabAt(1).getId());
+ assertEquals(1013, mTabModel.getTabAt(2).getId());
+
+ assertTrue(CloseRunnable.closeTabAt(mTabModel, 2));
+ assertEquals(2, mTabModel.getCount());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+ assertEquals(1012, mTabModel.getTabAt(1).getId());
+
+ assertTrue(CloseRunnable.closeTabAt(mTabModel, 0));
+ assertEquals(1, mTabModel.getCount());
+ assertEquals(1012, mTabModel.getTabAt(0).getId());
+
+ assertTrue(CloseRunnable.closeTabAt(mTabModel, 0));
+ assertEquals(0, mTabModel.getCount());
+
+ assertFalse(CloseRunnable.closeTabAt(mTabModel, 0));
+ }
+
+ /**
+ * Test that the DocumentTabModel.index() function works as expected as Tabs are selected and
+ * closed.
+ */
+ @SmallTest
+ public void testIndex() throws Exception {
+ mActivityDelegate.addTask(false, 1010, "http://erfworld.com");
+ mActivityDelegate.addTask(false, 1011, "http://reddit.com/r/android");
+ mActivityDelegate.addTask(false, 1012, "http://digg.com");
+ mActivityDelegate.addTask(false, 1013, "http://slashdot.org");
+
+ mStorageDelegate = new MockStorageDelegate(mContext.getCacheDir(), false);
+
+ Map<String, Object> data = new ArrayMap<String, Object>();
+ data.put(DocumentTabModelImpl.PREF_LAST_SHOWN_TAB_ID_REGULAR, 1011);
+ mContext.addSharedPreferences(DocumentTabModelImpl.PREF_PACKAGE, data);
+
+ // The ID stored in the SharedPreferences points at index 1.
+ setupDocumentTabModel();
+ assertEquals(1, mTabModel.index());
+
+ // Pick a different Tab.
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ TabModelUtils.setIndex(mTabModel, 3);
+ }
+ });
+ assertEquals(3, mTabModel.index());
+ assertEquals(1013, mTabModel.getTabAt(3).getId());
+ assertEquals(1013, data.get(DocumentTabModelImpl.PREF_LAST_SHOWN_TAB_ID_REGULAR));
+
+ // Select the MRU tab since the last known Tab was closed. The last shown ID isn't updated
+ // when the new Tab is selected; it's the job of the DocumentActivity to alert the
+ // DocumentTabModel about shown Tab changes.
+ assertTrue(CloseRunnable.closeTabAt(mTabModel, 3));
+ assertEquals(3, mTabModel.getCount());
+ assertEquals(0, mTabModel.index());
+ assertEquals(1010, mTabModel.getTabAt(0).getId());
+
+ // Close everything; index should be invalid.
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ mTabModel.closeAllTabs();
+ }
+ });
+ assertEquals(0, mTabModel.getCount());
+ assertEquals(TabModel.INVALID_TAB_INDEX, mTabModel.index());
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698