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()); } }