Node: removedFrom() and insertedInto() should use references.
[WebKit-https.git] / Source / WebCore / html / HTMLFrameElementBase.cpp
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 "Attribute.h"
28 #include "Document.h"
29 #include "EventNames.h"
30 #include "FocusController.h"
31 #include "Frame.h"
32 #include "FrameLoader.h"
33 #include "FrameView.h"
34 #include "HTMLNames.h"
35 #include "HTMLParserIdioms.h"
36 #include "URL.h"
37 #include "Page.h"
38 #include "RenderWidget.h"
39 #include "ScriptController.h"
40 #include "Settings.h"
41 #include "SubframeLoader.h"
42
43 namespace WebCore {
44
45 using namespace HTMLNames;
46
47 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document& document)
48     : HTMLFrameOwnerElement(tagName, document)
49     , m_scrolling(ScrollbarAuto)
50     , m_marginWidth(-1)
51     , m_marginHeight(-1)
52     , m_viewSource(false)
53 {
54     setHasCustomStyleResolveCallbacks();
55 }
56
57 bool HTMLFrameElementBase::isURLAllowed() const
58 {
59     if (m_URL.isEmpty())
60         return true;
61
62     const URL& completeURL = document().completeURL(m_URL);
63
64     if (protocolIsJavaScript(completeURL)) { 
65         Document* contentDoc = this->contentDocument();
66         if (contentDoc && !ScriptController::canAccessFromCurrentOrigin(contentDoc->frame()))
67             return false;
68     }
69
70     Frame* parentFrame = document().frame();
71     if (parentFrame)
72         return parentFrame->isURLAllowed(completeURL);
73
74     return true;
75 }
76
77 void HTMLFrameElementBase::openURL(bool lockHistory, bool lockBackForwardList)
78 {
79     if (!isURLAllowed())
80         return;
81
82     if (m_URL.isEmpty())
83         m_URL = blankURL().string();
84
85     Frame* parentFrame = document().frame();
86     if (!parentFrame)
87         return;
88
89     parentFrame->loader().subframeLoader().requestFrame(this, m_URL, m_frameName, lockHistory, lockBackForwardList);
90     if (contentFrame())
91         contentFrame()->setInViewSourceMode(viewSourceMode());
92 }
93
94 void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const AtomicString& value)
95 {
96     if (name == srcdocAttr)
97         setLocation("about:srcdoc");
98     else if (name == srcAttr && !fastHasAttribute(srcdocAttr))
99         setLocation(stripLeadingAndTrailingHTMLSpaces(value));
100     else if (isIdAttributeName(name)) {
101         // Important to call through to base for the id attribute so the hasID bit gets set.
102         HTMLFrameOwnerElement::parseAttribute(name, value);
103         m_frameName = value;
104     } else if (name == nameAttr) {
105         m_frameName = value;
106         // FIXME: If we are already attached, this doesn't actually change the frame's name.
107         // FIXME: If we are already attached, this doesn't check for frame name
108         // conflicts and generate a unique frame name.
109     } else if (name == marginwidthAttr) {
110         m_marginWidth = value.toInt();
111         // FIXME: If we are already attached, this has no effect.
112     } else if (name == marginheightAttr) {
113         m_marginHeight = value.toInt();
114         // FIXME: If we are already attached, this has no effect.
115     } else if (name == scrollingAttr) {
116         // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling."
117         if (equalIgnoringCase(value, "auto") || equalIgnoringCase(value, "yes"))
118             m_scrolling = document().frameElementsShouldIgnoreScrolling() ? ScrollbarAlwaysOff : ScrollbarAuto;
119         else if (equalIgnoringCase(value, "no"))
120             m_scrolling = ScrollbarAlwaysOff;
121         // FIXME: If we are already attached, this has no effect.
122 #if ENABLE(VIEWSOURCE_ATTRIBUTE)
123     } else if (name == viewsourceAttr) {
124         m_viewSource = !value.isNull();
125         if (contentFrame())
126             contentFrame()->setInViewSourceMode(viewSourceMode());
127 #endif
128     } else if (name == onbeforeloadAttr)
129         setAttributeEventListener(eventNames().beforeloadEvent, name, value);
130     else if (name == onbeforeunloadAttr) {
131         // FIXME: should <frame> elements have beforeunload handlers?
132         setAttributeEventListener(eventNames().beforeunloadEvent, name, value);
133     } else
134         HTMLFrameOwnerElement::parseAttribute(name, value);
135 }
136
137 void HTMLFrameElementBase::setNameAndOpenURL()
138 {
139     m_frameName = getNameAttribute();
140     if (m_frameName.isNull())
141         m_frameName = getIdAttribute();
142     openURL();
143 }
144
145 Node::InsertionNotificationRequest HTMLFrameElementBase::insertedInto(ContainerNode& insertionPoint)
146 {
147     HTMLFrameOwnerElement::insertedInto(insertionPoint);
148     if (insertionPoint.inDocument())
149         return InsertionShouldCallDidNotifySubtreeInsertions;
150     return InsertionDone;
151 }
152
153 void HTMLFrameElementBase::didNotifySubtreeInsertions(ContainerNode*)
154 {
155     if (!inDocument())
156         return;
157
158     // DocumentFragments don't kick of any loads.
159     if (!document().frame())
160         return;
161
162     if (!SubframeLoadingDisabler::canLoadFrame(*this))
163         return;
164
165     // JavaScript in src=javascript: and beforeonload can access the renderer
166     // during attribute parsing *before* the normal parser machinery would
167     // attach the element. To support this, we lazyAttach here, but only
168     // if we don't already have a renderer (if we're inserted
169     // as part of a DocumentFragment, insertedInto from an earlier element
170     // could have forced a style resolve and already attached us).
171     if (!renderer())
172         lazyAttach(DoNotSetAttached);
173     setNameAndOpenURL();
174 }
175
176 void HTMLFrameElementBase::didAttachRenderers()
177 {
178     if (RenderWidget* part = renderWidget()) {
179         if (Frame* frame = contentFrame())
180             part->setWidget(frame->view());
181     }
182 }
183
184 URL HTMLFrameElementBase::location() const
185 {
186     if (fastHasAttribute(srcdocAttr))
187         return URL(ParsedURLString, "about:srcdoc");
188     return document().completeURL(getAttribute(srcAttr));
189 }
190
191 void HTMLFrameElementBase::setLocation(const String& str)
192 {
193     Settings* settings = document().settings();
194     if (settings && settings->needsAcrobatFrameReloadingQuirk() && m_URL == str)
195         return;
196
197     m_URL = AtomicString(str);
198
199     if (inDocument())
200         openURL(false, false);
201 }
202
203 bool HTMLFrameElementBase::supportsFocus() const
204 {
205     return true;
206 }
207
208 void HTMLFrameElementBase::setFocus(bool received)
209 {
210     HTMLFrameOwnerElement::setFocus(received);
211     if (Page* page = document().page()) {
212         if (received)
213             page->focusController().setFocusedFrame(contentFrame());
214         else if (page->focusController().focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away.
215             page->focusController().setFocusedFrame(0);
216     }
217 }
218
219 bool HTMLFrameElementBase::isURLAttribute(const Attribute& attribute) const
220 {
221     return attribute.name() == srcAttr || HTMLFrameOwnerElement::isURLAttribute(attribute);
222 }
223
224 bool HTMLFrameElementBase::isHTMLContentAttribute(const Attribute& attribute) const
225 {
226     return attribute.name() == srcdocAttr || HTMLFrameOwnerElement::isHTMLContentAttribute(attribute);
227 }
228
229 int HTMLFrameElementBase::width()
230 {
231     document().updateLayoutIgnorePendingStylesheets();
232     if (!renderBox())
233         return 0;
234     return renderBox()->width();
235 }
236
237 int HTMLFrameElementBase::height()
238 {
239     document().updateLayoutIgnorePendingStylesheets();
240     if (!renderBox())
241         return 0;
242     return renderBox()->height();
243 }
244
245 } // namespace WebCore