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.html;
16
17 import org.htmlunit.Page;
18 import org.htmlunit.StringWebResponse;
19 import org.htmlunit.WebResponse;
20 import org.htmlunit.WebWindow;
21 import org.htmlunit.WebWindowImpl;
22
23 /**
24 * The web window for a frame or iframe.
25 *
26 * @author Brad Clarke
27 * @author Ahmed Ashour
28 * @author Ronald Brill
29 */
30 public class FrameWindow extends WebWindowImpl {
31
32 /** The different deny states. */
33 public enum PageDenied {
34 /** NONE. */
35 NONE,
36
37 /** BY_X_FRAME_OPTIONS. */
38 BY_X_FRAME_OPTIONS,
39
40 /** BY_CONTENT_SECURIRY_POLICY. */
41 BY_CONTENT_SECURIRY_POLICY }
42
43 private final BaseFrameElement frame_;
44 private PageDenied pageDenied_;
45
46 /**
47 * Creates an instance for a given frame.
48 */
49 FrameWindow(final BaseFrameElement frame) {
50 super(frame.getPage().getWebClient());
51 frame_ = frame;
52 performRegistration();
53
54 final WebWindowImpl parent = (WebWindowImpl) frame_.getPage().getEnclosingWindow();
55 parent.addChildWindow(this);
56 }
57
58 /**
59 * {@inheritDoc}
60 * A FrameWindow shares it's name with it's containing frame.
61 */
62 @Override
63 public String getName() {
64 return frame_.getNameAttribute();
65 }
66
67 /**
68 * {@inheritDoc}
69 * A FrameWindow shares it's name with it's containing frame.
70 */
71 @Override
72 public void setName(final String name) {
73 frame_.setNameAttribute(name);
74 }
75
76 /**
77 * {@inheritDoc}
78 */
79 @Override
80 public WebWindow getParentWindow() {
81 return frame_.getPage().getEnclosingWindow();
82 }
83
84 /**
85 * {@inheritDoc}
86 */
87 @Override
88 public WebWindow getTopWindow() {
89 return getParentWindow().getTopWindow();
90 }
91
92 /**
93 * {@inheritDoc}
94 */
95 @Override
96 protected boolean isJavaScriptInitializationNeeded(final Page page) {
97 return getScriptableObject() == null
98 || !(page.getWebResponse() instanceof StringWebResponse
99 && ((StringWebResponse) page.getWebResponse()).isFromJavascript());
100 // TODO: find a better way to distinguish content written by document.open(),...
101 }
102
103 /**
104 * Returns the HTML page in which the <frame> or <iframe> tag is contained
105 * for this frame window.
106 * This is a facility method for <code>(HtmlPage) (getParentWindow().getEnclosedPage())</code>.
107 * @return the page in the parent window
108 */
109 public HtmlPage getEnclosingPage() {
110 return (HtmlPage) frame_.getPage();
111 }
112
113 /**
114 * {@inheritDoc}
115 */
116 @Override
117 public void setEnclosedPage(final Page page) {
118 setPageDenied(PageDenied.NONE);
119 super.setEnclosedPage(page);
120
121 // we have updated a frame window by javascript write();
122 // so we have to disable future updates during initialization
123 // see org.htmlunit.html.HtmlPage.loadFrames()
124 final WebResponse webResponse = page.getWebResponse();
125 if (webResponse instanceof StringWebResponse) {
126 final StringWebResponse response = (StringWebResponse) webResponse;
127 if (response.isFromJavascript()) {
128 final BaseFrameElement frame = getFrameElement();
129 frame.setContentLoaded();
130 }
131 }
132 }
133
134 /**
135 * Gets the DOM node of the (i)frame containing this window.
136 * @return the DOM node
137 */
138 public BaseFrameElement getFrameElement() {
139 return frame_;
140 }
141
142 /**
143 * Gives a basic representation for debugging purposes.
144 * @return a basic representation
145 */
146 @Override
147 public String toString() {
148 return "FrameWindow[name=\"" + getName() + "\"]";
149 }
150
151 /**
152 * Closes this frame window.
153 */
154 public void close() {
155 final WebWindowImpl parent = (WebWindowImpl) getParentWindow();
156 parent.removeChildWindow(this);
157 getWebClient().deregisterWebWindow(this);
158 }
159
160 /**
161 * Marks that the page content as denied.
162 * @param pageDenied the new state
163 */
164 public void setPageDenied(final PageDenied pageDenied) {
165 pageDenied_ = pageDenied;
166 }
167
168 /**
169 * @return PageDenied if the page was denied
170 */
171 public PageDenied getPageDenied() {
172 return pageDenied_;
173 }
174 }