forked from mirrors/gecko-dev
		
	 aee0e76790
			
		
	
	
		aee0e76790
		
	
	
	
	
		
			
			To avoid unnecessary cloning of nsIInputStream, add a hasPostData boolean attribute to tell whether a nsISHEntry has populated postData. Differential Revision: https://phabricator.services.mozilla.com/D173237
		
			
				
	
	
		
			1137 lines
		
	
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1137 lines
		
	
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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 "nsSHEntry.h"
 | |
| 
 | |
| #include <algorithm>
 | |
| 
 | |
| #include "nsDocShell.h"
 | |
| #include "nsDocShellEditorData.h"
 | |
| #include "nsDocShellLoadState.h"
 | |
| #include "nsDocShellLoadTypes.h"
 | |
| #include "nsIContentSecurityPolicy.h"
 | |
| #include "nsIContentViewer.h"
 | |
| #include "nsIDocShellTreeItem.h"
 | |
| #include "nsIInputStream.h"
 | |
| #include "nsILayoutHistoryState.h"
 | |
| #include "nsIMutableArray.h"
 | |
| #include "nsIStructuredCloneContainer.h"
 | |
| #include "nsIURI.h"
 | |
| #include "nsSHEntryShared.h"
 | |
| #include "nsSHistory.h"
 | |
| 
 | |
| #include "mozilla/Logging.h"
 | |
| #include "nsIReferrerInfo.h"
 | |
| 
 | |
| extern mozilla::LazyLogModule gPageCacheLog;
 | |
| 
 | |
| static uint32_t gEntryID = 0;
 | |
| 
 | |
| nsSHEntry::nsSHEntry()
 | |
|     : mShared(new nsSHEntryShared()),
 | |
|       mLoadType(0),
 | |
|       mID(++gEntryID),  // SessionStore has special handling for 0 values.
 | |
|       mScrollPositionX(0),
 | |
|       mScrollPositionY(0),
 | |
|       mParent(nullptr),
 | |
|       mLoadReplace(false),
 | |
|       mURIWasModified(false),
 | |
|       mIsSrcdocEntry(false),
 | |
|       mScrollRestorationIsManual(false),
 | |
|       mLoadedInThisProcess(false),
 | |
|       mPersist(true),
 | |
|       mHasUserInteraction(false),
 | |
|       mHasUserActivation(false) {}
 | |
| 
 | |
| nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
 | |
|     : mShared(aOther.mShared),
 | |
|       mURI(aOther.mURI),
 | |
|       mOriginalURI(aOther.mOriginalURI),
 | |
|       mResultPrincipalURI(aOther.mResultPrincipalURI),
 | |
|       mUnstrippedURI(aOther.mUnstrippedURI),
 | |
|       mReferrerInfo(aOther.mReferrerInfo),
 | |
|       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),
 | |
|       mStateData(aOther.mStateData),
 | |
|       mSrcdocData(aOther.mSrcdocData),
 | |
|       mBaseURI(aOther.mBaseURI),
 | |
|       mLoadReplace(aOther.mLoadReplace),
 | |
|       mURIWasModified(aOther.mURIWasModified),
 | |
|       mIsSrcdocEntry(aOther.mIsSrcdocEntry),
 | |
|       mScrollRestorationIsManual(false),
 | |
|       mLoadedInThisProcess(aOther.mLoadedInThisProcess),
 | |
|       mPersist(aOther.mPersist),
 | |
|       mHasUserInteraction(false),
 | |
|       mHasUserActivation(aOther.mHasUserActivation) {}
 | |
| 
 | |
| nsSHEntry::~nsSHEntry() {
 | |
|   // Null out the mParent pointers on all our kids.
 | |
|   for (nsISHEntry* entry : mChildren) {
 | |
|     if (entry) {
 | |
|       entry->SetParent(nullptr);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(nsSHEntry, nsISHEntry)
 | |
| 
 | |
| 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::GetResultPrincipalURI(nsIURI** aResultPrincipalURI) {
 | |
|   *aResultPrincipalURI = mResultPrincipalURI;
 | |
|   NS_IF_ADDREF(*aResultPrincipalURI);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetResultPrincipalURI(nsIURI* aResultPrincipalURI) {
 | |
|   mResultPrincipalURI = aResultPrincipalURI;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetUnstrippedURI(nsIURI** aUnstrippedURI) {
 | |
|   *aUnstrippedURI = mUnstrippedURI;
 | |
|   NS_IF_ADDREF(*aUnstrippedURI);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetUnstrippedURI(nsIURI* aUnstrippedURI) {
 | |
|   mUnstrippedURI = aUnstrippedURI;
 | |
|   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::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
 | |
|   *aReferrerInfo = mReferrerInfo;
 | |
|   NS_IF_ADDREF(*aReferrerInfo);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
 | |
|   mReferrerInfo = aReferrerInfo;
 | |
|   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(nsAString& 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 = mTitle;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetTitle(const nsAString& aTitle) {
 | |
|   mTitle = aTitle;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetName(nsAString& aName) {
 | |
|   aName = mName;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetName(const nsAString& aName) {
 | |
|   mName = aName;
 | |
|   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::GetHasPostData(bool* aResult) {
 | |
|   *aResult = !!mPostData;
 | |
|   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::InitLayoutHistoryState(nsILayoutHistoryState** aState) {
 | |
|   if (!mShared->mLayoutHistoryState) {
 | |
|     nsCOMPtr<nsILayoutHistoryState> historyState;
 | |
|     historyState = NS_NewLayoutHistoryState();
 | |
|     SetLayoutHistoryState(historyState);
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsILayoutHistoryState> state = GetLayoutHistoryState();
 | |
|   state.forget(aState);
 | |
|   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;
 | |
| }
 | |
| 
 | |
| 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::GetHasUserInteraction(bool* aFlag) {
 | |
|   // The back button and menulist deal with root/top-level
 | |
|   // session history entries, thus we annotate only the root entry.
 | |
|   if (!mParent) {
 | |
|     *aFlag = mHasUserInteraction;
 | |
|   } else {
 | |
|     nsCOMPtr<nsISHEntry> root = nsSHistory::GetRootSHEntry(this);
 | |
|     root->GetHasUserInteraction(aFlag);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetHasUserInteraction(bool aFlag) {
 | |
|   // The back button and menulist deal with root/top-level
 | |
|   // session history entries, thus we annotate only the root entry.
 | |
|   if (!mParent) {
 | |
|     mHasUserInteraction = aFlag;
 | |
|   } else {
 | |
|     nsCOMPtr<nsISHEntry> root = nsSHistory::GetRootSHEntry(this);
 | |
|     root->SetHasUserInteraction(aFlag);
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetHasUserActivation(bool* aFlag) {
 | |
|   *aFlag = mHasUserActivation;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetHasUserActivation(bool aFlag) {
 | |
|   mHasUserActivation = aFlag;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetCacheKey(uint32_t* aResult) {
 | |
|   *aResult = mShared->mCacheKey;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetCacheKey(uint32_t aCacheKey) {
 | |
|   mShared->mCacheKey = aCacheKey;
 | |
|   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,
 | |
|     uint32_t aCacheKey, const nsACString& aContentType,
 | |
|     nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit,
 | |
|     nsIPrincipal* aPartitionedPrincipalToInherit,
 | |
|     nsIContentSecurityPolicy* aCsp, const nsID& aDocShellID,
 | |
|     bool aDynamicCreation, nsIURI* aOriginalURI, nsIURI* aResultPrincipalURI,
 | |
|     nsIURI* aUnstrippedURI, bool aLoadReplace, nsIReferrerInfo* aReferrerInfo,
 | |
|     const nsAString& aSrcdocData, bool aSrcdocEntry, nsIURI* aBaseURI,
 | |
|     bool aSaveLayoutState, bool aExpired, bool aUserActivation) {
 | |
|   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 = LOAD_HISTORY;
 | |
| 
 | |
|   mShared->mCacheKey = aCacheKey;
 | |
|   mShared->mContentType = aContentType;
 | |
|   mShared->mTriggeringPrincipal = aTriggeringPrincipal;
 | |
|   mShared->mPrincipalToInherit = aPrincipalToInherit;
 | |
|   mShared->mPartitionedPrincipalToInherit = aPartitionedPrincipalToInherit;
 | |
|   mShared->mCsp = aCsp;
 | |
|   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;
 | |
| 
 | |
|   mHasUserInteraction = false;
 | |
| 
 | |
|   mShared->mExpired = aExpired;
 | |
| 
 | |
|   mIsSrcdocEntry = aSrcdocEntry;
 | |
|   mSrcdocData = aSrcdocData;
 | |
| 
 | |
|   mBaseURI = aBaseURI;
 | |
| 
 | |
|   mLoadedInThisProcess = true;
 | |
| 
 | |
|   mOriginalURI = aOriginalURI;
 | |
|   mResultPrincipalURI = aResultPrincipalURI;
 | |
|   mUnstrippedURI = aUnstrippedURI;
 | |
|   mLoadReplace = aLoadReplace;
 | |
|   mReferrerInfo = aReferrerInfo;
 | |
| 
 | |
|   mHasUserActivation = aUserActivation;
 | |
| 
 | |
|   mShared->mLayoutHistoryState = nullptr;
 | |
| 
 | |
|   mShared->mSaveLayoutState = aSaveLayoutState;
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetParent(nsISHEntry** 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_(void)
 | |
| nsSHEntry::SetViewerBounds(const nsIntRect& aBounds) {
 | |
|   mShared->mViewerBounds = aBounds;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP_(void)
 | |
| nsSHEntry::GetViewerBounds(nsIntRect& aBounds) {
 | |
|   aBounds = mShared->mViewerBounds;
 | |
| }
 | |
| 
 | |
| 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::GetPartitionedPrincipalToInherit(
 | |
|     nsIPrincipal** aPartitionedPrincipalToInherit) {
 | |
|   NS_IF_ADDREF(*aPartitionedPrincipalToInherit =
 | |
|                    mShared->mPartitionedPrincipalToInherit);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetPartitionedPrincipalToInherit(
 | |
|     nsIPrincipal* aPartitionedPrincipalToInherit) {
 | |
|   mShared->mPartitionedPrincipalToInherit = aPartitionedPrincipalToInherit;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetCsp(nsIContentSecurityPolicy** aCsp) {
 | |
|   NS_IF_ADDREF(*aCsp = mShared->mCsp);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetCsp(nsIContentSecurityPolicy* aCsp) {
 | |
|   mShared->mCsp = aCsp;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::AdoptBFCacheEntry(nsISHEntry* aEntry) {
 | |
|   nsSHEntryShared* shared = static_cast<nsSHEntry*>(aEntry)->mShared;
 | |
|   NS_ENSURE_STATE(shared);
 | |
| 
 | |
|   mShared = shared;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SharesDocumentWith(nsISHEntry* aEntry, bool* aOut) {
 | |
|   NS_ENSURE_ARG_POINTER(aOut);
 | |
| 
 | |
|   *aOut = mShared == static_cast<nsSHEntry*>(aEntry)->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::GetLoadedInThisProcess(bool* aLoadedInThisProcess) {
 | |
|   *aLoadedInThisProcess = mLoadedInThisProcess;
 | |
|   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,
 | |
|                     bool aUseRemoteSubframes) {
 | |
|   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 = aChild ? aChild->IsDynamicallyAdded() : false;
 | |
| 
 | |
|   // 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) {
 | |
|         if (entry->IsDynamicallyAdded()) {
 | |
|           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) {
 | |
|           if (entry->IsDynamicallyAdded()) {
 | |
|             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) {
 | |
|         // Under Fission, this can happen when a network-created iframe starts
 | |
|         // out in-process, moves out-of-process, and then switches back. At that
 | |
|         // point, we'll create a new network-created DocShell at the same index
 | |
|         // where we already have an entry for the original network-created
 | |
|         // DocShell.
 | |
|         //
 | |
|         // This should ideally stop being an issue once the Fission-aware
 | |
|         // session history rewrite is complete.
 | |
|         NS_ASSERTION(
 | |
|             aUseRemoteSubframes,
 | |
|             "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;
 | |
|   if (aChild->IsDynamicallyAdded()) {
 | |
|     childRemoved = mChildren.RemoveObject(aChild);
 | |
|   } else {
 | |
|     int32_t index = mChildren.IndexOfObject(aChild);
 | |
|     if (index >= 0) {
 | |
|       // Other alive non-dynamic child docshells still keep mChildOffset,
 | |
|       // so we don't want to change the indices here.
 | |
|       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_(void)
 | |
| nsSHEntry::GetChildSHEntryIfHasNoDynamicallyAddedChild(int32_t aChildOffset,
 | |
|                                                        nsISHEntry** aChild) {
 | |
|   *aChild = nullptr;
 | |
| 
 | |
|   bool dynamicallyAddedChild = false;
 | |
|   HasDynamicallyAddedChild(&dynamicallyAddedChild);
 | |
|   if (dynamicallyAddedChild) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // If the user did a shift-reload on this frameset page,
 | |
|   // we don't want to load the subframes from history.
 | |
|   if (IsForceReloadType(mLoadType) || mLoadType == LOAD_REFRESH) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   /* Before looking for the subframe's url, check
 | |
|    * the expiration status of the parent. If the parent
 | |
|    * has expired from cache, then subframes will not be
 | |
|    * loaded from history in certain situations.
 | |
|    * If the user pressed reload and the parent frame has expired
 | |
|    *  from cache, we do not want to load the child frame from history.
 | |
|    */
 | |
|   if (mShared->mExpired && (mLoadType == LOAD_RELOAD_NORMAL)) {
 | |
|     // The parent has expired. Return null.
 | |
|     *aChild = nullptr;
 | |
|     return;
 | |
|   }
 | |
|   // Get the child subframe from session history.
 | |
|   GetChildAt(aChildOffset, aChild);
 | |
|   if (*aChild) {
 | |
|     // Set the parent's Load Type on the child
 | |
|     (*aChild)->SetLoadType(mLoadType);
 | |
|   }
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::ReplaceChild(nsISHEntry* aNewEntry) {
 | |
|   NS_ENSURE_STATE(aNewEntry);
 | |
| 
 | |
|   nsID docshellID;
 | |
|   aNewEntry->GetDocshellID(docshellID);
 | |
| 
 | |
|   for (int32_t i = 0; i < mChildren.Count(); ++i) {
 | |
|     if (mChildren[i]) {
 | |
|       nsID childDocshellID;
 | |
|       nsresult rv = mChildren[i]->GetDocshellID(childDocshellID);
 | |
|       NS_ENSURE_SUCCESS(rv, rv);
 | |
|       if (docshellID == childDocshellID) {
 | |
|         mChildren[i]->SetParent(nullptr);
 | |
|         mChildren.ReplaceObjectAt(aNewEntry, i);
 | |
|         return aNewEntry->SetParent(this);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return NS_ERROR_FAILURE;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP_(void) nsSHEntry::ClearEntry() {
 | |
|   int32_t childCount = GetChildCount();
 | |
|   // Remove all children of this entry
 | |
|   for (int32_t i = childCount - 1; i >= 0; i--) {
 | |
|     nsCOMPtr<nsISHEntry> child;
 | |
|     GetChildAt(i, getter_AddRefs(child));
 | |
|     RemoveChild(child);
 | |
|   }
 | |
|   AbandonBFCacheEntry();
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetStateData(nsIStructuredCloneContainer** aContainer) {
 | |
|   NS_IF_ADDREF(*aContainer = mStateData);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetStateData(nsIStructuredCloneContainer* aContainer) {
 | |
|   mStateData = aContainer;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP_(bool)
 | |
| nsSHEntry::IsDynamicallyAdded() { return mShared->mDynamicallyCreated; }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::HasDynamicallyAddedChild(bool* aAdded) {
 | |
|   *aAdded = false;
 | |
|   for (int32_t i = 0; i < mChildren.Count(); ++i) {
 | |
|     nsISHEntry* entry = mChildren[i];
 | |
|     if (entry) {
 | |
|       *aAdded = entry->IsDynamicallyAdded();
 | |
|       if (*aAdded) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetDocshellID(nsID& aID) {
 | |
|   aID = mShared->mDocShellID;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetDocshellID(const nsID& 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;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetShistory(nsISHistory** aSHistory) {
 | |
|   nsCOMPtr<nsISHistory> shistory(do_QueryReferent(mShared->mSHistory));
 | |
|   shistory.forget(aSHistory);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetShistory(nsISHistory* aSHistory) {
 | |
|   nsWeakPtr shistory = do_GetWeakReference(aSHistory);
 | |
|   // mSHistory can not be changed once it's set
 | |
|   MOZ_ASSERT(!mShared->mSHistory || (mShared->mSHistory == shistory));
 | |
|   mShared->mSHistory = shistory;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetLoadTypeAsHistory() {
 | |
|   // Set the LoadType by default to loadHistory during creation
 | |
|   mLoadType = LOAD_HISTORY;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetPersist(bool* aPersist) {
 | |
|   *aPersist = mPersist;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetPersist(bool aPersist) {
 | |
|   mPersist = aPersist;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::CreateLoadInfo(nsDocShellLoadState** aLoadState) {
 | |
|   nsCOMPtr<nsIURI> uri = GetURI();
 | |
|   RefPtr<nsDocShellLoadState> loadState(new nsDocShellLoadState(uri));
 | |
| 
 | |
|   nsCOMPtr<nsIURI> originalURI = GetOriginalURI();
 | |
|   loadState->SetOriginalURI(originalURI);
 | |
| 
 | |
|   mozilla::Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
 | |
|   nsCOMPtr<nsIURI> resultPrincipalURI = GetResultPrincipalURI();
 | |
|   emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
 | |
|   loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
 | |
| 
 | |
|   nsCOMPtr<nsIURI> unstrippedURI = GetUnstrippedURI();
 | |
|   loadState->SetUnstrippedURI(unstrippedURI);
 | |
| 
 | |
|   loadState->SetLoadReplace(GetLoadReplace());
 | |
|   nsCOMPtr<nsIInputStream> postData = GetPostData();
 | |
|   loadState->SetPostDataStream(postData);
 | |
| 
 | |
|   nsAutoCString contentType;
 | |
|   GetContentType(contentType);
 | |
|   loadState->SetTypeHint(contentType);
 | |
| 
 | |
|   nsCOMPtr<nsIPrincipal> triggeringPrincipal = GetTriggeringPrincipal();
 | |
|   loadState->SetTriggeringPrincipal(triggeringPrincipal);
 | |
|   nsCOMPtr<nsIPrincipal> principalToInherit = GetPrincipalToInherit();
 | |
|   loadState->SetPrincipalToInherit(principalToInherit);
 | |
|   nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
 | |
|       GetPartitionedPrincipalToInherit();
 | |
|   loadState->SetPartitionedPrincipalToInherit(partitionedPrincipalToInherit);
 | |
|   nsCOMPtr<nsIContentSecurityPolicy> csp = GetCsp();
 | |
|   loadState->SetCsp(csp);
 | |
|   nsCOMPtr<nsIReferrerInfo> referrerInfo = GetReferrerInfo();
 | |
|   loadState->SetReferrerInfo(referrerInfo);
 | |
| 
 | |
|   // Do not inherit principal from document (security-critical!);
 | |
|   uint32_t flags = nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_NONE;
 | |
| 
 | |
|   // Passing nullptr as aSourceDocShell gives the same behaviour as before
 | |
|   // aSourceDocShell was introduced. According to spec we should be passing
 | |
|   // the source browsing context that was used when the history entry was
 | |
|   // first created. bug 947716 has been created to address this issue.
 | |
|   nsAutoString srcdoc;
 | |
|   nsCOMPtr<nsIURI> baseURI;
 | |
|   if (GetIsSrcdocEntry()) {
 | |
|     GetSrcdocData(srcdoc);
 | |
|     baseURI = GetBaseURI();
 | |
|     flags |= nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
 | |
|   } else {
 | |
|     srcdoc = VoidString();
 | |
|   }
 | |
|   loadState->SetSrcdocData(srcdoc);
 | |
|   loadState->SetBaseURI(baseURI);
 | |
|   loadState->SetInternalLoadFlags(flags);
 | |
| 
 | |
|   loadState->SetFirstParty(true);
 | |
| 
 | |
|   loadState->SetHasValidUserGestureActivation(GetHasUserActivation());
 | |
| 
 | |
|   loadState->SetSHEntry(this);
 | |
| 
 | |
|   // When we create a load state from the history entry we already know if
 | |
|   // https-first was able to upgrade the request from http to https. There is no
 | |
|   // point in re-retrying to upgrade.
 | |
|   loadState->SetIsExemptFromHTTPSOnlyMode(true);
 | |
| 
 | |
|   loadState.forget(aLoadState);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP_(void)
 | |
| nsSHEntry::SyncTreesForSubframeNavigation(
 | |
|     nsISHEntry* aEntry, mozilla::dom::BrowsingContext* aTopBC,
 | |
|     mozilla::dom::BrowsingContext* aIgnoreBC) {
 | |
|   // XXX Keep this in sync with
 | |
|   // SessionHistoryEntry::SyncTreesForSubframeNavigation
 | |
|   //
 | |
|   // We need to sync up the browsing context and session history trees for
 | |
|   // subframe navigation.  If the load was in a subframe, we forward up to
 | |
|   // the top browsing context, which will then recursively sync up all browsing
 | |
|   // contexts to their corresponding entries in the new session history tree. If
 | |
|   // we don't do this, then we can cache a content viewer on the wrong cloned
 | |
|   // entry, and subsequently restore it at the wrong time.
 | |
|   nsCOMPtr<nsISHEntry> newRootEntry = nsSHistory::GetRootSHEntry(aEntry);
 | |
|   if (newRootEntry) {
 | |
|     // newRootEntry is now the new root entry.
 | |
|     // Find the old root entry as well.
 | |
| 
 | |
|     // Need a strong ref. on |oldRootEntry| so it isn't destroyed when
 | |
|     // SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
 | |
|     nsCOMPtr<nsISHEntry> oldRootEntry = nsSHistory::GetRootSHEntry(this);
 | |
| 
 | |
|     if (oldRootEntry) {
 | |
|       nsSHistory::SwapEntriesData data = {aIgnoreBC, newRootEntry, nullptr};
 | |
|       nsSHistory::SetChildHistoryEntry(oldRootEntry, aTopBC, 0, &data);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsSHEntry::EvictContentViewer() {
 | |
|   nsCOMPtr<nsIContentViewer> viewer = GetContentViewer();
 | |
|   if (viewer) {
 | |
|     mShared->NotifyListenersContentViewerEvicted();
 | |
|     // Drop the presentation state before destroying the viewer, so that
 | |
|     // document teardown is able to correctly persist the state.
 | |
|     SetContentViewer(nullptr);
 | |
|     SyncPresentationState();
 | |
|     viewer->Destroy();
 | |
|   }
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetContentViewer(nsIContentViewer* aViewer) {
 | |
|   return GetState()->SetContentViewer(aViewer);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetContentViewer(nsIContentViewer** aResult) {
 | |
|   *aResult = GetState()->mContentViewer;
 | |
|   NS_IF_ADDREF(*aResult);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetIsInBFCache(bool* aResult) {
 | |
|   *aResult = !!GetState()->mContentViewer;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::Clone(nsISHEntry** aResult) {
 | |
|   nsCOMPtr<nsISHEntry> entry = new nsSHEntry(*this);
 | |
|   entry.forget(aResult);
 | |
|   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::SetWindowState(nsISupports* aState) {
 | |
|   GetState()->mWindowState = aState;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetWindowState(nsISupports** aState) {
 | |
|   NS_IF_ADDREF(*aState = GetState()->mWindowState);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetRefreshURIList(nsIMutableArray** aList) {
 | |
|   NS_IF_ADDREF(*aList = GetState()->mRefreshURIList);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetRefreshURIList(nsIMutableArray* aList) {
 | |
|   GetState()->mRefreshURIList = aList;
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP_(void)
 | |
| nsSHEntry::AddChildShell(nsIDocShellTreeItem* aShell) {
 | |
|   MOZ_ASSERT(aShell, "Null child shell added to history entry");
 | |
|   GetState()->mChildShells.AppendObject(aShell);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem** aShell) {
 | |
|   NS_IF_ADDREF(*aShell = GetState()->mChildShells.SafeObjectAt(aIndex));
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP_(void)
 | |
| nsSHEntry::ClearChildShells() { GetState()->mChildShells.Clear(); }
 | |
| 
 | |
| NS_IMETHODIMP_(void)
 | |
| nsSHEntry::SyncPresentationState() { GetState()->SyncPresentationState(); }
 | |
| 
 | |
| nsDocShellEditorData* nsSHEntry::ForgetEditorData() {
 | |
|   // XXX jlebar Check how this is used.
 | |
|   return GetState()->mEditorData.release();
 | |
| }
 | |
| 
 | |
| void nsSHEntry::SetEditorData(nsDocShellEditorData* aData) {
 | |
|   NS_ASSERTION(!(aData && GetState()->mEditorData),
 | |
|                "We're going to overwrite an owning ref!");
 | |
|   if (GetState()->mEditorData != aData) {
 | |
|     GetState()->mEditorData = mozilla::WrapUnique(aData);
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool nsSHEntry::HasDetachedEditor() {
 | |
|   return GetState()->mEditorData != nullptr;
 | |
| }
 | |
| 
 | |
| bool nsSHEntry::HasBFCacheEntry(
 | |
|     mozilla::dom::SHEntrySharedParentState* aEntry) {
 | |
|   return GetState() == aEntry;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::AbandonBFCacheEntry() {
 | |
|   mShared = GetState()->Duplicate();
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetBfcacheID(uint64_t* aBFCacheID) {
 | |
|   *aBFCacheID = mShared->GetId();
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::GetWireframe(JSContext* aCx, JS::MutableHandle<JS::Value> aOut) {
 | |
|   aOut.set(JS::NullValue());
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsSHEntry::SetWireframe(JSContext* aCx, JS::Handle<JS::Value> aArg) {
 | |
|   return NS_ERROR_NOT_IMPLEMENTED;
 | |
| }
 |