123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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 "nsSHEntry.h"
- #include "nsIDocShellLoadInfo.h"
- #include "nsIDocShellTreeItem.h"
- #include "nsDocShellEditorData.h"
- #include "nsSHEntryShared.h"
- #include "nsILayoutHistoryState.h"
- #include "nsIContentViewer.h"
- #include "nsIStructuredCloneContainer.h"
- #include "nsIInputStream.h"
- #include "nsIURI.h"
- #include "mozilla/net/ReferrerPolicy.h"
- #include "nsArray.h"
- #include <algorithm>
- namespace dom = mozilla::dom;
- static uint32_t gEntryID = 0;
- nsSHEntry::nsSHEntry()
- : mShared(new nsSHEntryShared())
- , mLoadReplace(false)
- , mReferrerPolicy(mozilla::net::RP_Default)
- , mLoadType(0)
- , mID(gEntryID++)
- , mScrollPositionX(0)
- , mScrollPositionY(0)
- , mParent(nullptr)
- , mURIWasModified(false)
- , mIsSrcdocEntry(false)
- , mScrollRestorationIsManual(false)
- {
- }
- nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
- : mShared(aOther.mShared)
- , mURI(aOther.mURI)
- , mOriginalURI(aOther.mOriginalURI)
- , mLoadReplace(aOther.mLoadReplace)
- , mReferrerURI(aOther.mReferrerURI)
- , mReferrerPolicy(aOther.mReferrerPolicy)
- , mTitle(aOther.mTitle)
- , mPostData(aOther.mPostData)
- , mLoadType(0) // XXX why not copy?
- , mID(aOther.mID)
- , mScrollPositionX(0) // XXX why not copy?
- , mScrollPositionY(0) // XXX why not copy?
- , mParent(aOther.mParent)
- , mURIWasModified(aOther.mURIWasModified)
- , mStateData(aOther.mStateData)
- , mIsSrcdocEntry(aOther.mIsSrcdocEntry)
- , mScrollRestorationIsManual(false)
- , mSrcdocData(aOther.mSrcdocData)
- , mBaseURI(aOther.mBaseURI)
- {
- }
- static bool
- ClearParentPtr(nsISHEntry* aEntry, void* /* aData */)
- {
- if (aEntry) {
- aEntry->SetParent(nullptr);
- }
- return true;
- }
- nsSHEntry::~nsSHEntry()
- {
- // Null out the mParent pointers on all our kids.
- mChildren.EnumerateForwards(ClearParentPtr, nullptr);
- }
- NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
- NS_IMETHODIMP
- nsSHEntry::SetScrollPosition(int32_t aX, int32_t aY)
- {
- mScrollPositionX = aX;
- mScrollPositionY = aY;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetScrollPosition(int32_t* aX, int32_t* aY)
- {
- *aX = mScrollPositionX;
- *aY = mScrollPositionY;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetURIWasModified(bool* aOut)
- {
- *aOut = mURIWasModified;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetURIWasModified(bool aIn)
- {
- mURIWasModified = aIn;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetURI(nsIURI** aURI)
- {
- *aURI = mURI;
- NS_IF_ADDREF(*aURI);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetURI(nsIURI* aURI)
- {
- mURI = aURI;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetOriginalURI(nsIURI** aOriginalURI)
- {
- *aOriginalURI = mOriginalURI;
- NS_IF_ADDREF(*aOriginalURI);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI)
- {
- mOriginalURI = aOriginalURI;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetLoadReplace(bool* aLoadReplace)
- {
- *aLoadReplace = mLoadReplace;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetLoadReplace(bool aLoadReplace)
- {
- mLoadReplace = aLoadReplace;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetReferrerURI(nsIURI** aReferrerURI)
- {
- *aReferrerURI = mReferrerURI;
- NS_IF_ADDREF(*aReferrerURI);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetReferrerURI(nsIURI* aReferrerURI)
- {
- mReferrerURI = aReferrerURI;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetReferrerPolicy(uint32_t* aReferrerPolicy)
- {
- *aReferrerPolicy = mReferrerPolicy;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetReferrerPolicy(uint32_t aReferrerPolicy)
- {
- mReferrerPolicy = aReferrerPolicy;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetContentViewer(nsIContentViewer* aViewer)
- {
- return mShared->SetContentViewer(aViewer);
- }
- NS_IMETHODIMP
- nsSHEntry::GetContentViewer(nsIContentViewer** aResult)
- {
- *aResult = mShared->mContentViewer;
- NS_IF_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetAnyContentViewer(nsISHEntry** aOwnerEntry,
- nsIContentViewer** aResult)
- {
- // Find a content viewer in the root node or any of its children,
- // assuming that there is only one content viewer total in any one
- // nsSHEntry tree
- GetContentViewer(aResult);
- if (*aResult) {
- #ifdef DEBUG_PAGE_CACHE
- printf("Found content viewer\n");
- #endif
- *aOwnerEntry = this;
- NS_ADDREF(*aOwnerEntry);
- return NS_OK;
- }
- // The root SHEntry doesn't have a ContentViewer, so check child nodes
- for (int32_t i = 0; i < mChildren.Count(); i++) {
- nsISHEntry* child = mChildren[i];
- if (child) {
- #ifdef DEBUG_PAGE_CACHE
- printf("Evaluating SHEntry child %d\n", i);
- #endif
- child->GetAnyContentViewer(aOwnerEntry, aResult);
- if (*aResult) {
- return NS_OK;
- }
- }
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetSticky(bool aSticky)
- {
- mShared->mSticky = aSticky;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetSticky(bool* aSticky)
- {
- *aSticky = mShared->mSticky;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetTitle(char16_t** aTitle)
- {
- // Check for empty title...
- if (mTitle.IsEmpty() && mURI) {
- // Default title is the URL.
- nsAutoCString spec;
- if (NS_SUCCEEDED(mURI->GetSpec(spec))) {
- AppendUTF8toUTF16(spec, mTitle);
- }
- }
- *aTitle = ToNewUnicode(mTitle);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetTitle(const nsAString& aTitle)
- {
- mTitle = aTitle;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetPostData(nsIInputStream** aResult)
- {
- *aResult = mPostData;
- NS_IF_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetPostData(nsIInputStream* aPostData)
- {
- mPostData = aPostData;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult)
- {
- *aResult = mShared->mLayoutHistoryState;
- NS_IF_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState)
- {
- mShared->mLayoutHistoryState = aState;
- if (mShared->mLayoutHistoryState) {
- mShared->mLayoutHistoryState->SetScrollPositionOnly(
- !mShared->mSaveLayoutState);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetLoadType(uint32_t* aResult)
- {
- *aResult = mLoadType;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetLoadType(uint32_t aLoadType)
- {
- mLoadType = aLoadType;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetID(uint32_t* aResult)
- {
- *aResult = mID;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetID(uint32_t aID)
- {
- mID = aID;
- return NS_OK;
- }
- nsSHEntryShared*
- nsSHEntry::GetSharedState()
- {
- return mShared;
- }
- NS_IMETHODIMP
- nsSHEntry::GetIsSubFrame(bool* aFlag)
- {
- *aFlag = mShared->mIsFrameNavigation;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetIsSubFrame(bool aFlag)
- {
- mShared->mIsFrameNavigation = aFlag;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetCacheKey(nsISupports** aResult)
- {
- *aResult = mShared->mCacheKey;
- NS_IF_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetCacheKey(nsISupports* aCacheKey)
- {
- mShared->mCacheKey = aCacheKey;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetSaveLayoutStateFlag(bool* aFlag)
- {
- *aFlag = mShared->mSaveLayoutState;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetSaveLayoutStateFlag(bool aFlag)
- {
- mShared->mSaveLayoutState = aFlag;
- if (mShared->mLayoutHistoryState) {
- mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetExpirationStatus(bool* aFlag)
- {
- *aFlag = mShared->mExpired;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetExpirationStatus(bool aFlag)
- {
- mShared->mExpired = aFlag;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetContentType(nsACString& aContentType)
- {
- aContentType = mShared->mContentType;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetContentType(const nsACString& aContentType)
- {
- mShared->mContentType = aContentType;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
- nsIInputStream* aInputStream,
- nsILayoutHistoryState* aLayoutHistoryState,
- nsISupports* aCacheKey, const nsACString& aContentType,
- nsIPrincipal* aTriggeringPrincipal,
- nsIPrincipal* aPrincipalToInherit,
- uint64_t aDocShellID,
- bool aDynamicCreation)
- {
- MOZ_ASSERT(aTriggeringPrincipal,
- "need a valid triggeringPrincipal to create a session history entry");
- mURI = aURI;
- mTitle = aTitle;
- mPostData = aInputStream;
- // Set the LoadType by default to loadHistory during creation
- mLoadType = (uint32_t)nsIDocShellLoadInfo::loadHistory;
- mShared->mCacheKey = aCacheKey;
- mShared->mContentType = aContentType;
- mShared->mTriggeringPrincipal = aTriggeringPrincipal;
- mShared->mPrincipalToInherit = aPrincipalToInherit;
- mShared->mDocShellID = aDocShellID;
- mShared->mDynamicallyCreated = aDynamicCreation;
- // By default all entries are set false for subframe flag.
- // nsDocShell::CloneAndReplace() which creates entries for
- // all subframe navigations, sets the flag to true.
- mShared->mIsFrameNavigation = false;
- // By default we save LayoutHistoryState
- mShared->mSaveLayoutState = true;
- mShared->mLayoutHistoryState = aLayoutHistoryState;
- // By default the page is not expired
- mShared->mExpired = false;
- mIsSrcdocEntry = false;
- mSrcdocData = NullString();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::Clone(nsISHEntry** aResult)
- {
- *aResult = new nsSHEntry(*this);
- NS_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetParent(nsISHEntry** aResult)
- {
- NS_ENSURE_ARG_POINTER(aResult);
- *aResult = mParent;
- NS_IF_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetParent(nsISHEntry* aParent)
- {
- /* parent not Addrefed on purpose to avoid cyclic reference
- * Null parent is OK
- *
- * XXX this method should not be scriptable if this is the case!!
- */
- mParent = aParent;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetWindowState(nsISupports* aState)
- {
- mShared->mWindowState = aState;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetWindowState(nsISupports** aState)
- {
- NS_IF_ADDREF(*aState = mShared->mWindowState);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetViewerBounds(const nsIntRect& aBounds)
- {
- mShared->mViewerBounds = aBounds;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetViewerBounds(nsIntRect& aBounds)
- {
- aBounds = mShared->mViewerBounds;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetTriggeringPrincipal(nsIPrincipal** aTriggeringPrincipal)
- {
- NS_IF_ADDREF(*aTriggeringPrincipal = mShared->mTriggeringPrincipal);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
- {
- mShared->mTriggeringPrincipal = aTriggeringPrincipal;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetPrincipalToInherit(nsIPrincipal** aPrincipalToInherit)
- {
- NS_IF_ADDREF(*aPrincipalToInherit = mShared->mPrincipalToInherit);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit)
- {
- mShared->mPrincipalToInherit = aPrincipalToInherit;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry** aEntry)
- {
- NS_ENSURE_ARG_POINTER(aEntry);
- NS_IF_ADDREF(*aEntry = mShared);
- return NS_OK;
- }
- bool
- nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry* aEntry)
- {
- return static_cast<nsIBFCacheEntry*>(mShared) == aEntry;
- }
- NS_IMETHODIMP
- nsSHEntry::AdoptBFCacheEntry(nsISHEntry* aEntry)
- {
- nsCOMPtr<nsISHEntryInternal> shEntry = do_QueryInterface(aEntry);
- NS_ENSURE_STATE(shEntry);
- nsSHEntryShared* shared = shEntry->GetSharedState();
- NS_ENSURE_STATE(shared);
- mShared = shared;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SharesDocumentWith(nsISHEntry* aEntry, bool* aOut)
- {
- NS_ENSURE_ARG_POINTER(aOut);
- nsCOMPtr<nsISHEntryInternal> internal = do_QueryInterface(aEntry);
- NS_ENSURE_STATE(internal);
- *aOut = mShared == internal->GetSharedState();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::AbandonBFCacheEntry()
- {
- mShared = nsSHEntryShared::Duplicate(mShared);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry)
- {
- *aIsSrcdocEntry = mIsSrcdocEntry;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetSrcdocData(nsAString& aSrcdocData)
- {
- aSrcdocData = mSrcdocData;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetSrcdocData(const nsAString& aSrcdocData)
- {
- mSrcdocData = aSrcdocData;
- mIsSrcdocEntry = true;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetBaseURI(nsIURI** aBaseURI)
- {
- *aBaseURI = mBaseURI;
- NS_IF_ADDREF(*aBaseURI);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetBaseURI(nsIURI* aBaseURI)
- {
- mBaseURI = aBaseURI;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetScrollRestorationIsManual(bool* aIsManual)
- {
- *aIsManual = mScrollRestorationIsManual;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetScrollRestorationIsManual(bool aIsManual)
- {
- mScrollRestorationIsManual = aIsManual;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetChildCount(int32_t* aCount)
- {
- *aCount = mChildren.Count();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::AddChild(nsISHEntry* aChild, int32_t aOffset)
- {
- if (aChild) {
- NS_ENSURE_SUCCESS(aChild->SetParent(this), NS_ERROR_FAILURE);
- }
- if (aOffset < 0) {
- mChildren.AppendObject(aChild);
- return NS_OK;
- }
- //
- // Bug 52670: Ensure children are added in order.
- //
- // Later frames in the child list may load faster and get appended
- // before earlier frames, causing session history to be scrambled.
- // By growing the list here, they are added to the right position.
- //
- // Assert that aOffset will not be so high as to grow us a lot.
- //
- NS_ASSERTION(aOffset < (mChildren.Count() + 1023), "Large frames array!\n");
- bool newChildIsDyn = false;
- if (aChild) {
- aChild->IsDynamicallyAdded(&newChildIsDyn);
- }
- // If the new child is dynamically added, try to add it to aOffset, but if
- // there are non-dynamically added children, the child must be after those.
- if (newChildIsDyn) {
- int32_t lastNonDyn = aOffset - 1;
- for (int32_t i = aOffset; i < mChildren.Count(); ++i) {
- nsISHEntry* entry = mChildren[i];
- if (entry) {
- bool dyn = false;
- entry->IsDynamicallyAdded(&dyn);
- if (dyn) {
- break;
- } else {
- lastNonDyn = i;
- }
- }
- }
- // InsertObjectAt allows only appending one object.
- // If aOffset is larger than Count(), we must first manually
- // set the capacity.
- if (aOffset > mChildren.Count()) {
- mChildren.SetCount(aOffset);
- }
- if (!mChildren.InsertObjectAt(aChild, lastNonDyn + 1)) {
- NS_WARNING("Adding a child failed!");
- aChild->SetParent(nullptr);
- return NS_ERROR_FAILURE;
- }
- } else {
- // If the new child isn't dynamically added, it should be set to aOffset.
- // If there are dynamically added children before that, those must be
- // moved to be after aOffset.
- if (mChildren.Count() > 0) {
- int32_t start = std::min(mChildren.Count() - 1, aOffset);
- int32_t dynEntryIndex = -1;
- nsISHEntry* dynEntry = nullptr;
- for (int32_t i = start; i >= 0; --i) {
- nsISHEntry* entry = mChildren[i];
- if (entry) {
- bool dyn = false;
- entry->IsDynamicallyAdded(&dyn);
- if (dyn) {
- dynEntryIndex = i;
- dynEntry = entry;
- } else {
- break;
- }
- }
- }
- if (dynEntry) {
- nsCOMArray<nsISHEntry> tmp;
- tmp.SetCount(aOffset - dynEntryIndex + 1);
- mChildren.InsertObjectsAt(tmp, dynEntryIndex);
- NS_ASSERTION(mChildren[aOffset + 1] == dynEntry, "Whaat?");
- }
- }
- // Make sure there isn't anything at aOffset.
- if (aOffset < mChildren.Count()) {
- nsISHEntry* oldChild = mChildren[aOffset];
- if (oldChild && oldChild != aChild) {
- NS_ERROR("Adding a child where we already have a child? This may misbehave");
- oldChild->SetParent(nullptr);
- }
- }
- mChildren.ReplaceObjectAt(aChild, aOffset);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::RemoveChild(nsISHEntry* aChild)
- {
- NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE);
- bool childRemoved = false;
- bool dynamic = false;
- aChild->IsDynamicallyAdded(&dynamic);
- if (dynamic) {
- childRemoved = mChildren.RemoveObject(aChild);
- } else {
- int32_t index = mChildren.IndexOfObject(aChild);
- if (index >= 0) {
- mChildren.ReplaceObjectAt(nullptr, index);
- childRemoved = true;
- }
- }
- if (childRemoved) {
- aChild->SetParent(nullptr);
- // reduce the child count, i.e. remove empty children at the end
- for (int32_t i = mChildren.Count() - 1; i >= 0 && !mChildren[i]; --i) {
- if (!mChildren.RemoveObjectAt(i)) {
- break;
- }
- }
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetChildAt(int32_t aIndex, nsISHEntry** aResult)
- {
- if (aIndex >= 0 && aIndex < mChildren.Count()) {
- *aResult = mChildren[aIndex];
- // yes, mChildren can have holes in it. AddChild's offset parameter makes
- // that possible.
- NS_IF_ADDREF(*aResult);
- } else {
- *aResult = nullptr;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::ReplaceChild(nsISHEntry* aNewEntry)
- {
- NS_ENSURE_STATE(aNewEntry);
- uint64_t docshellID;
- aNewEntry->GetDocshellID(&docshellID);
- uint64_t otherID;
- for (int32_t i = 0; i < mChildren.Count(); ++i) {
- if (mChildren[i] && NS_SUCCEEDED(mChildren[i]->GetDocshellID(&otherID)) &&
- docshellID == otherID) {
- mChildren[i]->SetParent(nullptr);
- mChildren.ReplaceObjectAt(aNewEntry, i);
- return aNewEntry->SetParent(this);
- }
- }
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsSHEntry::AddChildShell(nsIDocShellTreeItem* aShell)
- {
- NS_ASSERTION(aShell, "Null child shell added to history entry");
- mShared->mChildShells.AppendObject(aShell);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem** aShell)
- {
- NS_IF_ADDREF(*aShell = mShared->mChildShells.SafeObjectAt(aIndex));
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::ClearChildShells()
- {
- mShared->mChildShells.Clear();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetRefreshURIList(nsIMutableArray** aList)
- {
- NS_IF_ADDREF(*aList = mShared->mRefreshURIList);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetRefreshURIList(nsIMutableArray* aList)
- {
- mShared->mRefreshURIList = aList;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SyncPresentationState()
- {
- return mShared->SyncPresentationState();
- }
- void
- nsSHEntry::RemoveFromBFCacheSync()
- {
- mShared->RemoveFromBFCacheSync();
- }
- void
- nsSHEntry::RemoveFromBFCacheAsync()
- {
- mShared->RemoveFromBFCacheAsync();
- }
- nsDocShellEditorData*
- nsSHEntry::ForgetEditorData()
- {
- // XXX jlebar Check how this is used.
- return mShared->mEditorData.forget();
- }
- void
- nsSHEntry::SetEditorData(nsDocShellEditorData* aData)
- {
- NS_ASSERTION(!(aData && mShared->mEditorData),
- "We're going to overwrite an owning ref!");
- if (mShared->mEditorData != aData) {
- mShared->mEditorData = aData;
- }
- }
- bool
- nsSHEntry::HasDetachedEditor()
- {
- return mShared->mEditorData != nullptr;
- }
- NS_IMETHODIMP
- nsSHEntry::GetStateData(nsIStructuredCloneContainer** aContainer)
- {
- NS_ENSURE_ARG_POINTER(aContainer);
- NS_IF_ADDREF(*aContainer = mStateData);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetStateData(nsIStructuredCloneContainer* aContainer)
- {
- mStateData = aContainer;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::IsDynamicallyAdded(bool* aAdded)
- {
- *aAdded = mShared->mDynamicallyCreated;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::HasDynamicallyAddedChild(bool* aAdded)
- {
- *aAdded = false;
- for (int32_t i = 0; i < mChildren.Count(); ++i) {
- nsISHEntry* entry = mChildren[i];
- if (entry) {
- entry->IsDynamicallyAdded(aAdded);
- if (*aAdded) {
- break;
- }
- }
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetDocshellID(uint64_t* aID)
- {
- *aID = mShared->mDocShellID;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetDocshellID(uint64_t aID)
- {
- mShared->mDocShellID = aID;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::GetLastTouched(uint32_t* aLastTouched)
- {
- *aLastTouched = mShared->mLastTouched;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSHEntry::SetLastTouched(uint32_t aLastTouched)
- {
- mShared->mLastTouched = aLastTouched;
- return NS_OK;
- }
|