View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.html;
16  
17  import java.net.URL;
18  import java.util.ArrayList;
19  import java.util.Arrays;
20  import java.util.List;
21  
22  import org.htmlunit.HttpHeader;
23  import org.htmlunit.MockWebConnection;
24  import org.htmlunit.WebClient;
25  import org.htmlunit.WebDriverTestCase;
26  import org.htmlunit.html.HtmlPage;
27  import org.htmlunit.junit.annotation.Alerts;
28  import org.htmlunit.junit.annotation.HtmlUnitNYI;
29  import org.htmlunit.util.MimeType;
30  import org.htmlunit.util.NameValuePair;
31  import org.junit.jupiter.api.Disabled;
32  import org.junit.jupiter.api.Test;
33  import org.openqa.selenium.By;
34  import org.openqa.selenium.JavascriptExecutor;
35  import org.openqa.selenium.WebDriver;
36  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
37  
38  /**
39   * Tests for {@link HTMLIFrameElement}.
40   *
41   * @author Marc Guillemot
42   * @author Ahmed Ashour
43   * @author Daniel Gredler
44   * @author Ronald Brill
45   * @author Frank Danek
46   */
47  public class HTMLIFrameElement3Test extends WebDriverTestCase {
48  
49      @Override
50      protected boolean needThreeConnections() {
51          return true;
52      }
53  
54      /**
55       * @throws Exception if the test fails
56       */
57      @Test
58      @Alerts("false")
59      public void style() throws Exception {
60          final String html = DOCTYPE_HTML
61              + "<html><head>\n"
62              + "<script>\n"
63              + LOG_TITLE_FUNCTION
64              + "function doTest() {\n"
65              + "  log(document.getElementById('myIFrame').style == undefined);\n"
66              + "}\n</script></head>\n"
67              + "<body onload='doTest()'>\n"
68              + "<iframe id='myIFrame' src='about:blank'></iframe>\n"
69              + "</body></html>";
70  
71          loadPageVerifyTitle2(html);
72      }
73  
74      /**
75       * @throws Exception if the test fails
76       */
77      @Test
78      @Alerts({"1", "myIFrame"})
79      public void referenceFromJavaScript() throws Exception {
80          final String html = DOCTYPE_HTML
81              + "<html><head>\n"
82              + "<script>\n"
83              + LOG_TITLE_FUNCTION
84              + "function doTest() {\n"
85              + "  log(window.frames.length);\n"
86              + "  log(window.frames['myIFrame'].name);\n"
87              + "}\n</script></head>\n"
88              + "<body onload='doTest()'>\n"
89              + "<iframe name='myIFrame' src='about:blank'></iframe></body></html>";
90  
91          loadPageVerifyTitle2(html);
92      }
93  
94      /**
95       * Regression test for bug 1562872.
96       * @throws Exception if the test fails
97       */
98      @Test
99      @Alerts({"about:blank", "about:blank"})
100     public void directAccessPerName() throws Exception {
101         final String html = DOCTYPE_HTML
102             + "<html><head>\n"
103             + "<script>\n"
104             + LOG_TITLE_FUNCTION
105             + "function doTest() {\n"
106             + "  log(myIFrame.location);\n"
107             + "  log(Frame.location);\n"
108             + "}\n</script></head>\n"
109             + "<body onload='doTest()'>\n"
110             + "<iframe name='myIFrame' src='about:blank'></iframe>\n"
111             + "<iframe name='Frame' src='about:blank'></iframe>\n"
112             + "</body></html>";
113 
114         loadPageVerifyTitle2(html);
115     }
116 
117     /**
118      * Tests that the <tt>&lt;iframe&gt;</tt> node is visible from the contained page when it is loaded.
119      * @throws Exception if the test fails
120      */
121     @Test
122     @Alerts("IFRAME")
123     public void onLoadGetsIFrameElementByIdInParent() throws Exception {
124         final String firstContent = DOCTYPE_HTML
125             + "<html><head><title>First</title></head>\n"
126             + "<body>\n"
127             + "<iframe id='myIFrame' src='frame.html'></iframe></body></html>";
128 
129         final String frameContent = DOCTYPE_HTML
130             + "<html><head>\n"
131             + "<title>Frame</title>\n"
132             + "<script>\n"
133             + LOG_WINDOW_NAME_FUNCTION
134             + "function doTest() {\n"
135             + "  log(parent.document.getElementById('myIFrame').tagName);\n"
136             + "}\n</script></head>\n"
137             + "<body onload='doTest()'>\n"
138             + "</body></html>";
139 
140         final MockWebConnection webConnection = getMockWebConnection();
141 
142         webConnection.setDefaultResponse(frameContent);
143 
144         loadPage2(firstContent);
145         verifyWindowName2(getWebDriver(), getExpectedAlerts());
146     }
147 
148     /**
149      * @throws Exception if the test fails
150      */
151     @Test
152     @Alerts({"[object HTMLDocument]", "true"})
153     public void contentDocument() throws Exception {
154         final String html = DOCTYPE_HTML
155             + "<html>\n"
156             + "<head>\n"
157             + "  <script>\n"
158             + LOG_TITLE_FUNCTION
159             + "    function test() {\n"
160             + "      log(document.getElementById('myFrame').contentDocument);\n"
161             + "      log(document.getElementById('myFrame').contentDocument == frames.foo.document);\n"
162             + "    }\n"
163             + "  </script>\n"
164             + "</head>\n"
165             + "<body onload='test()'>\n"
166             + "  <iframe name='foo' id='myFrame' src='about:blank'></iframe>\n"
167             + "</body></html>";
168         loadPageVerifyTitle2(html);
169     }
170 
171     /**
172      * @throws Exception if the test fails
173      */
174     @Test
175     @Alerts("true")
176     public void frameElement() throws Exception {
177         final String html = DOCTYPE_HTML
178             + "<html><head>\n"
179             + "<script>\n"
180             + LOG_TITLE_FUNCTION
181             + "function test() {\n"
182             + "  log(document.getElementById('myFrame') == frames.foo.frameElement);\n"
183             + "}\n"
184             + "</script></head>\n"
185             + "<body onload='test()'>\n"
186             + "<iframe name='foo' id='myFrame' src='about:blank'></iframe>\n"
187             + "</body></html>";
188 
189         loadPageVerifyTitle2(html);
190     }
191 
192     /**
193      * Verifies that writing to an iframe keeps the same intrinsic variables around (window,
194      * document, etc) and in a usable form. Bug detected via the jQuery 1.1.3.1 unit tests.
195      *
196      * @throws Exception if an error occurs
197      */
198     @Test
199     @Alerts({"false", "false", "true", "true", "true", "object", "object"})
200     public void writeToIFrame() throws Exception {
201         final String html = DOCTYPE_HTML
202             + "<html><body onload='test()'><script>\n"
203             + LOG_TITLE_FUNCTION
204             + "  function test() {\n"
205             + "    var frame = document.createElement('iframe');\n"
206             + "    document.body.appendChild(frame);\n"
207             + "    var win = frame.contentWindow;\n"
208             + "    var doc = frame.contentWindow.document;\n"
209             + "    log(win == window);\n"
210             + "    log(doc == document);\n"
211             + "    \n"
212             + "    doc.open();\n"
213             + "    doc.write(\"<html><body><input type='text'/></body></html>\");\n"
214             + "    doc.close();\n"
215             + "    var win2 = frame.contentWindow;\n"
216             + "    var doc2 = frame.contentWindow.document;\n"
217             + "    log(win == win2);\n"
218             + "    log(doc == doc2);\n"
219             + "    \n"
220             + "    var input = doc.getElementsByTagName('input')[0];\n"
221             + "    var input2 = doc2.getElementsByTagName('input')[0];\n"
222             + "    log(input == input2);\n"
223             + "    log(typeof input);\n"
224             + "    log(typeof input2);\n"
225             + "  }\n"
226             + "</script></body></html>";
227 
228         loadPageVerifyTitle2(html);
229     }
230 
231     /**
232      * Verifies that writing to an iframe keeps the same intrinsic variables around (window,
233      * document, etc) and in a usable form. Bug detected via the jQuery 1.1.3.1 unit tests.
234      *
235      * @throws Exception if an error occurs
236      */
237     @Test
238     @Alerts({"123", "undefined"})
239     public void iFrameReinitialized() throws Exception {
240         final String html = DOCTYPE_HTML
241             + "<html>\n"
242             + "<body>\n"
243             + "  <a id='test' href='2.html' target='theFrame'>page 2 in frame</a>\n"
244             + "  <iframe name='theFrame' src='1.html'></iframe>\n"
245             + "</body></html>";
246 
247         final String frame1 = DOCTYPE_HTML
248                 + "<html><head>\n"
249                 + "<script>\n"
250                 + LOG_WINDOW_NAME_FUNCTION
251                 + "window.foo = 123; log(window.foo);\n"
252                 + "</script>\n"
253                 + "</head></html>";
254         final String frame2 = DOCTYPE_HTML
255                 + "<html><head>\n"
256                 + "<script>\n"
257                 + LOG_WINDOW_NAME_FUNCTION
258                 + "log(window.foo);\n"
259                 + "</script>\n"
260                 + "</head></html>";
261 
262         final String[] alerts = getExpectedAlerts();
263         final MockWebConnection webConnection = getMockWebConnection();
264 
265         webConnection.setResponse(new URL(URL_FIRST, "1.html"), frame1);
266         webConnection.setResponse(new URL(URL_FIRST, "2.html"), frame2);
267 
268         final WebDriver driver = loadPage2(html);
269         verifyWindowName2(driver, alerts[0]);
270 
271         driver.findElement(By.id("test")).click();
272         verifyWindowName2(driver, alerts[1]);
273 
274         assertEquals(3, getMockWebConnection().getRequestCount());
275     }
276 
277     /**
278      * @throws Exception if the test fails
279      */
280     @Test
281     @Alerts("about:blank")
282     public void setSrc_JavascriptUrl() throws Exception {
283         final String html = DOCTYPE_HTML
284             + "<html><head>\n"
285             + "<script>\n"
286             + LOG_TITLE_FUNCTION
287             + "  function test() {\n"
288             + "    document.getElementById('iframe1').src = 'javascript:void(0)';\n"
289             + "    log(window.frames[0].location);\n"
290             + "  }\n"
291             + "</script></head>\n"
292             + "<body onload='test()'>\n"
293             + "<iframe id='iframe1'></iframe>\n"
294             + "</body></html>";
295 
296         loadPageVerifyTitle2(html);
297     }
298 
299     /**
300      * @throws Exception if an error occurs
301      */
302     @Test
303     @Alerts({"", "100", "foo", "20%", "-5", "30.2", "400", "abc", "-5", "100.2", "10%", "-12.56"})
304     public void width() throws Exception {
305         final String html = DOCTYPE_HTML
306             + "<html><body>\n"
307             + "<iframe id='i1'></iframe>\n"
308             + "<iframe id='i2' width='100'></iframe>\n"
309             + "<iframe id='i3' width='foo'></iframe>\n"
310             + "<iframe id='i4' width='20%'></iframe>\n"
311             + "<iframe id='i5' width='-5'></iframe>\n"
312             + "<iframe id='i6' width='30.2'></iframe>\n"
313             + "<script>\n"
314             + LOG_TITLE_FUNCTION
315             + "function set(e, value) {\n"
316             + "  try {\n"
317             + "    e.width = value;\n"
318             + "  } catch(e) { logEx(e); }\n"
319             + "}\n"
320             + "var i1 = document.getElementById('i1');\n"
321             + "var i2 = document.getElementById('i2');\n"
322             + "var i3 = document.getElementById('i3');\n"
323             + "var i4 = document.getElementById('i4');\n"
324             + "var i5 = document.getElementById('i5');\n"
325             + "var i6 = document.getElementById('i6');\n"
326             + "log(i1.width);\n"
327             + "log(i2.width);\n"
328             + "log(i3.width);\n"
329             + "log(i4.width);\n"
330             + "log(i5.width);\n"
331             + "log(i6.width);\n"
332             + "set(i1, '400');\n"
333             + "set(i2, 'abc');\n"
334             + "set(i3, -5);\n"
335             + "set(i4, 100.2);\n"
336             + "set(i5, '10%');\n"
337             + "set(i6, -12.56);\n"
338             + "log(i1.width);\n"
339             + "log(i2.width);\n"
340             + "log(i3.width);\n"
341             + "log(i4.width);\n"
342             + "log(i5.width);\n"
343             + "log(i6.width);\n"
344             + "</script>\n"
345             + "</body></html>";
346 
347         loadPageVerifyTitle2(html);
348     }
349 
350     /**
351      * @throws Exception if an error occurs
352      */
353     @Test
354     @Alerts({"", "100", "foo", "20%", "-5", "30.2", "400", "abc", "-5", "100.2", "10%", "-12.56"})
355     public void height() throws Exception {
356         final String html = DOCTYPE_HTML
357             + "<html><body>\n"
358             + "<iframe id='i1'></iframe>\n"
359             + "<iframe id='i2' height='100'></iframe>\n"
360             + "<iframe id='i3' height='foo'></iframe>\n"
361             + "<iframe id='i4' height='20%'></iframe>\n"
362             + "<iframe id='i5' height='-5'></iframe>\n"
363             + "<iframe id='i6' height='30.2'></iframe>\n"
364             + "<script>\n"
365             + LOG_TITLE_FUNCTION
366             + "function set(e, value) {\n"
367             + "  try {\n"
368             + "    e.height = value;\n"
369             + "  } catch(e) { logEx(e); }\n"
370             + "}\n"
371             + "var i1 = document.getElementById('i1');\n"
372             + "var i2 = document.getElementById('i2');\n"
373             + "var i3 = document.getElementById('i3');\n"
374             + "var i4 = document.getElementById('i4');\n"
375             + "var i5 = document.getElementById('i5');\n"
376             + "var i6 = document.getElementById('i6');\n"
377             + "log(i1.height);\n"
378             + "log(i2.height);\n"
379             + "log(i3.height);\n"
380             + "log(i4.height);\n"
381             + "log(i5.height);\n"
382             + "log(i6.height);\n"
383             + "set(i1, '400');\n"
384             + "set(i2, 'abc');\n"
385             + "set(i3, -5);\n"
386             + "set(i4, 100.2);\n"
387             + "set(i5, '10%');\n"
388             + "set(i6, -12.56);\n"
389             + "log(i1.height);\n"
390             + "log(i2.height);\n"
391             + "log(i3.height);\n"
392             + "log(i4.height);\n"
393             + "log(i5.height);\n"
394             + "log(i6.height);\n"
395             + "</script>\n"
396             + "</body></html>";
397 
398         loadPageVerifyTitle2(html);
399     }
400 
401     /**
402      * Test the ReadyState which is an IE feature.
403      * @throws Exception if the test fails
404      */
405     @Test
406     @Alerts(DEFAULT = {"uninitialized", "complete"},
407             CHROME = {"complete", "complete"},
408             EDGE = {"complete", "complete"})
409     @HtmlUnitNYI(CHROME = {"loading", "complete"},
410             EDGE = {"loading", "complete"},
411             FF = {"loading", "complete"},
412             FF_ESR = {"loading", "complete"})
413     public void readyState_IFrame() throws Exception {
414         final String html = DOCTYPE_HTML
415             + "<html><head></head>\n"
416             + "  <body>\n"
417             + "    <iframe id='i'></iframe>\n"
418             + "    <script>\n"
419             + LOG_TITLE_FUNCTION
420             + "      log(document.getElementById('i').contentWindow.document.readyState);\n"
421             + "      window.onload = function() {\n"
422             + "        log(document.getElementById('i').contentWindow.document.readyState);\n"
423             + "      };\n"
424             + "    </script>\n"
425             + "  </body>\n"
426             + "</html>";
427 
428         loadPageVerifyTitle2(html);
429     }
430 
431     /**
432      * @throws Exception if an error occurs
433      */
434     @Test
435     @Alerts({"null", "[object HTMLBodyElement]"})
436     public void body() throws Exception {
437         final String html = DOCTYPE_HTML
438             + "<html><body>\n"
439             + "  <iframe name='theFrame' src='1.html'></iframe>\n"
440             + "</body></html>";
441 
442         final String frame = DOCTYPE_HTML
443             + "<html><head>\n"
444             + "<script>\n"
445             + LOG_WINDOW_NAME_FUNCTION
446             + "log(document.body);\n"
447             + "</script>\n"
448             + "</head>\n"
449             + "<body><script>log(document.body);</script></html>";
450 
451         final MockWebConnection webConnection = getMockWebConnection();
452 
453         webConnection.setDefaultResponse(frame);
454 
455         loadPage2(html);
456         verifyWindowName2(getWebDriver(), getExpectedAlerts());
457     }
458 
459     /**
460      * @throws Exception if an error occurs
461      */
462     @Test
463     @Alerts("128px")
464     public void width_px() throws Exception {
465         final String html = DOCTYPE_HTML
466             + "<html><head>\n"
467             + "<script>\n"
468             + LOG_TITLE_FUNCTION
469             + "  function test() {\n"
470             + "    var iframe = document.getElementById('myFrame');\n"
471             + "    iframe.width = '128px';\n"
472             + "    log(iframe.width);\n"
473             + "  }\n"
474             + "</script>\n"
475             + "<body onload='test()'>\n"
476             + "  <iframe id='myFrame'></iframe>\n"
477             + "</body></html>";
478 
479         loadPageVerifyTitle2(html);
480     }
481 
482     /**
483      * IE: getElementById() returns a different object than with direct 'id' variable.
484      * @throws Exception if an error occurs
485      */
486     @Test
487     @Alerts({"[object HTMLIFrameElement]", "[object HTMLIFrameElement]", "", ""})
488     public void idByName() throws Exception {
489         final String html = DOCTYPE_HTML
490             + "<html><head>\n"
491             + "<script>\n"
492             + LOG_TITLE_FUNCTION
493             + "  function test() {\n"
494             + "    log(myFrame);\n"
495             + "    log(document.getElementById('myFrame'));\n"
496             + "    log(myFrame.width);\n"
497             + "    log(document.getElementById('myFrame').width);\n"
498             + "  }\n"
499             + "</script>\n"
500             + "<body onload='test()'>\n"
501             + "  <iframe id='myFrame'></iframe>\n"
502             + "</body></html>";
503 
504         loadPageVerifyTitle2(html);
505     }
506 
507     /**
508      * Regression test for bug 2940926.
509      * @throws Exception if an error occurs
510      */
511     @Test
512     @Alerts("foo")
513     public void settingInnerHtmlTriggersFrameLoad() throws Exception {
514         final String html = DOCTYPE_HTML
515             + "<html><body><div id='d' onclick='loadFrame()'>Click me to show frame</div><script>\n"
516             + "function loadFrame() {\n"
517             + "  var s = '<iframe id=\"i\" src=\"frame.html\">';\n"
518             + "  s += '<p>Your browser does not support frames</p>';\n"
519             + "  s += '</iframe>';\n"
520             + "  var d = document.getElementById('d');\n"
521             + "  d.innerHTML = s;\n"
522             + "}\n"
523             + "</script></body></html>";
524         final String html2 = DOCTYPE_HTML + "<html><body>foo</body></html>";
525 
526         final MockWebConnection conn = getMockWebConnection();
527         conn.setResponse(new URL(URL_FIRST, "frame.html"), html2);
528 
529         final WebDriver driver = loadPage2(html);
530 
531         driver.findElement(By.id("d")).click();
532 
533         driver.switchTo().frame("i");
534         final String content = driver.findElement(By.xpath("//html/body")).getText();
535         assertEquals(getExpectedAlerts()[0], content);
536     }
537 
538     /**
539      * @throws Exception if the test fails
540      */
541     @Test
542     @Alerts("something")
543     public void window() throws Exception {
544         final String html = DOCTYPE_HTML
545             + "<html><head><title>First</title><script>\n"
546             + "function test() {\n"
547             + "  var iframe = document.getElementById('myIFrame');\n"
548             + "  iframe.contentWindow.contents = 'something';\n"
549             + "  iframe.src = 'javascript:window[\\'contents\\']';\n"
550             + "}\n</script></head>\n"
551             + "<body onload='test()'>\n"
552             + "<iframe id='myIFrame' src='about:blank'></iframe></body></html>";
553 
554         final WebDriver driver = loadPage2(html);
555 
556         driver.switchTo().frame(0);
557         final String content = driver.findElement(By.xpath("//html/body")).getText();
558         assertEquals(getExpectedAlerts()[0], content);
559     }
560 
561     /**
562      * @throws Exception if the test fails
563      */
564     @Test
565     @Alerts("something")
566     public void settingSrc() throws Exception {
567         final String html = DOCTYPE_HTML
568             + "<html><head><title>First</title><script>\n"
569             + "function test() {\n"
570             + "  var iframe = document.createElement('iframe');\n"
571             + "  var content = 'something';\n"
572             + "  iframe.src = 'about:blank';\n"
573             + "  document.body.appendChild(iframe);\n"
574             + "  iframe.contentWindow.document.open('text/html', 'replace');\n"
575             + "  iframe.contentWindow.document.write(content);\n"
576             + "  iframe.contentWindow.document.close();\n"
577             + "}\n</script></head>\n"
578             + "<body onload='test()'></body></html>";
579 
580         final WebDriver driver = loadPage2(html);
581 
582         driver.switchTo().frame(0);
583         final String content = driver.findElement(By.xpath("//html/body")).getText();
584         assertEquals(getExpectedAlerts()[0], content);
585     }
586 
587     /**
588      * @throws Exception if the test fails
589      */
590     @Test
591     @Alerts("iframe onload")
592     public void writeTriggersOnload() throws Exception {
593         final String html = DOCTYPE_HTML
594             + "<html><head>\n"
595             + "<script>\n"
596             + "function test() {\n"
597             + LOG_TITLE_FUNCTION
598             + "  var iframe = document.createElement('iframe');\n"
599             + "  var content = 'something';\n"
600             + "  document.body.appendChild(iframe);\n"
601 
602             + "  iframe.onload = function() {log('iframe onload')};\n"
603             + "  iframe.contentWindow.document.open('text/html', 'replace');\n"
604             + "  iframe.contentWindow.document.write(content);\n"
605             + "  iframe.contentWindow.document.close();\n"
606             + "}\n</script></head>\n"
607             + "<body>\n"
608             + "  <button type='button' id='clickme' onClick='test();'>Click me</a>\n"
609             + "</body></html>";
610 
611         final WebDriver driver = loadPage2(html);
612         driver.findElement(By.id("clickme")).click();
613         verifyTitle2(driver, getExpectedAlerts());
614     }
615 
616     /**
617      * @throws Exception if the test fails
618      */
619     @Test
620     @Alerts({"localhost", "localhost", "localhost", "localhost",
621                 "true", "true", "true"})
622     public void domain() throws Exception {
623         final String html = DOCTYPE_HTML
624             + "<html>\n"
625             + "<head>\n"
626             + "  <script>\n"
627             + LOG_TITLE_FUNCTION
628             + "    function doTest() {\n"
629             + "      var docDomain = document.domain;\n"
630             + "      var frame1Domain = document.getElementById('frame1').contentWindow.document.domain;\n"
631             + "      var frame2Domain = document.getElementById('frame2').contentWindow.document.domain;\n"
632             + "      var frame3Domain = document.getElementById('frame3').contentWindow.document.domain;\n"
633             + "      log(docDomain);\n"
634             + "      log(frame1Domain);\n"
635             + "      log(frame2Domain);\n"
636             + "      log(frame3Domain);\n"
637             + "      log(docDomain === frame1Domain);\n"
638             + "      log(docDomain === frame2Domain);\n"
639             + "      log(docDomain === frame3Domain);\n"
640             + "    }\n"
641             + "  </script>\n"
642             + "</head>\n"
643             + "<body onload='doTest()'>\n"
644             + "  <iframe id='frame1' ></iframe>\n"
645             + "  <iframe id='frame2' src='about:blank'></iframe>\n"
646             + "  <iframe id='frame3' src='content.html'></iframe>\n"
647             + "</body>\n"
648             + "</html>";
649 
650         final String left = DOCTYPE_HTML
651                 + "<html><head><title>Left</title></head>\n"
652                 + "<body>left</body>\n"
653                 + "</html>";
654 
655         getMockWebConnection().setResponse(new URL(URL_FIRST, "content.html"), left);
656 
657         loadPageVerifyTitle2(html);
658         assertEquals(2, getMockWebConnection().getRequestCount());
659     }
660 
661     /**
662      * @throws Exception if the test fails
663      */
664     @Test
665     @Alerts({"localhost", "localhost", "true"})
666     public void domainDynamic() throws Exception {
667         final String html = DOCTYPE_HTML
668             + "<html>\n"
669             + "<head>\n"
670             + "  <script>\n"
671             + LOG_TITLE_FUNCTION
672             + "    function doTest() {\n"
673             + "      var myFrame = document.createElement('iframe');\n"
674             + "      myFrame.id = 'idMyFrame';\n"
675             + "      myFrame.src = 'about:blank';\n"
676             + "      document.body.appendChild(myFrame);\n"
677 
678             + "      var docDomain = document.domain;\n"
679             + "      var myFrameDomain = myFrame.contentDocument.domain;\n"
680 
681             + "      log(docDomain);\n"
682             + "      log(myFrameDomain);\n"
683             + "      log(docDomain === myFrameDomain);\n"
684             + "    }\n"
685             + "  </script>\n"
686             + "</head>\n"
687             + "<body onload='doTest()'>\n"
688             + "</body>\n"
689             + "</html>";
690 
691         loadPageVerifyTitle2(html);
692         assertEquals(1, getMockWebConnection().getRequestCount());
693     }
694 
695     /**
696      * @throws Exception if the test fails
697      */
698     @Test
699     @Alerts({"[object Window]", "topbody", "framebody", "[object Window]", "frame", "frameinput"})
700     @Disabled
701     // check expectations
702     public void contentWindowAndActiveElement() throws Exception {
703         final String firstContent = DOCTYPE_HTML
704             + "<html>\n"
705             + "<head>\n"
706             + "  <script>\n"
707             + LOG_TITLE_FUNCTION
708             + "    function check() {\n"
709             + "      log(document.getElementById('frame').contentWindow);\n"
710             + "      log(document.activeElement.id);\n"
711             + "      log(window.frame.window.document.activeElement.id);\n"
712             + "    }\n"
713             + "  </script>\n"
714             + "</head>\n"
715             + "<body id='topbody'>\n"
716             + "  <iframe id='frame' name='frame' src='" + URL_SECOND + "'></iframe>\n"
717             + "</body></html>";
718 
719         final String frameContent = DOCTYPE_HTML
720             + "<html>\n"
721             + "<body id='framebody'>\n"
722             + "  <input id='frameinput'>\n"
723             + "</body></html>";
724 
725         final String[] alerts = getExpectedAlerts();
726         int i = 0;
727 
728         final MockWebConnection webConnection = getMockWebConnection();
729 
730         webConnection.setResponse(URL_SECOND, frameContent);
731 
732         final WebDriver driver = loadPage2(firstContent);
733         final JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
734 
735         jsExecutor.executeScript("check();");
736         verifyAlerts(driver, alerts[i++], alerts[i++], alerts[i++]);
737 
738         driver.switchTo().frame("frame");
739         driver.findElement(By.id("frameinput")).click();
740 
741         driver.switchTo().defaultContent();
742         jsExecutor.executeScript("check();");
743         verifyTitle2(driver, alerts[i++], alerts[i++], alerts[i++]);
744     }
745 
746     /**
747      * @throws Exception if the test fails
748      */
749     @Test
750     @Alerts({"loaded", "null"})
751     public void deny() throws Exception {
752         retrictByHeader(
753                 new NameValuePair(HttpHeader.X_FRAME_OPTIONS, "DENY"),
754                 new URL(URL_FIRST, "content.html"));
755     }
756 
757     /**
758      * @throws Exception if the test fails
759      */
760     @Test
761     @Alerts({"loaded", "null"})
762     public void csp_None() throws Exception {
763         retrictByHeader(
764                 new NameValuePair(HttpHeader.CONTENT_SECURIRY_POLICY, "frame-ancestors 'none';"),
765                 new URL(URL_FIRST, "content.html"));
766     }
767 
768     /**
769      * @throws Exception if the test fails
770      */
771     @Test
772     @Alerts({"loaded", "[object HTMLDocument]"})
773     public void csp_Self() throws Exception {
774         retrictByHeader(
775                 new NameValuePair(HttpHeader.CONTENT_SECURIRY_POLICY, "frame-ancestors 'self';"),
776                 new URL(URL_FIRST, "content.html"));
777     }
778 
779     /**
780      * @throws Exception if the test fails
781      */
782     @Test
783     @Alerts({"loaded", "[object HTMLDocument]"})
784     public void csp_SelfDifferentPath() throws Exception {
785         retrictByHeader(
786                 new NameValuePair(HttpHeader.CONTENT_SECURIRY_POLICY, "frame-ancestors 'self';"),
787                 new URL(URL_FIRST, "/path2/content.html"));
788     }
789 
790     /**
791      * @throws Exception if the test fails
792      */
793     @Test
794     @Alerts({"loaded", "[object HTMLDocument]"})
795     public void csp_Url() throws Exception {
796         retrictByHeader(
797                 new NameValuePair(HttpHeader.CONTENT_SECURIRY_POLICY, "frame-ancestors 'self';"),
798                 new URL(new URL("http://localhost:" + PORT + "/"), "content.html"));
799     }
800 
801     /**
802      * @throws Exception if the test fails
803      */
804     @Test
805     @Alerts({"loaded", "null"})
806     public void csp_UrlDifferentPort() throws Exception {
807         retrictByHeader(
808                 new NameValuePair(HttpHeader.CONTENT_SECURIRY_POLICY, "frame-ancestors 'self';"),
809                 new URL(new URL("http://localhost:" + PORT2 + "/"), "content.html"));
810     }
811 
812     /**
813      * @throws Exception if the test fails
814      */
815     @Test
816     @Alerts({"loaded", "null"})
817     public void csp_many() throws Exception {
818         retrictByHeader(
819                 new NameValuePair(HttpHeader.CONTENT_SECURIRY_POLICY,
820                         "default-src 'none'; script-src 'self'; frame-ancestors 'self';"),
821                 new URL(new URL("http://localhost:" + PORT2 + "/"), "content.html"));
822     }
823 
824     private void retrictByHeader(final NameValuePair header, final URL contentUrl) throws Exception {
825         final String html = DOCTYPE_HTML
826             + "<html>\n"
827             + "<head>\n"
828             + "  <script>\n"
829             + LOG_WINDOW_NAME_FUNCTION
830             + "    function check() {\n"
831             + "      try {\n"
832             + "        log(document.getElementById(\"frame1\").contentDocument);\n"
833             + "      } catch(e) { log('error'); }\n"
834             + "    }\n"
835             + "  </script>\n"
836             + "</head>\n"
837             + "<body>\n"
838             + "  <iframe id='frame1' src='" + contentUrl + "' "
839                     + "onLoad='log(\"loaded\")' onError='log(\"error\")'></iframe>\n"
840             + "  <button type='button' id='clickme' onClick='check()'>Click me</a>\n"
841             + "</body>\n"
842             + "</html>";
843 
844         final String content = DOCTYPE_HTML
845                 + "<html><head><title>IFrame Title</title></head>\n"
846                 + "<body>IFrame Content</body>\n"
847                 + "</html>";
848 
849         final List<NameValuePair> headers = new ArrayList<>();
850         headers.add(header);
851 
852         getMockWebConnection().setResponse(contentUrl, content,
853                 200, "OK", MimeType.TEXT_HTML, headers);
854 
855         final String[] expectedAlerts = getExpectedAlerts();
856         final WebDriver driver = loadPage2(html, new URL(URL_FIRST, "path"));
857         verifyWindowName2(driver, Arrays.copyOf(expectedAlerts, expectedAlerts.length - 1));
858 
859         driver.findElement(By.id("clickme")).click();
860         verifyWindowName2(driver, expectedAlerts);
861 
862         assertEquals(2, getMockWebConnection().getRequestCount());
863     }
864 
865     /**
866      * @throws Exception if the test fails
867      */
868     @Test
869     @Alerts({"loaded", "[object HTMLDocument]", "2"})
870     public void recursive() throws Exception {
871         final String html = DOCTYPE_HTML
872             + "<html>\n"
873             + "<head>\n"
874             + "  <script>\n"
875             + LOG_TITLE_FUNCTION
876             + "    function check() {\n"
877             + "      try {\n"
878             + "        log(document.getElementById(\"frame1\").contentDocument);\n"
879             + "      } catch(e) { log('error'); }\n"
880             + "    }\n"
881             + "  </script>\n"
882             + "</head>\n"
883             + "<body>\n"
884             + "  <iframe id='frame1' src='" + URL_FIRST + "' "
885                         + "onLoad='log(\"loaded\")'></iframe>\n"
886             + "  <button type='button' id='clickme' onClick='check()'>Click me</a>\n"
887             + "</body>\n"
888             + "</html>";
889 
890         final String[] expectedAlerts = getExpectedAlerts();
891         final WebDriver driver = loadPage2(html);
892         verifyTitle2(driver, expectedAlerts[0]);
893 
894         driver.findElement(By.id("clickme")).click();
895         verifyTitle2(driver, expectedAlerts[0], expectedAlerts[1]);
896 
897         assertEquals(Integer.parseInt(expectedAlerts[2]), getMockWebConnection().getRequestCount());
898     }
899 
900     /**
901      * @throws Exception if the test fails
902      */
903     @Test
904     @Alerts({"loaded", "3"})
905     @HtmlUnitNYI(
906             CHROME = {"loaded", "2"},
907             EDGE = {"loaded", "2"},
908             FF = {"loaded", "2"},
909             FF_ESR = {"loaded", "2"})
910     public void recursiveContent() throws Exception {
911         final String html = DOCTYPE_HTML
912             + "<html>\n"
913             + "<head>\n"
914             + "  <script>\n"
915             + LOG_TITLE_FUNCTION
916             + "  </script>\n"
917             + "</head>\n"
918             + "<body>\n"
919             + "  <iframe id='frame1' src='content.html' "
920                         + "onLoad='log(\"loaded\")'></iframe>\n"
921             + "</body>\n"
922             + "</html>";
923 
924         final String content = DOCTYPE_HTML
925                 + "<html>"
926                 + "<head><title>IFrame Title</title></head>\n"
927                 + "<body>IFrame Content\n"
928                 + "  <iframe id='frame1' src='content.html'></iframe>\n"
929                 + "</body>\n"
930                 + "</html>";
931 
932         getMockWebConnection().setDefaultResponse(content);
933 
934         final String[] expectedAlerts = getExpectedAlerts();
935         loadPage2(html);
936         verifyTitle2(getWebDriver(), expectedAlerts[0]);
937 
938         assertEquals(Integer.parseInt(expectedAlerts[1]), getMockWebConnection().getRequestCount());
939     }
940 
941     /**
942      * @throws Exception if the test fails
943      */
944     @Test
945     @Alerts(DEFAULT = {"loaded", "6"},
946             FF_ESR = {"loaded", "19"},
947             FF = {"loaded", "19"})
948     @HtmlUnitNYI(CHROME = {"loaded", "21"},
949             EDGE = {"loaded", "21"},
950             FF = {"loaded", "21"},
951             FF_ESR = {"loaded", "21"})
952     public void recursiveContentRedirectHeader() throws Exception {
953         final String html = DOCTYPE_HTML
954             + "<html>\n"
955             + "<head>\n"
956             + "  <script>\n"
957             + LOG_TITLE_FUNCTION
958             + "  </script>\n"
959             + "</head>\n"
960             + "<body>\n"
961             + "  <iframe id='frame1' src='content.html' "
962                         + "onLoad='log(\"loaded\")'></iframe>\n"
963             + "</body>\n"
964             + "</html>";
965 
966         final String content = DOCTYPE_HTML
967                 + "<html>"
968                 + "<head><title>IFrame Title</title></head>\n"
969                 + "<body>IFrame Content\n"
970                 + "  <iframe id='frame1' src='content.html'></iframe>\n"
971                 + "  <input id='myButton' type=button onclick=\"javascript:sayHello('%28%A')\" value='My Button'>\n"
972                 + "</body>\n"
973                 + "</html>";
974 
975         getMockWebConnection().setDefaultResponse(content);
976 
977         final List<NameValuePair> headers = new ArrayList<>();
978         headers.add(new NameValuePair("Location", "content2.html"));
979         getMockWebConnection().setResponse(new URL(URL_FIRST, "content.html"), "",
980                     302, "Moved", MimeType.TEXT_HTML, headers);
981 
982         final String[] expectedAlerts = getExpectedAlerts();
983         loadPage2(html);
984         verifyTitle2(getWebDriver(), expectedAlerts[0]);
985 
986         assertEquals(Integer.parseInt(expectedAlerts[1]), getMockWebConnection().getRequestCount());
987     }
988 
989     /**
990      * @throws Exception if the test fails
991      */
992     @Test
993     @Alerts("Injected from parent frame")
994     public void writeIntoIFrameContentDocument() throws Exception {
995         final String html = DOCTYPE_HTML
996             + "<html>\n"
997             + "<head>\n"
998             + "  <script>\n"
999             + "    function doIt() {\n"
1000             + "      var html = '<h1>Injected from parent frame</h1>';\n"
1001             + "      document.getElementById(\"tester\").contentDocument.write(html);\n"
1002             + "    }\n"
1003             + "  </script>\n"
1004             + "</head>\n"
1005             + "<body>\n"
1006             + "  <iframe id='tester'></iframe>\n"
1007             + "  <input id='myButton' type=button onclick=\"javascript:doIt()\" value='Write'>\n"
1008             + "</body>\n"
1009             + "</html>";
1010 
1011         getMockWebConnection().setDefaultResponse(html);
1012         final WebDriver driver = loadPage2(html);
1013 
1014         driver.findElement(By.id("myButton")).click();
1015 
1016         driver.switchTo().frame("tester");
1017         verify(() -> driver.findElement(By.tagName("body")).getText(), getExpectedAlerts()[0]);
1018 
1019         if (driver instanceof HtmlUnitDriver) {
1020             final WebClient webClient = ((HtmlUnitDriver) driver).getWebClient();
1021 
1022             final HtmlPage page = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
1023 
1024             assertEquals(1, page.getFrames().size());
1025 
1026             final HtmlPage framePage = (HtmlPage) page.getFrames().get(0).getEnclosedPage();
1027             assertEquals("Injected from parent frame", framePage.getBody().asNormalizedText());
1028         }
1029     }
1030 }