3048b490fa53f3fd4151e0210436c64fa9471479
[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-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