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. 4 5#include "config.h" 6#include "public/web/WebFrame.h" 7 8#include "core/frame/RemoteFrame.h" 9#include "web/OpenedFrameTracker.h" 10#include "web/WebLocalFrameImpl.h" 11#include "web/WebRemoteFrameImpl.h" 12#include <algorithm> 13 14 15namespace blink { 16 17WebCore::Frame* toWebCoreFrame(const WebFrame* frame) 18{ 19 if (!frame) 20 return 0; 21 22 return frame->isWebLocalFrame() 23 ? static_cast<WebCore::Frame*>(toWebLocalFrameImpl(frame)->frame()) 24 : toWebRemoteFrameImpl(frame)->frame(); 25} 26 27void WebFrame::swap(WebFrame* frame) 28{ 29 using std::swap; 30 31 if (m_parent) { 32 if (m_parent->m_firstChild == this) 33 m_parent->m_firstChild = frame; 34 if (m_parent->m_lastChild == this) 35 m_parent->m_lastChild = frame; 36 swap(m_parent, frame->m_parent); 37 } 38 if (m_previousSibling) { 39 m_previousSibling->m_nextSibling = frame; 40 swap(m_previousSibling, frame->m_previousSibling); 41 } 42 if (m_nextSibling) { 43 m_nextSibling->m_previousSibling = frame; 44 swap(m_nextSibling, frame->m_nextSibling); 45 } 46 if (m_opener) { 47 m_opener->m_openedFrameTracker->remove(this); 48 m_opener->m_openedFrameTracker->add(frame); 49 swap(m_opener, frame->m_opener); 50 } 51 if (!m_openedFrameTracker->isEmpty()) { 52 m_openedFrameTracker->updateOpener(frame); 53 frame->m_openedFrameTracker.reset(m_openedFrameTracker.release()); 54 } 55} 56 57WebFrame* WebFrame::opener() const 58{ 59 return m_opener; 60} 61 62void WebFrame::setOpener(WebFrame* opener) 63{ 64 if (m_opener) 65 m_opener->m_openedFrameTracker->remove(this); 66 if (opener) 67 opener->m_openedFrameTracker->add(this); 68 m_opener = opener; 69} 70 71void WebFrame::appendChild(WebFrame* child) 72{ 73 // FIXME: Original code asserts that the frames have the same Page. We 74 // should add an equivalent check... figure out what. 75 child->m_parent = this; 76 WebFrame* oldLast = m_lastChild; 77 m_lastChild = child; 78 79 if (oldLast) { 80 child->m_previousSibling = oldLast; 81 oldLast->m_nextSibling = child; 82 } else { 83 m_firstChild = child; 84 } 85 86 toWebCoreFrame(this)->tree().invalidateScopedChildCount(); 87} 88 89void WebFrame::removeChild(WebFrame* child) 90{ 91 child->m_parent = 0; 92 93 if (m_firstChild == child) 94 m_firstChild = child->m_nextSibling; 95 else 96 child->m_previousSibling->m_nextSibling = child->m_nextSibling; 97 98 if (m_lastChild == child) 99 m_lastChild = child->m_previousSibling; 100 else 101 child->m_nextSibling->m_previousSibling = child->m_previousSibling; 102 103 child->m_previousSibling = child->m_nextSibling = 0; 104 105 toWebCoreFrame(this)->tree().invalidateScopedChildCount(); 106} 107 108WebFrame* WebFrame::parent() const 109{ 110 return m_parent; 111} 112 113WebFrame* WebFrame::top() const 114{ 115 WebFrame* frame = const_cast<WebFrame*>(this); 116 for (WebFrame* parent = frame; parent; parent = parent->m_parent) 117 frame = parent; 118 return frame; 119} 120 121WebFrame* WebFrame::firstChild() const 122{ 123 return m_firstChild; 124} 125 126WebFrame* WebFrame::lastChild() const 127{ 128 return m_lastChild; 129} 130 131WebFrame* WebFrame::previousSibling() const 132{ 133 return m_previousSibling; 134} 135 136WebFrame* WebFrame::nextSibling() const 137{ 138 return m_nextSibling; 139} 140 141WebFrame* WebFrame::traversePrevious(bool wrap) const 142{ 143 WebCore::Frame* frame = toWebCoreFrame(this); 144 if (!frame) 145 return 0; 146 return fromFrame(frame->tree().traversePreviousWithWrap(wrap)); 147} 148 149WebFrame* WebFrame::traverseNext(bool wrap) const 150{ 151 WebCore::Frame* frame = toWebCoreFrame(this); 152 if (!frame) 153 return 0; 154 return fromFrame(frame->tree().traverseNextWithWrap(wrap)); 155} 156 157WebFrame* WebFrame::findChildByName(const WebString& name) const 158{ 159 WebCore::Frame* frame = toWebCoreFrame(this); 160 if (!frame) 161 return 0; 162 // FIXME: It's not clear this should ever be called to find a remote frame. 163 // Perhaps just disallow that completely? 164 return fromFrame(frame->tree().child(name)); 165} 166 167WebFrame* WebFrame::fromFrame(WebCore::Frame* frame) 168{ 169 if (!frame) 170 return 0; 171 172 if (frame->isLocalFrame()) 173 return WebLocalFrameImpl::fromFrame(toLocalFrame(*frame)); 174 return WebRemoteFrameImpl::fromFrame(toRemoteFrame(*frame)); 175} 176 177WebFrame::WebFrame() 178 : m_parent(0) 179 , m_previousSibling(0) 180 , m_nextSibling(0) 181 , m_firstChild(0) 182 , m_lastChild(0) 183 , m_opener(0) 184 , m_openedFrameTracker(new OpenedFrameTracker) 185{ 186} 187 188WebFrame::~WebFrame() 189{ 190 m_openedFrameTracker.reset(0); 191} 192 193} // namespace blink 194