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-2017 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 "Document.h" |
28 | #include "FocusController.h" |
29 | #include "Frame.h" |
30 | #include "FrameLoader.h" |
31 | #include "FrameView.h" |
32 | #include "HTMLNames.h" |
33 | #include "HTMLParserIdioms.h" |
34 | #include "JSDOMBindingSecurity.h" |
35 | #include "Page.h" |
36 | #include "RenderWidget.h" |
37 | #include "ScriptController.h" |
38 | #include "Settings.h" |
39 | #include "SubframeLoader.h" |
40 | #include <wtf/IsoMallocInlines.h> |
41 | #include <wtf/URL.h> |
42 | |
43 | namespace WebCore { |
44 | |
45 | WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLFrameElementBase); |
46 | |
47 | using namespace HTMLNames; |
48 | |
49 | HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document& document) |
50 | : HTMLFrameOwnerElement(tagName, document) |
51 | , m_scrolling(ScrollbarAuto) |
52 | , m_marginWidth(-1) |
53 | , m_marginHeight(-1) |
54 | { |
55 | setHasCustomStyleResolveCallbacks(); |
56 | } |
57 | |
58 | bool HTMLFrameElementBase::isURLAllowed() const |
59 | { |
60 | if (m_URL.isEmpty()) |
61 | return true; |
62 | |
63 | return isURLAllowed(document().completeURL(m_URL)); |
64 | } |
65 | |
66 | bool HTMLFrameElementBase::isURLAllowed(const URL& completeURL) const |
67 | { |
68 | if (document().page() && document().page()->subframeCount() >= Page::maxNumberOfFrames) |
69 | return false; |
70 | |
71 | if (completeURL.isEmpty()) |
72 | return true; |
73 | |
74 | if (WTF::protocolIsJavaScript(completeURL)) { |
75 | RefPtr<Document> contentDoc = this->contentDocument(); |
76 | if (contentDoc && !ScriptController::canAccessFromCurrentOrigin(contentDoc->frame())) |
77 | return false; |
78 | } |
79 | |
80 | RefPtr<Frame> parentFrame = document().frame(); |
81 | if (parentFrame) |
82 | return parentFrame->isURLAllowed(completeURL); |
83 | |
84 | return true; |
85 | } |
86 | |
87 | void HTMLFrameElementBase::openURL(LockHistory lockHistory, LockBackForwardList lockBackForwardList) |
88 | { |
89 | if (!isURLAllowed()) |
90 | return; |
91 | |
92 | if (m_URL.isEmpty()) |
93 | m_URL = WTF::blankURL().string(); |
94 | |
95 | RefPtr<Frame> parentFrame = document().frame(); |
96 | if (!parentFrame) |
97 | return; |
98 | |
99 | String frameName = getNameAttribute(); |
100 | if (frameName.isNull() && UNLIKELY(document().settings().needsFrameNameFallbackToIdQuirk())) |
101 | frameName = getIdAttribute(); |
102 | |
103 | parentFrame->loader().subframeLoader().requestFrame(*this, m_URL, frameName, lockHistory, lockBackForwardList); |
104 | } |
105 | |
106 | void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const AtomicString& value) |
107 | { |
108 | if (name == srcdocAttr) |
109 | setLocation("about:srcdoc" ); |
110 | else if (name == srcAttr && !hasAttributeWithoutSynchronization(srcdocAttr)) |
111 | setLocation(stripLeadingAndTrailingHTMLSpaces(value)); |
112 | else if (name == marginwidthAttr) { |
113 | m_marginWidth = value.toInt(); |
114 | // FIXME: If we are already attached, this has no effect. |
115 | } else if (name == marginheightAttr) { |
116 | m_marginHeight = value.toInt(); |
117 | // FIXME: If we are already attached, this has no effect. |
118 | } else if (name == scrollingAttr) { |
119 | // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling." |
120 | if (equalLettersIgnoringASCIICase(value, "auto" ) || equalLettersIgnoringASCIICase(value, "yes" )) |
121 | m_scrolling = ScrollbarAuto; |
122 | else if (equalLettersIgnoringASCIICase(value, "no" )) |
123 | m_scrolling = ScrollbarAlwaysOff; |
124 | // FIXME: If we are already attached, this has no effect. |
125 | } else |
126 | HTMLFrameOwnerElement::parseAttribute(name, value); |
127 | } |
128 | |
129 | Node::InsertedIntoAncestorResult HTMLFrameElementBase::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree) |
130 | { |
131 | HTMLFrameOwnerElement::insertedIntoAncestor(insertionType, parentOfInsertedTree); |
132 | if (insertionType.connectedToDocument) |
133 | return InsertedIntoAncestorResult::NeedsPostInsertionCallback; |
134 | return InsertedIntoAncestorResult::Done; |
135 | } |
136 | |
137 | void HTMLFrameElementBase::didFinishInsertingNode() |
138 | { |
139 | if (!isConnected()) |
140 | return; |
141 | |
142 | // DocumentFragments don't kick off any loads. |
143 | if (!document().frame()) |
144 | return; |
145 | |
146 | if (!SubframeLoadingDisabler::canLoadFrame(*this)) |
147 | return; |
148 | |
149 | if (!renderer()) |
150 | invalidateStyleAndRenderersForSubtree(); |
151 | openURL(); |
152 | } |
153 | |
154 | void HTMLFrameElementBase::didAttachRenderers() |
155 | { |
156 | if (RenderWidget* part = renderWidget()) { |
157 | if (RefPtr<Frame> frame = contentFrame()) |
158 | part->setWidget(frame->view()); |
159 | } |
160 | } |
161 | |
162 | URL HTMLFrameElementBase::location() const |
163 | { |
164 | if (hasAttributeWithoutSynchronization(srcdocAttr)) |
165 | return URL({ }, "about:srcdoc" ); |
166 | return document().completeURL(attributeWithoutSynchronization(srcAttr)); |
167 | } |
168 | |
169 | void HTMLFrameElementBase::setLocation(const String& str) |
170 | { |
171 | if (document().settings().needsAcrobatFrameReloadingQuirk() && m_URL == str) |
172 | return; |
173 | |
174 | m_URL = AtomicString(str); |
175 | |
176 | if (isConnected()) |
177 | openURL(LockHistory::No, LockBackForwardList::No); |
178 | } |
179 | |
180 | void HTMLFrameElementBase::setLocation(JSC::ExecState& state, const String& newLocation) |
181 | { |
182 | if (WTF::protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(newLocation))) { |
183 | if (!BindingSecurity::shouldAllowAccessToNode(state, contentDocument())) |
184 | return; |
185 | } |
186 | |
187 | setLocation(newLocation); |
188 | } |
189 | |
190 | bool HTMLFrameElementBase::supportsFocus() const |
191 | { |
192 | return true; |
193 | } |
194 | |
195 | void HTMLFrameElementBase::setFocus(bool received) |
196 | { |
197 | HTMLFrameOwnerElement::setFocus(received); |
198 | if (Page* page = document().page()) { |
199 | if (received) |
200 | page->focusController().setFocusedFrame(contentFrame()); |
201 | else if (page->focusController().focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away. |
202 | page->focusController().setFocusedFrame(0); |
203 | } |
204 | } |
205 | |
206 | bool HTMLFrameElementBase::isURLAttribute(const Attribute& attribute) const |
207 | { |
208 | return attribute.name() == srcAttr || attribute.name() == longdescAttr || HTMLFrameOwnerElement::isURLAttribute(attribute); |
209 | } |
210 | |
211 | bool HTMLFrameElementBase::isHTMLContentAttribute(const Attribute& attribute) const |
212 | { |
213 | return attribute.name() == srcdocAttr || HTMLFrameOwnerElement::isHTMLContentAttribute(attribute); |
214 | } |
215 | |
216 | int HTMLFrameElementBase::width() |
217 | { |
218 | document().updateLayoutIgnorePendingStylesheets(); |
219 | if (!renderBox()) |
220 | return 0; |
221 | return renderBox()->width(); |
222 | } |
223 | |
224 | int HTMLFrameElementBase::height() |
225 | { |
226 | document().updateLayoutIgnorePendingStylesheets(); |
227 | if (!renderBox()) |
228 | return 0; |
229 | return renderBox()->height(); |
230 | } |
231 | |
232 | } // namespace WebCore |
233 | |