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