15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Apple Computer, Inc.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/FrameTree.h"
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
25d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/frame/FrameClient.h"
261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/frame/FrameView.h"
27d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/LocalFrame.h"
285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/frame/RemoteFrame.h"
295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/frame/RemoteFrameView.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Page.h"
31591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/Vector.h"
32591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/text/CString.h"
33591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/text/StringBuilder.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using std::swap;
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
37c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)namespace {
4009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
41197021e6b966cfb06891637935ef33fff06433d1Ben Murdochconst unsigned invalidChildCount = ~0U;
4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} // namespace
4409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
45d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)FrameTree::FrameTree(Frame* thisFrame)
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    : m_thisFrame(thisFrame)
4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_scopedChildCount(invalidChildCount)
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FrameTree::~FrameTree()
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#if !ENABLE(OILPAN)
54d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // FIXME: Why is this here? Doesn't this parallel what we already do in ~LocalFrame?
555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* child = firstChild(); child; child = child->tree().nextSibling()) {
565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (child->isLocalFrame())
575d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            toLocalFrame(child)->setView(nullptr);
585d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        else if (child->isRemoteFrame())
595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            toRemoteFrame(child)->setView(nullptr);
605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#endif
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
64a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid FrameTree::setName(const AtomicString& name, const AtomicString& fallbackName)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_name = name;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!parent()) {
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_uniqueName = name;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_uniqueName = AtomicString(); // Remove our old frame name so it's not considered in uniqueChildName.
72a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    m_uniqueName = parent()->tree().uniqueChildName(name.isEmpty() ? fallbackName : name);
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::parent() const
7602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
77d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!m_thisFrame->client())
7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return 0;
795d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return m_thisFrame->client()->parent();
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::top() const
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: top() should never return null, so here are some hacks to deal
8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // with EmptyFrameLoaderClient and cases where the frame is detached
8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // already...
87d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!m_thisFrame->client())
885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return m_thisFrame;
895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Frame* candidate = m_thisFrame->client()->top();
907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return candidate ? candidate : m_thisFrame.get();
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::previousSibling() const
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
95d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!m_thisFrame->client())
9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return 0;
975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return m_thisFrame->client()->previousSibling();
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::nextSibling() const
10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
102d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!m_thisFrame->client())
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return 0;
1045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return m_thisFrame->client()->nextSibling();
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::firstChild() const
10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
109d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!m_thisFrame->client())
11009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return 0;
1115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return m_thisFrame->client()->firstChild();
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::lastChild() const
11509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
116d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!m_thisFrame->client())
11709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return 0;
1185d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return m_thisFrame->client()->lastChild();
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochbool FrameTree::uniqueNameExists(const AtomicString& name) const
12207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch{
1235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* frame = top(); frame; frame = frame->tree().traverseNext()) {
12407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (frame->tree().uniqueName() == name)
12507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
12607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
12707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    return false;
12807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
12907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)AtomicString FrameTree::uniqueChildName(const AtomicString& requestedName) const
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!requestedName.isEmpty() && !uniqueNameExists(requestedName) && requestedName != "_blank")
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return requestedName;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Create a repeatable name for a child about to be added to us. The name must be
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // unique within the frame tree. The string we generate includes a "path" of names
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // from the root frame down to us. For this path to be unique, each set of siblings must
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // contribute a unique name to the path, which can't collide with any HTML-assigned names.
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We generate this path component by index in the child list along with an unlikely
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // frame name that can't be set in HTML because it collides with comment syntax.
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const char framePathPrefix[] = "<!--framePath ";
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const int framePathPrefixLength = 14;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const int framePathSuffixLength = 3;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Find the nearest parent that has a frame with a path in it.
1475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Vector<Frame*, 16> chain;
1485d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Frame* frame;
1495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (frame = m_thisFrame; frame; frame = frame->tree().parent()) {
150f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        if (frame->tree().uniqueName().startsWith(framePathPrefix))
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        chain.append(frame);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuilder name;
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    name.append(framePathPrefix);
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (frame) {
157f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        name.append(frame->tree().uniqueName().string().substring(framePathPrefixLength,
158f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)            frame->tree().uniqueName().length() - framePathPrefixLength - framePathSuffixLength));
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = chain.size() - 1; i >= 0; --i) {
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        frame = chain[i];
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        name.append('/');
163f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        name.append(frame->tree().uniqueName());
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    name.appendLiteral("/<!--frame");
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    name.appendNumber(childCount() - 1);
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    name.appendLiteral("-->-->");
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return name.toAtomicString();
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::scopedChild(unsigned index) const
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (!m_thisFrame->isLocalFrame())
1765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return 0;
177d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    TreeScope* scope = toLocalFrame(m_thisFrame)->document();
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!scope)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned scopedIndex = 0;
1825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* result = firstChild(); result; result = result->tree().nextSibling()) {
1835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (result->isLocalFrame() && toLocalFrame(result)->inScope(scope)) {
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (scopedIndex == index)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return result;
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            scopedIndex++;
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::scopedChild(const AtomicString& name) const
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (!m_thisFrame->isLocalFrame())
1965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return 0;
1975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
198d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    TreeScope* scope = toLocalFrame(m_thisFrame)->document();
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!scope)
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* child = firstChild(); child; child = child->tree().nextSibling())
2035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (child->tree().name() == name && child->isLocalFrame() && toLocalFrame(child)->inScope(scope))
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return child;
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned FrameTree::scopedChildCount(TreeScope* scope) const
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!scope)
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned scopedCount = 0;
2145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* result = firstChild(); result; result = result->tree().nextSibling()) {
2155d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (result->isLocalFrame() && toLocalFrame(result)->inScope(scope))
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            scopedCount++;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return scopedCount;
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned FrameTree::scopedChildCount() const
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
22409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_scopedChildCount == invalidChildCount)
225d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        m_scopedChildCount = scopedChildCount(toLocalFrame(m_thisFrame)->document());
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_scopedChildCount;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
22909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void FrameTree::invalidateScopedChildCount()
23009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
23109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_scopedChildCount = invalidChildCount;
23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned FrameTree::childCount() const
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned count = 0;
2375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* result = firstChild(); result; result = result->tree().nextSibling())
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++count;
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return count;
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2425d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::child(const AtomicString& name) const
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* child = firstChild(); child; child = child->tree().nextSibling())
24507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (child->tree().name() == name)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return child;
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::find(const AtomicString& name) const
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (name == "_self" || name == "_current" || name.isEmpty())
2535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return m_thisFrame;
25402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (name == "_top")
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return top();
25702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (name == "_parent")
2597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return parent() ? parent() : m_thisFrame.get();
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Since "_blank" should never be any frame's name, the following just amounts to an optimization.
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (name == "_blank")
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Search subtree starting with this frame first.
2665d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* frame = m_thisFrame; frame; frame = frame->tree().traverseNext(m_thisFrame))
26707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (frame->tree().name() == name)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return frame;
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Search the entire tree for this page next.
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Page* page = m_thisFrame->page();
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The frame could have been detached from the page, so check it.
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!page)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext())
27807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (frame->tree().name() == name)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return frame;
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Search the entire tree of each of the other pages in this namespace.
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Is random order OK?
283d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const HashSet<Page*>& pages = Page::ordinaryPages();
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HashSet<Page*>::const_iterator end = pages.end();
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) {
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Page* otherPage = *it;
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (otherPage != page) {
2885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree().traverseNext()) {
28907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                if (frame->tree().name() == name)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return frame;
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool FrameTree::isDescendantOf(const Frame* ancestor) const
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!ancestor)
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_thisFrame->page() != ancestor->page())
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* frame = m_thisFrame; frame; frame = frame->tree().parent())
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (frame == ancestor)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::traverseNext(const Frame* stayWithin) const
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Frame* child = firstChild();
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child) {
316f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        ASSERT(!stayWithin || child->tree().isDescendantOf(stayWithin));
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return child;
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_thisFrame == stayWithin)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Frame* sibling = nextSibling();
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (sibling) {
325f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        ASSERT(!stayWithin || sibling->tree().isDescendantOf(stayWithin));
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return sibling;
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Frame* frame = m_thisFrame;
330f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    while (!sibling && (!stayWithin || frame->tree().parent() != stayWithin)) {
331f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        frame = frame->tree().parent();
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!frame)
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
334f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        sibling = frame->tree().nextSibling();
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (frame) {
338f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        ASSERT(!stayWithin || !sibling || sibling->tree().isDescendantOf(stayWithin));
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return sibling;
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::traverseNextWithWrap(bool wrap) const
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (Frame* result = traverseNext())
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (wrap)
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_thisFrame->page()->mainFrame();
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::traversePreviousWithWrap(bool wrap) const
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: besides the wrap feature, this is just the traversePreviousNode algorithm
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (Frame* prevSibling = previousSibling())
361f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        return prevSibling->tree().deepLastChild();
3625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (Frame* parentFrame = parent())
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return parentFrame;
36402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // no siblings, no parent, self==top
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (wrap)
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return deepLastChild();
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // top view is always the last one in this ordering, so prev is nil without wrap
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)Frame* FrameTree::deepLastChild() const
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Frame* result = m_thisFrame;
3765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Frame* last = lastChild(); last; last = last->tree().lastChild())
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = last;
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid FrameTree::trace(Visitor* visitor)
3837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
3847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    visitor->trace(m_thisFrame);
3857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
3867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
387c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void printIndent(int indent)
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 0; i < indent; ++i)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printf("    ");
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
397c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static void printFrames(const blink::Frame* frame, const blink::Frame* targetFrame, int indent)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (frame == targetFrame) {
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printf("--> ");
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printIndent(indent - 1);
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printIndent(indent);
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
405c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    blink::FrameView* view = frame->isLocalFrame() ? toLocalFrame(frame)->view() : 0;
4065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    printf("Frame %p %dx%d\n", frame, view ? view->width() : 0, view ? view->height() : 0);
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printIndent(indent);
408f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    printf("  owner=%p\n", frame->owner());
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printIndent(indent);
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("  frameView=%p\n", view);
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printIndent(indent);
4125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    printf("  document=%p\n", frame->isLocalFrame() ? toLocalFrame(frame)->document() : 0);
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printIndent(indent);
4145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    printf("  uri=%s\n\n", frame->isLocalFrame() ? toLocalFrame(frame)->document()->url().string().utf8().data() : 0);
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
416c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    for (blink::Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling())
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printFrames(child, targetFrame, indent + 1);
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
420c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void showFrameTree(const blink::Frame* frame)
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!frame) {
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printf("Null input frame\n");
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
427f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    printFrames(frame->tree().top(), frame, 0);
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
431