Commit add2c76b authored by Evan Stade's avatar Evan Stade Committed by Commit Bot

WebLayer: defer (rather than ignore) window.alert on background tabs.

This matches Chrome behavior. When a window.alert is triggered on a bg
tab, it will be deferred until that tab becomes foregrounded. This
logic is implemented in TabModalDialogManager, so there are minimal
changes required to WebLayer.

Note that other js dialogs are simply ignored on backgrounded tabs,
with a console message logged.

Bug: 1025256
Change-Id: I05bce9195198db3685c814246e73721269a4b979
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2075053
Commit-Queue: Evan Stade <estade@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745149}
parent 865a1e45
......@@ -196,11 +196,12 @@ public class InstrumentationActivityTestRule extends ActivityTestRule<Instrument
/**
* Executes the script passed in and waits for the result.
*/
public JSONObject executeScriptSync(String script, boolean useSeparateIsolate) {
public JSONObject executeScriptSync(String script, boolean useSeparateIsolate, Tab tab) {
JSONCallbackHelper callbackHelper = new JSONCallbackHelper();
int count = callbackHelper.getCallCount();
TestThreadUtils.runOnUiThreadBlocking(() -> {
getActivity().getBrowser().getActiveTab().executeScript(script, useSeparateIsolate,
Tab scriptTab = tab == null ? getActivity().getBrowser().getActiveTab() : tab;
scriptTab.executeScript(script, useSeparateIsolate,
(JSONObject result) -> { callbackHelper.notifyCalled(result); });
});
try {
......@@ -211,6 +212,10 @@ public class InstrumentationActivityTestRule extends ActivityTestRule<Instrument
return callbackHelper.getResult();
}
public JSONObject executeScriptSync(String script, boolean useSeparateIsolate) {
return executeScriptSync(script, useSeparateIsolate, null);
}
public int executeScriptAndExtractInt(String script) {
try {
return executeScriptSync(script, true /* useSeparateIsolate */)
......
......@@ -137,7 +137,6 @@ public class TabCallbackTest {
Assert.assertEquals("anchor text", params[0].linkText);
}
// Requires implementation M82.
@Test
@SmallTest
public void testTabModalOverlay() throws TimeoutException {
......@@ -170,4 +169,62 @@ public class TabCallbackTest {
callbackHelper.waitForCallback(callCount);
Assert.assertEquals(false, isTabModalShowingResult[0]);
}
@Test
@SmallTest
public void testTabModalOverlayOnBackgroundTab() throws TimeoutException {
// Create a tab.
String url = mActivityTestRule.getTestDataURL("new_browser.html");
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(url);
Assert.assertNotNull(activity);
NewTabCallbackImpl callback = new NewTabCallbackImpl();
Tab firstTab = TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
Tab tab = activity.getBrowser().getActiveTab();
tab.setNewTabCallback(callback);
return tab;
});
// Tapping it creates a second tab, which is active.
EventUtils.simulateTouchCenterOfView(activity.getWindow().getDecorView());
callback.waitForNewTab();
Tab secondTab = TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
Assert.assertEquals(2, activity.getBrowser().getTabs().size());
return activity.getBrowser().getActiveTab();
});
Assert.assertNotSame(firstTab, secondTab);
// Track tab modal updates.
Boolean isTabModalShowingResult[] = new Boolean[1];
CallbackHelper callbackHelper = new CallbackHelper();
int callCount = callbackHelper.getCallCount();
TestThreadUtils.runOnUiThreadBlocking(() -> {
firstTab.registerTabCallback(new TabCallback() {
@Override
public void onTabModalStateChanged(boolean isTabModalShowing) {
isTabModalShowingResult[0] = isTabModalShowing;
callbackHelper.notifyCalled();
}
});
});
// Create an alert from the background tab. It shouldn't display. There's no way to
// consistently verify that nothing happens, but the script execution should finish, which
// is not the case for dialogs that show on an active tab until they're dismissed.
mActivityTestRule.executeScriptSync("window.alert('foo');", true, firstTab);
Assert.assertEquals(0, callbackHelper.getCallCount());
// When that tab becomes active again, the alert should show.
TestThreadUtils.runOnUiThreadBlocking(
() -> { activity.getBrowser().setActiveTab(firstTab); });
callbackHelper.waitForCallback(callCount);
Assert.assertEquals(true, isTabModalShowingResult[0]);
// Switch away from the tab again; the alert should be hidden.
callCount = callbackHelper.getCallCount();
TestThreadUtils.runOnUiThreadBlocking(
() -> { activity.getBrowser().setActiveTab(secondTab); });
callbackHelper.waitForCallback(callCount);
Assert.assertEquals(false, isTabModalShowingResult[0]);
}
}
......@@ -440,11 +440,6 @@ void TabImpl::DidNavigateMainFramePostCommit(
content::JavaScriptDialogManager* TabImpl::GetJavaScriptDialogManager(
content::WebContents* web_contents) {
#if defined(OS_ANDROID)
// Simply ignore javascript dialog requests from non-foremost tabs.
// TODO(crbug.com/1025256): revisit this behavior.
if (!IsActive())
return nullptr;
return javascript_dialogs::TabModalDialogManager::FromWebContents(
web_contents);
#else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment