1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Simon Hausmann (hausmann@kde.org)
5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2004, 2006, 2008, 2009 Apple Inc. All rights reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #include "config.h"
25 #include "HTMLFrameElementBase.h"
26
27 #include "CSSHelper.h"
28 #include "Document.h"
29 #include "EventNames.h"
30 #include "FocusController.h"
31 #include "Frame.h"
32 #include "FrameLoader.h"
33 #include "FrameTree.h"
34 #include "FrameView.h"
35 #include "HTMLFrameSetElement.h"
36 #include "HTMLNames.h"
37 #include "KURL.h"
38 #include "Page.h"
39 #include "RenderFrame.h"
40 #include "Settings.h"
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45
HTMLFrameElementBase(const QualifiedName & tagName,Document * doc,bool createdByParser)46 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document* doc, bool createdByParser)
47 : HTMLFrameOwnerElement(tagName, doc, createdByParser)
48 , m_scrolling(ScrollbarAuto)
49 , m_marginWidth(-1)
50 , m_marginHeight(-1)
51 , m_noResize(false)
52 , m_viewSource(false)
53 , m_shouldOpenURLAfterAttach(false)
54 {
55 }
56
isURLAllowed(const AtomicString & URLString) const57 bool HTMLFrameElementBase::isURLAllowed(const AtomicString& URLString) const
58 {
59 if (URLString.isEmpty())
60 return true;
61
62 const KURL& completeURL = document()->completeURL(URLString);
63
64 // Don't allow more than 200 total frames in a set. This seems
65 // like a reasonable upper bound, and otherwise mutually recursive
66 // frameset pages can quickly bring the program to its knees with
67 // exponential growth in the number of frames.
68 // FIXME: This limit could be higher, but because WebKit has some
69 // algorithms that happen while loading which appear to be N^2 or
70 // worse in the number of frames, we'll keep it at 200 for now.
71 if (Frame* parentFrame = document()->frame()) {
72 if (parentFrame->page()->frameCount() > 200)
73 return false;
74 }
75
76 // We allow one level of self-reference because some sites depend on that.
77 // But we don't allow more than one.
78 bool foundSelfReference = false;
79 for (Frame* frame = document()->frame(); frame; frame = frame->tree()->parent()) {
80 if (equalIgnoringRef(frame->loader()->url(), completeURL)) {
81 if (foundSelfReference)
82 return false;
83 foundSelfReference = true;
84 }
85 }
86
87 return true;
88 }
89
openURL()90 void HTMLFrameElementBase::openURL()
91 {
92 ASSERT(!m_frameName.isEmpty());
93
94 if (!isURLAllowed(m_URL))
95 return;
96
97 if (m_URL.isEmpty())
98 m_URL = blankURL().string();
99
100 Frame* parentFrame = document()->frame();
101 if (!parentFrame)
102 return;
103
104 parentFrame->loader()->requestFrame(this, m_URL, m_frameName);
105 if (contentFrame())
106 contentFrame()->setInViewSourceMode(viewSourceMode());
107 }
108
parseMappedAttribute(MappedAttribute * attr)109 void HTMLFrameElementBase::parseMappedAttribute(MappedAttribute *attr)
110 {
111 if (attr->name() == srcAttr)
112 setLocation(parseURL(attr->value()));
113 else if (attr->name() == idAttr) {
114 // Important to call through to base for the id attribute so the hasID bit gets set.
115 HTMLFrameOwnerElement::parseMappedAttribute(attr);
116 m_frameName = attr->value();
117 } else if (attr->name() == nameAttr) {
118 m_frameName = attr->value();
119 // FIXME: If we are already attached, this doesn't actually change the frame's name.
120 // FIXME: If we are already attached, this doesn't check for frame name
121 // conflicts and generate a unique frame name.
122 } else if (attr->name() == marginwidthAttr) {
123 m_marginWidth = attr->value().toInt();
124 // FIXME: If we are already attached, this has no effect.
125 } else if (attr->name() == marginheightAttr) {
126 m_marginHeight = attr->value().toInt();
127 // FIXME: If we are already attached, this has no effect.
128 } else if (attr->name() == noresizeAttr) {
129 m_noResize = true;
130 // FIXME: If we are already attached, this has no effect.
131 } else if (attr->name() == scrollingAttr) {
132 // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling."
133 if (equalIgnoringCase(attr->value(), "auto") || equalIgnoringCase(attr->value(), "yes"))
134 m_scrolling = document()->frameElementsShouldIgnoreScrolling() ? ScrollbarAlwaysOff : ScrollbarAuto;
135 else if (equalIgnoringCase(attr->value(), "no"))
136 m_scrolling = ScrollbarAlwaysOff;
137 // FIXME: If we are already attached, this has no effect.
138 } else if (attr->name() == viewsourceAttr) {
139 m_viewSource = !attr->isNull();
140 if (contentFrame())
141 contentFrame()->setInViewSourceMode(viewSourceMode());
142 } else if (attr->name() == onloadAttr) {
143 setInlineEventListenerForTypeAndAttribute(eventNames().loadEvent, attr);
144 } else if (attr->name() == onbeforeunloadAttr) {
145 // FIXME: should <frame> elements have beforeunload handlers?
146 setInlineEventListenerForTypeAndAttribute(eventNames().beforeunloadEvent, attr);
147 } else
148 HTMLFrameOwnerElement::parseMappedAttribute(attr);
149 }
150
setNameAndOpenURL()151 void HTMLFrameElementBase::setNameAndOpenURL()
152 {
153 m_frameName = getAttribute(nameAttr);
154 if (m_frameName.isNull())
155 m_frameName = getAttribute(idAttr);
156
157 if (Frame* parentFrame = document()->frame())
158 m_frameName = parentFrame->tree()->uniqueChildName(m_frameName);
159
160 openURL();
161 }
162
setNameAndOpenURLCallback(Node * n)163 void HTMLFrameElementBase::setNameAndOpenURLCallback(Node* n)
164 {
165 static_cast<HTMLFrameElementBase*>(n)->setNameAndOpenURL();
166 }
167
insertedIntoDocument()168 void HTMLFrameElementBase::insertedIntoDocument()
169 {
170 HTMLFrameOwnerElement::insertedIntoDocument();
171
172 // We delay frame loading until after the render tree is fully constructed.
173 // Othewise, a synchronous load that executed JavaScript would see incorrect
174 // (0) values for the frame's renderer-dependent properties, like width.
175 m_shouldOpenURLAfterAttach = true;
176 }
177
removedFromDocument()178 void HTMLFrameElementBase::removedFromDocument()
179 {
180 m_shouldOpenURLAfterAttach = false;
181
182 HTMLFrameOwnerElement::removedFromDocument();
183 }
184
attach()185 void HTMLFrameElementBase::attach()
186 {
187 if (m_shouldOpenURLAfterAttach) {
188 m_shouldOpenURLAfterAttach = false;
189 queuePostAttachCallback(&HTMLFrameElementBase::setNameAndOpenURLCallback, this);
190 }
191
192 HTMLFrameOwnerElement::attach();
193
194 if (RenderPart* renderPart = static_cast<RenderPart*>(renderer()))
195 if (Frame* frame = contentFrame())
196 renderPart->setWidget(frame->view());
197 }
198
location() const199 KURL HTMLFrameElementBase::location() const
200 {
201 return src();
202 }
203
setLocation(const String & str)204 void HTMLFrameElementBase::setLocation(const String& str)
205 {
206 Settings* settings = document()->settings();
207 if (settings && settings->needsAcrobatFrameReloadingQuirk() && m_URL == str)
208 return;
209
210 m_URL = AtomicString(str);
211
212 if (inDocument())
213 openURL();
214 }
215
isFocusable() const216 bool HTMLFrameElementBase::isFocusable() const
217 {
218 return renderer();
219 }
220
setFocus(bool received)221 void HTMLFrameElementBase::setFocus(bool received)
222 {
223 HTMLFrameOwnerElement::setFocus(received);
224 if (Page* page = document()->page())
225 page->focusController()->setFocusedFrame(received ? contentFrame() : 0);
226 }
227
isURLAttribute(Attribute * attr) const228 bool HTMLFrameElementBase::isURLAttribute(Attribute *attr) const
229 {
230 return attr->name() == srcAttr;
231 }
232
frameBorder() const233 String HTMLFrameElementBase::frameBorder() const
234 {
235 return getAttribute(frameborderAttr);
236 }
237
setFrameBorder(const String & value)238 void HTMLFrameElementBase::setFrameBorder(const String &value)
239 {
240 setAttribute(frameborderAttr, value);
241 }
242
longDesc() const243 String HTMLFrameElementBase::longDesc() const
244 {
245 return getAttribute(longdescAttr);
246 }
247
setLongDesc(const String & value)248 void HTMLFrameElementBase::setLongDesc(const String &value)
249 {
250 setAttribute(longdescAttr, value);
251 }
252
marginHeight() const253 String HTMLFrameElementBase::marginHeight() const
254 {
255 return getAttribute(marginheightAttr);
256 }
257
setMarginHeight(const String & value)258 void HTMLFrameElementBase::setMarginHeight(const String &value)
259 {
260 setAttribute(marginheightAttr, value);
261 }
262
marginWidth() const263 String HTMLFrameElementBase::marginWidth() const
264 {
265 return getAttribute(marginwidthAttr);
266 }
267
setMarginWidth(const String & value)268 void HTMLFrameElementBase::setMarginWidth(const String &value)
269 {
270 setAttribute(marginwidthAttr, value);
271 }
272
name() const273 String HTMLFrameElementBase::name() const
274 {
275 return getAttribute(nameAttr);
276 }
277
setName(const String & value)278 void HTMLFrameElementBase::setName(const String &value)
279 {
280 setAttribute(nameAttr, value);
281 }
282
setNoResize(bool noResize)283 void HTMLFrameElementBase::setNoResize(bool noResize)
284 {
285 setAttribute(noresizeAttr, noResize ? "" : 0);
286 }
287
scrolling() const288 String HTMLFrameElementBase::scrolling() const
289 {
290 return getAttribute(scrollingAttr);
291 }
292
setScrolling(const String & value)293 void HTMLFrameElementBase::setScrolling(const String &value)
294 {
295 setAttribute(scrollingAttr, value);
296 }
297
src() const298 KURL HTMLFrameElementBase::src() const
299 {
300 return document()->completeURL(getAttribute(srcAttr));
301 }
302
setSrc(const String & value)303 void HTMLFrameElementBase::setSrc(const String &value)
304 {
305 setAttribute(srcAttr, value);
306 }
307
width() const308 int HTMLFrameElementBase::width() const
309 {
310 if (!renderer())
311 return 0;
312
313 document()->updateLayoutIgnorePendingStylesheets();
314 return toRenderBox(renderer())->width();
315 }
316
height() const317 int HTMLFrameElementBase::height() const
318 {
319 if (!renderer())
320 return 0;
321
322 document()->updateLayoutIgnorePendingStylesheets();
323 return toRenderBox(renderer())->height();
324 }
325
326 } // namespace WebCore
327