Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / web / WebFrame.cpp
blob98042f6431e1ae83107a2ba1ef6af0f1cef8498a
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "config.h"
6 #include "public/web/WebFrame.h"
8 #include "bindings/core/v8/WindowProxyManager.h"
9 #include "core/frame/FrameHost.h"
10 #include "core/frame/FrameView.h"
11 #include "core/frame/LocalFrame.h"
12 #include "core/frame/RemoteFrame.h"
13 #include "core/html/HTMLFrameElementBase.h"
14 #include "core/html/HTMLFrameOwnerElement.h"
15 #include "core/page/Page.h"
16 #include "platform/UserGestureIndicator.h"
17 #include "platform/heap/Handle.h"
18 #include "public/web/WebElement.h"
19 #include "public/web/WebSandboxFlags.h"
20 #include "web/OpenedFrameTracker.h"
21 #include "web/RemoteBridgeFrameOwner.h"
22 #include "web/WebLocalFrameImpl.h"
23 #include "web/WebRemoteFrameImpl.h"
24 #include <algorithm>
26 namespace blink {
28 Frame* toCoreFrame(const WebFrame* frame)
30 if (!frame)
31 return 0;
33 return frame->isWebLocalFrame()
34 ? static_cast<Frame*>(toWebLocalFrameImpl(frame)->frame())
35 : toWebRemoteFrameImpl(frame)->frame();
38 bool WebFrame::swap(WebFrame* frame)
40 using std::swap;
41 RefPtrWillBeRawPtr<Frame> oldFrame = toCoreFrame(this);
42 #if !ENABLE(OILPAN)
43 RefPtrWillBeRawPtr<WebLocalFrameImpl> protectWebLocalFrame = isWebLocalFrame() ? toWebLocalFrameImpl(this) : nullptr;
44 RefPtrWillBeRawPtr<WebRemoteFrameImpl> protectWebRemoteFrame = isWebRemoteFrame() ? toWebRemoteFrameImpl(this) : nullptr;
45 #endif
47 // Unload the current Document in this frame: this calls unload handlers,
48 // detaches child frames, etc. Since this runs script, make sure this frame
49 // wasn't detached before continuing with the swap.
50 // FIXME: There is no unit test for this condition, so one needs to be
51 // written.
52 if (!oldFrame->prepareForCommit())
53 return false;
55 if (m_parent) {
56 if (m_parent->m_firstChild == this)
57 m_parent->m_firstChild = frame;
58 if (m_parent->m_lastChild == this)
59 m_parent->m_lastChild = frame;
60 // FIXME: This is due to the fact that the |frame| may be a provisional
61 // local frame, because we don't know if the navigation will result in
62 // an actual page or something else, like a download. The PlzNavigate
63 // project will remove the need for provisional local frames.
64 frame->m_parent = m_parent;
67 if (m_previousSibling) {
68 m_previousSibling->m_nextSibling = frame;
69 swap(m_previousSibling, frame->m_previousSibling);
71 if (m_nextSibling) {
72 m_nextSibling->m_previousSibling = frame;
73 swap(m_nextSibling, frame->m_nextSibling);
76 if (m_opener) {
77 m_opener->m_openedFrameTracker->remove(this);
78 m_opener->m_openedFrameTracker->add(frame);
79 swap(m_opener, frame->m_opener);
81 if (!m_openedFrameTracker->isEmpty()) {
82 m_openedFrameTracker->updateOpener(frame);
83 frame->m_openedFrameTracker.reset(m_openedFrameTracker.release());
86 // Finally, clone the state of the current Frame into one matching
87 // the type of the passed in WebFrame.
88 // FIXME: This is a bit clunky; this results in pointless decrements and
89 // increments of connected subframes.
90 FrameOwner* owner = oldFrame->owner();
91 oldFrame->disconnectOwnerElement();
92 if (frame->isWebLocalFrame()) {
93 LocalFrame& localFrame = *toWebLocalFrameImpl(frame)->frame();
94 ASSERT(owner == localFrame.owner());
95 if (owner) {
96 if (owner->isLocal()) {
97 HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(owner);
98 ownerElement->setContentFrame(localFrame);
99 ownerElement->setWidget(localFrame.view());
100 } else {
101 toRemoteBridgeFrameOwner(owner)->setContentFrame(toWebLocalFrameImpl(frame));
103 } else {
104 localFrame.page()->setMainFrame(&localFrame);
106 } else {
107 toWebRemoteFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name());
109 toCoreFrame(frame)->finishSwapFrom(oldFrame.get());
111 // Although the Document in this frame is now unloaded, many resources
112 // associated with the frame itself have not yet been freed yet.
113 oldFrame->detach(FrameDetachType::Swap);
114 m_parent = nullptr;
116 return true;
119 void WebFrame::detach()
121 toCoreFrame(this)->detach(FrameDetachType::Remove);
124 WebSecurityOrigin WebFrame::securityOrigin() const
126 return WebSecurityOrigin(toCoreFrame(this)->securityContext()->securityOrigin());
130 void WebFrame::setFrameOwnerSandboxFlags(WebSandboxFlags flags)
132 // At the moment, this is only used to replicate sandbox flags
133 // for frames with a remote owner.
134 FrameOwner* owner = toCoreFrame(this)->owner();
135 ASSERT(owner);
136 toRemoteBridgeFrameOwner(owner)->setSandboxFlags(static_cast<SandboxFlags>(flags));
139 WebFrame* WebFrame::opener() const
141 return m_opener;
144 void WebFrame::setOpener(WebFrame* opener)
146 if (m_opener)
147 m_opener->m_openedFrameTracker->remove(this);
148 if (opener)
149 opener->m_openedFrameTracker->add(this);
150 m_opener = opener;
153 void WebFrame::insertAfter(WebFrame* newChild, WebFrame* previousSibling)
155 newChild->m_parent = this;
157 WebFrame* next;
158 if (!previousSibling) {
159 // Insert at the beginning if no previous sibling is specified.
160 next = m_firstChild;
161 m_firstChild = newChild;
162 } else {
163 ASSERT(previousSibling->m_parent == this);
164 next = previousSibling->m_nextSibling;
165 previousSibling->m_nextSibling = newChild;
166 newChild->m_previousSibling = previousSibling;
169 if (next) {
170 newChild->m_nextSibling = next;
171 next->m_previousSibling = newChild;
172 } else {
173 m_lastChild = newChild;
176 toCoreFrame(this)->tree().invalidateScopedChildCount();
177 toCoreFrame(this)->host()->incrementSubframeCount();
180 void WebFrame::appendChild(WebFrame* child)
182 // TODO(dcheng): Original code asserts that the frames have the same Page.
183 // We should add an equivalent check... figure out what.
184 insertAfter(child, m_lastChild);
187 void WebFrame::removeChild(WebFrame* child)
189 child->m_parent = 0;
191 if (m_firstChild == child)
192 m_firstChild = child->m_nextSibling;
193 else
194 child->m_previousSibling->m_nextSibling = child->m_nextSibling;
196 if (m_lastChild == child)
197 m_lastChild = child->m_previousSibling;
198 else
199 child->m_nextSibling->m_previousSibling = child->m_previousSibling;
201 child->m_previousSibling = child->m_nextSibling = 0;
203 toCoreFrame(this)->tree().invalidateScopedChildCount();
204 toCoreFrame(this)->host()->decrementSubframeCount();
207 void WebFrame::setParent(WebFrame* parent)
209 m_parent = parent;
212 WebFrame* WebFrame::parent() const
214 return m_parent;
217 WebFrame* WebFrame::top() const
219 WebFrame* frame = const_cast<WebFrame*>(this);
220 for (WebFrame* parent = frame; parent; parent = parent->m_parent)
221 frame = parent;
222 return frame;
225 WebFrame* WebFrame::firstChild() const
227 return m_firstChild;
230 WebFrame* WebFrame::lastChild() const
232 return m_lastChild;
235 WebFrame* WebFrame::previousSibling() const
237 return m_previousSibling;
240 WebFrame* WebFrame::nextSibling() const
242 return m_nextSibling;
245 WebFrame* WebFrame::traversePrevious(bool wrap) const
247 if (Frame* frame = toCoreFrame(this))
248 return fromFrame(frame->tree().traversePreviousWithWrap(wrap));
249 return 0;
252 WebFrame* WebFrame::traverseNext(bool wrap) const
254 if (Frame* frame = toCoreFrame(this))
255 return fromFrame(frame->tree().traverseNextWithWrap(wrap));
256 return 0;
259 WebFrame* WebFrame::findChildByName(const WebString& name) const
261 Frame* frame = toCoreFrame(this);
262 if (!frame)
263 return 0;
264 // FIXME: It's not clear this should ever be called to find a remote frame.
265 // Perhaps just disallow that completely?
266 return fromFrame(frame->tree().child(name));
269 WebFrame* WebFrame::fromFrameOwnerElement(const WebElement& webElement)
271 Element* element = PassRefPtrWillBeRawPtr<Element>(webElement).get();
273 if (!isHTMLFrameElementBase(element))
274 return nullptr;
275 return fromFrame(toHTMLFrameElementBase(element)->contentFrame());
278 WebFrame* WebFrame::fromFrame(Frame* frame)
280 if (!frame)
281 return 0;
283 if (frame->isLocalFrame())
284 return WebLocalFrameImpl::fromFrame(toLocalFrame(*frame));
285 return WebRemoteFrameImpl::fromFrame(toRemoteFrame(*frame));
288 WebFrame::WebFrame(WebTreeScopeType scope)
289 : m_scope(scope)
290 , m_parent(0)
291 , m_previousSibling(0)
292 , m_nextSibling(0)
293 , m_firstChild(0)
294 , m_lastChild(0)
295 , m_opener(0)
296 , m_openedFrameTracker(new OpenedFrameTracker)
300 WebFrame::~WebFrame()
302 m_openedFrameTracker.reset(0);
305 #if ENABLE(OILPAN)
306 ALWAYS_INLINE bool WebFrame::isFrameAlive(const WebFrame* frame)
308 if (!frame)
309 return true;
311 if (frame->isWebLocalFrame())
312 return Heap::isHeapObjectAlive(toWebLocalFrameImpl(frame));
314 return Heap::isHeapObjectAlive(toWebRemoteFrameImpl(frame));
317 template <typename VisitorDispatcher>
318 ALWAYS_INLINE void WebFrame::traceFrameImpl(VisitorDispatcher visitor, WebFrame* frame)
320 if (!frame)
321 return;
323 if (frame->isWebLocalFrame())
324 visitor->trace(toWebLocalFrameImpl(frame));
325 else
326 visitor->trace(toWebRemoteFrameImpl(frame));
329 template <typename VisitorDispatcher>
330 ALWAYS_INLINE void WebFrame::traceFramesImpl(VisitorDispatcher visitor, WebFrame* frame)
332 ASSERT(frame);
333 traceFrame(visitor, frame->m_parent);
334 for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
335 traceFrame(visitor, child);
336 // m_opener is a weak reference.
337 frame->m_openedFrameTracker->traceFrames(visitor);
340 template <typename VisitorDispatcher>
341 ALWAYS_INLINE void WebFrame::clearWeakFramesImpl(VisitorDispatcher visitor)
343 if (!isFrameAlive(m_opener))
344 m_opener = nullptr;
347 #define DEFINE_VISITOR_METHOD(VisitorDispatcher) \
348 void WebFrame::traceFrame(VisitorDispatcher visitor, WebFrame* frame) { traceFrameImpl(visitor, frame); } \
349 void WebFrame::traceFrames(VisitorDispatcher visitor, WebFrame* frame) { traceFramesImpl(visitor, frame); } \
350 void WebFrame::clearWeakFrames(VisitorDispatcher visitor) { clearWeakFramesImpl(visitor); }
352 DEFINE_VISITOR_METHOD(Visitor*)
353 DEFINE_VISITOR_METHOD(InlinedGlobalMarkingVisitor)
355 #undef DEFINE_VISITOR_METHOD
356 #endif
358 } // namespace blink