Blame docshell/shistory/nsSHEntry.cpp

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