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.
6 #include "public/web/WebFrame.h"
8 #include "core/frame/RemoteFrame.h"
9 #include "core/html/HTMLFrameOwnerElement.h"
10 #include "platform/UserGestureIndicator.h"
11 #include "platform/heap/Handle.h"
12 #include "web/OpenedFrameTracker.h"
13 #include "web/WebLocalFrameImpl.h"
14 #include "web/WebRemoteFrameImpl.h"
19 Frame* toCoreFrame(const WebFrame* frame)
24 return frame->isWebLocalFrame()
25 ? static_cast<Frame*>(toWebLocalFrameImpl(frame)->frame())
26 : toWebRemoteFrameImpl(frame)->frame();
29 bool WebFrame::swap(WebFrame* frame)
32 RefPtrWillBeRawPtr<Frame> oldFrame = toCoreFrame(this);
34 // All child frames must be detached first.
35 oldFrame->detachChildren();
37 // If the frame has been detached during detaching its children, return
39 // FIXME: There is no unit test for this condition, so one needs to be
41 if (!oldFrame->host())
44 // The frame being swapped in should not have a Frame associated
46 ASSERT(!toCoreFrame(frame));
49 if (m_parent->m_firstChild == this)
50 m_parent->m_firstChild = frame;
51 if (m_parent->m_lastChild == this)
52 m_parent->m_lastChild = frame;
53 swap(m_parent, frame->m_parent);
56 if (m_previousSibling) {
57 m_previousSibling->m_nextSibling = frame;
58 swap(m_previousSibling, frame->m_previousSibling);
61 m_nextSibling->m_previousSibling = frame;
62 swap(m_nextSibling, frame->m_nextSibling);
66 m_opener->m_openedFrameTracker->remove(this);
67 m_opener->m_openedFrameTracker->add(frame);
68 swap(m_opener, frame->m_opener);
70 if (!m_openedFrameTracker->isEmpty()) {
71 m_openedFrameTracker->updateOpener(frame);
72 frame->m_openedFrameTracker.reset(m_openedFrameTracker.release());
75 // Finally, clone the state of the current Frame into one matching
76 // the type of the passed in WebFrame.
77 // FIXME: This is a bit clunky; this results in pointless decrements and
78 // increments of connected subframes.
79 FrameOwner* owner = oldFrame->owner();
80 oldFrame->disconnectOwnerElement();
81 if (frame->isWebLocalFrame()) {
82 toWebLocalFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name(), nullAtom);
84 toWebRemoteFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name());
90 void WebFrame::detach()
92 toCoreFrame(this)->detach();
95 WebFrame* WebFrame::opener() const
100 void WebFrame::setOpener(WebFrame* opener)
103 m_opener->m_openedFrameTracker->remove(this);
105 opener->m_openedFrameTracker->add(this);
109 void WebFrame::appendChild(WebFrame* child)
111 // FIXME: Original code asserts that the frames have the same Page. We
112 // should add an equivalent check... figure out what.
113 child->m_parent = this;
114 WebFrame* oldLast = m_lastChild;
118 child->m_previousSibling = oldLast;
119 oldLast->m_nextSibling = child;
121 m_firstChild = child;
124 toCoreFrame(this)->tree().invalidateScopedChildCount();
127 void WebFrame::removeChild(WebFrame* child)
131 if (m_firstChild == child)
132 m_firstChild = child->m_nextSibling;
134 child->m_previousSibling->m_nextSibling = child->m_nextSibling;
136 if (m_lastChild == child)
137 m_lastChild = child->m_previousSibling;
139 child->m_nextSibling->m_previousSibling = child->m_previousSibling;
141 child->m_previousSibling = child->m_nextSibling = 0;
143 toCoreFrame(this)->tree().invalidateScopedChildCount();
146 WebFrame* WebFrame::parent() const
151 WebFrame* WebFrame::top() const
153 WebFrame* frame = const_cast<WebFrame*>(this);
154 for (WebFrame* parent = frame; parent; parent = parent->m_parent)
159 WebFrame* WebFrame::firstChild() const
164 WebFrame* WebFrame::lastChild() const
169 WebFrame* WebFrame::previousSibling() const
171 return m_previousSibling;
174 WebFrame* WebFrame::nextSibling() const
176 return m_nextSibling;
179 WebFrame* WebFrame::traversePrevious(bool wrap) const
181 if (Frame* frame = toCoreFrame(this))
182 return fromFrame(frame->tree().traversePreviousWithWrap(wrap));
186 WebFrame* WebFrame::traverseNext(bool wrap) const
188 if (Frame* frame = toCoreFrame(this))
189 return fromFrame(frame->tree().traverseNextWithWrap(wrap));
193 WebFrame* WebFrame::findChildByName(const WebString& name) const
195 Frame* frame = toCoreFrame(this);
198 // FIXME: It's not clear this should ever be called to find a remote frame.
199 // Perhaps just disallow that completely?
200 return fromFrame(frame->tree().child(name));
203 WebFrame* WebFrame::fromFrame(Frame* frame)
208 if (frame->isLocalFrame())
209 return WebLocalFrameImpl::fromFrame(toLocalFrame(*frame));
210 return WebRemoteFrameImpl::fromFrame(toRemoteFrame(*frame));
215 , m_previousSibling(0)
220 , m_openedFrameTracker(new OpenedFrameTracker)
224 WebFrame::~WebFrame()
226 m_openedFrameTracker.reset(0);
229 void WebFrame::traceChildren(Visitor* visitor, WebFrame* frame)
232 // Trace the children frames.
233 WebFrame* child = frame ? frame->firstChild() : 0;
235 if (child->isWebLocalFrame())
236 visitor->trace(toWebLocalFrameImpl(child));
238 visitor->trace(toWebRemoteFrameImpl(child));
240 child = child->nextSibling();