michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #include "nsDocShellEnumerator.h" michael@0: michael@0: #include "nsIDocShellTreeItem.h" michael@0: michael@0: nsDocShellEnumerator::nsDocShellEnumerator(int32_t inEnumerationDirection) michael@0: : mRootItem(nullptr) michael@0: , mCurIndex(0) michael@0: , mDocShellType(nsIDocShellTreeItem::typeAll) michael@0: , mArrayValid(false) michael@0: , mEnumerationDirection(inEnumerationDirection) michael@0: { michael@0: } michael@0: michael@0: nsDocShellEnumerator::~nsDocShellEnumerator() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsDocShellEnumerator, nsISimpleEnumerator) michael@0: michael@0: michael@0: /* nsISupports getNext (); */ michael@0: NS_IMETHODIMP nsDocShellEnumerator::GetNext(nsISupports **outCurItem) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(outCurItem); michael@0: *outCurItem = nullptr; michael@0: michael@0: nsresult rv = EnsureDocShellArray(); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: if (mCurIndex >= mItemArray.Length()) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: // post-increment is important here michael@0: nsCOMPtr item = do_QueryReferent(mItemArray[mCurIndex++], &rv); michael@0: item.forget(outCurItem); michael@0: return rv; michael@0: } michael@0: michael@0: /* boolean hasMoreElements (); */ michael@0: NS_IMETHODIMP nsDocShellEnumerator::HasMoreElements(bool *outHasMore) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(outHasMore); michael@0: *outHasMore = false; michael@0: michael@0: nsresult rv = EnsureDocShellArray(); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: *outHasMore = (mCurIndex < mItemArray.Length()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::GetEnumerationRootItem(nsIDocShellTreeItem * *aEnumerationRootItem) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aEnumerationRootItem); michael@0: nsCOMPtr item = do_QueryReferent(mRootItem); michael@0: item.forget(aEnumerationRootItem); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::SetEnumerationRootItem(nsIDocShellTreeItem * aEnumerationRootItem) michael@0: { michael@0: mRootItem = do_GetWeakReference(aEnumerationRootItem); michael@0: ClearState(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::GetEnumDocShellType(int32_t *aEnumerationItemType) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aEnumerationItemType); michael@0: *aEnumerationItemType = mDocShellType; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::SetEnumDocShellType(int32_t aEnumerationItemType) michael@0: { michael@0: mDocShellType = aEnumerationItemType; michael@0: ClearState(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::First() michael@0: { michael@0: mCurIndex = 0; michael@0: return EnsureDocShellArray(); michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::EnsureDocShellArray() michael@0: { michael@0: if (!mArrayValid) michael@0: { michael@0: mArrayValid = true; michael@0: return BuildDocShellArray(mItemArray); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::ClearState() michael@0: { michael@0: mItemArray.Clear(); michael@0: mArrayValid = false; michael@0: mCurIndex = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsDocShellEnumerator::BuildDocShellArray(nsTArray& inItemArray) michael@0: { michael@0: NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED); michael@0: inItemArray.Clear(); michael@0: nsCOMPtr item = do_QueryReferent(mRootItem); michael@0: return BuildArrayRecursive(item, inItemArray); michael@0: } michael@0: michael@0: nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) michael@0: { michael@0: nsresult rv; michael@0: michael@0: // add this item to the array michael@0: if (mDocShellType == nsIDocShellTreeItem::typeAll || michael@0: inItem->ItemType() == mDocShellType) { michael@0: nsWeakPtr weakItem = do_GetWeakReference(inItem); michael@0: if (!inItemArray.AppendElement(weakItem)) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: int32_t numChildren; michael@0: rv = inItem->GetChildCount(&numChildren); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: for (int32_t i = 0; i < numChildren; ++i) michael@0: { michael@0: nsCOMPtr curChild; michael@0: rv = inItem->GetChildAt(i, getter_AddRefs(curChild)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = BuildArrayRecursive(curChild, inItemArray); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) michael@0: { michael@0: nsresult rv; michael@0: michael@0: int32_t numChildren; michael@0: rv = inItem->GetChildCount(&numChildren); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: for (int32_t i = numChildren - 1; i >= 0; --i) michael@0: { michael@0: nsCOMPtr curChild; michael@0: rv = inItem->GetChildAt(i, getter_AddRefs(curChild)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = BuildArrayRecursive(curChild, inItemArray); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: // add this item to the array michael@0: if (mDocShellType == nsIDocShellTreeItem::typeAll || michael@0: inItem->ItemType() == mDocShellType) { michael@0: nsWeakPtr weakItem = do_GetWeakReference(inItem); michael@0: if (!inItemArray.AppendElement(weakItem)) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: return NS_OK; michael@0: }