1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.android_webview.test; 6 7 import android.graphics.Rect; 8 import android.net.Uri; 9 import android.support.test.InstrumentationRegistry; 10 import android.webkit.JavascriptInterface; 11 12 import androidx.test.filters.SmallTest; 13 14 import org.hamcrest.Matchers; 15 import org.junit.After; 16 import org.junit.Assert; 17 import org.junit.Before; 18 import org.junit.Rule; 19 import org.junit.Test; 20 import org.junit.runner.RunWith; 21 22 import org.chromium.android_webview.AwContents; 23 import org.chromium.android_webview.JsReplyProxy; 24 import org.chromium.android_webview.WebMessageListener; 25 import org.chromium.android_webview.test.AwActivityTestRule.PopupInfo; 26 import org.chromium.android_webview.test.TestAwContentsClient.ShouldInterceptRequestHelper; 27 import org.chromium.android_webview.test.util.CommonResources; 28 import org.chromium.base.ThreadUtils; 29 import org.chromium.base.test.util.Criteria; 30 import org.chromium.base.test.util.CriteriaHelper; 31 import org.chromium.base.test.util.CriteriaNotSatisfiedException; 32 import org.chromium.base.test.util.Feature; 33 import org.chromium.content_public.browser.MessagePort; 34 import org.chromium.content_public.browser.SelectionPopupController; 35 import org.chromium.content_public.browser.test.util.DOMUtils; 36 import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer; 37 import org.chromium.content_public.browser.test.util.TestThreadUtils; 38 import org.chromium.net.test.util.TestWebServer; 39 40 import java.util.List; 41 import java.util.Locale; 42 import java.util.concurrent.LinkedBlockingQueue; 43 import java.util.concurrent.TimeUnit; 44 45 /** 46 * Tests for pop up window flow. 47 */ 48 @RunWith(AwJUnit4ClassRunner.class) 49 public class PopupWindowTest { 50 @Rule 51 public AwActivityTestRule mActivityTestRule = new AwActivityTestRule(); 52 53 private TestAwContentsClient mParentContentsClient; 54 private AwTestContainerView mParentContainerView; 55 private AwContents mParentContents; 56 private TestWebServer mWebServer; 57 58 private static final String POPUP_TITLE = "Popup Window"; 59 60 @Before setUp()61 public void setUp() throws Exception { 62 mParentContentsClient = new TestAwContentsClient(); 63 mParentContainerView = 64 mActivityTestRule.createAwTestContainerViewOnMainSync(mParentContentsClient); 65 mParentContents = mParentContainerView.getAwContents(); 66 mWebServer = TestWebServer.start(); 67 } 68 69 @After tearDown()70 public void tearDown() { 71 if (mWebServer != null) { 72 mWebServer.shutdown(); 73 } 74 } 75 76 @Test 77 @SmallTest 78 @Feature({"AndroidWebView"}) testPopupWindow()79 public void testPopupWindow() throws Throwable { 80 final String popupPath = "/popup.html"; 81 final String parentPageHtml = CommonResources.makeHtmlPageFrom("", "<script>" 82 + "function tryOpenWindow() {" 83 + " var newWindow = window.open('" + popupPath + "');" 84 + "}</script>"); 85 86 final String popupPageHtml = CommonResources.makeHtmlPageFrom( 87 "<title>" + POPUP_TITLE + "</title>", 88 "This is a popup window"); 89 90 mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer, 91 parentPageHtml, popupPageHtml, popupPath, "tryOpenWindow()"); 92 AwContents popupContents = 93 mActivityTestRule.connectPendingPopup(mParentContents).popupContents; 94 Assert.assertEquals(POPUP_TITLE, mActivityTestRule.getTitleOnUiThread(popupContents)); 95 } 96 97 @Test 98 @SmallTest 99 @Feature({"AndroidWebView"}) testJavascriptInterfaceForPopupWindow()100 public void testJavascriptInterfaceForPopupWindow() throws Throwable { 101 // android.webkit.cts.WebViewTest#testJavascriptInterfaceForClientPopup 102 final String popupPath = "/popup.html"; 103 final String parentPageHtml = CommonResources.makeHtmlPageFrom("", 104 "<script>" 105 + "function tryOpenWindow() {" 106 + " var newWindow = window.open('" + popupPath + "');" 107 + "}</script>"); 108 109 final String popupPageHtml = CommonResources.makeHtmlPageFrom( 110 "<title>" + POPUP_TITLE + "</title>", "This is a popup window"); 111 112 mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer, 113 parentPageHtml, popupPageHtml, popupPath, "tryOpenWindow()"); 114 PopupInfo popupInfo = mActivityTestRule.createPopupContents(mParentContents); 115 TestAwContentsClient popupContentsClient = popupInfo.popupContentsClient; 116 final AwContents popupContents = popupInfo.popupContents; 117 118 class DummyJavaScriptInterface { 119 @JavascriptInterface 120 public int test() { 121 return 42; 122 } 123 } 124 final DummyJavaScriptInterface obj = new DummyJavaScriptInterface(); 125 126 AwActivityTestRule.addJavascriptInterfaceOnUiThread(popupContents, obj, "dummy"); 127 128 mActivityTestRule.loadPopupContents(mParentContents, popupInfo, null); 129 130 AwActivityTestRule.pollInstrumentationThread(() -> { 131 String ans = mActivityTestRule.executeJavaScriptAndWaitForResult( 132 popupContents, popupContentsClient, "dummy.test()"); 133 134 return ans.equals("42"); 135 }); 136 } 137 138 @Test 139 @SmallTest 140 @Feature({"AndroidWebView"}) testDefaultUserAgentsInParentAndChildWindows()141 public void testDefaultUserAgentsInParentAndChildWindows() throws Throwable { 142 mActivityTestRule.getAwSettingsOnUiThread(mParentContents).setJavaScriptEnabled(true); 143 mActivityTestRule.loadUrlSync( 144 mParentContents, mParentContentsClient.getOnPageFinishedHelper(), "about:blank"); 145 String parentUserAgent = mActivityTestRule.executeJavaScriptAndWaitForResult( 146 mParentContents, mParentContentsClient, "navigator.userAgent"); 147 148 final String popupPath = "/popup.html"; 149 final String myUserAgentString = "myUserAgent"; 150 final String parentPageHtml = CommonResources.makeHtmlPageFrom("", 151 "<script>" 152 + "function tryOpenWindow() {" 153 + " var newWindow = window.open('" + popupPath + "');" 154 + "}</script>"); 155 156 final String popupPageHtml = "<html><head><script>" 157 + "document.title = navigator.userAgent;" 158 + "</script><body><div id='a'></div></body></html>"; 159 160 mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer, 161 parentPageHtml, popupPageHtml, popupPath, "tryOpenWindow()"); 162 163 PopupInfo popupInfo = mActivityTestRule.createPopupContents(mParentContents); 164 TestAwContentsClient popupContentsClient = popupInfo.popupContentsClient; 165 final AwContents popupContents = popupInfo.popupContents; 166 167 mActivityTestRule.loadPopupContents(mParentContents, popupInfo, null); 168 169 final String childUserAgent = mActivityTestRule.executeJavaScriptAndWaitForResult( 170 popupContents, popupContentsClient, "navigator.userAgent"); 171 172 Assert.assertEquals(parentUserAgent, childUserAgent); 173 } 174 175 @Test 176 @SmallTest 177 @Feature({"AndroidWebView"}) testOverrideUserAgentInOnCreateWindow()178 public void testOverrideUserAgentInOnCreateWindow() throws Throwable { 179 final String popupPath = "/popup.html"; 180 final String myUserAgentString = "myUserAgent"; 181 final String parentPageHtml = CommonResources.makeHtmlPageFrom("", 182 "<script>" 183 + "function tryOpenWindow() {" 184 + " var newWindow = window.open('" + popupPath + "');" 185 + "}</script>"); 186 187 final String popupPageHtml = "<html><head><script>" 188 + "document.title = navigator.userAgent;" 189 + "</script><body><div id='a'></div></body></html>"; 190 191 mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer, 192 parentPageHtml, popupPageHtml, popupPath, "tryOpenWindow()"); 193 194 PopupInfo popupInfo = mActivityTestRule.createPopupContents(mParentContents); 195 TestAwContentsClient popupContentsClient = popupInfo.popupContentsClient; 196 final AwContents popupContents = popupInfo.popupContents; 197 198 // Override the user agent string for the popup window. 199 mActivityTestRule.loadPopupContents( 200 mParentContents, popupInfo, new AwActivityTestRule.OnCreateWindowHandler() { 201 @Override 202 public boolean onCreateWindow(AwContents awContents) { 203 awContents.getSettings().setUserAgentString(myUserAgentString); 204 return true; 205 } 206 }); 207 208 CriteriaHelper.pollUiThread(() -> { 209 try { 210 Criteria.checkThat(mActivityTestRule.getTitleOnUiThread(popupContents), 211 Matchers.is(myUserAgentString)); 212 } catch (Exception e) { 213 throw new CriteriaNotSatisfiedException(e); 214 } 215 }); 216 } 217 218 @Test 219 @SmallTest 220 @Feature({"AndroidWebView"}) testOnPageFinishedCalledOnDomModificationAfterNavigation()221 public void testOnPageFinishedCalledOnDomModificationAfterNavigation() throws Throwable { 222 final String popupPath = "/popup.html"; 223 final String parentPageHtml = CommonResources.makeHtmlPageFrom("", 224 "<script>" 225 + "function tryOpenWindow() {" 226 + " window.popupWindow = window.open('" + popupPath + "');" 227 + "}" 228 + "function modifyDomOfPopup() {" 229 + " window.popupWindow.document.body.innerHTML = 'Hello from the parent!';" 230 + "}</script>"); 231 232 mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer, 233 parentPageHtml, "<html></html>", popupPath, "tryOpenWindow()"); 234 PopupInfo popupInfo = mActivityTestRule.createPopupContents(mParentContents); 235 TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = 236 popupInfo.popupContentsClient.getOnPageFinishedHelper(); 237 ShouldInterceptRequestHelper shouldInterceptRequestHelper = 238 popupInfo.popupContentsClient.getShouldInterceptRequestHelper(); 239 int onPageFinishedCount = onPageFinishedHelper.getCallCount(); 240 int shouldInterceptRequestCount = shouldInterceptRequestHelper.getCallCount(); 241 // Modify DOM before navigation gets committed. Once it gets committed, then 242 // DidAccessInitialDocument does not get triggered. 243 popupInfo.popupContentsClient.getShouldInterceptRequestHelper().runDuringFirstTimeCallback( 244 () -> { 245 ThreadUtils.assertOnBackgroundThread(); 246 try { 247 // Ensures that we modify DOM before navigation gets committed. 248 mActivityTestRule.executeJavaScriptAndWaitForResult( 249 mParentContents, mParentContentsClient, "modifyDomOfPopup()"); 250 } catch (Exception e) { 251 throw new RuntimeException(e); 252 } 253 }); 254 mActivityTestRule.loadPopupContents(mParentContents, popupInfo, null); 255 shouldInterceptRequestHelper.waitForCallback(shouldInterceptRequestCount); 256 // Modifying DOM in the middle while loading a popup window - this causes navigation state 257 // change through AwWebContentsDelegateAdapter#navigationStateChanged(), resulting in an 258 // additional onPageFinished() callback. Also, this eventually affects commit stage of the 259 // navigation which creates additional navigationStateChanged() and one additional 260 // onPageFinished() callback. 261 onPageFinishedHelper.waitForCallback(onPageFinishedCount, 4); 262 // This is the URL that gets shown to the user because parent changed DOM of the popup 263 // window. 264 List<String> urlList = onPageFinishedHelper.getUrlList(); 265 Assert.assertEquals("about:blank", urlList.get(onPageFinishedCount)); 266 // Note that in this test we do not stop the navigation and we still navigate to the page 267 // that we wanted. The loaded page does not have the changed DOM. This is slightly different 268 // from the original workflow in b/19325392 as there is no good hook to stop navigation and 269 // trigger DidAccessInitialDocument at the same time. 270 Assert.assertTrue(urlList.get(onPageFinishedCount + 2).endsWith(popupPath)); 271 Assert.assertTrue(urlList.get(onPageFinishedCount + 3).endsWith(popupPath)); 272 } 273 274 @Test 275 @SmallTest 276 @Feature({"AndroidWebView"}) testPopupWindowTextHandle()277 public void testPopupWindowTextHandle() throws Throwable { 278 final String popupPath = "/popup.html"; 279 final String parentPageHtml = CommonResources.makeHtmlPageFrom("", "<script>" 280 + "function tryOpenWindow() {" 281 + " var newWindow = window.open('" + popupPath + "');" 282 + "}</script>"); 283 284 final String popupPageHtml = CommonResources.makeHtmlPageFrom( 285 "<title>" + POPUP_TITLE + "</title>", 286 "<span id=\"plain_text\" class=\"full_view\">This is a popup window.</span>"); 287 288 mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer, 289 parentPageHtml, popupPageHtml, popupPath, "tryOpenWindow()"); 290 PopupInfo popupInfo = mActivityTestRule.connectPendingPopup(mParentContents); 291 final AwContents popupContents = popupInfo.popupContents; 292 TestAwContentsClient popupContentsClient = popupInfo.popupContentsClient; 293 Assert.assertEquals(POPUP_TITLE, mActivityTestRule.getTitleOnUiThread(popupContents)); 294 295 AwActivityTestRule.enableJavaScriptOnUiThread(popupContents); 296 297 // Now long press on some texts and see if the text handles show up. 298 DOMUtils.longPressNode(popupContents.getWebContents(), "plain_text"); 299 SelectionPopupController controller = TestThreadUtils.runOnUiThreadBlocking( 300 () -> SelectionPopupController.fromWebContents(popupContents.getWebContents())); 301 assertWaitForSelectActionBarStatus(true, controller); 302 Assert.assertTrue(TestThreadUtils.runOnUiThreadBlocking(() -> controller.hasSelection())); 303 304 // Now hide the select action bar. This should hide the text handles and 305 // clear the selection. 306 hideSelectActionMode(controller); 307 308 assertWaitForSelectActionBarStatus(false, controller); 309 String jsGetSelection = "window.getSelection().toString()"; 310 // Test window.getSelection() returns empty string "" literally. 311 Assert.assertEquals("\"\"", 312 mActivityTestRule.executeJavaScriptAndWaitForResult( 313 popupContents, popupContentsClient, jsGetSelection)); 314 } 315 316 @Test 317 @SmallTest 318 @Feature({"AndroidWebView"}) testPopupWindowHasUserGestureForUserInitiated()319 public void testPopupWindowHasUserGestureForUserInitiated() throws Throwable { 320 runPopupUserGestureTest(true); 321 } 322 323 @Test 324 @SmallTest 325 @Feature({"AndroidWebView"}) testPopupWindowHasUserGestureForUserInitiatedNoOpener()326 public void testPopupWindowHasUserGestureForUserInitiatedNoOpener() throws Throwable { 327 runPopupUserGestureTest(false); 328 } 329 runPopupUserGestureTest(boolean hasOpener)330 private void runPopupUserGestureTest(boolean hasOpener) throws Throwable { 331 TestThreadUtils.runOnUiThreadBlocking(() -> { 332 mParentContents.getSettings().setJavaScriptEnabled(true); 333 mParentContents.getSettings().setSupportMultipleWindows(true); 334 mParentContents.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 335 }); 336 337 final String body = String.format(Locale.US, 338 "<a href=\"popup.html\" id=\"link\" %s target=\"_blank\">example.com</a>", 339 hasOpener ? "" : "rel=\"noopener noreferrer\""); 340 final String mainHtml = CommonResources.makeHtmlPageFrom("", body); 341 final String openerUrl = mWebServer.setResponse("/popupOpener.html", mainHtml, null); 342 final String popupUrl = mWebServer.setResponse("/popup.html", 343 CommonResources.makeHtmlPageFrom( 344 "<title>" + POPUP_TITLE + "</title>", "This is a popup window"), 345 null); 346 347 mParentContentsClient.getOnCreateWindowHelper().setReturnValue(true); 348 mActivityTestRule.loadUrlSync( 349 mParentContents, mParentContentsClient.getOnPageFinishedHelper(), openerUrl); 350 351 TestAwContentsClient.OnCreateWindowHelper onCreateWindowHelper = 352 mParentContentsClient.getOnCreateWindowHelper(); 353 int currentCallCount = onCreateWindowHelper.getCallCount(); 354 DOMUtils.clickNode(mParentContents.getWebContents(), "link"); 355 onCreateWindowHelper.waitForCallback( 356 currentCallCount, 1, AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); 357 358 Assert.assertTrue(onCreateWindowHelper.getIsUserGesture()); 359 } 360 361 @Test 362 @SmallTest 363 @Feature({"AndroidWebView"}) testPopupWindowNoUserGestureForJsInitiated()364 public void testPopupWindowNoUserGestureForJsInitiated() throws Throwable { 365 final String popupPath = "/popup.html"; 366 final String openerPageHtml = CommonResources.makeHtmlPageFrom("", 367 "<script>" 368 + "function tryOpenWindow() {" 369 + " var newWindow = window.open('" + popupPath + "');" 370 + "}</script>"); 371 372 final String popupPageHtml = CommonResources.makeHtmlPageFrom( 373 "<title>" + POPUP_TITLE + "</title>", "This is a popup window"); 374 375 mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer, 376 openerPageHtml, popupPageHtml, popupPath, "tryOpenWindow()"); 377 TestAwContentsClient.OnCreateWindowHelper onCreateWindowHelper = 378 mParentContentsClient.getOnCreateWindowHelper(); 379 Assert.assertFalse(onCreateWindowHelper.getIsUserGesture()); 380 } 381 382 private static class TestWebMessageListener implements WebMessageListener { 383 private LinkedBlockingQueue<Data> mQueue = new LinkedBlockingQueue<>(); 384 385 public static class Data { 386 public String mMessage; 387 public boolean mIsMainFrame; 388 public JsReplyProxy mReplyProxy; 389 Data(String message, boolean isMainFrame, JsReplyProxy replyProxy)390 public Data(String message, boolean isMainFrame, JsReplyProxy replyProxy) { 391 mMessage = message; 392 mIsMainFrame = isMainFrame; 393 mReplyProxy = replyProxy; 394 } 395 } 396 397 @Override onPostMessage(String message, Uri sourceOrigin, boolean isMainFrame, JsReplyProxy replyProxy, MessagePort[] ports)398 public void onPostMessage(String message, Uri sourceOrigin, boolean isMainFrame, 399 JsReplyProxy replyProxy, MessagePort[] ports) { 400 mQueue.add(new Data(message, isMainFrame, replyProxy)); 401 } 402 waitForOnPostMessage()403 public Data waitForOnPostMessage() throws Exception { 404 return AwActivityTestRule.waitForNextQueueElement(mQueue); 405 } 406 } 407 408 // Regression test for crbug.com/1083819. 409 // 410 // The setup of this test is to have an iframe inside of a main frame, give the iframe user 411 // gesture, then window.open() on javascript: scheme. We are verifying that the 412 // JavaScript code isn't running in the main frame's context when 413 // getJavaScriptCanOpenWindowsAutomatically() is false. 414 // 415 // There are several steps in this test: 416 // 1. Load the web page (main.html), which has an cross-origin iframe (iframe.html). 417 // 2. main frame send a message to browser to establish the connection. 418 // 3. iframe send a message to browser to estiablish the connection and notify the location of 419 // the |iframe_link| element. 420 // 4. Click the iframe_link element to give user gesture. 421 // 5. Browser waits until receives "clicked" message. 422 // 6. Browser asks the iframe to call window.open() and waits for the "done" message. 423 // 7. Browser asks the main frame to check if an element was injected and waits the result. 424 @Test 425 @SmallTest 426 @Feature({"AndroidWebView"}) testSingleWindowModeJsInjection()427 public void testSingleWindowModeJsInjection() throws Throwable { 428 // Choose a free port which is different from |mWebServer| so they have different origins. 429 TestWebServer crossOriginWebServer = TestWebServer.startAdditional(); 430 431 final String windowOpenJavaScript = "javascript:{" 432 + " let elem = document.createElement('p');" 433 + " elem.setAttribute('id', 'inject');" 434 + " document.body.append(elem);" 435 + "}"; 436 final String iframeHtml = "<html><head>" 437 + "<script>" 438 + " myObject.onmessage = function(e) {" 439 + " window.open(\"" + windowOpenJavaScript + "\");" 440 + " myObject.postMessage('done');" 441 + " };" 442 + " window.onload = function() {" 443 + " let link = document.getElementById('iframe_link');" 444 + " let rect = link.getBoundingClientRect();" 445 + " let message = Math.round(rect.left) + ';' + Math.round(rect.top) + ';';" 446 + " message += Math.round(rect.right) + ';' + Math.round(rect.bottom);" 447 + " myObject.postMessage(message);" 448 + " };" 449 + "</script>" 450 + "</head><body>" 451 + " <div>I am iframe.</div>" 452 + " <a href='#' id='iframe_link' onclick='myObject.postMessage(\"clicked\");'>" 453 + " iframe link" 454 + " </a>" 455 + "</body></html>"; 456 final String iframeHtmlPath = 457 crossOriginWebServer.setResponse("/iframe.html", iframeHtml, null); 458 final String mainHtml = "<html><head><script>" 459 + " myObject.onmessage = function(e) {" 460 + " let elem = document.getElementById('inject');" 461 + " if (elem) { myObject.postMessage('failed'); }" 462 + " else { myObject.postMessage('succeed'); }" 463 + " };" 464 + " myObject.postMessage('init');" 465 + "</script></head><body>" 466 + "<iframe src='" + iframeHtmlPath + "'></iframe>" 467 + "<div>I am main frame</div>" 468 + "</body></html>"; 469 final String mainHtmlPath = mWebServer.setResponse("/main.html", mainHtml, null); 470 471 TestWebMessageListener webMessageListener = new TestWebMessageListener(); 472 TestThreadUtils.runOnUiThreadBlocking(() -> { 473 mParentContents.getSettings().setJavaScriptEnabled(true); 474 // |false| is the default setting for setSupportMultipleWindows(), we explicitly set it 475 // to |false| here for better readability. 476 mParentContents.getSettings().setSupportMultipleWindows(false); 477 mParentContents.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 478 mParentContents.addWebMessageListener( 479 "myObject", new String[] {"*"}, webMessageListener); 480 }); 481 482 // Step 1. 483 mActivityTestRule.loadUrlSync( 484 mParentContents, mParentContentsClient.getOnPageFinishedHelper(), mainHtmlPath); 485 486 // Step 2 and 3, the sequence doesn't matter. 487 JsReplyProxy mainFrameReplyProxy = null; 488 JsReplyProxy iframeReplyProxy = null; 489 Rect rect = null; 490 for (int i = 0; i < 2; ++i) { 491 TestWebMessageListener.Data data = webMessageListener.waitForOnPostMessage(); 492 if (data.mIsMainFrame) { 493 // The connection between browser and main frame established. 494 Assert.assertEquals("init", data.mMessage); 495 mainFrameReplyProxy = data.mReplyProxy; 496 } else { 497 // The connection between browser and iframe established. 498 iframeReplyProxy = data.mReplyProxy; 499 // iframe_link location. 500 String[] c = data.mMessage.split(";"); 501 rect = new Rect(Integer.parseInt(c[0]), Integer.parseInt(c[1]), 502 Integer.parseInt(c[2]), Integer.parseInt(c[3])); 503 } 504 } 505 506 Assert.assertNotNull("rect should not be null", rect); 507 Assert.assertNotNull("mainFrameReplyProxy should not be null.", mainFrameReplyProxy); 508 Assert.assertNotNull("iframeReplyProxy should not be null.", iframeReplyProxy); 509 510 // Step 4. Click iframe_link to give user gesture. 511 DOMUtils.clickRect(mParentContents.getWebContents(), rect); 512 513 // Step 5. Waits until the element got clicked. 514 TestWebMessageListener.Data clicked = webMessageListener.waitForOnPostMessage(); 515 Assert.assertEquals("clicked", clicked.mMessage); 516 517 // Step 6. Send an arbitrary message to call window.open on javascript: URI. 518 iframeReplyProxy.postMessage("hello"); 519 TestWebMessageListener.Data data = webMessageListener.waitForOnPostMessage(); 520 Assert.assertEquals("done", data.mMessage); 521 522 // Step 7. Send an arbitrary message to trigger the check. Main frame will check if there is 523 // an injected element by running |windowOpenJavaScript|. 524 mainFrameReplyProxy.postMessage("hello"); 525 526 // If |succeed| received, then there was no injection. 527 TestWebMessageListener.Data data2 = webMessageListener.waitForOnPostMessage(); 528 Assert.assertEquals("succeed", data2.mMessage); 529 530 // Cleanup the test web server. 531 crossOriginWebServer.shutdown(); 532 } 533 534 // Copied from imeTest.java. assertWaitForSelectActionBarStatus( boolean show, final SelectionPopupController controller)535 private void assertWaitForSelectActionBarStatus( 536 boolean show, final SelectionPopupController controller) { 537 CriteriaHelper.pollUiThread(() -> { 538 Criteria.checkThat(controller.isSelectActionBarShowing(), Matchers.is(show)); 539 }); 540 } 541 hideSelectActionMode(final SelectionPopupController controller)542 private void hideSelectActionMode(final SelectionPopupController controller) { 543 InstrumentationRegistry.getInstrumentation().runOnMainSync( 544 () -> controller.destroySelectActionMode()); 545 } 546 } 547