[go: nahoru, domu]

blob: 6e8c033580cdc5f62389ef190f43c5efbd4d5883 [file] [log] [blame]
// Copyright 2018 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.modaldialog;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertTrue;
import static org.chromium.chrome.test.util.ViewUtils.onViewWaiting;
import static org.chromium.components.browser_ui.modaldialog.ModalDialogTestUtils.checkCurrentPresenter;
import static org.chromium.components.browser_ui.modaldialog.ModalDialogTestUtils.checkDialogDismissalCause;
import static org.chromium.components.browser_ui.modaldialog.ModalDialogTestUtils.checkPendingSize;
import static org.chromium.components.browser_ui.modaldialog.ModalDialogTestUtils.createDialog;
import static org.chromium.components.browser_ui.modaldialog.ModalDialogTestUtils.showDialog;
import android.support.test.InstrumentationRegistry;
import android.view.View;
import android.view.ViewGroup;
import androidx.test.espresso.Espresso;
import androidx.test.filters.SmallTest;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Restriction;
import org.chromium.cc.input.BrowserControlsState;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.omnibox.UrlBar;
import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.OmniboxTestUtils;
import org.chromium.components.browser_ui.modaldialog.ModalDialogTestUtils;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.test.util.DisableAnimationsTestRule;
import org.chromium.ui.test.util.UiRestriction;
/**
* Tests for {@link ChromeTabModalPresenter}.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class ChromeTabModalPresenterTest {
private class TestObserver extends EmptyTabObserver
implements UrlFocusChangeListener, ModalDialogTestUtils.TestDialogDismissedObserver {
public final CallbackHelper onUrlFocusChangedCallback = new CallbackHelper();
public final CallbackHelper onDialogDismissedCallback = new CallbackHelper();
public final CallbackHelper onTabInteractabilityChangedCallback = new CallbackHelper();
@Override
public void onUrlFocusChange(boolean hasFocus) {
onUrlFocusChangedCallback.notifyCalled();
}
@Override
public void onInteractabilityChanged(Tab tab, boolean isInteractable) {
onTabInteractabilityChangedCallback.notifyCalled();
}
@Override
public void onDialogDismissed(int dismissalCause) {
onDialogDismissedCallback.notifyCalled();
checkDialogDismissalCause(mExpectedDismissalCause, dismissalCause);
}
}
// Disable animations to reduce flakiness.
@ClassRule
public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule();
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
private ChromeTabbedActivity mActivity;
private ModalDialogManager mManager;
private ChromeTabModalPresenter mTabModalPresenter;
private TestObserver mTestObserver;
private Integer mExpectedDismissalCause;
@Before
public void setUp() {
mActivityTestRule.startMainActivityOnBlankPage();
mActivity = mActivityTestRule.getActivity();
mManager =
TestThreadUtils.runOnUiThreadBlockingNoException(mActivity::getModalDialogManager);
mTestObserver = new TestObserver();
mActivity.getToolbarManager()
.getToolbarLayoutForTesting()
.getLocationBar()
.getFakeboxDelegate()
.addUrlFocusChangeListener(mTestObserver);
mTabModalPresenter =
(ChromeTabModalPresenter) mManager.getPresenterForTest(ModalDialogType.TAB);
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testShow_UrlBarFocused() throws Exception {
// Show a tab modal dialog. The dialog should be shown on top of the toolbar.
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
showDialog(mManager, dialog1, ModalDialogType.TAB);
final View dialogContainer = mTabModalPresenter.getDialogContainerForTest();
final View controlContainer = mActivity.findViewById(R.id.control_container);
final ViewGroup containerParent = mTabModalPresenter.getContainerParentForTest();
ensureDialogContainerVisible();
TestThreadUtils.runOnUiThreadBlocking(() -> {
Assert.assertThat(containerParent.indexOfChild(dialogContainer),
Matchers.greaterThan(containerParent.indexOfChild(controlContainer)));
});
// When editing URL, it should be shown on top of the dialog.
UrlBar urlBar = mActivity.findViewById(R.id.url_bar);
int callCount = mTestObserver.onUrlFocusChangedCallback.getCallCount();
OmniboxTestUtils.toggleUrlBarFocus(urlBar, true);
// TODO(crbug/812066): Following line helps narrow down the cause of flakiness. Previous
// call to toggleUrlBarFocus() should have focused urlBar. Screenshots indicate that
// sometimes it doesn't happen. toggleUrlBarFocus() simulates tap in the middle of the view,
// maybe there are some timing issues there. Accurately simulating tap is not necessary for
// the purpose of this test therefore as an alternative we could call requestFocus() on
// urlBar view.
Assert.assertTrue(
"UrlBar didn't get focused", OmniboxTestUtils.doesUrlBarHaveFocus(urlBar));
mTestObserver.onUrlFocusChangedCallback.waitForCallback(callCount);
TestThreadUtils.runOnUiThreadBlocking(() -> {
Assert.assertThat(containerParent.indexOfChild(dialogContainer),
Matchers.lessThan(containerParent.indexOfChild(controlContainer)));
});
// When URL bar is not focused, the dialog should be shown on top of the toolbar again.
callCount = mTestObserver.onUrlFocusChangedCallback.getCallCount();
OmniboxTestUtils.toggleUrlBarFocus(urlBar, false);
mTestObserver.onUrlFocusChangedCallback.waitForCallback(callCount);
TestThreadUtils.runOnUiThreadBlocking(() -> {
Assert.assertThat(containerParent.indexOfChild(dialogContainer),
Matchers.greaterThan(containerParent.indexOfChild(controlContainer)));
});
// Dismiss the dialog by clicking OK.
onView(withText(R.string.ok)).perform(click());
}
@Test
@SmallTest
@Feature({"ModalDialog"})
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testSuspend_ToggleOverview() throws Exception {
mActivity.getActivityTab().addObserver(mTestObserver);
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
PropertyModel dialog2 = createDialog(mActivity, mManager, "2", null);
PropertyModel dialog3 = createDialog(mActivity, mManager, "3", null);
// Initially there are no dialogs in the pending list. Browser controls are not restricted.
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Add two tab modal dialogs available for showing.
showDialog(mManager, dialog1, ModalDialogType.TAB);
showDialog(mManager, dialog2, ModalDialogType.TAB);
checkPendingSize(mManager, ModalDialogType.TAB, 1);
onViewWaiting(withId(R.id.tab_modal_dialog_container))
.check(matches(
allOf(hasDescendant(withText("1")), not(hasDescendant(withText("2"))))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Tab modal dialogs should be suspended on entering tab switcher.
onView(withId(R.id.tab_switcher_button)).perform(click());
checkPendingSize(mManager, ModalDialogType.TAB, 2);
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(allOf(
not(hasDescendant(withText("1"))), not(hasDescendant(withText("2"))))));
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// An app modal dialog can be shown in tab switcher.
showDialog(mManager, dialog3, ModalDialogType.APP);
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 2);
onView(withId(R.id.tab_modal_dialog_container)).check(doesNotExist());
onView(withText("3")).check(matches(isDisplayed()));
checkCurrentPresenter(mManager, ModalDialogType.APP);
// Close the app modal dialog and verify that the tab modal dialog is still queued.
onView(withText(R.string.ok)).perform(click());
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 2);
// Exit overview mode. The first dialog should be showing again.
int callCount = mTestObserver.onTabInteractabilityChangedCallback.getCallCount();
onView(withId(R.id.tab_switcher_mode_tab_switcher_button)).perform(click());
mTestObserver.onTabInteractabilityChangedCallback.waitForCallback(callCount);
checkPendingSize(mManager, ModalDialogType.TAB, 1);
ensureDialogContainerVisible();
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(
allOf(hasDescendant(withText("1")), not(hasDescendant(withText("2"))))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Dismiss the first dialog. The second dialog should be shown.
onView(withText(R.string.ok)).perform(click());
checkPendingSize(mManager, ModalDialogType.TAB, 0);
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(
allOf(not(hasDescendant(withText("1"))), hasDescendant(withText("2")))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Reset states.
mActivity.getActivityTab().removeObserver(mTestObserver);
}
@Test
@SmallTest
@Feature({"ModalDialog"})
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testSuspend_LastTabClosed() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
// Make sure there is only one opened tab.
while (mActivity.getCurrentTabModel().getCount() > 1) {
ChromeTabUtils.closeCurrentTab(InstrumentationRegistry.getInstrumentation(), mActivity);
}
// Initially there are no dialogs in the pending list. Browser controls are not restricted.
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Add a tab modal dialog available for showing.
showDialog(mManager, dialog1, ModalDialogType.TAB);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
ensureDialogContainerVisible();
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(hasDescendant(withText("1"))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Tab modal dialogs should be suspended on entering tab switcher.
onView(withId(R.id.tab_switcher_button)).perform(click());
checkPendingSize(mManager, ModalDialogType.TAB, 1);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Close the only tab in the tab switcher. Verify that the queued tab modal dialogs are
// cleared.
ChromeTabUtils.closeCurrentTab(InstrumentationRegistry.getInstrumentation(), mActivity);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
}
@Test
@SmallTest
@Feature({"ModalDialog"})
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testSuspend_TabClosed() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
PropertyModel dialog2 = createDialog(mActivity, mManager, "2", null);
PropertyModel dialog3 = createDialog(mActivity, mManager, "3", null);
mActivityTestRule.loadUrlInNewTab("about:blank");
// Initially there are no dialogs in the pending list. Browser controls are not restricted.
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Add a tab modal dialog available for showing.
showDialog(mManager, dialog1, ModalDialogType.TAB);
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
ensureDialogContainerVisible();
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(hasDescendant(withText("1"))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Tab modal dialogs should be suspended on entering tab switcher.
onView(withId(R.id.tab_switcher_button)).perform(click());
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 1);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Close current tab in the tab switcher.
ChromeTabUtils.closeCurrentTab(InstrumentationRegistry.getInstrumentation(), mActivity);
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Show a new tab modal dialog, and it should be suspended in tab switcher.
showDialog(mManager, dialog2, ModalDialogType.TAB);
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 1);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Show an app modal dialog. The app modal dialog should be shown.
showDialog(mManager, dialog3, ModalDialogType.APP);
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 1);
onView(withText("3")).check(matches(isDisplayed()));
checkCurrentPresenter(mManager, ModalDialogType.APP);
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testDismiss_SwitchTab() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
PropertyModel dialog2 = createDialog(mActivity, mManager, "2", null);
// Open a new tab and make sure that the current tab is at index 0.
mActivityTestRule.loadUrlInNewTab("about:blank");
ChromeTabUtils.switchTabInCurrentTabModel(mActivity, 0);
// Initially there are no dialogs in the pending list. Browser controls are not restricted.
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Add a tab modal dialog available for showing.
showDialog(mManager, dialog1, ModalDialogType.TAB);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
ensureDialogContainerVisible();
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(hasDescendant(withText("1"))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Dialog should be dismissed after switching to a different tab.
ChromeTabUtils.switchTabInCurrentTabModel(mActivity, 1);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Open a tab modal dialog in the current tab. The dialog should be shown.
showDialog(mManager, dialog2, ModalDialogType.TAB);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
ensureDialogContainerVisible();
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(hasDescendant(withText("2"))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testDismiss_BackPressed() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
PropertyModel dialog2 = createDialog(mActivity, mManager, "2", null);
// Initially there are no dialogs in the pending list. Browser controls are not restricted.
checkPendingSize(mManager, ModalDialogType.TAB, 0);
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
// Add two tab modal dialogs available for showing. The first dialog should be shown first.
showDialog(mManager, dialog1, ModalDialogType.TAB);
showDialog(mManager, dialog2, ModalDialogType.TAB);
checkPendingSize(mManager, ModalDialogType.TAB, 1);
onViewWaiting(withId(R.id.tab_modal_dialog_container))
.check(matches(hasDescendant(withText("1"))));
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Perform a back press. The first tab modal dialog should be dismissed.
Espresso.pressBack();
checkPendingSize(mManager, ModalDialogType.TAB, 0);
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(
allOf(not(hasDescendant(withText("1"))), hasDescendant(withText("2")))));
checkBrowserControls(true);
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Perform a second back press. The second tab modal dialog should be dismissed.
Espresso.pressBack();
checkPendingSize(mManager, ModalDialogType.APP, 0);
checkPendingSize(mManager, ModalDialogType.TAB, 0);
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(allOf(
not(hasDescendant(withText("1"))), not(hasDescendant(withText("2"))))));
checkBrowserControls(false);
checkCurrentPresenter(mManager, null);
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testDismiss_CancelOnTouchOutside() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
// Show a tab modal dialog and verify it shows.
showDialog(mManager, dialog1, ModalDialogType.TAB);
onViewWaiting(withId(R.id.tab_modal_dialog_container))
.check(matches(hasDescendant(withText("1"))));
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Click dialog container and verify the dialog is not dismissed.
final View dialogContainer = mTabModalPresenter.getDialogContainerForTest();
assertTrue(dialogContainer.isClickable());
TestThreadUtils.runOnUiThreadBlocking(dialogContainer::performClick);
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(hasDescendant(withText("1"))));
checkCurrentPresenter(mManager, ModalDialogType.TAB);
// Enable cancel on touch outside and verify the dialog is dismissed.
TestThreadUtils.runOnUiThreadBlocking(
() -> dialog1.set(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true));
assertTrue(dialogContainer.isClickable());
TestThreadUtils.runOnUiThreadBlocking(dialogContainer::performClick);
onView(withId(R.id.tab_modal_dialog_container))
.check(matches(not(hasDescendant(withText("1")))));
checkCurrentPresenter(mManager, null);
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testDismiss_DismissalCause_BackPressed() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", mTestObserver);
mExpectedDismissalCause = DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE;
showDialog(mManager, dialog1, ModalDialogType.TAB);
// Dismiss the tab modal dialog and verify dismissal cause.
int callCount = mTestObserver.onDialogDismissedCallback.getCallCount();
Espresso.pressBack();
mTestObserver.onDialogDismissedCallback.waitForCallback(callCount);
mExpectedDismissalCause = null;
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testDismiss_DismissalCause_TabSwitched() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", mTestObserver);
mExpectedDismissalCause = DialogDismissalCause.TAB_SWITCHED;
int callCount = mTestObserver.onDialogDismissedCallback.getCallCount();
// Open a new tab and make sure that the current tab is at index 0.
mActivityTestRule.loadUrlInNewTab("about:blank");
ChromeTabUtils.switchTabInCurrentTabModel(mActivity, 0);
// Show a tab modal dialog and then switch tab.
showDialog(mManager, dialog1, ModalDialogType.TAB);
ChromeTabUtils.switchTabInCurrentTabModel(mActivity, 1);
mTestObserver.onDialogDismissedCallback.waitForCallback(callCount);
mExpectedDismissalCause = null;
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testDismiss_DismissalCause_TabDestroyed() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", mTestObserver);
mExpectedDismissalCause = DialogDismissalCause.TAB_DESTROYED;
int callCount = mTestObserver.onDialogDismissedCallback.getCallCount();
// Show a tab modal dialog and then close tab.
showDialog(mManager, dialog1, ModalDialogType.TAB);
ChromeTabUtils.closeCurrentTab(InstrumentationRegistry.getInstrumentation(), mActivity);
mTestObserver.onDialogDismissedCallback.waitForCallback(callCount);
mExpectedDismissalCause = null;
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testDismiss_DismissalCause_TabNavigated() throws Exception {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", mTestObserver);
mExpectedDismissalCause = DialogDismissalCause.NAVIGATE;
int callCount = mTestObserver.onDialogDismissedCallback.getCallCount();
// Show a tab modal dialog and then navigate to a different page.
showDialog(mManager, dialog1, ModalDialogType.TAB);
EmbeddedTestServer server =
EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
mActivityTestRule.loadUrl(server.getURL("/chrome/test/data/android/simple.html"));
mTestObserver.onDialogDismissedCallback.waitForCallback(callCount);
mExpectedDismissalCause = null;
server.stopAndDestroyServer();
}
@Test
@SmallTest
@Feature({"ModalDialog"})
public void testBrowserControlContraints_ShowHide() {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
Assert.assertEquals(BrowserControlsState.BOTH, getBrowserControlsConstraints());
showDialog(mManager, dialog1, ModalDialogType.TAB);
Assert.assertEquals(BrowserControlsState.SHOWN, getBrowserControlsConstraints());
TestThreadUtils.runOnUiThreadBlocking(
()
-> mManager.dismissDialog(
dialog1, DialogDismissalCause.NEGATIVE_BUTTON_CLICKED));
Assert.assertEquals(BrowserControlsState.BOTH, getBrowserControlsConstraints());
}
@Test
@SmallTest
@Feature({"ModalDialog"})
// Ensures an exception isn't thrown when a dialog is dismissed and the View is no longer
// attached to a Window. See https://crbug.com/1127254 for the specifics.
public void testDismissAfterRemovingView() throws Throwable {
PropertyModel dialog1 = createDialog(mActivity, mManager, "1", null);
TestThreadUtils.runOnUiThreadBlocking(() -> {
mManager.showDialog(dialog1, ModalDialogType.TAB);
ViewGroup containerParent = (ViewGroup) mTabModalPresenter.getContainerParentForTest();
// This is a bit hacky and intended to correspond to a case where the hosting
// ViewGroup is no longer attached to a Window.
containerParent.removeAllViews();
mManager.dismissAllDialogs(DialogDismissalCause.UNKNOWN);
});
}
@BrowserControlsState
private int getBrowserControlsConstraints() {
return TestThreadUtils.runOnUiThreadBlockingNoException(
() -> mTabModalPresenter.getBrowserControlsVisibilityDelegate().get());
}
private void checkBrowserControls(boolean restricted) {
boolean isViewObscuringAllTabs = TestThreadUtils.runOnUiThreadBlockingNoException(
() -> mActivity.getTabObscuringHandler().areAllTabsObscured());
boolean isMenuEnabled = TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
View menu = mActivity.getToolbarManager().getMenuButtonView();
Assert.assertNotNull("Toolbar menu is incorrectly null.", menu);
return menu.isEnabled();
});
if (restricted) {
assertTrue("All tabs should be obscured", isViewObscuringAllTabs);
Assert.assertFalse("Menu is incorrectly enabled.", isMenuEnabled);
} else {
Assert.assertFalse("Tabs shouldn't be obscured", isViewObscuringAllTabs);
assertTrue("Menu is incorrectly disabled.", isMenuEnabled);
}
}
private void ensureDialogContainerVisible() {
final View dialogContainer = mTabModalPresenter.getDialogContainerForTest();
onViewWaiting(allOf(is(dialogContainer), isDisplayed()));
}
}