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
toWebCoreFrame(const WebFrame * frame)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
swap(WebFrame * frame)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
opener() const57 WebFrame* WebFrame::opener() const
58 {
59 return m_opener;
60 }
61
setOpener(WebFrame * opener)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
appendChild(WebFrame * child)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
removeChild(WebFrame * child)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
parent() const108 WebFrame* WebFrame::parent() const
109 {
110 return m_parent;
111 }
112
top() const113 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
firstChild() const121 WebFrame* WebFrame::firstChild() const
122 {
123 return m_firstChild;
124 }
125
lastChild() const126 WebFrame* WebFrame::lastChild() const
127 {
128 return m_lastChild;
129 }
130
previousSibling() const131 WebFrame* WebFrame::previousSibling() const
132 {
133 return m_previousSibling;
134 }
135
nextSibling() const136 WebFrame* WebFrame::nextSibling() const
137 {
138 return m_nextSibling;
139 }
140
traversePrevious(bool wrap) const141 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
traverseNext(bool wrap) const149 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
findChildByName(const WebString & name) const157 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
fromFrame(WebCore::Frame * frame)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
WebFrame()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
~WebFrame()188 WebFrame::~WebFrame()
189 {
190 m_openedFrameTracker.reset(0);
191 }
192
193 } // namespace blink
194