diff options
Diffstat (limited to 'docshell/base/nsDocShellEnumerator.cpp')
-rw-r--r-- | docshell/base/nsDocShellEnumerator.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/docshell/base/nsDocShellEnumerator.cpp b/docshell/base/nsDocShellEnumerator.cpp new file mode 100644 index 0000000000..1f870cd01f --- /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; +} |