2 * This file is part of the DOM implementation for KDE.
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5 * (C) 1999 Antti Koivisto (koivisto@kde.org)
6 * (C) 2000 Simon Hausmann (hausmann@kde.org)
7 * (C) 2001 Dirk Mueller (mueller@kde.org)
8 * Copyright (C) 2004, 2006 Apple Computer, Inc.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
26 #include "HTMLFrameElement.h"
28 #include "csshelper.h"
30 #include "EventNames.h"
32 #include "FrameTree.h"
33 #include "FrameView.h"
34 #include "HTMLNames.h"
35 #include "HTMLFrameSetElement.h"
37 #include "RenderFrame.h"
41 using namespace EventNames;
42 using namespace HTMLNames;
44 HTMLFrameElement::HTMLFrameElement(Document *doc)
45 : HTMLElement(frameTag, doc)
50 HTMLFrameElement::HTMLFrameElement(const QualifiedName& tagName, Document *doc)
51 : HTMLElement(tagName, doc)
56 void HTMLFrameElement::init()
59 m_frameBorderSet = false;
62 m_scrolling = ScrollBarAuto;
67 HTMLFrameElement::~HTMLFrameElement()
71 bool HTMLFrameElement::isURLAllowed(const AtomicString &URLString) const
73 if (URLString.isEmpty())
76 FrameView* w = document()->view();
80 KURL newURL(document()->completeURL(URLString.deprecatedString()));
81 newURL.setRef(DeprecatedString::null);
83 // Don't allow more than 200 total frames in a set. This seems
84 // like a reasonable upper bound, and otherwise mutually recursive
85 // frameset pages can quickly bring the program to its knees with
86 // exponential growth in the number of frames.
88 // FIXME: This limit could be higher, but WebKit has some
89 // algorithms that happen while loading which appear to be N^2 or
90 // worse in the number of frames
91 if (w->frame()->page()->frameCount() > 200)
94 // We allow one level of self-reference because some sites depend on that.
95 // But we don't allow more than one.
96 bool foundSelfReference = false;
97 for (Frame *frame = w->frame(); frame; frame = frame->tree()->parent()) {
98 KURL frameURL = frame->url();
99 frameURL.setRef(DeprecatedString::null);
100 if (frameURL == newURL) {
101 if (foundSelfReference)
103 foundSelfReference = true;
110 void HTMLFrameElement::openURL()
112 if (!isURLAllowed(m_URL))
116 m_URL = "about:blank";
118 document()->frame()->requestFrame(this, m_URL, m_name);
121 contentFrame()->setInViewSourceMode(viewSourceMode());
124 void HTMLFrameElement::parseMappedAttribute(MappedAttribute *attr)
126 if (attr->name() == srcAttr)
127 setLocation(parseURL(attr->value()));
128 else if (attr->name() == idAttr) {
129 // Important to call through to base for the id attribute so the hasID bit gets set.
130 HTMLElement::parseMappedAttribute(attr);
131 m_name = attr->value();
132 } else if (attr->name() == nameAttr) {
133 m_name = attr->value();
134 // FIXME: If we are already attached, this doesn't actually change the frame's name.
135 // FIXME: If we are already attached, this doesn't check for frame name
136 // conflicts and generate a unique frame name.
137 } else if (attr->name() == frameborderAttr) {
138 m_frameBorder = attr->value().toInt();
139 m_frameBorderSet = !attr->isNull();
140 // FIXME: If we are already attached, this has no effect.
141 } else if (attr->name() == marginwidthAttr) {
142 m_marginWidth = attr->value().toInt();
143 // FIXME: If we are already attached, this has no effect.
144 } else if (attr->name() == marginheightAttr) {
145 m_marginHeight = attr->value().toInt();
146 // FIXME: If we are already attached, this has no effect.
147 } else if (attr->name() == noresizeAttr) {
149 // FIXME: If we are already attached, this has no effect.
150 } else if (attr->name() == scrollingAttr) {
151 // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling."
152 if (equalIgnoringCase(attr->value(), "auto") || equalIgnoringCase(attr->value(), "yes"))
153 m_scrolling = ScrollBarAuto;
154 else if (equalIgnoringCase(attr->value(), "no"))
155 m_scrolling = ScrollBarAlwaysOff;
156 // FIXME: If we are already attached, this has no effect.
157 } else if (attr->name() == viewsourceAttr) {
158 m_viewSource = !attr->isNull();
160 contentFrame()->setInViewSourceMode(viewSourceMode());
161 } else if (attr->name() == onloadAttr) {
162 setHTMLEventListener(loadEvent, attr);
163 } else if (attr->name() == onbeforeunloadAttr) {
164 // FIXME: should <frame> elements have beforeunload handlers?
165 setHTMLEventListener(beforeunloadEvent, attr);
166 } else if (attr->name() == onunloadAttr) {
167 setHTMLEventListener(unloadEvent, attr);
169 HTMLElement::parseMappedAttribute(attr);
172 bool HTMLFrameElement::rendererIsNeeded(RenderStyle *style)
174 // Ignore display: none.
175 return isURLAllowed(m_URL);
178 RenderObject *HTMLFrameElement::createRenderer(RenderArena *arena, RenderStyle *style)
180 return new (arena) RenderFrame(this);
183 void HTMLFrameElement::insertedIntoDocument()
185 HTMLElement::insertedIntoDocument();
187 m_name = getAttribute(nameAttr);
189 m_name = getAttribute(idAttr);
191 if (Frame* parentFrame = document()->frame())
192 m_name = parentFrame->tree()->uniqueChildName(m_name);
195 void HTMLFrameElement::attach()
197 HTMLElement::attach();
199 if (hasTagName(frameTag)) {
200 if (HTMLFrameSetElement* frameSetElement = containingFrameSetElement()) {
201 if (!m_frameBorderSet)
202 m_frameBorder = frameSetElement->frameBorder();
204 m_noResize = frameSetElement->noResize();
212 void HTMLFrameElement::close()
214 Frame* frame = contentFrame();
215 if (frame && renderer()) {
216 frame->frameDetached();
217 frame->disconnectOwnerElement();
221 void HTMLFrameElement::willRemove()
223 // close the frame and dissociate the renderer, but leave the
224 // node attached so that frame does not get re-attached before
225 // actually leaving the document. see <rdar://problem/4132581>
228 renderer()->destroy();
232 HTMLElement::willRemove();
235 void HTMLFrameElement::detach()
238 HTMLElement::detach();
241 void HTMLFrameElement::setLocation(const String& str)
243 m_URL = AtomicString(str);
249 // Handle the common case where we decided not to make a frame the first time.
250 // Detach and the let attach() decide again whether to make the frame for this URL.
251 if (!renderer() && !hasTagName(iframeTag)) {
260 bool HTMLFrameElement::isFocusable() const
265 void HTMLFrameElement::setFocus(bool received)
267 HTMLElement::setFocus(received);
268 RenderFrame *renderFrame = static_cast<RenderFrame *>(renderer());
269 if (!renderFrame || !renderFrame->widget())
272 renderFrame->widget()->setFocus();
274 renderFrame->widget()->clearFocus();
277 Frame* HTMLFrameElement::contentFrame() const
279 // Start with the part that contains this element, our ownerDocument.
280 Frame* parentFrame = document()->frame();
284 // Find the part for the subframe that this element represents.
285 return parentFrame->tree()->child(m_name);
288 Document* HTMLFrameElement::contentDocument() const
290 Frame* frame = contentFrame();
293 return frame->document();
296 HTMLFrameSetElement* HTMLFrameElement::containingFrameSetElement() const
298 for (Node* node = parentNode(); node; node = node->parentNode())
299 if (node->hasTagName(framesetTag))
300 return static_cast<HTMLFrameSetElement*>(node);
305 bool HTMLFrameElement::isURLAttribute(Attribute *attr) const
307 return attr->name() == srcAttr;
310 String HTMLFrameElement::frameBorder() const
312 return getAttribute(frameborderAttr);
315 void HTMLFrameElement::setFrameBorder(const String &value)
317 setAttribute(frameborderAttr, value);
320 String HTMLFrameElement::longDesc() const
322 return getAttribute(longdescAttr);
325 void HTMLFrameElement::setLongDesc(const String &value)
327 setAttribute(longdescAttr, value);
330 String HTMLFrameElement::marginHeight() const
332 return getAttribute(marginheightAttr);
335 void HTMLFrameElement::setMarginHeight(const String &value)
337 setAttribute(marginheightAttr, value);
340 String HTMLFrameElement::marginWidth() const
342 return getAttribute(marginwidthAttr);
345 void HTMLFrameElement::setMarginWidth(const String &value)
347 setAttribute(marginwidthAttr, value);
350 String HTMLFrameElement::name() const
352 return getAttribute(nameAttr);
355 void HTMLFrameElement::setName(const String &value)
357 setAttribute(nameAttr, value);
360 void HTMLFrameElement::setNoResize(bool noResize)
362 setAttribute(noresizeAttr, noResize ? "" : 0);
365 String HTMLFrameElement::scrolling() const
367 return getAttribute(scrollingAttr);
370 void HTMLFrameElement::setScrolling(const String &value)
372 setAttribute(scrollingAttr, value);
375 String HTMLFrameElement::src() const
377 return document()->completeURL(getAttribute(srcAttr));
380 void HTMLFrameElement::setSrc(const String &value)
382 setAttribute(srcAttr, value);
385 int HTMLFrameElement::frameWidth() const
390 document()->updateLayoutIgnorePendingStylesheets();
391 return renderer()->width();
394 int HTMLFrameElement::frameHeight() const
399 document()->updateLayoutIgnorePendingStylesheets();
400 return renderer()->height();