• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20 
21 #include "config.h"
22 #include "core/html/HTMLFrameOwnerElement.h"
23 
24 #include "bindings/core/v8/ExceptionMessages.h"
25 #include "bindings/core/v8/ExceptionState.h"
26 #include "core/accessibility/AXObjectCache.h"
27 #include "core/dom/ExceptionCode.h"
28 #include "core/events/Event.h"
29 #include "core/frame/FrameView.h"
30 #include "core/frame/LocalFrame.h"
31 #include "core/loader/FrameLoader.h"
32 #include "core/loader/FrameLoaderClient.h"
33 #include "core/rendering/RenderLayer.h"
34 #include "core/rendering/RenderPart.h"
35 #include "core/rendering/compositing/RenderLayerCompositor.h"
36 #include "platform/weborigin/SecurityOrigin.h"
37 #include "platform/weborigin/SecurityPolicy.h"
38 
39 namespace blink {
40 
41 typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap;
widgetNewParentMap()42 static WidgetToParentMap& widgetNewParentMap()
43 {
44     DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ());
45     return map;
46 }
47 
disabledSubtreeRoots()48 WillBeHeapHashCountedSet<RawPtrWillBeMember<Node> >& SubframeLoadingDisabler::disabledSubtreeRoots()
49 {
50     DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WillBeHeapHashCountedSet<RawPtrWillBeMember<Node> > >, nodes, (adoptPtrWillBeNoop(new WillBeHeapHashCountedSet<RawPtrWillBeMember<Node> >())));
51     return *nodes;
52 }
53 
54 static unsigned s_updateSuspendCount = 0;
55 
UpdateSuspendScope()56 HTMLFrameOwnerElement::UpdateSuspendScope::UpdateSuspendScope()
57 {
58     ++s_updateSuspendCount;
59 }
60 
performDeferredWidgetTreeOperations()61 void HTMLFrameOwnerElement::UpdateSuspendScope::performDeferredWidgetTreeOperations()
62 {
63     WidgetToParentMap map;
64     widgetNewParentMap().swap(map);
65     WidgetToParentMap::iterator end = map.end();
66     for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) {
67         Widget* child = it->key.get();
68         ScrollView* currentParent = toScrollView(child->parent());
69         FrameView* newParent = it->value;
70         if (newParent != currentParent) {
71             if (currentParent)
72                 currentParent->removeChild(child);
73             if (newParent)
74                 newParent->addChild(child);
75         }
76     }
77 }
78 
~UpdateSuspendScope()79 HTMLFrameOwnerElement::UpdateSuspendScope::~UpdateSuspendScope()
80 {
81     ASSERT(s_updateSuspendCount > 0);
82     if (s_updateSuspendCount == 1)
83         performDeferredWidgetTreeOperations();
84     --s_updateSuspendCount;
85 }
86 
moveWidgetToParentSoon(Widget * child,FrameView * parent)87 static void moveWidgetToParentSoon(Widget* child, FrameView* parent)
88 {
89     if (!s_updateSuspendCount) {
90         if (parent)
91             parent->addChild(child);
92         else if (toScrollView(child->parent()))
93             toScrollView(child->parent())->removeChild(child);
94         return;
95     }
96     widgetNewParentMap().set(child, parent);
97 }
98 
HTMLFrameOwnerElement(const QualifiedName & tagName,Document & document)99 HTMLFrameOwnerElement::HTMLFrameOwnerElement(const QualifiedName& tagName, Document& document)
100     : HTMLElement(tagName, document)
101     , m_contentFrame(nullptr)
102     , m_widget(nullptr)
103     , m_sandboxFlags(SandboxNone)
104 {
105 }
106 
renderPart() const107 RenderPart* HTMLFrameOwnerElement::renderPart() const
108 {
109     // HTMLObjectElement and HTMLEmbedElement may return arbitrary renderers
110     // when using fallback content.
111     if (!renderer() || !renderer()->isRenderPart())
112         return 0;
113     return toRenderPart(renderer());
114 }
115 
setContentFrame(Frame & frame)116 void HTMLFrameOwnerElement::setContentFrame(Frame& frame)
117 {
118     // Make sure we will not end up with two frames referencing the same owner element.
119     ASSERT(!m_contentFrame || m_contentFrame->owner() != this);
120     // Disconnected frames should not be allowed to load.
121     ASSERT(inDocument());
122     m_contentFrame = &frame;
123 
124     for (ContainerNode* node = this; node; node = node->parentOrShadowHostNode())
125         node->incrementConnectedSubframeCount();
126 }
127 
clearContentFrame()128 void HTMLFrameOwnerElement::clearContentFrame()
129 {
130     if (!m_contentFrame)
131         return;
132 
133     m_contentFrame = nullptr;
134 
135     for (ContainerNode* node = this; node; node = node->parentOrShadowHostNode())
136         node->decrementConnectedSubframeCount();
137 }
138 
disconnectContentFrame()139 void HTMLFrameOwnerElement::disconnectContentFrame()
140 {
141     // FIXME: Currently we don't do this in removedFrom because this causes an
142     // unload event in the subframe which could execute script that could then
143     // reach up into this document and then attempt to look back down. We should
144     // see if this behavior is really needed as Gecko does not allow this.
145     if (RefPtrWillBeRawPtr<Frame> frame = contentFrame()) {
146         frame->detach();
147 #if ENABLE(OILPAN)
148         // FIXME: Oilpan: the plugin container is released and finalized here
149         // in order to work around the current inability to make the plugin
150         // container a FrameDestructionObserver (it needs to effectively be on
151         // the heap, and Widget isn't). Hence, release it here while its
152         // frame reference is still valid.
153         if (m_widget && m_widget->isPluginContainer())
154             m_widget = nullptr;
155 #endif
156         frame->disconnectOwnerElement();
157     }
158 }
159 
~HTMLFrameOwnerElement()160 HTMLFrameOwnerElement::~HTMLFrameOwnerElement()
161 {
162 #if ENABLE(OILPAN)
163     // An owner must by now have been informed of detachment
164     // when the frame was closed.
165     ASSERT(!m_contentFrame);
166 #else
167     if (m_contentFrame)
168         m_contentFrame->disconnectOwnerElement();
169 #endif
170 }
171 
contentDocument() const172 Document* HTMLFrameOwnerElement::contentDocument() const
173 {
174     return (m_contentFrame && m_contentFrame->isLocalFrame()) ? toLocalFrame(m_contentFrame)->document() : 0;
175 }
176 
contentWindow() const177 LocalDOMWindow* HTMLFrameOwnerElement::contentWindow() const
178 {
179     return m_contentFrame ? m_contentFrame->domWindow() : 0;
180 }
181 
setSandboxFlags(SandboxFlags flags)182 void HTMLFrameOwnerElement::setSandboxFlags(SandboxFlags flags)
183 {
184     m_sandboxFlags = flags;
185 }
186 
isKeyboardFocusable() const187 bool HTMLFrameOwnerElement::isKeyboardFocusable() const
188 {
189     return m_contentFrame && HTMLElement::isKeyboardFocusable();
190 }
191 
dispatchLoad()192 void HTMLFrameOwnerElement::dispatchLoad()
193 {
194     dispatchEvent(Event::create(EventTypeNames::load));
195 }
196 
getSVGDocument(ExceptionState & exceptionState) const197 Document* HTMLFrameOwnerElement::getSVGDocument(ExceptionState& exceptionState) const
198 {
199     Document* doc = contentDocument();
200     if (doc && doc->isSVGDocument())
201         return doc;
202     return 0;
203 }
204 
setWidget(PassRefPtr<Widget> widget)205 void HTMLFrameOwnerElement::setWidget(PassRefPtr<Widget> widget)
206 {
207     if (widget == m_widget)
208         return;
209 
210     if (m_widget) {
211         if (m_widget->parent())
212             moveWidgetToParentSoon(m_widget.get(), 0);
213         m_widget = nullptr;
214     }
215 
216     m_widget = widget;
217 
218     RenderWidget* renderWidget = toRenderWidget(renderer());
219     if (!renderWidget)
220         return;
221 
222     if (m_widget) {
223         renderWidget->updateOnWidgetChange();
224 
225         ASSERT(document().view() == renderWidget->frameView());
226         ASSERT(renderWidget->frameView());
227         moveWidgetToParentSoon(m_widget.get(), renderWidget->frameView());
228     }
229 
230     if (AXObjectCache* cache = document().existingAXObjectCache())
231         cache->childrenChanged(renderWidget);
232 }
233 
ownedWidget() const234 Widget* HTMLFrameOwnerElement::ownedWidget() const
235 {
236     return m_widget.get();
237 }
238 
loadOrRedirectSubframe(const KURL & url,const AtomicString & frameName,bool lockBackForwardList)239 bool HTMLFrameOwnerElement::loadOrRedirectSubframe(const KURL& url, const AtomicString& frameName, bool lockBackForwardList)
240 {
241     RefPtrWillBeRawPtr<LocalFrame> parentFrame = document().frame();
242     // FIXME(kenrb): The necessary semantics for RemoteFrames have not been worked out yet, but this will likely need some logic to handle them.
243     if (contentFrame() && contentFrame()->isLocalFrame()) {
244         toLocalFrame(contentFrame())->navigationScheduler().scheduleLocationChange(&document(), url.string(), Referrer(document().outgoingReferrer(), document().referrerPolicy()), lockBackForwardList);
245         return true;
246     }
247 
248     if (!document().securityOrigin()->canDisplay(url)) {
249         FrameLoader::reportLocalLoadFailed(parentFrame.get(), url.string());
250         return false;
251     }
252 
253     if (!SubframeLoadingDisabler::canLoadFrame(*this))
254         return false;
255 
256     String referrer = SecurityPolicy::generateReferrerHeader(document().referrerPolicy(), url, document().outgoingReferrer());
257     return parentFrame->loader().client()->createFrame(url, frameName, Referrer(referrer, document().referrerPolicy()), this);
258 }
259 
trace(Visitor * visitor)260 void HTMLFrameOwnerElement::trace(Visitor* visitor)
261 {
262     visitor->trace(m_contentFrame);
263     HTMLElement::trace(visitor);
264     FrameOwner::trace(visitor);
265 }
266 
267 
268 } // namespace blink
269