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 15 namespace blink { 16 17 WebCore::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 27 void 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 57 WebFrame* WebFrame::opener() const 58 { 59 return m_opener; 60 } 61 62 void 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 71 void 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 89 void 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 108 WebFrame* WebFrame::parent() const 109 { 110 return m_parent; 111 } 112 113 WebFrame* 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 121 WebFrame* WebFrame::firstChild() const 122 { 123 return m_firstChild; 124 } 125 126 WebFrame* WebFrame::lastChild() const 127 { 128 return m_lastChild; 129 } 130 131 WebFrame* WebFrame::previousSibling() const 132 { 133 return m_previousSibling; 134 } 135 136 WebFrame* WebFrame::nextSibling() const 137 { 138 return m_nextSibling; 139 } 140 141 WebFrame* 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 149 WebFrame* 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 157 WebFrame* 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 167 WebFrame* 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 177 WebFrame::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 188 WebFrame::~WebFrame() 189 { 190 m_openedFrameTracker.reset(0); 191 } 192 193 } // namespace blink 194