Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsDocShellEnumerator.h"
8 :
9 : #include "nsIDocShellTreeItem.h"
10 :
11 0 : nsDocShellEnumerator::nsDocShellEnumerator(int32_t aEnumerationDirection)
12 : : mRootItem(nullptr)
13 : , mCurIndex(0)
14 : , mDocShellType(nsIDocShellTreeItem::typeAll)
15 : , mArrayValid(false)
16 0 : , mEnumerationDirection(aEnumerationDirection)
17 : {
18 0 : }
19 :
20 0 : nsDocShellEnumerator::~nsDocShellEnumerator()
21 : {
22 0 : }
23 :
24 0 : NS_IMPL_ISUPPORTS(nsDocShellEnumerator, nsISimpleEnumerator)
25 :
26 : NS_IMETHODIMP
27 0 : nsDocShellEnumerator::GetNext(nsISupports** aResult)
28 : {
29 0 : NS_ENSURE_ARG_POINTER(aResult);
30 0 : *aResult = nullptr;
31 :
32 0 : nsresult rv = EnsureDocShellArray();
33 0 : if (NS_FAILED(rv)) {
34 0 : return rv;
35 : }
36 :
37 0 : if (mCurIndex >= mItemArray.Length()) {
38 0 : return NS_ERROR_FAILURE;
39 : }
40 :
41 : // post-increment is important here
42 0 : nsCOMPtr<nsISupports> item = do_QueryReferent(mItemArray[mCurIndex++], &rv);
43 0 : item.forget(aResult);
44 0 : return rv;
45 : }
46 :
47 : NS_IMETHODIMP
48 0 : nsDocShellEnumerator::HasMoreElements(bool* aResult)
49 : {
50 0 : NS_ENSURE_ARG_POINTER(aResult);
51 0 : *aResult = false;
52 :
53 0 : nsresult rv = EnsureDocShellArray();
54 0 : if (NS_FAILED(rv)) {
55 0 : return rv;
56 : }
57 :
58 0 : *aResult = (mCurIndex < mItemArray.Length());
59 0 : return NS_OK;
60 : }
61 :
62 : nsresult
63 0 : nsDocShellEnumerator::GetEnumerationRootItem(
64 : nsIDocShellTreeItem** aEnumerationRootItem)
65 : {
66 0 : NS_ENSURE_ARG_POINTER(aEnumerationRootItem);
67 0 : nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
68 0 : item.forget(aEnumerationRootItem);
69 0 : return NS_OK;
70 : }
71 :
72 : nsresult
73 0 : nsDocShellEnumerator::SetEnumerationRootItem(
74 : nsIDocShellTreeItem* aEnumerationRootItem)
75 : {
76 0 : mRootItem = do_GetWeakReference(aEnumerationRootItem);
77 0 : ClearState();
78 0 : return NS_OK;
79 : }
80 :
81 : nsresult
82 0 : nsDocShellEnumerator::GetEnumDocShellType(int32_t* aEnumerationItemType)
83 : {
84 0 : NS_ENSURE_ARG_POINTER(aEnumerationItemType);
85 0 : *aEnumerationItemType = mDocShellType;
86 0 : return NS_OK;
87 : }
88 :
89 : nsresult
90 0 : nsDocShellEnumerator::SetEnumDocShellType(int32_t aEnumerationItemType)
91 : {
92 0 : mDocShellType = aEnumerationItemType;
93 0 : ClearState();
94 0 : return NS_OK;
95 : }
96 :
97 : nsresult
98 0 : nsDocShellEnumerator::First()
99 : {
100 0 : mCurIndex = 0;
101 0 : return EnsureDocShellArray();
102 : }
103 :
104 : nsresult
105 0 : nsDocShellEnumerator::EnsureDocShellArray()
106 : {
107 0 : if (!mArrayValid) {
108 0 : mArrayValid = true;
109 0 : return BuildDocShellArray(mItemArray);
110 : }
111 :
112 0 : return NS_OK;
113 : }
114 :
115 : nsresult
116 0 : nsDocShellEnumerator::ClearState()
117 : {
118 0 : mItemArray.Clear();
119 0 : mArrayValid = false;
120 0 : mCurIndex = 0;
121 0 : return NS_OK;
122 : }
123 :
124 : nsresult
125 0 : nsDocShellEnumerator::BuildDocShellArray(nsTArray<nsWeakPtr>& aItemArray)
126 : {
127 0 : NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED);
128 0 : aItemArray.Clear();
129 0 : nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
130 0 : return BuildArrayRecursive(item, aItemArray);
131 : }
132 :
133 : nsresult
134 0 : nsDocShellForwardsEnumerator::BuildArrayRecursive(
135 : nsIDocShellTreeItem* aItem,
136 : nsTArray<nsWeakPtr>& aItemArray)
137 : {
138 : nsresult rv;
139 :
140 : // add this item to the array
141 0 : if (mDocShellType == nsIDocShellTreeItem::typeAll ||
142 0 : aItem->ItemType() == mDocShellType) {
143 0 : if (!aItemArray.AppendElement(do_GetWeakReference(aItem))) {
144 0 : return NS_ERROR_OUT_OF_MEMORY;
145 : }
146 : }
147 :
148 : int32_t numChildren;
149 0 : rv = aItem->GetChildCount(&numChildren);
150 0 : if (NS_FAILED(rv)) {
151 0 : return rv;
152 : }
153 :
154 0 : for (int32_t i = 0; i < numChildren; ++i) {
155 0 : nsCOMPtr<nsIDocShellTreeItem> curChild;
156 0 : rv = aItem->GetChildAt(i, getter_AddRefs(curChild));
157 0 : if (NS_FAILED(rv)) {
158 0 : return rv;
159 : }
160 :
161 0 : rv = BuildArrayRecursive(curChild, aItemArray);
162 0 : if (NS_FAILED(rv)) {
163 0 : return rv;
164 : }
165 : }
166 :
167 0 : return NS_OK;
168 : }
169 :
170 : nsresult
171 0 : nsDocShellBackwardsEnumerator::BuildArrayRecursive(
172 : nsIDocShellTreeItem* aItem,
173 : nsTArray<nsWeakPtr>& aItemArray)
174 : {
175 : nsresult rv;
176 :
177 : int32_t numChildren;
178 0 : rv = aItem->GetChildCount(&numChildren);
179 0 : if (NS_FAILED(rv)) {
180 0 : return rv;
181 : }
182 :
183 0 : for (int32_t i = numChildren - 1; i >= 0; --i) {
184 0 : nsCOMPtr<nsIDocShellTreeItem> curChild;
185 0 : rv = aItem->GetChildAt(i, getter_AddRefs(curChild));
186 0 : if (NS_FAILED(rv)) {
187 0 : return rv;
188 : }
189 :
190 0 : rv = BuildArrayRecursive(curChild, aItemArray);
191 0 : if (NS_FAILED(rv)) {
192 0 : return rv;
193 : }
194 : }
195 :
196 : // add this item to the array
197 0 : if (mDocShellType == nsIDocShellTreeItem::typeAll ||
198 0 : aItem->ItemType() == mDocShellType) {
199 0 : if (!aItemArray.AppendElement(do_GetWeakReference(aItem))) {
200 0 : return NS_ERROR_OUT_OF_MEMORY;
201 : }
202 : }
203 :
204 0 : return NS_OK;
205 : }
|