atnak · GitHub

Problem in brief

This following Javascript will reload the "topFrame" frame, but to the wrong address if the code was run from a different frame.

parent.topFrame.location.reload();

Reproducing

frameset.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
<html>
<frameset rows="150,*">
<frame name="topFrame" src="top.html">
<frame name="bottomFrame" src="bottom.html">
</frameset>
</html>

bottom.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script>
function test() {
  parent.topFrame.location.reload();
}
</script>
</head>
<body>
<button onclick="test()">test</button>
</body>
</html>
  • When the button "test" in the bottom frame is clicked, the topFrame is reloaded.
  • However, the topFrame is reloaded to the new address of "bottom.html" instead of "top.html".
  • Therefore, both the top and bottom frames become "bottom.html".

Details

The problem appears to be due to the use of getWindow(getStartingScope()) here in reload() rather than window_. I do not know what the purpose of getWindow(getStartingScope()) is here but since a location instance holds its own address in window_, I don't know why getStartingScope() is being used instead of window_.

Another place using getStartingScope() is in Location.setHref() and I think it makes more sense.

I think reload() was implemented as setHref(getHref()) in the past and when it was later refactored to the current form, getWindow(getStartingScope()) was copied here incorrectly.

Suggested fix

      * @throws IOException if there is a problem reloading the page
      * @see <a href="http://msdn.microsoft.com/en-us/library/ms536342.aspx">MSDN Documentation</a>
      */
     @JsxFunction
     public void reload(final boolean force) throws IOException {
-        final HtmlPage htmlPage = (HtmlPage) getWindow(getStartingScope()).getWebWindow().getEnclosedPage();
+        final HtmlPage htmlPage = (HtmlPage) window_.getWebWindow().getEnclosedPage();
         final WebRequest request = htmlPage.getWebResponse().getWebRequest();
         if (getBrowserVersion().hasFeature(JS_LOCATION_RELOAD_REFERRER)) {

Test case

Here's a test that can be used in LocationTest.java.

    /**
     * Tests that location.reload() works correctly when invoked across frames.
     */
    @Test
    public void reloadAcrossFrames() throws Exception {
        try (final WebClient webClient = getWebClient();
                final MockWebConnection webConnection = new MockWebConnection()) {
            final String framesetContent = ""
                + "<html>\n"
                + "  <frameset rows='100,*'>\n"
                + "    <frame name='upper' src='upper.html'/>\n"
                + "    <frame name='lower' src='lower.html'/>\n"
                + "  </frameset>\n"
                + "</html>";
            final String upperContent = "<html><body><h1>upper</h1></body></html>";
            final String lowerContent = ""
                + "<html><head>\n"
                + "<script>\n"
                + "function test() {\n"
                + "  parent.upper.location.reload();\n"
                + "}\n"
                + "</script>\n"
                + "</head>\n"
                + "<body><h1>lower</h1><button onclick=\"test()\">test</button></body></html>";
            webConnection.setResponse(URL_FIRST, framesetContent);
            webConnection.setResponse(new URL(URL_FIRST, "upper.html"), upperContent);
            webConnection.setResponse(new URL(URL_FIRST, "lower.html"), lowerContent);
            webClient.setWebConnection(webConnection);
            webClient.getPage(URL_FIRST);
            assertEquals(3, webClient.getWebWindows().size());
            assertEquals("/upper.html", webClient.getWebWindowByName("upper").getEnclosedPage().getUrl().getFile());
            assertEquals("/lower.html", webClient.getWebWindowByName("lower").getEnclosedPage().getUrl().getFile());
            final HtmlPage p = (HtmlPage)webClient.getWebWindowByName("lower").getEnclosedPage();
            p.<HtmlButton>getFirstByXPath("//button").click();
            assertEquals("/upper.html", webClient.getWebWindowByName("upper").getEnclosedPage().getUrl().getFile());
            assertEquals("/lower.html", webClient.getWebWindowByName("lower").getEnclosedPage().getUrl().getFile());
        }
    }

Read the original on github.com ↗