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 "core/html/HTMLFrameElementBase.h"
26
27 #include "HTMLNames.h"
28 #include "bindings/v8/ScriptController.h"
29 #include "bindings/v8/ScriptEventListener.h"
30 #include "core/dom/Attribute.h"
31 #include "core/dom/Document.h"
32 #include "core/events/ThreadLocalEventNames.h"
33 #include "core/html/parser/HTMLParserIdioms.h"
34 #include "core/loader/FrameLoader.h"
35 #include "core/page/FocusController.h"
36 #include "core/frame/Frame.h"
37 #include "core/frame/FrameView.h"
38 #include "core/page/Page.h"
39 #include "core/rendering/RenderPart.h"
40
41 namespace WebCore {
42
43 using namespace HTMLNames;
44
HTMLFrameElementBase(const QualifiedName & tagName,Document & document)45 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document& document)
46 : HTMLFrameOwnerElement(tagName, document)
47 , m_scrolling(ScrollbarAuto)
48 , m_marginWidth(-1)
49 , m_marginHeight(-1)
50 {
51 }
52
isURLAllowed() const53 bool HTMLFrameElementBase::isURLAllowed() const
54 {
55 if (m_URL.isEmpty())
56 return true;
57
58 const KURL& completeURL = document().completeURL(m_URL);
59
60 if (protocolIsJavaScript(completeURL)) {
61 Document* contentDoc = this->contentDocument();
62 if (contentDoc && !ScriptController::canAccessFromCurrentOrigin(contentDoc->frame()))
63 return false;
64 }
65
66 Frame* parentFrame = document().frame();
67 if (parentFrame)
68 return parentFrame->isURLAllowed(completeURL);
69
70 return true;
71 }
72
openURL(bool lockBackForwardList)73 void HTMLFrameElementBase::openURL(bool lockBackForwardList)
74 {
75 if (!isURLAllowed())
76 return;
77
78 if (m_URL.isEmpty())
79 m_URL = blankURL().string();
80
81 Frame* parentFrame = document().frame();
82 if (!parentFrame)
83 return;
84
85 // Support for <frame src="javascript:string">
86 KURL scriptURL;
87 KURL url = document().completeURL(m_URL);
88 if (protocolIsJavaScript(m_URL)) {
89 scriptURL = url;
90 url = blankURL();
91 }
92
93 if (!loadOrRedirectSubframe(url, m_frameName, lockBackForwardList))
94 return;
95 if (!contentFrame() || scriptURL.isEmpty())
96 return;
97 contentFrame()->script().executeScriptIfJavaScriptURL(scriptURL);
98 }
99
parseAttribute(const QualifiedName & name,const AtomicString & value)100 void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const AtomicString& value)
101 {
102 if (name == srcdocAttr)
103 setLocation("about:srcdoc");
104 else if (name == srcAttr && !fastHasAttribute(srcdocAttr))
105 setLocation(stripLeadingAndTrailingHTMLSpaces(value));
106 else if (isIdAttributeName(name)) {
107 // Important to call through to base for the id attribute so the hasID bit gets set.
108 HTMLFrameOwnerElement::parseAttribute(name, value);
109 m_frameName = value;
110 } else if (name == nameAttr) {
111 m_frameName = value;
112 // FIXME: If we are already attached, this doesn't actually change the frame's name.
113 // FIXME: If we are already attached, this doesn't check for frame name
114 // conflicts and generate a unique frame name.
115 } else if (name == marginwidthAttr) {
116 m_marginWidth = value.toInt();
117 // FIXME: If we are already attached, this has no effect.
118 } else if (name == marginheightAttr) {
119 m_marginHeight = value.toInt();
120 // FIXME: If we are already attached, this has no effect.
121 } else if (name == scrollingAttr) {
122 // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling."
123 if (equalIgnoringCase(value, "auto") || equalIgnoringCase(value, "yes"))
124 m_scrolling = ScrollbarAuto;
125 else if (equalIgnoringCase(value, "no"))
126 m_scrolling = ScrollbarAlwaysOff;
127 // FIXME: If we are already attached, this has no effect.
128 } else if (name == onbeforeloadAttr)
129 setAttributeEventListener(EventTypeNames::beforeload, createAttributeEventListener(this, name, value));
130 else if (name == onbeforeunloadAttr) {
131 // FIXME: should <frame> elements have beforeunload handlers?
132 setAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(this, name, value));
133 } else
134 HTMLFrameOwnerElement::parseAttribute(name, value);
135 }
136
setNameAndOpenURL()137 void HTMLFrameElementBase::setNameAndOpenURL()
138 {
139 m_frameName = getNameAttribute();
140 if (m_frameName.isNull())
141 m_frameName = getIdAttribute();
142 openURL();
143 }
144
insertedInto(ContainerNode * insertionPoint)145 Node::InsertionNotificationRequest HTMLFrameElementBase::insertedInto(ContainerNode* insertionPoint)
146 {
147 HTMLFrameOwnerElement::insertedInto(insertionPoint);
148 return InsertionShouldCallDidNotifySubtreeInsertions;
149 }
150
didNotifySubtreeInsertionsToDocument()151 void HTMLFrameElementBase::didNotifySubtreeInsertionsToDocument()
152 {
153 if (!document().frame())
154 return;
155
156 if (!SubframeLoadingDisabler::canLoadFrame(*this))
157 return;
158
159 setNameAndOpenURL();
160 }
161
attach(const AttachContext & context)162 void HTMLFrameElementBase::attach(const AttachContext& context)
163 {
164 HTMLFrameOwnerElement::attach(context);
165
166 if (RenderPart* part = renderPart()) {
167 if (Frame* frame = contentFrame())
168 part->setWidget(frame->view());
169 }
170 }
171
location() const172 KURL HTMLFrameElementBase::location() const
173 {
174 if (fastHasAttribute(srcdocAttr))
175 return KURL(ParsedURLString, "about:srcdoc");
176 return document().completeURL(getAttribute(srcAttr));
177 }
178
setLocation(const String & str)179 void HTMLFrameElementBase::setLocation(const String& str)
180 {
181 m_URL = AtomicString(str);
182
183 if (inDocument())
184 openURL(false);
185 }
186
supportsFocus() const187 bool HTMLFrameElementBase::supportsFocus() const
188 {
189 return true;
190 }
191
setFocus(bool received)192 void HTMLFrameElementBase::setFocus(bool received)
193 {
194 HTMLFrameOwnerElement::setFocus(received);
195 if (Page* page = document().page()) {
196 if (received)
197 page->focusController().setFocusedFrame(contentFrame());
198 else if (page->focusController().focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away.
199 page->focusController().setFocusedFrame(0);
200 }
201 }
202
isURLAttribute(const Attribute & attribute) const203 bool HTMLFrameElementBase::isURLAttribute(const Attribute& attribute) const
204 {
205 return attribute.name() == longdescAttr || attribute.name() == srcAttr
206 || HTMLFrameOwnerElement::isURLAttribute(attribute);
207 }
208
isHTMLContentAttribute(const Attribute & attribute) const209 bool HTMLFrameElementBase::isHTMLContentAttribute(const Attribute& attribute) const
210 {
211 return attribute.name() == srcdocAttr || HTMLFrameOwnerElement::isHTMLContentAttribute(attribute);
212 }
213
width()214 int HTMLFrameElementBase::width()
215 {
216 document().updateLayoutIgnorePendingStylesheets();
217 if (!renderBox())
218 return 0;
219 return renderBox()->width();
220 }
221
height()222 int HTMLFrameElementBase::height()
223 {
224 document().updateLayoutIgnorePendingStylesheets();
225 if (!renderBox())
226 return 0;
227 return renderBox()->height();
228 }
229
230 } // namespace WebCore
231