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 "bindings/v8/ScriptController.h"
28 #include "bindings/v8/ScriptEventListener.h"
29 #include "core/HTMLNames.h"
30 #include "core/dom/Attribute.h"
31 #include "core/dom/Document.h"
32 #include "core/frame/FrameView.h"
33 #include "core/frame/LocalFrame.h"
34 #include "core/html/parser/HTMLParserIdioms.h"
35 #include "core/loader/FrameLoader.h"
36 #include "core/page/ChromeClient.h"
37 #include "core/page/FocusController.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 LocalFrame* 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 = AtomicString(blankURL().string());
80
81 LocalFrame* 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() || !contentFrame()->isLocalFrame())
96 return;
97 toLocalFrame(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 == onbeforeunloadAttr) {
129 // FIXME: should <frame> elements have beforeunload handlers?
130 setAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(this, name, value, eventParameterName()));
131 } else
132 HTMLFrameOwnerElement::parseAttribute(name, value);
133 }
134
setNameAndOpenURL()135 void HTMLFrameElementBase::setNameAndOpenURL()
136 {
137 m_frameName = getNameAttribute();
138 openURL();
139 }
140
insertedInto(ContainerNode * insertionPoint)141 Node::InsertionNotificationRequest HTMLFrameElementBase::insertedInto(ContainerNode* insertionPoint)
142 {
143 HTMLFrameOwnerElement::insertedInto(insertionPoint);
144 return InsertionShouldCallDidNotifySubtreeInsertions;
145 }
146
didNotifySubtreeInsertionsToDocument()147 void HTMLFrameElementBase::didNotifySubtreeInsertionsToDocument()
148 {
149 if (!document().frame())
150 return;
151
152 if (!SubframeLoadingDisabler::canLoadFrame(*this))
153 return;
154
155 setNameAndOpenURL();
156 }
157
attach(const AttachContext & context)158 void HTMLFrameElementBase::attach(const AttachContext& context)
159 {
160 HTMLFrameOwnerElement::attach(context);
161
162 if (renderPart()) {
163 if (Frame* frame = contentFrame()) {
164 if (frame->isLocalFrame())
165 setWidget(toLocalFrame(frame)->view());
166 }
167 }
168 }
169
setLocation(const String & str)170 void HTMLFrameElementBase::setLocation(const String& str)
171 {
172 m_URL = AtomicString(str);
173
174 if (inDocument())
175 openURL(false);
176 }
177
supportsFocus() const178 bool HTMLFrameElementBase::supportsFocus() const
179 {
180 return true;
181 }
182
setFocus(bool received)183 void HTMLFrameElementBase::setFocus(bool received)
184 {
185 HTMLFrameOwnerElement::setFocus(received);
186 if (Page* page = document().page()) {
187 if (received)
188 page->focusController().setFocusedFrame(contentFrame());
189 else if (page->focusController().focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away.
190 page->focusController().setFocusedFrame(nullptr);
191 }
192 }
193
isURLAttribute(const Attribute & attribute) const194 bool HTMLFrameElementBase::isURLAttribute(const Attribute& attribute) const
195 {
196 return attribute.name() == longdescAttr || attribute.name() == srcAttr
197 || HTMLFrameOwnerElement::isURLAttribute(attribute);
198 }
199
hasLegalLinkAttribute(const QualifiedName & name) const200 bool HTMLFrameElementBase::hasLegalLinkAttribute(const QualifiedName& name) const
201 {
202 return name == srcAttr || HTMLFrameOwnerElement::hasLegalLinkAttribute(name);
203 }
204
isHTMLContentAttribute(const Attribute & attribute) const205 bool HTMLFrameElementBase::isHTMLContentAttribute(const Attribute& attribute) const
206 {
207 return attribute.name() == srcdocAttr || HTMLFrameOwnerElement::isHTMLContentAttribute(attribute);
208 }
209
width()210 int HTMLFrameElementBase::width()
211 {
212 document().updateLayoutIgnorePendingStylesheets();
213 if (!renderBox())
214 return 0;
215 return renderBox()->width();
216 }
217
height()218 int HTMLFrameElementBase::height()
219 {
220 document().updateLayoutIgnorePendingStylesheets();
221 if (!renderBox())
222 return 0;
223 return renderBox()->height();
224 }
225
226 // FIXME: Remove this code once we have input routing in the browser
227 // process. See http://crbug.com/339659.
defaultEventHandler(Event * event)228 void HTMLFrameElementBase::defaultEventHandler(Event* event)
229 {
230 if (contentFrame() && contentFrame()->isRemoteFrameTemporary()) {
231 contentFrame()->chromeClient().forwardInputEvent(contentFrame(), event);
232 return;
233 }
234 HTMLFrameOwnerElement::defaultEventHandler(event);
235 }
236
237 } // namespace WebCore
238