예제 #1
0
 public void loadUrlSyncAndExpectError(
     final AwContents awContents,
     CallbackHelper onPageFinishedHelper,
     CallbackHelper onReceivedErrorHelper,
     final String url)
     throws Exception {
   int onErrorCallCount = onReceivedErrorHelper.getCallCount();
   int onFinishedCallCount = onPageFinishedHelper.getCallCount();
   loadUrlAsync(awContents, url);
   onReceivedErrorHelper.waitForCallback(
       onErrorCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
   onPageFinishedHelper.waitForCallback(
       onFinishedCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testJsScrollFromBody() throws Throwable {
    final TestAwContentsClient contentsClient = new TestAwContentsClient();
    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
    enableJavaScriptOnUiThread(testContainerView.getAwContents());

    final double deviceDIPScale =
        DeviceDisplayInfo.create(testContainerView.getContext()).getDIPScale();
    final int targetScrollXCss = 132;
    final int targetScrollYCss = 243;
    final int targetScrollXPix = (int) Math.floor(targetScrollXCss * deviceDIPScale);
    final int targetScrollYPix = (int) Math.floor(targetScrollYCss * deviceDIPScale);

    final String scrollFromBodyScript =
        "<script> "
            + "  window.scrollTo("
            + targetScrollXCss
            + ", "
            + targetScrollYCss
            + "); "
            + "</script> ";

    final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper();
    final int scrollToCallCount = onScrollToCallbackHelper.getCallCount();
    loadDataAsync(
        testContainerView.getAwContents(),
        makeTestPage(null, null, scrollFromBodyScript),
        "text/html",
        false);
    onScrollToCallbackHelper.waitForCallback(scrollToCallCount);

    assertScrollOnMainSync(testContainerView, targetScrollXPix, targetScrollYPix);
  }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testJsScrollReflectedInUi() throws Throwable {
    final TestAwContentsClient contentsClient = new TestAwContentsClient();
    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
    enableJavaScriptOnUiThread(testContainerView.getAwContents());

    final double deviceDIPScale =
        DeviceDisplayInfo.create(testContainerView.getContext()).getDIPScale();
    final int targetScrollXCss = 132;
    final int targetScrollYCss = 243;
    final int targetScrollXPix = (int) Math.floor(targetScrollXCss * deviceDIPScale);
    final int targetScrollYPix = (int) Math.floor(targetScrollYCss * deviceDIPScale);

    loadDataSync(
        testContainerView.getAwContents(),
        contentsClient.getOnPageFinishedHelper(),
        makeTestPage(null, null, ""),
        "text/html",
        false);

    final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper();
    final int scrollToCallCount = onScrollToCallbackHelper.getCallCount();
    executeJavaScriptAndWaitForResult(
        testContainerView.getAwContents(),
        contentsClient,
        String.format("window.scrollTo(%d, %d);", targetScrollXCss, targetScrollYCss));
    onScrollToCallbackHelper.waitForCallback(scrollToCallCount);

    assertScrollOnMainSync(testContainerView, targetScrollXPix, targetScrollYPix);
  }
 /** Loads url on the UI thread and blocks until onPageFinished is called. */
 protected void loadUrlSync(
     final AwContents awContents, CallbackHelper onPageFinishedHelper, final String url)
     throws Throwable {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   loadUrlAsync(awContents, url);
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
 }
 private void waitForNavigationRunnableAndAssertTitleChanged(Runnable navigationRunnable)
     throws Exception {
   CallbackHelper onPageFinishedHelper = mContentsClient.getOnPageFinishedHelper();
   final int callCount = onPageFinishedHelper.getCallCount();
   final String oldTitle = getTitleOnUiThread(mAwContents);
   getInstrumentation().runOnMainSync(navigationRunnable);
   onPageFinishedHelper.waitForCallback(callCount);
   assertFalse(oldTitle.equals(getTitleOnUiThread(mAwContents)));
 }
예제 #6
0
 /** Posts url on the UI thread and blocks until onPageFinished is called. */
 public void postUrlSync(
     final AwContents awContents,
     CallbackHelper onPageFinishedHelper,
     final String url,
     byte[] postData)
     throws Exception {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   postUrlAsync(awContents, url, postData);
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 }
예제 #7
0
 public void loadUrlSync(
     final AwContents awContents,
     CallbackHelper onPageFinishedHelper,
     final String url,
     final Map<String, String> extraHeaders)
     throws Exception {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   loadUrlAsync(awContents, url, extraHeaders);
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 }
예제 #8
0
 /** Loads data on the UI thread and blocks until onPageFinished is called. */
 public void loadDataSync(
     final AwContents awContents,
     CallbackHelper onPageFinishedHelper,
     final String data,
     final String mimeType,
     final boolean isBase64Encoded)
     throws Exception {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   loadDataAsync(awContents, data, mimeType, isBase64Encoded);
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 }
예제 #9
0
  /**
   * Types the passed text in the omnibox to trigger a navigation. You can pass a URL or a search
   * term. This code triggers suggestions and prerendering; unless you are testing these features
   * specifically, you should use loadUrl() which is less prone to flakyness.
   *
   * @param url The URL to navigate to.
   * @return the URL in the omnibox.
   * @throws InterruptedException
   */
  private String typeInOmniboxAndNavigate(final String url) throws InterruptedException {
    final UrlBar urlBar = (UrlBar) getActivity().findViewById(R.id.url_bar);
    assertNotNull("urlBar is null", urlBar);
    ThreadUtils.runOnUiThreadBlocking(
        new Runnable() {
          @Override
          public void run() {
            urlBar.requestFocus();
            urlBar.setText(url);
          }
        });
    final LocationBarLayout locationBar =
        (LocationBarLayout) getActivity().findViewById(R.id.location_bar);
    OmniboxTestUtils.waitForOmniboxSuggestions(locationBar);

    Tab currentTab = getActivity().getActivityTab();
    final CallbackHelper loadedCallback = new CallbackHelper();
    final AtomicBoolean tabCrashReceived = new AtomicBoolean();
    currentTab.addObserver(
        new EmptyTabObserver() {
          @Override
          public void onPageLoadFinished(Tab tab) {
            loadedCallback.notifyCalled();
            tab.removeObserver(this);
          }

          @Override
          public void onCrash(Tab tab, boolean sadTabShown) {
            tabCrashReceived.set(true);
            tab.removeObserver(this);
          }
        });

    // Loads the url.
    KeyUtils.singleKeyEventView(getInstrumentation(), urlBar, KeyEvent.KEYCODE_ENTER);

    boolean pageLoadReceived = true;
    try {
      loadedCallback.waitForCallback(0);
    } catch (TimeoutException ex) {
      pageLoadReceived = false;
    }

    assertTrue(
        "Neither PAGE_LOAD_FINISHED nor a TAB_CRASHED event was received",
        pageLoadReceived || tabCrashReceived.get());
    getInstrumentation().waitForIdleSync();

    // The URL has been set before the page notification was broadcast, so it is safe to access.
    return urlBar.getText().toString();
  }
예제 #10
0
 public void loadDataWithBaseUrlSync(
     final AwContents awContents,
     CallbackHelper onPageFinishedHelper,
     final String data,
     final String mimeType,
     final boolean isBase64Encoded,
     final String baseUrl,
     final String historyUrl)
     throws Throwable {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   loadDataWithBaseUrlAsync(awContents, data, mimeType, isBase64Encoded, baseUrl, historyUrl);
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 }
예제 #11
0
 /** Reloads the current page synchronously. */
 public void reloadSync(final AwContents awContents, CallbackHelper onPageFinishedHelper)
     throws Exception {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   getInstrumentation()
       .runOnMainSync(
           new Runnable() {
             @Override
             public void run() {
               awContents.getNavigationController().reload(true);
             }
           });
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testTouchScrollCanBeAlteredByUi() throws Throwable {
    final TestAwContentsClient contentsClient = new TestAwContentsClient();
    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
    enableJavaScriptOnUiThread(testContainerView.getAwContents());

    final int dragSteps = 10;
    final int dragStepSize = 24;
    // Watch out when modifying - if the y or x delta aren't big enough vertical or horizontal
    // scroll snapping will kick in.
    final int targetScrollXPix = dragStepSize * dragSteps;
    final int targetScrollYPix = dragStepSize * dragSteps;

    final double deviceDIPScale =
        DeviceDisplayInfo.create(testContainerView.getContext()).getDIPScale();
    final int maxScrollXPix = 101;
    final int maxScrollYPix = 211;
    // Make sure we can't hit these values simply as a result of scrolling.
    assert (maxScrollXPix % dragStepSize) != 0;
    assert (maxScrollYPix % dragStepSize) != 0;
    final int maxScrollXCss = (int) Math.floor(maxScrollXPix / deviceDIPScale);
    final int maxScrollYCss = (int) Math.floor(maxScrollYPix / deviceDIPScale);

    setMaxScrollOnMainSync(testContainerView, maxScrollXPix, maxScrollYPix);

    loadTestPageAndWaitForFirstFrame(testContainerView, contentsClient, null, "");

    final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper();
    final int scrollToCallCount = onScrollToCallbackHelper.getCallCount();
    AwTestTouchUtils.dragCompleteView(
        testContainerView,
        0,
        -targetScrollXPix, // these need to be negative as we're scrolling down.
        0,
        -targetScrollYPix,
        dragSteps,
        null /* completionLatch */);

    for (int i = 1; i <= dragSteps; ++i) {
      onScrollToCallbackHelper.waitForCallback(scrollToCallCount, i);
      if (checkScrollOnMainSync(testContainerView, maxScrollXPix, maxScrollYPix)) break;
    }

    assertScrollOnMainSync(testContainerView, maxScrollXPix, maxScrollYPix);
    assertScrollInJs(
        testContainerView.getAwContents(), contentsClient, maxScrollXCss, maxScrollYCss);
  }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testTouchScrollingConsumesScrollByGesture() throws Throwable {
    final TestAwContentsClient contentsClient = new TestAwContentsClient();
    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
    final TestGestureStateListener testGestureStateListener = new TestGestureStateListener();
    enableJavaScriptOnUiThread(testContainerView.getAwContents());

    final int dragSteps = 10;
    final int dragStepSize = 24;
    // Watch out when modifying - if the y or x delta aren't big enough vertical or horizontal
    // scroll snapping will kick in.
    final int targetScrollXPix = dragStepSize * dragSteps;
    final int targetScrollYPix = dragStepSize * dragSteps;

    loadTestPageAndWaitForFirstFrame(
        testContainerView,
        contentsClient,
        null,
        "<div>"
            + "  <div style=\"width:10000px; height: 10000px;\"> force scrolling </div>"
            + "</div>");

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                testContainerView
                    .getContentViewCore()
                    .addGestureStateListener(testGestureStateListener);
              }
            });
    final CallbackHelper onScrollUpdateGestureConsumedHelper =
        testGestureStateListener.getOnScrollUpdateGestureConsumedHelper();

    final int callCount = onScrollUpdateGestureConsumedHelper.getCallCount();
    AwTestTouchUtils.dragCompleteView(
        testContainerView,
        0,
        -targetScrollXPix, // these need to be negative as we're scrolling down.
        0,
        -targetScrollYPix,
        dragSteps,
        null /* completionLatch */);
    onScrollUpdateGestureConsumedHelper.waitForCallback(callCount);
  }
예제 #14
0
  @SmallTest
  @Feature({"Tab"})
  public void testTitleDelayUpdate() throws Throwable {
    final String oldTitle = "oldTitle";
    final String newTitle = "newTitle";

    loadUrl(
        "data:text/html;charset=utf-8,<html><head><title>"
            + oldTitle
            + "</title></head><body/></html>");
    assertEquals("title does not match initial title", oldTitle, mTab.getTitle());
    int currentCallCount = mOnTitleUpdatedHelper.getCallCount();
    runJavaScriptCodeInCurrentTab("document.title='" + newTitle + "';");
    mOnTitleUpdatedHelper.waitForCallback(currentCallCount);
    assertEquals("title does not update", newTitle, mTab.getTitle());
  }
예제 #15
0
  @Feature({"AndroidWebView"})
  @SmallTest
  public void testEscapingOfErrorPage() throws Throwable {
    AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
    AwContents awContents = testView.getAwContents();
    String SCRIPT = "window.failed == true";

    enableJavaScriptOnUiThread(awContents);
    CallbackHelper onPageFinishedHelper = mContentsClient.getOnPageFinishedHelper();
    int currentCallCount = onPageFinishedHelper.getCallCount();
    loadUrlAsync(
        awContents, "file:///file-that-does-not-exist#<script>window.failed = true;</script>");
    // We must wait for two onPageFinished callbacks. One for the original failing URL, and
    // one for the error page that we then display to the user.
    onPageFinishedHelper.waitForCallback(
        currentCallCount, 2, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);

    assertEquals("false", executeJavaScriptAndWaitForResult(awContents, mContentsClient, SCRIPT));
  }
 protected void loadDataSyncWithCharset(
     final AwContents awContents,
     CallbackHelper onPageFinishedHelper,
     final String data,
     final String mimeType,
     final boolean isBase64Encoded,
     final String charset)
     throws Throwable {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   runTestOnUiThread(
       new Runnable() {
         @Override
         public void run() {
           awContents.loadUrl(
               LoadUrlParams.createLoadDataParams(data, mimeType, isBase64Encoded, charset));
         }
       });
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
 }
예제 #17
0
  @Feature({"AndroidWebView", "JavaBridge"})
  @SmallTest
  public void testJavaBridge() throws Throwable {
    final AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
    final CallbackHelper callback = new CallbackHelper();

    runTestOnUiThread(
        new Runnable() {
          @Override
          public void run() {
            AwContents awContents = testView.getAwContents();
            AwSettings awSettings = awContents.getSettings();
            awSettings.setJavaScriptEnabled(true);
            awContents.addPossiblyUnsafeJavascriptInterface(
                new JavaScriptObject(callback), "bridge", null);
            awContents.evaluateJavaScriptEvenIfNotYetNavigated("javascript:window.bridge.run();");
          }
        });
    callback.waitForCallback(0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
  }
  @Restriction(RESTRICTION_TYPE_LOW_END_DEVICE)
  @MediumTest
  public void testNewTabLoadLowEnd() throws Exception {
    launchViaLaunchDocumentInstance(false, HREF_LINK, "href link page");

    final AtomicReference<Tab> backgroundTab = new AtomicReference<Tab>();
    final CallbackHelper tabCreatedCallback = new CallbackHelper();
    final CallbackHelper tabLoadStartedCallback = new CallbackHelper();

    final DocumentTabModelSelector selector = ChromeApplication.getDocumentTabModelSelector();
    selector.addObserver(
        new EmptyTabModelSelectorObserver() {
          @Override
          public void onNewTabCreated(final Tab newTab) {
            selector.removeObserver(this);
            backgroundTab.set(newTab);
            tabCreatedCallback.notifyCalled();

            assertFalse(newTab.getWebContents().isLoadingToDifferentDocument());

            newTab.addObserver(
                new EmptyTabObserver() {
                  @Override
                  public void onPageLoadStarted(Tab tab, String url) {
                    newTab.removeObserver(this);
                    tabLoadStartedCallback.notifyCalled();
                  }
                });
          }
        });

    openLinkInBackgroundTab();

    // Tab should be created, but shouldn't start loading until we switch to it.
    assertEquals(1, tabCreatedCallback.getCallCount());
    assertEquals(0, tabLoadStartedCallback.getCallCount());

    switchToTab(backgroundTab.get());

    tabLoadStartedCallback.waitForCallback(0);
  }
예제 #19
0
 public void loadDataSyncWithCharset(
     final AwContents awContents,
     CallbackHelper onPageFinishedHelper,
     final String data,
     final String mimeType,
     final boolean isBase64Encoded,
     final String charset)
     throws Exception {
   int currentCallCount = onPageFinishedHelper.getCallCount();
   getInstrumentation()
       .runOnMainSync(
           new Runnable() {
             @Override
             public void run() {
               awContents.loadUrl(
                   LoadUrlParams.createLoadDataParams(data, mimeType, isBase64Encoded, charset));
             }
           });
   onPageFinishedHelper.waitForCallback(
       currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testPageDown() throws Throwable {
    final TestAwContentsClient contentsClient = new TestAwContentsClient();
    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
    enableJavaScriptOnUiThread(testContainerView.getAwContents());

    loadTestPageAndWaitForFirstFrame(testContainerView, contentsClient, null, "");

    assertScrollOnMainSync(testContainerView, 0, 0);

    final int maxScrollYPix =
        runTestOnUiThreadAndGetResult(
            new Callable<Integer>() {
              @Override
              public Integer call() {
                return (testContainerView.getAwContents().computeVerticalScrollRange()
                    - testContainerView.getHeight());
              }
            });

    final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper();
    final int scrollToCallCount = onScrollToCallbackHelper.getCallCount();

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                testContainerView.getAwContents().pageDown(true);
              }
            });

    // Wait for the animation to hit the bottom of the page.
    for (int i = 1; ; ++i) {
      onScrollToCallbackHelper.waitForCallback(scrollToCallCount, i);
      if (checkScrollOnMainSync(testContainerView, 0, maxScrollYPix)) break;
    }
  }
예제 #21
0
 public void waitForVisualStateCallback(final AwContents awContents) throws Exception {
   final CallbackHelper ch = new CallbackHelper();
   final int chCount = ch.getCallCount();
   getInstrumentation()
       .runOnMainSync(
           new Runnable() {
             @Override
             public void run() {
               final long requestId = 666;
               awContents.insertVisualStateCallback(
                   requestId,
                   new AwContents.VisualStateCallback() {
                     @Override
                     public void onComplete(long id) {
                       assertEquals(requestId, id);
                       ch.notifyCalled();
                     }
                   });
             }
           });
   ch.waitForCallback(chCount);
 }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testPageUp() throws Throwable {
    final TestAwContentsClient contentsClient = new TestAwContentsClient();
    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
    enableJavaScriptOnUiThread(testContainerView.getAwContents());

    final double deviceDIPScale =
        DeviceDisplayInfo.create(testContainerView.getContext()).getDIPScale();
    final int targetScrollYCss = 243;
    final int targetScrollYPix = (int) Math.ceil(targetScrollYCss * deviceDIPScale);

    loadTestPageAndWaitForFirstFrame(testContainerView, contentsClient, null, "");

    assertScrollOnMainSync(testContainerView, 0, 0);

    scrollToOnMainSync(testContainerView, 0, targetScrollYPix);

    final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper();
    final int scrollToCallCount = onScrollToCallbackHelper.getCallCount();

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                testContainerView.getAwContents().pageUp(true);
              }
            });

    // Wait for the animation to hit the bottom of the page.
    for (int i = 1; ; ++i) {
      onScrollToCallbackHelper.waitForCallback(scrollToCallCount, i);
      if (checkScrollOnMainSync(testContainerView, 0, 0)) break;
    }
  }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testFlingScroll() throws Throwable {
    final TestAwContentsClient contentsClient = new TestAwContentsClient();
    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
    enableJavaScriptOnUiThread(testContainerView.getAwContents());

    loadTestPageAndWaitForFirstFrame(testContainerView, contentsClient, null, "");

    assertScrollOnMainSync(testContainerView, 0, 0);

    final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper();
    final int scrollToCallCount = onScrollToCallbackHelper.getCallCount();

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                testContainerView.getAwContents().flingScroll(1000, 1000);
              }
            });

    onScrollToCallbackHelper.waitForCallback(scrollToCallCount);

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                assertTrue(testContainerView.getScrollX() > 0);
                assertTrue(testContainerView.getScrollY() > 0);
              }
            });
  }
  @SmallTest
  @Feature({"AndroidWebView"})
  public void testFlingScrollOnPopup() throws Throwable {
    final TestAwContentsClient parentContentsClient = new TestAwContentsClient();
    final ScrollTestContainerView parentContainerView =
        (ScrollTestContainerView) createAwTestContainerViewOnMainSync(parentContentsClient);
    final AwContents parentContents = parentContainerView.getAwContents();
    enableJavaScriptOnUiThread(parentContents);

    final String popupPath = "/popup.html";
    final String parentPageHtml =
        CommonResources.makeHtmlPageFrom(
            "",
            "<script>"
                + "function tryOpenWindow() {"
                + "  var newWindow = window.open('"
                + popupPath
                + "');"
                + "}</script> <h1>Parent</h1>");

    final String popupPageHtml =
        CommonResources.makeHtmlPageFrom(
            "<title>" + "Popup Window" + "</title>", "This is a popup window");

    triggerPopup(
        parentContents,
        parentContentsClient,
        mWebServer,
        parentPageHtml,
        popupPageHtml,
        popupPath,
        "tryOpenWindow()");
    final PopupInfo popupInfo = connectPendingPopup(parentContents);
    assertEquals("Popup Window", getTitleOnUiThread(popupInfo.popupContents));

    final ScrollTestContainerView testContainerView =
        (ScrollTestContainerView) popupInfo.popupContainerView;
    enableJavaScriptOnUiThread(testContainerView.getAwContents());
    loadTestPageAndWaitForFirstFrame(testContainerView, popupInfo.popupContentsClient, null, "");

    assertScrollOnMainSync(testContainerView, 0, 0);

    final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper();
    final int scrollToCallCount = onScrollToCallbackHelper.getCallCount();

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                testContainerView.getAwContents().flingScroll(1000, 1000);
              }
            });

    onScrollToCallbackHelper.waitForCallback(scrollToCallCount);

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                assertTrue(testContainerView.getScrollX() > 0);
                assertTrue(testContainerView.getScrollY() > 0);
              }
            });
  }