• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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