summaryrefslogtreecommitdiffstats
path: root/docshell/base/nsDocShellEnumerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docshell/base/nsDocShellEnumerator.cpp')
-rw-r--r--docshell/base/nsDocShellEnumerator.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/docshell/base/nsDocShellEnumerator.cpp b/docshell/base/nsDocShellEnumerator.cpp
new file mode 100644
index 000000000..1f870cd01
--- /dev/null
+++ b/docshell/base/nsDocShellEnumerator.cpp
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsDocShellEnumerator.h"
+
+#include "nsIDocShellTreeItem.h"
+
+nsDocShellEnumerator::nsDocShellEnumerator(int32_t aEnumerationDirection)
+ : mRootItem(nullptr)
+ , mCurIndex(0)
+ , mDocShellType(nsIDocShellTreeItem::typeAll)
+ , mArrayValid(false)
+ , mEnumerationDirection(aEnumerationDirection)
+{
+}
+
+nsDocShellEnumerator::~nsDocShellEnumerator()
+{
+}
+
+NS_IMPL_ISUPPORTS(nsDocShellEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsDocShellEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = nullptr;
+
+ nsresult rv = EnsureDocShellArray();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (mCurIndex >= mItemArray.Length()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // post-increment is important here
+ nsCOMPtr<nsISupports> item = do_QueryReferent(mItemArray[mCurIndex++], &rv);
+ item.forget(aResult);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDocShellEnumerator::HasMoreElements(bool* aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = false;
+
+ nsresult rv = EnsureDocShellArray();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ *aResult = (mCurIndex < mItemArray.Length());
+ return NS_OK;
+}
+
+nsresult
+nsDocShellEnumerator::GetEnumerationRootItem(
+ nsIDocShellTreeItem** aEnumerationRootItem)
+{
+ NS_ENSURE_ARG_POINTER(aEnumerationRootItem);
+ nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
+ item.forget(aEnumerationRootItem);
+ return NS_OK;
+}
+
+nsresult
+nsDocShellEnumerator::SetEnumerationRootItem(
+ nsIDocShellTreeItem* aEnumerationRootItem)
+{
+ mRootItem = do_GetWeakReference(aEnumerationRootItem);
+ ClearState();
+ return NS_OK;
+}
+
+nsresult
+nsDocShellEnumerator::GetEnumDocShellType(int32_t* aEnumerationItemType)
+{
+ NS_ENSURE_ARG_POINTER(aEnumerationItemType);
+ *aEnumerationItemType = mDocShellType;
+ return NS_OK;
+}
+
+nsresult
+nsDocShellEnumerator::SetEnumDocShellType(int32_t aEnumerationItemType)
+{
+ mDocShellType = aEnumerationItemType;
+ ClearState();
+ return NS_OK;
+}
+
+nsresult
+nsDocShellEnumerator::First()
+{
+ mCurIndex = 0;
+ return EnsureDocShellArray();
+}
+
+nsresult
+nsDocShellEnumerator::EnsureDocShellArray()
+{
+ if (!mArrayValid) {
+ mArrayValid = true;
+ return BuildDocShellArray(mItemArray);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsDocShellEnumerator::ClearState()
+{
+ mItemArray.Clear();
+ mArrayValid = false;
+ mCurIndex = 0;
+ return NS_OK;
+}
+
+nsresult
+nsDocShellEnumerator::BuildDocShellArray(nsTArray<nsWeakPtr>& aItemArray)
+{
+ NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED);
+ aItemArray.Clear();
+ nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
+ return BuildArrayRecursive(item, aItemArray);
+}
+
+nsresult
+nsDocShellForwardsEnumerator::BuildArrayRecursive(
+ nsIDocShellTreeItem* aItem,
+ nsTArray<nsWeakPtr>& aItemArray)
+{
+ nsresult rv;
+
+ // add this item to the array
+ if (mDocShellType == nsIDocShellTreeItem::typeAll ||
+ aItem->ItemType() == mDocShellType) {
+ if (!aItemArray.AppendElement(do_GetWeakReference(aItem))) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ int32_t numChildren;
+ rv = aItem->GetChildCount(&numChildren);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ for (int32_t i = 0; i < numChildren; ++i) {
+ nsCOMPtr<nsIDocShellTreeItem> curChild;
+ rv = aItem->GetChildAt(i, getter_AddRefs(curChild));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = BuildArrayRecursive(curChild, aItemArray);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsDocShellBackwardsEnumerator::BuildArrayRecursive(
+ nsIDocShellTreeItem* aItem,
+ nsTArray<nsWeakPtr>& aItemArray)
+{
+ nsresult rv;
+
+ int32_t numChildren;
+ rv = aItem->GetChildCount(&numChildren);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ for (int32_t i = numChildren - 1; i >= 0; --i) {
+ nsCOMPtr<nsIDocShellTreeItem> curChild;
+ rv = aItem->GetChildAt(i, getter_AddRefs(curChild));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = BuildArrayRecursive(curChild, aItemArray);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+
+ // add this item to the array
+ if (mDocShellType == nsIDocShellTreeItem::typeAll ||
+ aItem->ItemType() == mDocShellType) {
+ if (!aItemArray.AppendElement(do_GetWeakReference(aItem))) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ return NS_OK;
+}