1 /* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package test.javafx.scene.web; 27 28 import static javafx.concurrent.Worker.State.READY; 29 import static javafx.concurrent.Worker.State.RUNNING; 30 import static javafx.concurrent.Worker.State.FAILED; 31 import static javafx.concurrent.Worker.State.SUCCEEDED; 32 import static org.junit.Assert.assertEquals; 33 import static org.junit.Assert.assertNotNull; 34 import static org.junit.Assert.assertNull; 35 import static org.junit.Assert.assertTrue; 36 import java.io.File; 37 import java.util.concurrent.Callable; 38 import java.util.concurrent.CountDownLatch; 39 import javafx.concurrent.Worker.State; 40 import javafx.event.EventHandler; 41 import javafx.scene.web.WebEngine; 42 import org.junit.Test; 43 import org.w3c.dom.Document; 44 import org.w3c.dom.Element; 45 import org.w3c.dom.Node; 46 import org.w3c.dom.NodeList; 47 import org.w3c.dom.Text; 48 49 50 public class LoadTest extends TestBase { 51 52 private State getLoadState() { 53 return submit(() -> getEngine().getLoadWorker().getState()); 54 } 55 56 @Test public void testLoadGoodUrl() { 57 final String FILE = "src/test/resources/test/html/ipsum.html"; 58 load(new File(FILE)); 59 WebEngine web = getEngine(); 60 61 assertTrue("Load task completed successfully", getLoadState() == SUCCEEDED); 62 assertTrue("Location.endsWith(FILE)", web.getLocation().endsWith(FILE)); 63 assertEquals("Title", "Lorem Ipsum", web.getTitle()); 64 assertNotNull("Document should not be null", web.getDocument()); 65 } 66 67 @Test public void testLoadBadUrl() { 68 final String URL = "bad://url"; 69 load(URL); 70 WebEngine web = getEngine(); 71 72 assertTrue("Load task failed", getLoadState() == FAILED); 73 assertEquals("Location", URL, web.getLocation()); 74 assertNull("Title should be null", web.getTitle()); 75 assertNull("Document should be null", web.getDocument()); 76 } 77 78 @Test public void testLoadHtmlContent() { 79 final String TITLE = "In a Silent Way"; 80 loadContent("<html><head><title>" + TITLE + "</title></head></html>"); 81 WebEngine web = getEngine(); 82 83 assertTrue("Load task completed successfully", getLoadState() == SUCCEEDED); 84 assertEquals("Location", "", web.getLocation()); 85 assertEquals("Title", TITLE, web.getTitle()); 86 assertNotNull("Document should not be null", web.getDocument()); 87 } 88 89 @Test public void testLoadPlainContent() { 90 final String TEXT = 91 "<html><head><title>Hidden Really Well</title></head></html>"; 92 loadContent(TEXT, "text/plain"); 93 final WebEngine web = getEngine(); 94 95 assertTrue("Load task completed successfully", getLoadState() == SUCCEEDED); 96 assertEquals("Location", "", web.getLocation()); 97 assertNull("Title should be null", web.getTitle()); 98 99 // DOM access should happen on FX thread 100 submit(() -> { 101 Document doc = web.getDocument(); 102 assertNotNull("Document should not be null", doc); 103 Node el = // html -> body -> pre -> text 104 doc.getDocumentElement().getLastChild().getFirstChild().getFirstChild(); 105 String text = ((Text)el).getNodeValue(); 106 assertEquals("Plain text should not be interpreted as HTML", 107 TEXT, text); 108 }); 109 } 110 111 @Test public void testLoadEmpty() { 112 testLoadEmpty(null); 113 testLoadEmpty(""); 114 testLoadEmpty("about:blank"); 115 } 116 117 private void testLoadEmpty(String url) { 118 load(url); 119 final WebEngine web = getEngine(); 120 121 assertTrue("Load task completed successfully", getLoadState() == SUCCEEDED); 122 assertEquals("Location", "about:blank", web.getLocation()); 123 assertNull("Title should be null", web.getTitle()); 124 125 submit(() -> { 126 Document doc = web.getDocument(); 127 assertNotNull("Document should not be null", doc); 128 129 Element html = doc.getDocumentElement(); 130 assertNotNull("There should be an HTML element", html); 131 assertEquals("HTML element should have tag HTML", "HTML", html.getTagName()); 132 133 NodeList htmlNodes = html.getChildNodes(); 134 assertNotNull("HTML element should have two children", htmlNodes); 135 assertEquals("HTML element should have two children", 2, htmlNodes.getLength()); 136 137 Element head = (Element) htmlNodes.item(0); 138 NodeList headNodes = head.getChildNodes(); 139 assertNotNull("There should be a HEAD element", head); 140 assertEquals("HEAD element should have tag HEAD", "HEAD", head.getTagName()); 141 assertTrue("HEAD element should have no children", 142 headNodes == null || headNodes.getLength() == 0); 143 144 Element body = (Element) htmlNodes.item(1); 145 NodeList bodyNodes = body.getChildNodes(); 146 assertNotNull("There should be a BODY element", body); 147 assertEquals("BODY element should have tag BODY", "BODY", body.getTagName()); 148 assertTrue("BODY element should have no children", 149 bodyNodes == null || bodyNodes.getLength() == 0); 150 }); 151 } 152 153 @Test public void testLoadUrlWithEncodedSpaces() { 154 final String URL = "http://localhost/test.php?param=a%20b%20c"; 155 load(URL); 156 WebEngine web = getEngine(); 157 158 assertEquals("Unexpected location", URL, web.getLocation()); 159 } 160 161 @Test public void testLoadUrlWithUnencodedSpaces() { 162 final String URL = "http://localhost/test.php?param=a b c"; 163 load(URL); 164 WebEngine web = getEngine(); 165 166 assertEquals("Unexpected location", 167 URL.replace(" ", "%20"), web.getLocation()); 168 } 169 170 @Test public void testLoadContentWithLocalScript() { 171 WebEngine webEngine = getEngine(); 172 173 final StringBuilder result = new StringBuilder(); 174 webEngine.setOnAlert(event -> { 175 result.append("ALERT: ").append(event.getData()); 176 }); 177 178 String scriptUrl = 179 new File("src/test/resources/test/html/invoke-alert.js").toURI().toASCIIString(); 180 String html = 181 "<html>\n" + 182 "<head><script src=\"" + scriptUrl + "\"></script></head>\n" + 183 "<body><script>invokeAlert('foo');</script></body>\n" + 184 "</html>"; 185 loadContent(html); 186 187 assertEquals("Unexpected result", "ALERT: foo", result.toString()); 188 assertEquals("Unexpected load state", SUCCEEDED, getLoadState()); 189 assertEquals("Unexpected location", "", webEngine.getLocation()); 190 assertNotNull("Document is null", webEngine.getDocument()); 191 } 192 193 /** 194 * @test 195 * @bug 8140501 196 * summary loadContent on location changed 197 */ 198 @Test public void loadContentOnLocationChange() throws Exception { 199 final CountDownLatch latch = new CountDownLatch(2); 200 201 submit(() -> { 202 WebEngine webEngine = new WebEngine(); 203 webEngine.locationProperty().addListener((observable, oldValue, newValue) -> { 204 // NOTE: blank url == about:blank 205 // loading a empty or null url to WebKit 206 // will be treated as blank url 207 // ref : https://html.spec.whatwg.org 208 if (newValue.equalsIgnoreCase("about:blank")) { 209 webEngine.loadContent(""); 210 assertTrue("loadContent in READY State", webEngine.getLoadWorker().getState() == READY); 211 } 212 }); 213 214 webEngine.getLoadWorker().stateProperty().addListener(((observable, oldValue, newValue) -> { 215 if (newValue == SUCCEEDED) { 216 latch.countDown(); 217 } 218 })); 219 220 webEngine.load(""); 221 assertTrue("load task completed successfully", webEngine.getLoadWorker().getState() == SUCCEEDED); 222 }); 223 try { 224 latch.await(); 225 } catch (InterruptedException ex) { 226 throw new AssertionError(ex); 227 } 228 } 229 230 /** 231 * @test 232 * @bug 8140501 233 * summary load url on location changed 234 */ 235 @Test public void loadUrlOnLocationChange() throws Exception { 236 // Cancelling loadContent is synchronous, 237 // there wont be 2 SUCCEEDED event 238 final CountDownLatch latch = new CountDownLatch(1); 239 240 submit(() -> { 241 WebEngine webEngine = new WebEngine(); 242 webEngine.locationProperty().addListener((observable, oldValue, newValue) -> { 243 if (newValue.equalsIgnoreCase("")) { 244 webEngine.load(""); 245 assertTrue("Load in READY State", webEngine.getLoadWorker().getState() == READY); 246 } 247 }); 248 249 webEngine.getLoadWorker().stateProperty().addListener(((observable, oldValue, newValue) -> { 250 if (newValue == SUCCEEDED) { 251 latch.countDown(); 252 } 253 })); 254 255 webEngine.loadContent(""); 256 assertTrue("loadContent task running", webEngine.getLoadWorker().getState() == RUNNING); 257 }); 258 try { 259 latch.await(); 260 } catch (InterruptedException ex) { 261 throw new AssertionError(ex); 262 } 263 } 264 265 /** 266 * @test 267 * @bug 8152420 268 * summary loading relative sub-resource from jar 269 */ 270 @Test public void loadJarFile() throws Exception { 271 272 // archive-root0.html -- src archive-r0.js, c/archive-c0.js 273 load("jar:" + new File(System.getProperties().get("WEB_ARCHIVE_JAR_TEST_DIR").toString() 274 + "/webArchiveJar.jar").toURI().toASCIIString() + "!/archive-root0.html"); 275 assertEquals("archive-root0.html failed to load src='archive-r0.js'", 276 executeScript("jsr0()").toString(), "loaded"); 277 278 assertEquals("archive-root0.html failed to load src='c/archive-c0.js'", 279 executeScript("jsc0()").toString(), "loaded"); 280 281 // archive-root1.html -- src ./archive-r0.js, ./c/archive-c0.js 282 load("jar:" + new File(System.getProperties().get("WEB_ARCHIVE_JAR_TEST_DIR").toString() 283 + "/webArchiveJar.jar").toURI().toASCIIString() + "!/archive-root1.html"); 284 assertEquals("archive-root1.html failed to load src='./archive-r0.js'", 285 executeScript("jsr0()").toString(), "loaded"); 286 287 assertEquals("archive-root1.html failed to load src='./c/archive-c0.js'", 288 executeScript("jsc0()").toString(), "loaded"); 289 290 // archive-root2.html -- src ./c/../archive-r0.js, ./c/./././archive-c0.js 291 load("jar:" + new File(System.getProperties().get("WEB_ARCHIVE_JAR_TEST_DIR").toString() 292 + "/webArchiveJar.jar").toURI().toASCIIString() + "!/archive-root2.html"); 293 assertEquals("archive-root2.html failed to load src='./c/../archive-r0.js'", 294 executeScript("jsr0()").toString(), "loaded"); 295 296 assertEquals("archive-root2.html failed to load src='./c/./././archive-c0.js'", 297 executeScript("jsc0()").toString(), "loaded"); 298 } 299 }