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.
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.
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.
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.
25 #include "HTMLFrameElementBase.h"
27 #include "Attribute.h"
29 #include "EventNames.h"
30 #include "FocusController.h"
32 #include "FrameLoader.h"
33 #include "FrameView.h"
34 #include "HTMLNames.h"
35 #include "HTMLParserIdioms.h"
38 #include "RenderPart.h"
39 #include "ScriptController.h"
40 #include "ScriptEventListener.h"
45 using namespace HTMLNames;
47 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document* document)
48 : HTMLFrameOwnerElement(tagName, document)
49 , m_scrolling(ScrollbarAuto)
52 , m_checkInDocumentTimer(this, &HTMLFrameElementBase::checkInDocumentTimerFired)
54 , m_remainsAliveOnRemovalFromTree(false)
58 bool HTMLFrameElementBase::isURLAllowed() const
63 const KURL& completeURL = document()->completeURL(m_URL);
65 if (protocolIsJavaScript(completeURL)) {
66 Document* contentDoc = this->contentDocument();
67 if (contentDoc && !ScriptController::canAccessFromCurrentOrigin(contentDoc->frame()))
71 if (Frame* parentFrame = document()->frame()) {
72 if (parentFrame->page()->frameCount() >= Page::maxNumberOfFrames)
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 (equalIgnoringFragmentIdentifier(frame->document()->url(), completeURL)) {
81 if (foundSelfReference)
83 foundSelfReference = true;
90 void HTMLFrameElementBase::openURL(bool lockHistory, bool lockBackForwardList)
96 m_URL = blankURL().string();
98 Frame* parentFrame = document()->frame();
102 parentFrame->loader()->subframeLoader()->requestFrame(this, m_URL, m_frameName, lockHistory, lockBackForwardList);
104 contentFrame()->setInViewSourceMode(viewSourceMode());
107 void HTMLFrameElementBase::parseMappedAttribute(Attribute* attr)
109 if (attr->name() == srcAttr)
110 setLocation(stripLeadingAndTrailingHTMLSpaces(attr->value()));
111 else if (isIdAttributeName(attr->name())) {
112 // Important to call through to base for the id attribute so the hasID bit gets set.
113 HTMLFrameOwnerElement::parseMappedAttribute(attr);
114 m_frameName = attr->value();
115 } else if (attr->name() == nameAttr) {
116 m_frameName = attr->value();
117 // FIXME: If we are already attached, this doesn't actually change the frame's name.
118 // FIXME: If we are already attached, this doesn't check for frame name
119 // conflicts and generate a unique frame name.
120 } else if (attr->name() == marginwidthAttr) {
121 m_marginWidth = attr->value().toInt();
122 // FIXME: If we are already attached, this has no effect.
123 } else if (attr->name() == marginheightAttr) {
124 m_marginHeight = attr->value().toInt();
125 // FIXME: If we are already attached, this has no effect.
126 } else if (attr->name() == scrollingAttr) {
127 // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling."
128 if (equalIgnoringCase(attr->value(), "auto") || equalIgnoringCase(attr->value(), "yes"))
129 m_scrolling = document()->frameElementsShouldIgnoreScrolling() ? ScrollbarAlwaysOff : ScrollbarAuto;
130 else if (equalIgnoringCase(attr->value(), "no"))
131 m_scrolling = ScrollbarAlwaysOff;
132 // FIXME: If we are already attached, this has no effect.
133 } else if (attr->name() == viewsourceAttr) {
134 m_viewSource = !attr->isNull();
136 contentFrame()->setInViewSourceMode(viewSourceMode());
137 } else if (attr->name() == onloadAttr)
138 setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr));
139 else if (attr->name() == onbeforeloadAttr)
140 setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, attr));
141 else if (attr->name() == onbeforeunloadAttr) {
142 // FIXME: should <frame> elements have beforeunload handlers?
143 setAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(this, attr));
145 HTMLFrameOwnerElement::parseMappedAttribute(attr);
148 void HTMLFrameElementBase::setNameAndOpenURL()
150 m_frameName = getAttribute(nameAttr);
151 if (m_frameName.isNull())
152 m_frameName = getIdAttribute();
156 void HTMLFrameElementBase::updateOnReparenting()
158 ASSERT(m_remainsAliveOnRemovalFromTree);
160 if (Frame* frame = contentFrame())
161 frame->transferChildFrameToNewDocument();
164 void HTMLFrameElementBase::insertedIntoDocument()
166 HTMLFrameOwnerElement::insertedIntoDocument();
168 if (m_remainsAliveOnRemovalFromTree) {
169 updateOnReparenting();
170 setRemainsAliveOnRemovalFromTree(false);
173 // DocumentFragments don't kick of any loads.
174 if (!document()->frame())
177 // Loads may cause synchronous javascript execution (e.g. beforeload or
178 // src=javascript), which could try to access the renderer before the normal
179 // parser machinery would call lazyAttach() and set us as needing style
180 // resolve. Any code which expects this to be attached will resolve style
181 // before using renderer(), so this will make sure we attach in time.
182 // FIXME: Normally lazyAttach marks the renderer as attached(), but we don't
183 // want to do that here, as as callers expect to call attach() right after
184 // this and attach() will ASSERT(!attached())
185 ASSERT(!renderer()); // This recalc is unecessary if we already have a renderer.
186 lazyAttach(DoNotSetAttached);
190 void HTMLFrameElementBase::attach()
192 HTMLFrameOwnerElement::attach();
194 if (RenderPart* part = renderPart()) {
195 if (Frame* frame = contentFrame())
196 part->setWidget(frame->view());
200 KURL HTMLFrameElementBase::location() const
202 return document()->completeURL(getAttribute(srcAttr));
205 void HTMLFrameElementBase::setLocation(const String& str)
207 Settings* settings = document()->settings();
208 if (settings && settings->needsAcrobatFrameReloadingQuirk() && m_URL == str)
211 m_URL = AtomicString(str);
214 openURL(false, false);
217 bool HTMLFrameElementBase::supportsFocus() const
222 void HTMLFrameElementBase::setFocus(bool received)
224 HTMLFrameOwnerElement::setFocus(received);
225 if (Page* page = document()->page()) {
227 page->focusController()->setFocusedFrame(contentFrame());
228 else if (page->focusController()->focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away.
229 page->focusController()->setFocusedFrame(0);
233 bool HTMLFrameElementBase::isURLAttribute(Attribute *attr) const
235 return attr->name() == srcAttr;
238 int HTMLFrameElementBase::width()
240 document()->updateLayoutIgnorePendingStylesheets();
243 return renderBox()->width();
246 int HTMLFrameElementBase::height()
248 document()->updateLayoutIgnorePendingStylesheets();
251 return renderBox()->height();
254 void HTMLFrameElementBase::setRemainsAliveOnRemovalFromTree(bool value)
256 m_remainsAliveOnRemovalFromTree = value;
258 // There is a possibility that JS will do document.adoptNode() on this element but will not insert it into the tree.
259 // Start the async timer that is normally stopped by attach(). If it's not stopped and fires, it'll unload the frame.
261 m_checkInDocumentTimer.startOneShot(0);
263 m_checkInDocumentTimer.stop();
266 void HTMLFrameElementBase::checkInDocumentTimerFired(Timer<HTMLFrameElementBase>*)
269 ASSERT(m_remainsAliveOnRemovalFromTree);
271 m_remainsAliveOnRemovalFromTree = false;
275 void HTMLFrameElementBase::willRemove()
277 if (m_remainsAliveOnRemovalFromTree)
280 HTMLFrameOwnerElement::willRemove();
283 #if ENABLE(FULLSCREEN_API)
284 bool HTMLFrameElementBase::allowFullScreen() const
286 return hasAttribute(webkitallowfullscreenAttr);
290 } // namespace WebCore