2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3 * Copyright (C) 2006 Apple Computer, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #include "core/page/FrameTree.h"
24 #include "core/dom/Document.h"
25 #include "core/frame/Frame.h"
26 #include "core/frame/FrameView.h"
27 #include "core/page/Page.h"
28 #include "core/page/PageGroup.h"
29 #include "wtf/Vector.h"
30 #include "wtf/text/CString.h"
31 #include "wtf/text/StringBuilder.h"
37 FrameTree::~FrameTree()
39 for (Frame* child = firstChild(); child; child = child->tree().nextSibling())
43 void FrameTree::setName(const AtomicString& name)
50 m_uniqueName = AtomicString(); // Remove our old frame name so it's not considered in uniqueChildName.
51 m_uniqueName = parent()->tree().uniqueChildName(name);
54 Frame* FrameTree::parent() const
59 void FrameTree::appendChild(PassRefPtr<Frame> child)
61 ASSERT(child->page() == m_thisFrame->page());
62 child->tree().m_parent = m_thisFrame;
63 Frame* oldLast = m_lastChild;
64 m_lastChild = child.get();
67 child->tree().m_previousSibling = oldLast;
68 oldLast->tree().m_nextSibling = child;
72 m_scopedChildCount = invalidCount;
74 ASSERT(!m_lastChild->tree().m_nextSibling);
77 void FrameTree::removeChild(Frame* child)
79 child->tree().m_parent = 0;
81 // Slightly tricky way to prevent deleting the child until we are done with it, w/o
82 // extra refs. These swaps leave the child in a circular list by itself. Clearing its
83 // previous and next will then finally deref it.
85 RefPtr<Frame>& newLocationForNext = m_firstChild == child ? m_firstChild : child->tree().m_previousSibling->tree().m_nextSibling;
86 Frame*& newLocationForPrevious = m_lastChild == child ? m_lastChild : child->tree().m_nextSibling->tree().m_previousSibling;
87 swap(newLocationForNext, child->tree().m_nextSibling);
88 // For some inexplicable reason, the following line does not compile without the explicit std:: namespace
89 std::swap(newLocationForPrevious, child->tree().m_previousSibling);
91 child->tree().m_previousSibling = 0;
92 child->tree().m_nextSibling = 0;
94 m_scopedChildCount = invalidCount;
97 AtomicString FrameTree::uniqueChildName(const AtomicString& requestedName) const
99 if (!requestedName.isEmpty() && !child(requestedName) && requestedName != "_blank")
100 return requestedName;
102 // Create a repeatable name for a child about to be added to us. The name must be
103 // unique within the frame tree. The string we generate includes a "path" of names
104 // from the root frame down to us. For this path to be unique, each set of siblings must
105 // contribute a unique name to the path, which can't collide with any HTML-assigned names.
106 // We generate this path component by index in the child list along with an unlikely
107 // frame name that can't be set in HTML because it collides with comment syntax.
109 const char framePathPrefix[] = "<!--framePath ";
110 const int framePathPrefixLength = 14;
111 const int framePathSuffixLength = 3;
113 // Find the nearest parent that has a frame with a path in it.
114 Vector<Frame*, 16> chain;
116 for (frame = m_thisFrame; frame; frame = frame->tree().parent()) {
117 if (frame->tree().uniqueName().startsWith(framePathPrefix))
122 name.append(framePathPrefix);
124 name.append(frame->tree().uniqueName().string().substring(framePathPrefixLength,
125 frame->tree().uniqueName().length() - framePathPrefixLength - framePathSuffixLength));
127 for (int i = chain.size() - 1; i >= 0; --i) {
130 name.append(frame->tree().uniqueName());
133 name.appendLiteral("/<!--frame");
134 name.appendNumber(childCount());
135 name.appendLiteral("-->-->");
137 return name.toAtomicString();
140 Frame* FrameTree::scopedChild(unsigned index) const
142 TreeScope* scope = m_thisFrame->document();
146 unsigned scopedIndex = 0;
147 for (Frame* result = firstChild(); result; result = result->tree().nextSibling()) {
148 if (result->inScope(scope)) {
149 if (scopedIndex == index)
158 Frame* FrameTree::scopedChild(const AtomicString& name) const
160 TreeScope* scope = m_thisFrame->document();
164 for (Frame* child = firstChild(); child; child = child->tree().nextSibling())
165 if (child->tree().uniqueName() == name && child->inScope(scope))
170 inline unsigned FrameTree::scopedChildCount(TreeScope* scope) const
175 unsigned scopedCount = 0;
176 for (Frame* result = firstChild(); result; result = result->tree().nextSibling()) {
177 if (result->inScope(scope))
184 unsigned FrameTree::scopedChildCount() const
186 if (m_scopedChildCount == invalidCount)
187 m_scopedChildCount = scopedChildCount(m_thisFrame->document());
188 return m_scopedChildCount;
191 unsigned FrameTree::childCount() const
194 for (Frame* result = firstChild(); result; result = result->tree().nextSibling())
199 Frame* FrameTree::child(const AtomicString& name) const
201 for (Frame* child = firstChild(); child; child = child->tree().nextSibling())
202 if (child->tree().uniqueName() == name)
207 Frame* FrameTree::find(const AtomicString& name) const
209 if (name == "_self" || name == "_current" || name.isEmpty())
215 if (name == "_parent")
216 return parent() ? parent() : m_thisFrame;
218 // Since "_blank" should never be any frame's name, the following just amounts to an optimization.
219 if (name == "_blank")
222 // Search subtree starting with this frame first.
223 for (Frame* frame = m_thisFrame; frame; frame = frame->tree().traverseNext(m_thisFrame))
224 if (frame->tree().uniqueName() == name)
227 // Search the entire tree for this page next.
228 Page* page = m_thisFrame->page();
230 // The frame could have been detached from the page, so check it.
234 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext())
235 if (frame->tree().uniqueName() == name)
238 // Search the entire tree of each of the other pages in this namespace.
239 // FIXME: Is random order OK?
240 const HashSet<Page*>& pages = page->group().pages();
241 HashSet<Page*>::const_iterator end = pages.end();
242 for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) {
243 Page* otherPage = *it;
244 if (otherPage != page) {
245 for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree().traverseNext()) {
246 if (frame->tree().uniqueName() == name)
255 bool FrameTree::isDescendantOf(const Frame* ancestor) const
260 if (m_thisFrame->page() != ancestor->page())
263 for (Frame* frame = m_thisFrame; frame; frame = frame->tree().parent())
264 if (frame == ancestor)
269 Frame* FrameTree::traverseNext(const Frame* stayWithin) const
271 Frame* child = firstChild();
273 ASSERT(!stayWithin || child->tree().isDescendantOf(stayWithin));
277 if (m_thisFrame == stayWithin)
280 Frame* sibling = nextSibling();
282 ASSERT(!stayWithin || sibling->tree().isDescendantOf(stayWithin));
286 Frame* frame = m_thisFrame;
287 while (!sibling && (!stayWithin || frame->tree().parent() != stayWithin)) {
288 frame = frame->tree().parent();
291 sibling = frame->tree().nextSibling();
295 ASSERT(!stayWithin || !sibling || sibling->tree().isDescendantOf(stayWithin));
302 Frame* FrameTree::traverseNextWithWrap(bool wrap) const
304 if (Frame* result = traverseNext())
308 return m_thisFrame->page()->mainFrame();
313 Frame* FrameTree::traversePreviousWithWrap(bool wrap) const
315 // FIXME: besides the wrap feature, this is just the traversePreviousNode algorithm
317 if (Frame* prevSibling = previousSibling())
318 return prevSibling->tree().deepLastChild();
319 if (Frame* parentFrame = parent())
322 // no siblings, no parent, self==top
324 return deepLastChild();
326 // top view is always the last one in this ordering, so prev is nil without wrap
330 Frame* FrameTree::deepLastChild() const
332 Frame* result = m_thisFrame;
333 for (Frame* last = lastChild(); last; last = last->tree().lastChild())
339 Frame* FrameTree::top() const
341 Frame* frame = m_thisFrame;
342 for (Frame* parent = m_thisFrame; parent; parent = parent->tree().parent())
347 } // namespace WebCore
351 static void printIndent(int indent)
353 for (int i = 0; i < indent; ++i)
357 static void printFrames(const WebCore::Frame* frame, const WebCore::Frame* targetFrame, int indent)
359 if (frame == targetFrame) {
361 printIndent(indent - 1);
365 WebCore::FrameView* view = frame->view();
366 printf("Frame %p %dx%d\n", frame, view ? view->width() : 0, view ? view->height() : 0);
368 printf(" ownerElement=%p\n", frame->ownerElement());
370 printf(" frameView=%p\n", view);
372 printf(" document=%p\n", frame->document());
374 printf(" uri=%s\n\n", frame->document()->documentURI().utf8().data());
376 for (WebCore::Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling())
377 printFrames(child, targetFrame, indent + 1);
380 void showFrameTree(const WebCore::Frame* frame)
383 printf("Null input frame\n");
387 printFrames(frame->tree().top(), frame, 0);