• 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 "ScriptEventListener.h"
38 #include "KURL.h"
39 #include "MappedAttribute.h"
40 #include "Page.h"
41 #include "RenderFrame.h"
42 #include "Settings.h"
43 
44 namespace WebCore {
45 
46 using namespace HTMLNames;
47 
HTMLFrameElementBase(const QualifiedName & tagName,Document * document)48 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document* document)
49     : HTMLFrameOwnerElement(tagName, document)
50     , m_scrolling(ScrollbarAuto)
51     , m_marginWidth(-1)
52     , m_marginHeight(-1)
53     , m_noResize(false)
54     , m_viewSource(false)
55     , m_shouldOpenURLAfterAttach(false)
56 {
57 }
58 
isURLAllowed(const AtomicString & URLString) const59 bool HTMLFrameElementBase::isURLAllowed(const AtomicString& URLString) const
60 {
61     if (URLString.isEmpty())
62         return true;
63 
64     const KURL& completeURL = document()->completeURL(URLString);
65 
66     // Don't allow more than 200 total frames in a set. This seems
67     // like a reasonable upper bound, and otherwise mutually recursive
68     // frameset pages can quickly bring the program to its knees with
69     // exponential growth in the number of frames.
70     // FIXME: This limit could be higher, but because WebKit has some
71     // algorithms that happen while loading which appear to be N^2 or
72     // worse in the number of frames, we'll keep it at 200 for now.
73     if (Frame* parentFrame = document()->frame()) {
74         if (parentFrame->page()->frameCount() > 200)
75             return false;
76     }
77 
78     // We allow one level of self-reference because some sites depend on that.
79     // But we don't allow more than one.
80     bool foundSelfReference = false;
81     for (Frame* frame = document()->frame(); frame; frame = frame->tree()->parent()) {
82         if (equalIgnoringFragmentIdentifier(frame->loader()->url(), completeURL)) {
83             if (foundSelfReference)
84                 return false;
85             foundSelfReference = true;
86         }
87     }
88 
89     return true;
90 }
91 
openURL()92 void HTMLFrameElementBase::openURL()
93 {
94     ASSERT(!m_frameName.isEmpty());
95 
96     if (!isURLAllowed(m_URL))
97         return;
98 
99     if (m_URL.isEmpty())
100         m_URL = blankURL().string();
101 
102     Frame* parentFrame = document()->frame();
103     if (!parentFrame)
104         return;
105 
106     parentFrame->loader()->requestFrame(this, m_URL, m_frameName);
107     if (contentFrame())
108         contentFrame()->setInViewSourceMode(viewSourceMode());
109 }
110 
parseMappedAttribute(MappedAttribute * attr)111 void HTMLFrameElementBase::parseMappedAttribute(MappedAttribute *attr)
112 {
113     if (attr->name() == srcAttr)
114         setLocation(deprecatedParseURL(attr->value()));
115     else if (attr->name() == idAttr) {
116         // Important to call through to base for the id attribute so the hasID bit gets set.
117         HTMLFrameOwnerElement::parseMappedAttribute(attr);
118         m_frameName = attr->value();
119     } else if (attr->name() == nameAttr) {
120         m_frameName = attr->value();
121         // FIXME: If we are already attached, this doesn't actually change the frame's name.
122         // FIXME: If we are already attached, this doesn't check for frame name
123         // conflicts and generate a unique frame name.
124     } else if (attr->name() == marginwidthAttr) {
125         m_marginWidth = attr->value().toInt();
126         // FIXME: If we are already attached, this has no effect.
127     } else if (attr->name() == marginheightAttr) {
128         m_marginHeight = attr->value().toInt();
129         // FIXME: If we are already attached, this has no effect.
130     } else if (attr->name() == noresizeAttr) {
131         m_noResize = true;
132         // FIXME: If we are already attached, this has no effect.
133     } else if (attr->name() == scrollingAttr) {
134         // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling."
135         if (equalIgnoringCase(attr->value(), "auto") || equalIgnoringCase(attr->value(), "yes"))
136             m_scrolling = document()->frameElementsShouldIgnoreScrolling() ? ScrollbarAlwaysOff : ScrollbarAuto;
137         else if (equalIgnoringCase(attr->value(), "no"))
138             m_scrolling = ScrollbarAlwaysOff;
139         // FIXME: If we are already attached, this has no effect.
140     } else if (attr->name() == viewsourceAttr) {
141         m_viewSource = !attr->isNull();
142         if (contentFrame())
143             contentFrame()->setInViewSourceMode(viewSourceMode());
144     } else if (attr->name() == onloadAttr) {
145         setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr));
146     } else if (attr->name() == onbeforeunloadAttr) {
147         // FIXME: should <frame> elements have beforeunload handlers?
148         setAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(this, attr));
149     } else
150         HTMLFrameOwnerElement::parseMappedAttribute(attr);
151 }
152 
setNameAndOpenURL()153 void HTMLFrameElementBase::setNameAndOpenURL()
154 {
155     m_frameName = getAttribute(nameAttr);
156     if (m_frameName.isNull())
157         m_frameName = getAttribute(idAttr);
158 
159     if (Frame* parentFrame = document()->frame())
160         m_frameName = parentFrame->tree()->uniqueChildName(m_frameName);
161 
162     openURL();
163 }
164 
setNameAndOpenURLCallback(Node * n)165 void HTMLFrameElementBase::setNameAndOpenURLCallback(Node* n)
166 {
167     static_cast<HTMLFrameElementBase*>(n)->setNameAndOpenURL();
168 }
169 
insertedIntoDocument()170 void HTMLFrameElementBase::insertedIntoDocument()
171 {
172     HTMLFrameOwnerElement::insertedIntoDocument();
173 
174     // We delay frame loading until after the render tree is fully constructed.
175     // Othewise, a synchronous load that executed JavaScript would see incorrect
176     // (0) values for the frame's renderer-dependent properties, like width.
177     m_shouldOpenURLAfterAttach = true;
178 }
179 
removedFromDocument()180 void HTMLFrameElementBase::removedFromDocument()
181 {
182     m_shouldOpenURLAfterAttach = false;
183 
184     HTMLFrameOwnerElement::removedFromDocument();
185 }
186 
attach()187 void HTMLFrameElementBase::attach()
188 {
189     if (m_shouldOpenURLAfterAttach) {
190         m_shouldOpenURLAfterAttach = false;
191         queuePostAttachCallback(&HTMLFrameElementBase::setNameAndOpenURLCallback, this);
192     }
193 
194     HTMLFrameOwnerElement::attach();
195 
196     if (RenderPart* renderPart = toRenderPart(renderer())) {
197         if (Frame* frame = contentFrame())
198             renderPart->setWidget(frame->view());
199     }
200 }
201 
location() const202 KURL HTMLFrameElementBase::location() const
203 {
204     return src();
205 }
206 
setLocation(const String & str)207 void HTMLFrameElementBase::setLocation(const String& str)
208 {
209     Settings* settings = document()->settings();
210     if (settings && settings->needsAcrobatFrameReloadingQuirk() && m_URL == str)
211         return;
212 
213     m_URL = AtomicString(str);
214 
215     if (inDocument())
216         openURL();
217 }
218 
isFocusable() const219 bool HTMLFrameElementBase::isFocusable() const
220 {
221     return renderer();
222 }
223 
setFocus(bool received)224 void HTMLFrameElementBase::setFocus(bool received)
225 {
226     HTMLFrameOwnerElement::setFocus(received);
227     if (Page* page = document()->page())
228         page->focusController()->setFocusedFrame(received ? contentFrame() : 0);
229 }
230 
isURLAttribute(Attribute * attr) const231 bool HTMLFrameElementBase::isURLAttribute(Attribute *attr) const
232 {
233     return attr->name() == srcAttr;
234 }
235 
frameBorder() const236 String HTMLFrameElementBase::frameBorder() const
237 {
238     return getAttribute(frameborderAttr);
239 }
240 
setFrameBorder(const String & value)241 void HTMLFrameElementBase::setFrameBorder(const String &value)
242 {
243     setAttribute(frameborderAttr, value);
244 }
245 
longDesc() const246 String HTMLFrameElementBase::longDesc() const
247 {
248     return getAttribute(longdescAttr);
249 }
250 
setLongDesc(const String & value)251 void HTMLFrameElementBase::setLongDesc(const String &value)
252 {
253     setAttribute(longdescAttr, value);
254 }
255 
marginHeight() const256 String HTMLFrameElementBase::marginHeight() const
257 {
258     return getAttribute(marginheightAttr);
259 }
260 
setMarginHeight(const String & value)261 void HTMLFrameElementBase::setMarginHeight(const String &value)
262 {
263     setAttribute(marginheightAttr, value);
264 }
265 
marginWidth() const266 String HTMLFrameElementBase::marginWidth() const
267 {
268     return getAttribute(marginwidthAttr);
269 }
270 
setMarginWidth(const String & value)271 void HTMLFrameElementBase::setMarginWidth(const String &value)
272 {
273     setAttribute(marginwidthAttr, value);
274 }
275 
name() const276 String HTMLFrameElementBase::name() const
277 {
278     return getAttribute(nameAttr);
279 }
280 
setName(const String & value)281 void HTMLFrameElementBase::setName(const String &value)
282 {
283     setAttribute(nameAttr, value);
284 }
285 
setNoResize(bool noResize)286 void HTMLFrameElementBase::setNoResize(bool noResize)
287 {
288     setAttribute(noresizeAttr, noResize ? "" : 0);
289 }
290 
scrolling() const291 String HTMLFrameElementBase::scrolling() const
292 {
293     return getAttribute(scrollingAttr);
294 }
295 
setScrolling(const String & value)296 void HTMLFrameElementBase::setScrolling(const String &value)
297 {
298     setAttribute(scrollingAttr, value);
299 }
300 
src() const301 KURL HTMLFrameElementBase::src() const
302 {
303     return document()->completeURL(getAttribute(srcAttr));
304 }
305 
setSrc(const String & value)306 void HTMLFrameElementBase::setSrc(const String &value)
307 {
308     setAttribute(srcAttr, value);
309 }
310 
width() const311 int HTMLFrameElementBase::width() const
312 {
313     if (!renderer())
314         return 0;
315 
316     document()->updateLayoutIgnorePendingStylesheets();
317     return toRenderBox(renderer())->width();
318 }
319 
height() const320 int HTMLFrameElementBase::height() const
321 {
322     if (!renderer())
323         return 0;
324 
325     document()->updateLayoutIgnorePendingStylesheets();
326     return toRenderBox(renderer())->height();
327 }
328 
329 } // namespace WebCore
330