OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
3 * Copyright (C) 2006 Apple Computer, Inc. | 3 * Copyright (C) 2006 Apple Computer, Inc. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 * Library General Public License for more details. | 13 * Library General Public License for more details. |
14 * | 14 * |
15 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 * Boston, MA 02110-1301, USA. | 18 * Boston, MA 02110-1301, USA. |
19 */ | 19 */ |
20 | 20 |
21 #include "config.h" | 21 #include "config.h" |
22 #include "core/page/FrameTree.h" | 22 #include "core/page/FrameTree.h" |
23 | 23 |
24 #include "core/dom/Document.h" | 24 #include "core/dom/Document.h" |
25 #include "core/frame/Frame.h" | 25 #include "core/frame/Frame.h" |
26 #include "core/frame/FrameView.h" | 26 #include "core/frame/FrameView.h" |
| 27 #include "core/loader/FrameLoaderClient.h" |
27 #include "core/page/Page.h" | 28 #include "core/page/Page.h" |
28 #include "core/page/PageGroup.h" | 29 #include "core/page/PageGroup.h" |
29 #include "wtf/Vector.h" | 30 #include "wtf/Vector.h" |
30 #include "wtf/text/CString.h" | 31 #include "wtf/text/CString.h" |
31 #include "wtf/text/StringBuilder.h" | 32 #include "wtf/text/StringBuilder.h" |
32 | 33 |
33 using std::swap; | 34 using std::swap; |
34 | 35 |
35 namespace WebCore { | 36 namespace WebCore { |
36 | 37 |
| 38 namespace { |
| 39 |
| 40 const unsigned invalidChildCount = ~0; |
| 41 |
| 42 } // namespace |
| 43 |
| 44 FrameTree::FrameTree(Frame* thisFrame) |
| 45 : m_thisFrame(thisFrame) |
| 46 , m_scopedChildCount(invalidChildCount) |
| 47 { |
| 48 } |
| 49 |
37 FrameTree::~FrameTree() | 50 FrameTree::~FrameTree() |
38 { | 51 { |
| 52 // FIXME: Why is this here? Doesn't this parallel what we already do in ~Fra
me? |
39 for (Frame* child = firstChild(); child; child = child->tree().nextSibling()
) | 53 for (Frame* child = firstChild(); child; child = child->tree().nextSibling()
) |
40 child->setView(0); | 54 child->setView(0); |
41 } | 55 } |
42 | 56 |
43 void FrameTree::setName(const AtomicString& name) | 57 void FrameTree::setName(const AtomicString& name) |
44 { | 58 { |
45 m_name = name; | 59 m_name = name; |
46 if (!parent()) { | 60 if (!parent()) { |
47 m_uniqueName = name; | 61 m_uniqueName = name; |
48 return; | 62 return; |
49 } | 63 } |
50 m_uniqueName = AtomicString(); // Remove our old frame name so it's not cons
idered in uniqueChildName. | 64 m_uniqueName = AtomicString(); // Remove our old frame name so it's not cons
idered in uniqueChildName. |
51 m_uniqueName = parent()->tree().uniqueChildName(name); | 65 m_uniqueName = parent()->tree().uniqueChildName(name); |
52 } | 66 } |
53 | 67 |
54 Frame* FrameTree::parent() const | 68 Frame* FrameTree::parent() const |
55 { | 69 { |
56 return m_parent; | 70 if (!m_thisFrame->loader().client()) |
| 71 return 0; |
| 72 return m_thisFrame->loader().client()->parent(); |
57 } | 73 } |
58 | 74 |
59 void FrameTree::appendChild(PassRefPtr<Frame> child) | 75 Frame* FrameTree::top() const |
60 { | 76 { |
61 ASSERT(child->page() == m_thisFrame->page()); | 77 // FIXME: top() should never return null, so here are some hacks to deal |
62 child->tree().m_parent = m_thisFrame; | 78 // with EmptyFrameLoaderClient and cases where the frame is detached |
63 Frame* oldLast = m_lastChild; | 79 // already... |
64 m_lastChild = child.get(); | 80 if (!m_thisFrame->loader().client()) |
65 | 81 return m_thisFrame; |
66 if (oldLast) { | 82 Frame* candidate = m_thisFrame->loader().client()->top(); |
67 child->tree().m_previousSibling = oldLast; | 83 return candidate ? candidate : m_thisFrame; |
68 oldLast->tree().m_nextSibling = child; | |
69 } else | |
70 m_firstChild = child; | |
71 | |
72 m_scopedChildCount = invalidCount; | |
73 | |
74 ASSERT(!m_lastChild->tree().m_nextSibling); | |
75 } | 84 } |
76 | 85 |
77 void FrameTree::removeChild(Frame* child) | 86 Frame* FrameTree::previousSibling() const |
78 { | 87 { |
79 child->tree().m_parent = 0; | 88 if (!m_thisFrame->loader().client()) |
| 89 return 0; |
| 90 return m_thisFrame->loader().client()->previousSibling(); |
| 91 } |
80 | 92 |
81 // Slightly tricky way to prevent deleting the child until we are done with
it, w/o | 93 Frame* FrameTree::nextSibling() const |
82 // extra refs. These swaps leave the child in a circular list by itself. Cle
aring its | 94 { |
83 // previous and next will then finally deref it. | 95 if (!m_thisFrame->loader().client()) |
| 96 return 0; |
| 97 return m_thisFrame->loader().client()->nextSibling(); |
| 98 } |
84 | 99 |
85 RefPtr<Frame>& newLocationForNext = m_firstChild == child ? m_firstChild : c
hild->tree().m_previousSibling->tree().m_nextSibling; | 100 Frame* FrameTree::firstChild() const |
86 Frame*& newLocationForPrevious = m_lastChild == child ? m_lastChild : child-
>tree().m_nextSibling->tree().m_previousSibling; | 101 { |
87 swap(newLocationForNext, child->tree().m_nextSibling); | 102 if (!m_thisFrame->loader().client()) |
88 // For some inexplicable reason, the following line does not compile without
the explicit std:: namespace | 103 return 0; |
89 std::swap(newLocationForPrevious, child->tree().m_previousSibling); | 104 return m_thisFrame->loader().client()->firstChild(); |
| 105 } |
90 | 106 |
91 child->tree().m_previousSibling = 0; | 107 Frame* FrameTree::lastChild() const |
92 child->tree().m_nextSibling = 0; | 108 { |
93 | 109 if (!m_thisFrame->loader().client()) |
94 m_scopedChildCount = invalidCount; | 110 return 0; |
| 111 return m_thisFrame->loader().client()->lastChild(); |
95 } | 112 } |
96 | 113 |
97 AtomicString FrameTree::uniqueChildName(const AtomicString& requestedName) const | 114 AtomicString FrameTree::uniqueChildName(const AtomicString& requestedName) const |
98 { | 115 { |
99 if (!requestedName.isEmpty() && !child(requestedName) && requestedName != "_
blank") | 116 if (!requestedName.isEmpty() && !child(requestedName) && requestedName != "_
blank") |
100 return requestedName; | 117 return requestedName; |
101 | 118 |
102 // Create a repeatable name for a child about to be added to us. The name mu
st be | 119 // Create a repeatable name for a child about to be added to us. The name mu
st be |
103 // unique within the frame tree. The string we generate includes a "path" of
names | 120 // 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 s
iblings must | 121 // from the root frame down to us. For this path to be unique, each set of s
iblings must |
(...skipping 19 matching lines...) Expand all Loading... |
124 name.append(frame->tree().uniqueName().string().substring(framePathPrefi
xLength, | 141 name.append(frame->tree().uniqueName().string().substring(framePathPrefi
xLength, |
125 frame->tree().uniqueName().length() - framePathPrefixLength - frameP
athSuffixLength)); | 142 frame->tree().uniqueName().length() - framePathPrefixLength - frameP
athSuffixLength)); |
126 } | 143 } |
127 for (int i = chain.size() - 1; i >= 0; --i) { | 144 for (int i = chain.size() - 1; i >= 0; --i) { |
128 frame = chain[i]; | 145 frame = chain[i]; |
129 name.append('/'); | 146 name.append('/'); |
130 name.append(frame->tree().uniqueName()); | 147 name.append(frame->tree().uniqueName()); |
131 } | 148 } |
132 | 149 |
133 name.appendLiteral("/<!--frame"); | 150 name.appendLiteral("/<!--frame"); |
134 name.appendNumber(childCount()); | 151 name.appendNumber(childCount() - 1); |
135 name.appendLiteral("-->-->"); | 152 name.appendLiteral("-->-->"); |
136 | 153 |
137 return name.toAtomicString(); | 154 return name.toAtomicString(); |
138 } | 155 } |
139 | 156 |
140 Frame* FrameTree::scopedChild(unsigned index) const | 157 Frame* FrameTree::scopedChild(unsigned index) const |
141 { | 158 { |
142 TreeScope* scope = m_thisFrame->document(); | 159 TreeScope* scope = m_thisFrame->document(); |
143 if (!scope) | 160 if (!scope) |
144 return 0; | 161 return 0; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 for (Frame* result = firstChild(); result; result = result->tree().nextSibli
ng()) { | 193 for (Frame* result = firstChild(); result; result = result->tree().nextSibli
ng()) { |
177 if (result->inScope(scope)) | 194 if (result->inScope(scope)) |
178 scopedCount++; | 195 scopedCount++; |
179 } | 196 } |
180 | 197 |
181 return scopedCount; | 198 return scopedCount; |
182 } | 199 } |
183 | 200 |
184 unsigned FrameTree::scopedChildCount() const | 201 unsigned FrameTree::scopedChildCount() const |
185 { | 202 { |
186 if (m_scopedChildCount == invalidCount) | 203 if (m_scopedChildCount == invalidChildCount) |
187 m_scopedChildCount = scopedChildCount(m_thisFrame->document()); | 204 m_scopedChildCount = scopedChildCount(m_thisFrame->document()); |
188 return m_scopedChildCount; | 205 return m_scopedChildCount; |
189 } | 206 } |
190 | 207 |
| 208 void FrameTree::invalidateScopedChildCount() |
| 209 { |
| 210 m_scopedChildCount = invalidChildCount; |
| 211 } |
| 212 |
191 unsigned FrameTree::childCount() const | 213 unsigned FrameTree::childCount() const |
192 { | 214 { |
193 unsigned count = 0; | 215 unsigned count = 0; |
194 for (Frame* result = firstChild(); result; result = result->tree().nextSibli
ng()) | 216 for (Frame* result = firstChild(); result; result = result->tree().nextSibli
ng()) |
195 ++count; | 217 ++count; |
196 return count; | 218 return count; |
197 } | 219 } |
198 | 220 |
199 Frame* FrameTree::child(const AtomicString& name) const | 221 Frame* FrameTree::child(const AtomicString& name) const |
200 { | 222 { |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 | 351 |
330 Frame* FrameTree::deepLastChild() const | 352 Frame* FrameTree::deepLastChild() const |
331 { | 353 { |
332 Frame* result = m_thisFrame; | 354 Frame* result = m_thisFrame; |
333 for (Frame* last = lastChild(); last; last = last->tree().lastChild()) | 355 for (Frame* last = lastChild(); last; last = last->tree().lastChild()) |
334 result = last; | 356 result = last; |
335 | 357 |
336 return result; | 358 return result; |
337 } | 359 } |
338 | 360 |
339 Frame* FrameTree::top() const | |
340 { | |
341 Frame* frame = m_thisFrame; | |
342 for (Frame* parent = m_thisFrame; parent; parent = parent->tree().parent()) | |
343 frame = parent; | |
344 return frame; | |
345 } | |
346 | |
347 } // namespace WebCore | 361 } // namespace WebCore |
348 | 362 |
349 #ifndef NDEBUG | 363 #ifndef NDEBUG |
350 | 364 |
351 static void printIndent(int indent) | 365 static void printIndent(int indent) |
352 { | 366 { |
353 for (int i = 0; i < indent; ++i) | 367 for (int i = 0; i < indent; ++i) |
354 printf(" "); | 368 printf(" "); |
355 } | 369 } |
356 | 370 |
(...skipping 24 matching lines...) Expand all Loading... |
381 { | 395 { |
382 if (!frame) { | 396 if (!frame) { |
383 printf("Null input frame\n"); | 397 printf("Null input frame\n"); |
384 return; | 398 return; |
385 } | 399 } |
386 | 400 |
387 printFrames(frame->tree().top(), frame, 0); | 401 printFrames(frame->tree().top(), frame, 0); |
388 } | 402 } |
389 | 403 |
390 #endif | 404 #endif |
OLD | NEW |