Add an argument indicating the type of insertion to Node::insertedInto
[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 "URL.h"
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45
46 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document& document)
47     : HTMLFrameOwnerElement(tagName, document)
48     , m_scrolling(ScrollbarAuto)
49     , m_marginWidth(-1)
50     , m_marginHeight(-1)
51 {
52     setHasCustomStyleResolveCallbacks();
53 }
54
55 bool HTMLFrameElementBase::isURLAllowed() const
56 {
57     if (m_URL.isEmpty())
58         return true;
59
60     return isURLAllowed(document().completeURL(m_URL));
61 }
62
63 bool HTMLFrameElementBase::isURLAllowed(const URL& completeURL) const
64 {
65     if (document().page() && document().page()->subframeCount() >= Page::maxNumberOfFrames)
66         return false;
67
68     if (completeURL.isEmpty())
69         return true;
70
71     if (protocolIsJavaScript(completeURL)) {
72         Document* contentDoc = this->contentDocument();
73         if (contentDoc && !ScriptController::canAccessFromCurrentOrigin(contentDoc->frame()))
74             return false;
75     }
76
77     Frame* parentFrame = document().frame();
78     if (parentFrame)
79         return parentFrame->isURLAllowed(completeURL);
80
81     return true;
82 }
83
84 void HTMLFrameElementBase::openURL(LockHistory lockHistory, LockBackForwardList lockBackForwardList)
85 {
86     if (!isURLAllowed())
87         return;
88
89     if (m_URL.isEmpty())
90         m_URL = blankURL().string();
91
92     Frame* parentFrame = document().frame();
93     if (!parentFrame)
94         return;
95
96     parentFrame->loader().subframeLoader().requestFrame(*this, m_URL, m_frameName, lockHistory, lockBackForwardList);
97 }
98
99 void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const AtomicString& value)
100 {
101     if (name == srcdocAttr)
102         setLocation("about:srcdoc");
103     else if (name == srcAttr && !hasAttributeWithoutSynchronization(srcdocAttr))
104         setLocation(stripLeadingAndTrailingHTMLSpaces(value));
105     else if (name == idAttr) {
106         HTMLFrameOwnerElement::parseAttribute(name, value);
107         // Falling back to using the 'id' attribute is not standard but some content relies on this behavior.
108         if (!hasAttributeWithoutSynchronization(nameAttr))
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 (equalLettersIgnoringASCIICase(value, "auto") || equalLettersIgnoringASCIICase(value, "yes"))
124             m_scrolling = ScrollbarAuto;
125         else if (equalLettersIgnoringASCIICase(value, "no"))
126             m_scrolling = ScrollbarAlwaysOff;
127         // FIXME: If we are already attached, this has no effect.
128     } else
129         HTMLFrameOwnerElement::parseAttribute(name, value);
130 }
131
132 void HTMLFrameElementBase::setNameAndOpenURL()
133 {
134     m_frameName = getNameAttribute();
135     // Falling back to using the 'id' attribute is not standard but some content relies on this behavior.
136     if (m_frameName.isNull())
137         m_frameName = getIdAttribute();
138     openURL();
139 }
140
141 Node::InsertedIntoResult HTMLFrameElementBase::insertedInto(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
142 {
143     HTMLFrameOwnerElement::insertedInto(insertionType, parentOfInsertedTree);
144     if (insertionType.connectedToDocument)
145         return InsertedIntoResult::NeedsPostInsertionCallback;
146     return InsertedIntoResult::Done;
147 }
148
149 void HTMLFrameElementBase::didFinishInsertingNode()
150 {
151     if (!isConnected())
152         return;
153
154     // DocumentFragments don't kick off any loads.
155     if (!document().frame())
156         return;
157
158     if (!SubframeLoadingDisabler::canLoadFrame(*this))
159         return;
160
161     if (!renderer())
162         invalidateStyleAndRenderersForSubtree();
163     setNameAndOpenURL();
164 }
165
166 void HTMLFrameElementBase::didAttachRenderers()
167 {
168     if (RenderWidget* part = renderWidget()) {
169         if (Frame* frame = contentFrame())
170             part->setWidget(frame->view());
171     }
172 }
173
174 URL HTMLFrameElementBase::location() const
175 {
176     if (hasAttributeWithoutSynchronization(srcdocAttr))
177         return URL(ParsedURLString, "about:srcdoc");
178     return document().completeURL(attributeWithoutSynchronization(srcAttr));
179 }
180
181 void HTMLFrameElementBase::setLocation(const String& str)
182 {
183     if (document().settings().needsAcrobatFrameReloadingQuirk() && m_URL == str)
184         return;
185
186     m_URL = AtomicString(str);
187
188     if (isConnected())
189         openURL(LockHistory::No, LockBackForwardList::No);
190 }
191
192 void HTMLFrameElementBase::setLocation(JSC::ExecState& state, const String& newLocation)
193 {
194     if (protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(newLocation))) {
195         if (!BindingSecurity::shouldAllowAccessToNode(state, contentDocument()))
196             return;
197     }
198
199     setLocation(newLocation);
200 }
201
202 bool HTMLFrameElementBase::supportsFocus() const
203 {
204     return true;
205 }
206
207 void HTMLFrameElementBase::setFocus(bool received)
208 {
209     HTMLFrameOwnerElement::setFocus(received);
210     if (Page* page = document().page()) {
211         if (received)
212             page->focusController().setFocusedFrame(contentFrame());
213         else if (page->focusController().focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away.
214             page->focusController().setFocusedFrame(0);
215     }
216 }
217
218 bool HTMLFrameElementBase::isURLAttribute(const Attribute& attribute) const
219 {
220     return attribute.name() == srcAttr || attribute.name() == longdescAttr || HTMLFrameOwnerElement::isURLAttribute(attribute);
221 }
222
223 bool HTMLFrameElementBase::isHTMLContentAttribute(const Attribute& attribute) const
224 {
225     return attribute.name() == srcdocAttr || HTMLFrameOwnerElement::isHTMLContentAttribute(attribute);
226 }
227
228 int HTMLFrameElementBase::width()
229 {
230     document().updateLayoutIgnorePendingStylesheets();
231     if (!renderBox())
232         return 0;
233     return renderBox()->width();
234 }
235
236 int HTMLFrameElementBase::height()
237 {
238     document().updateLayoutIgnorePendingStylesheets();
239     if (!renderBox())
240         return 0;
241     return renderBox()->height();
242 }
243
244 } // namespace WebCore