| Index: Source/web/WebFrameImpl.cpp
|
| diff --git a/Source/web/WebFrameImpl.cpp b/Source/web/WebFrameImpl.cpp
|
| index 487675737c5866caeae933894a3d329cbf423a31..80c0872ed419b65f2515389be62fbef57ea371b7 100644
|
| --- a/Source/web/WebFrameImpl.cpp
|
| +++ b/Source/web/WebFrameImpl.cpp
|
| @@ -647,68 +647,90 @@ void WebFrameImpl::setOpener(const WebFrame* webFrame)
|
|
|
| void WebFrameImpl::appendChild(WebFrame* child)
|
| {
|
| - // FIXME: Implement after this revision rolls into Chrome.
|
| + // FIXME: Original code asserts that the frames have the same Page. We
|
| + // should add an equivalent check... figure out what.
|
| + WebFrameImpl* childImpl = toWebFrameImpl(child);
|
| + childImpl->m_parent = this;
|
| + WebFrameImpl* oldLast = m_lastChild;
|
| + m_lastChild = childImpl;
|
| +
|
| + if (oldLast) {
|
| + childImpl->m_previousSibling = oldLast;
|
| + oldLast->m_nextSibling = childImpl;
|
| + } else {
|
| + m_firstChild = childImpl;
|
| + }
|
| + // FIXME: Not sure if this is a legitimate assert.
|
| + ASSERT(frame());
|
| + frame()->tree().invalidateScopedChildCount();
|
| }
|
|
|
| void WebFrameImpl::removeChild(WebFrame* child)
|
| {
|
| - // FIXME: Implement after this revision rolls into Chrome.
|
| + WebFrameImpl* childImpl = toWebFrameImpl(child);
|
| + childImpl->m_parent = 0;
|
| +
|
| + if (m_firstChild == childImpl)
|
| + m_firstChild = childImpl->m_nextSibling;
|
| + else
|
| + childImpl->m_previousSibling->m_nextSibling = childImpl->m_nextSibling;
|
| +
|
| + if (m_lastChild == childImpl)
|
| + m_lastChild = childImpl->m_previousSibling;
|
| + else
|
| + childImpl->m_nextSibling->m_previousSibling = childImpl->m_previousSibling;
|
| +
|
| + childImpl->m_previousSibling = childImpl->m_nextSibling = 0;
|
| + // FIXME: Not sure if this is a legitimate assert.
|
| + ASSERT(frame());
|
| + frame()->tree().invalidateScopedChildCount();
|
| }
|
|
|
| WebFrame* WebFrameImpl::parent() const
|
| {
|
| - if (!frame())
|
| - return 0;
|
| - return fromFrame(frame()->tree().parent());
|
| + return m_parent;
|
| }
|
|
|
| WebFrame* WebFrameImpl::top() const
|
| {
|
| - if (!frame())
|
| - return 0;
|
| - return fromFrame(frame()->tree().top());
|
| + WebFrameImpl* frame = const_cast<WebFrameImpl*>(this);
|
| + for (WebFrameImpl* parent = frame; parent; parent = parent->m_parent)
|
| + frame = parent;
|
| + return frame;
|
| }
|
|
|
| -WebFrame* WebFrameImpl::firstChild() const
|
| +WebFrame* WebFrameImpl::previousSibling() const
|
| {
|
| - if (!frame())
|
| - return 0;
|
| - return fromFrame(frame()->tree().firstChild());
|
| + return m_previousSibling;
|
| }
|
|
|
| -WebFrame* WebFrameImpl::lastChild() const
|
| +WebFrame* WebFrameImpl::nextSibling() const
|
| {
|
| - if (!frame())
|
| - return 0;
|
| - return fromFrame(frame()->tree().lastChild());
|
| + return m_nextSibling;
|
| }
|
|
|
| -WebFrame* WebFrameImpl::nextSibling() const
|
| +WebFrame* WebFrameImpl::firstChild() const
|
| {
|
| - if (!frame())
|
| - return 0;
|
| - return fromFrame(frame()->tree().nextSibling());
|
| + return m_firstChild;
|
| }
|
|
|
| -WebFrame* WebFrameImpl::previousSibling() const
|
| +WebFrame* WebFrameImpl::lastChild() const
|
| {
|
| - if (!frame())
|
| - return 0;
|
| - return fromFrame(frame()->tree().previousSibling());
|
| + return m_lastChild;
|
| }
|
|
|
| -WebFrame* WebFrameImpl::traverseNext(bool wrap) const
|
| +WebFrame* WebFrameImpl::traversePrevious(bool wrap) const
|
| {
|
| if (!frame())
|
| return 0;
|
| - return fromFrame(frame()->tree().traverseNextWithWrap(wrap));
|
| + return fromFrame(frame()->tree().traversePreviousWithWrap(wrap));
|
| }
|
|
|
| -WebFrame* WebFrameImpl::traversePrevious(bool wrap) const
|
| +WebFrame* WebFrameImpl::traverseNext(bool wrap) const
|
| {
|
| if (!frame())
|
| return 0;
|
| - return fromFrame(frame()->tree().traversePreviousWithWrap(wrap));
|
| + return fromFrame(frame()->tree().traverseNextWithWrap(wrap));
|
| }
|
|
|
| WebFrame* WebFrameImpl::findChildByName(const WebString& name) const
|
| @@ -2093,6 +2115,11 @@ WebFrameImpl* WebFrameImpl::create(WebFrameClient* client, long long embedderIde
|
|
|
| WebFrameImpl::WebFrameImpl(WebFrameClient* client, long long embedderIdentifier)
|
| : m_frameInit(WebFrameInit::create(this, embedderIdentifier))
|
| + , m_parent(0)
|
| + , m_previousSibling(0)
|
| + , m_nextSibling(0)
|
| + , m_firstChild(0)
|
| + , m_lastChild(0)
|
| , m_client(client)
|
| , m_permissionClient(0)
|
| , m_currentActiveMatchFrame(0)
|
| @@ -2151,8 +2178,7 @@ PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request
|
|
|
| childFrame->tree().setName(request.frameName());
|
|
|
| - frame()->tree().appendChild(childFrame);
|
| -
|
| + // FIXME: This comment is not quite accurate anymore.
|
| // Frame::init() can trigger onload event in the parent frame,
|
| // which may detach this frame and trigger a null-pointer access
|
| // in FrameTree::removeChild. Move init() after appendChild call
|
|
|