docshell/shistory/src/nsSHEntry.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 // Local Includes
     7 #include "nsSHEntry.h"
     8 #include "nsIDocShellLoadInfo.h"
     9 #include "nsIDocShellTreeItem.h"
    10 #include "nsDocShellEditorData.h"
    11 #include "nsSHEntryShared.h"
    12 #include "nsILayoutHistoryState.h"
    13 #include "nsIContentViewer.h"
    14 #include "nsISupportsArray.h"
    15 #include "nsIStructuredCloneContainer.h"
    16 #include "nsIInputStream.h"
    17 #include "nsIURI.h"
    18 #include <algorithm>
    20 namespace dom = mozilla::dom;
    22 static uint32_t gEntryID = 0;
    24 //*****************************************************************************
    25 //***    nsSHEntry: Object Management
    26 //*****************************************************************************
    29 nsSHEntry::nsSHEntry()
    30   : mLoadType(0)
    31   , mID(gEntryID++)
    32   , mScrollPositionX(0)
    33   , mScrollPositionY(0)
    34   , mParent(nullptr)
    35   , mURIWasModified(false)
    36   , mIsSrcdocEntry(false)
    37 {
    38   mShared = new nsSHEntryShared();
    39 }
    41 nsSHEntry::nsSHEntry(const nsSHEntry &other)
    42   : mShared(other.mShared)
    43   , mURI(other.mURI)
    44   , mReferrerURI(other.mReferrerURI)
    45   , mTitle(other.mTitle)
    46   , mPostData(other.mPostData)
    47   , mLoadType(0)         // XXX why not copy?
    48   , mID(other.mID)
    49   , mScrollPositionX(0)  // XXX why not copy?
    50   , mScrollPositionY(0)  // XXX why not copy?
    51   , mParent(other.mParent)
    52   , mURIWasModified(other.mURIWasModified)
    53   , mStateData(other.mStateData)
    54   , mIsSrcdocEntry(other.mIsSrcdocEntry)
    55   , mSrcdocData(other.mSrcdocData)
    56   , mBaseURI(other.mBaseURI)
    57 {
    58 }
    60 static bool
    61 ClearParentPtr(nsISHEntry* aEntry, void* /* aData */)
    62 {
    63   if (aEntry) {
    64     aEntry->SetParent(nullptr);
    65   }
    66   return true;
    67 }
    69 nsSHEntry::~nsSHEntry()
    70 {
    71   // Null out the mParent pointers on all our kids.
    72   mChildren.EnumerateForwards(ClearParentPtr, nullptr);
    73 }
    75 //*****************************************************************************
    76 //    nsSHEntry: nsISupports
    77 //*****************************************************************************
    79 NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
    81 //*****************************************************************************
    82 //    nsSHEntry: nsISHEntry
    83 //*****************************************************************************
    85 NS_IMETHODIMP nsSHEntry::SetScrollPosition(int32_t x, int32_t y)
    86 {
    87   mScrollPositionX = x;
    88   mScrollPositionY = y;
    89   return NS_OK;
    90 }
    92 NS_IMETHODIMP nsSHEntry::GetScrollPosition(int32_t *x, int32_t *y)
    93 {
    94   *x = mScrollPositionX;
    95   *y = mScrollPositionY;
    96   return NS_OK;
    97 }
    99 NS_IMETHODIMP nsSHEntry::GetURIWasModified(bool* aOut)
   100 {
   101   *aOut = mURIWasModified;
   102   return NS_OK;
   103 }
   105 NS_IMETHODIMP nsSHEntry::SetURIWasModified(bool aIn)
   106 {
   107   mURIWasModified = aIn;
   108   return NS_OK;
   109 }
   111 NS_IMETHODIMP nsSHEntry::GetURI(nsIURI** aURI)
   112 {
   113   *aURI = mURI;
   114   NS_IF_ADDREF(*aURI);
   115   return NS_OK;
   116 }
   118 NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI)
   119 {
   120   mURI = aURI;
   121   return NS_OK;
   122 }
   124 NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI)
   125 {
   126   *aReferrerURI = mReferrerURI;
   127   NS_IF_ADDREF(*aReferrerURI);
   128   return NS_OK;
   129 }
   131 NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
   132 {
   133   mReferrerURI = aReferrerURI;
   134   return NS_OK;
   135 }
   137 NS_IMETHODIMP
   138 nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
   139 {
   140   return mShared->SetContentViewer(aViewer);
   141 }
   143 NS_IMETHODIMP
   144 nsSHEntry::GetContentViewer(nsIContentViewer **aResult)
   145 {
   146   *aResult = mShared->mContentViewer;
   147   NS_IF_ADDREF(*aResult);
   148   return NS_OK;
   149 }
   151 NS_IMETHODIMP
   152 nsSHEntry::GetAnyContentViewer(nsISHEntry **aOwnerEntry,
   153                                nsIContentViewer **aResult)
   154 {
   155   // Find a content viewer in the root node or any of its children,
   156   // assuming that there is only one content viewer total in any one
   157   // nsSHEntry tree
   158   GetContentViewer(aResult);
   159   if (*aResult) {
   160 #ifdef DEBUG_PAGE_CACHE 
   161     printf("Found content viewer\n");
   162 #endif
   163     *aOwnerEntry = this;
   164     NS_ADDREF(*aOwnerEntry);
   165     return NS_OK;
   166   }
   167   // The root SHEntry doesn't have a ContentViewer, so check child nodes
   168   for (int32_t i = 0; i < mChildren.Count(); i++) {
   169     nsISHEntry* child = mChildren[i];
   170     if (child) {
   171 #ifdef DEBUG_PAGE_CACHE
   172       printf("Evaluating SHEntry child %d\n", i);
   173 #endif
   174       child->GetAnyContentViewer(aOwnerEntry, aResult);
   175       if (*aResult) {
   176         return NS_OK;
   177       }
   178     }
   179   }
   180   return NS_OK;
   181 }
   183 NS_IMETHODIMP
   184 nsSHEntry::SetSticky(bool aSticky)
   185 {
   186   mShared->mSticky = aSticky;
   187   return NS_OK;
   188 }
   190 NS_IMETHODIMP
   191 nsSHEntry::GetSticky(bool *aSticky)
   192 {
   193   *aSticky = mShared->mSticky;
   194   return NS_OK;
   195 }
   197 NS_IMETHODIMP nsSHEntry::GetTitle(char16_t** aTitle)
   198 {
   199   // Check for empty title...
   200   if (mTitle.IsEmpty() && mURI) {
   201     // Default title is the URL.
   202     nsAutoCString spec;
   203     if (NS_SUCCEEDED(mURI->GetSpec(spec)))
   204       AppendUTF8toUTF16(spec, mTitle);
   205   }
   207   *aTitle = ToNewUnicode(mTitle);
   208   return NS_OK;
   209 }
   211 NS_IMETHODIMP nsSHEntry::SetTitle(const nsAString &aTitle)
   212 {
   213   mTitle = aTitle;
   214   return NS_OK;
   215 }
   217 NS_IMETHODIMP nsSHEntry::GetPostData(nsIInputStream** aResult)
   218 {
   219   *aResult = mPostData;
   220   NS_IF_ADDREF(*aResult);
   221   return NS_OK;
   222 }
   224 NS_IMETHODIMP nsSHEntry::SetPostData(nsIInputStream* aPostData)
   225 {
   226   mPostData = aPostData;
   227   return NS_OK;
   228 }
   230 NS_IMETHODIMP nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult)
   231 {
   232   *aResult = mShared->mLayoutHistoryState;
   233   NS_IF_ADDREF(*aResult);
   234   return NS_OK;
   235 }
   237 NS_IMETHODIMP nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState)
   238 {
   239   mShared->mLayoutHistoryState = aState;
   240   if (mShared->mLayoutHistoryState) {
   241     mShared->mLayoutHistoryState->
   242       SetScrollPositionOnly(!mShared->mSaveLayoutState);
   243   }
   245   return NS_OK;
   246 }
   248 NS_IMETHODIMP nsSHEntry::GetLoadType(uint32_t * aResult)
   249 {
   250   *aResult = mLoadType;
   251   return NS_OK;
   252 }
   254 NS_IMETHODIMP nsSHEntry::SetLoadType(uint32_t  aLoadType)
   255 {
   256   mLoadType = aLoadType;
   257   return NS_OK;
   258 }
   260 NS_IMETHODIMP nsSHEntry::GetID(uint32_t * aResult)
   261 {
   262   *aResult = mID;
   263   return NS_OK;
   264 }
   266 NS_IMETHODIMP nsSHEntry::SetID(uint32_t  aID)
   267 {
   268   mID = aID;
   269   return NS_OK;
   270 }
   272 nsSHEntryShared* nsSHEntry::GetSharedState()
   273 {
   274   return mShared;
   275 }
   277 NS_IMETHODIMP nsSHEntry::GetIsSubFrame(bool * aFlag)
   278 {
   279   *aFlag = mShared->mIsFrameNavigation;
   280   return NS_OK;
   281 }
   283 NS_IMETHODIMP nsSHEntry::SetIsSubFrame(bool    aFlag)
   284 {
   285   mShared->mIsFrameNavigation = aFlag;
   286   return NS_OK;
   287 }
   289 NS_IMETHODIMP nsSHEntry::GetCacheKey(nsISupports** aResult)
   290 {
   291   *aResult = mShared->mCacheKey;
   292   NS_IF_ADDREF(*aResult);
   293   return NS_OK;
   294 }
   296 NS_IMETHODIMP nsSHEntry::SetCacheKey(nsISupports* aCacheKey)
   297 {
   298   mShared->mCacheKey = aCacheKey;
   299   return NS_OK;
   300 }
   302 NS_IMETHODIMP nsSHEntry::GetSaveLayoutStateFlag(bool * aFlag)
   303 {
   304   *aFlag = mShared->mSaveLayoutState;
   305   return NS_OK;
   306 }
   308 NS_IMETHODIMP nsSHEntry::SetSaveLayoutStateFlag(bool    aFlag)
   309 {
   310   mShared->mSaveLayoutState = aFlag;
   311   if (mShared->mLayoutHistoryState) {
   312     mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
   313   }
   315   return NS_OK;
   316 }
   318 NS_IMETHODIMP nsSHEntry::GetExpirationStatus(bool * aFlag)
   319 {
   320   *aFlag = mShared->mExpired;
   321   return NS_OK;
   322 }
   324 NS_IMETHODIMP nsSHEntry::SetExpirationStatus(bool    aFlag)
   325 {
   326   mShared->mExpired = aFlag;
   327   return NS_OK;
   328 }
   330 NS_IMETHODIMP nsSHEntry::GetContentType(nsACString& aContentType)
   331 {
   332   aContentType = mShared->mContentType;
   333   return NS_OK;
   334 }
   336 NS_IMETHODIMP nsSHEntry::SetContentType(const nsACString& aContentType)
   337 {
   338   mShared->mContentType = aContentType;
   339   return NS_OK;
   340 }
   342 NS_IMETHODIMP
   343 nsSHEntry::Create(nsIURI * aURI, const nsAString &aTitle,
   344                   nsIInputStream * aInputStream,
   345                   nsILayoutHistoryState * aLayoutHistoryState,
   346                   nsISupports * aCacheKey, const nsACString& aContentType,
   347                   nsISupports* aOwner,
   348                   uint64_t aDocShellID, bool aDynamicCreation)
   349 {
   350   mURI = aURI;
   351   mTitle = aTitle;
   352   mPostData = aInputStream;
   354   // Set the LoadType by default to loadHistory during creation
   355   mLoadType = (uint32_t) nsIDocShellLoadInfo::loadHistory;
   357   mShared->mCacheKey = aCacheKey;
   358   mShared->mContentType = aContentType;
   359   mShared->mOwner = aOwner;
   360   mShared->mDocShellID = aDocShellID;
   361   mShared->mDynamicallyCreated = aDynamicCreation;
   363   // By default all entries are set false for subframe flag. 
   364   // nsDocShell::CloneAndReplace() which creates entries for
   365   // all subframe navigations, sets the flag to true.
   366   mShared->mIsFrameNavigation = false;
   368   // By default we save LayoutHistoryState
   369   mShared->mSaveLayoutState = true;
   370   mShared->mLayoutHistoryState = aLayoutHistoryState;
   372   //By default the page is not expired
   373   mShared->mExpired = false;
   375   mIsSrcdocEntry = false;
   376   mSrcdocData = NullString();
   378   return NS_OK;
   379 }
   381 NS_IMETHODIMP
   382 nsSHEntry::Clone(nsISHEntry ** aResult)
   383 {
   384   *aResult = new nsSHEntry(*this);
   385   NS_ADDREF(*aResult);
   386   return NS_OK;
   387 }
   389 NS_IMETHODIMP
   390 nsSHEntry::GetParent(nsISHEntry ** aResult)
   391 {
   392   NS_ENSURE_ARG_POINTER(aResult);
   393   *aResult = mParent;
   394   NS_IF_ADDREF(*aResult);
   395   return NS_OK;
   396 }
   398 NS_IMETHODIMP
   399 nsSHEntry::SetParent(nsISHEntry * aParent)
   400 {
   401   /* parent not Addrefed on purpose to avoid cyclic reference
   402    * Null parent is OK
   403    *
   404    * XXX this method should not be scriptable if this is the case!!
   405    */
   406   mParent = aParent;
   407   return NS_OK;
   408 }
   410 NS_IMETHODIMP
   411 nsSHEntry::SetWindowState(nsISupports *aState)
   412 {
   413   mShared->mWindowState = aState;
   414   return NS_OK;
   415 }
   417 NS_IMETHODIMP
   418 nsSHEntry::GetWindowState(nsISupports **aState)
   419 {
   420   NS_IF_ADDREF(*aState = mShared->mWindowState);
   421   return NS_OK;
   422 }
   424 NS_IMETHODIMP
   425 nsSHEntry::SetViewerBounds(const nsIntRect &aBounds)
   426 {
   427   mShared->mViewerBounds = aBounds;
   428   return NS_OK;
   429 }
   431 NS_IMETHODIMP
   432 nsSHEntry::GetViewerBounds(nsIntRect &aBounds)
   433 {
   434   aBounds = mShared->mViewerBounds;
   435   return NS_OK;
   436 }
   438 NS_IMETHODIMP
   439 nsSHEntry::GetOwner(nsISupports **aOwner)
   440 {
   441   NS_IF_ADDREF(*aOwner = mShared->mOwner);
   442   return NS_OK;
   443 }
   445 NS_IMETHODIMP
   446 nsSHEntry::SetOwner(nsISupports *aOwner)
   447 {
   448   mShared->mOwner = aOwner;
   449   return NS_OK;
   450 }
   452 NS_IMETHODIMP
   453 nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry **aEntry)
   454 {
   455   NS_ENSURE_ARG_POINTER(aEntry);
   456   NS_IF_ADDREF(*aEntry = mShared);
   457   return NS_OK;
   458 }
   460 bool
   461 nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry *aEntry)
   462 {
   463   return static_cast<nsIBFCacheEntry*>(mShared) == aEntry;
   464 }
   466 NS_IMETHODIMP
   467 nsSHEntry::AdoptBFCacheEntry(nsISHEntry *aEntry)
   468 {
   469   nsCOMPtr<nsISHEntryInternal> shEntry = do_QueryInterface(aEntry);
   470   NS_ENSURE_STATE(shEntry);
   472   nsSHEntryShared *shared = shEntry->GetSharedState();
   473   NS_ENSURE_STATE(shared);
   475   mShared = shared;
   476   return NS_OK;
   477 }
   479 NS_IMETHODIMP
   480 nsSHEntry::SharesDocumentWith(nsISHEntry *aEntry, bool *aOut)
   481 {
   482   NS_ENSURE_ARG_POINTER(aOut);
   484   nsCOMPtr<nsISHEntryInternal> internal = do_QueryInterface(aEntry); 
   485   NS_ENSURE_STATE(internal);
   487   *aOut = mShared == internal->GetSharedState();
   488   return NS_OK;
   489 }
   491 NS_IMETHODIMP
   492 nsSHEntry::AbandonBFCacheEntry()
   493 {
   494   mShared = nsSHEntryShared::Duplicate(mShared);
   495   return NS_OK;
   496 }
   498 NS_IMETHODIMP
   499 nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry)
   500 {
   501   *aIsSrcdocEntry = mIsSrcdocEntry;
   502   return NS_OK;
   503 }
   505 NS_IMETHODIMP
   506 nsSHEntry::GetSrcdocData(nsAString &aSrcdocData)
   507 {
   508   aSrcdocData = mSrcdocData;
   509   return NS_OK;
   510 }
   512 NS_IMETHODIMP
   513 nsSHEntry::SetSrcdocData(const nsAString &aSrcdocData)
   514 {
   515   mSrcdocData = aSrcdocData;
   516   mIsSrcdocEntry = true;
   517   return NS_OK;
   518 }
   520 NS_IMETHODIMP
   521 nsSHEntry::GetBaseURI(nsIURI **aBaseURI)
   522 {
   523   *aBaseURI = mBaseURI;
   524   NS_IF_ADDREF(*aBaseURI);
   525   return NS_OK;
   526 }
   528 NS_IMETHODIMP
   529 nsSHEntry::SetBaseURI(nsIURI *aBaseURI)
   530 {
   531   mBaseURI = aBaseURI;
   532   return NS_OK;
   533 }
   535 //*****************************************************************************
   536 //    nsSHEntry: nsISHContainer
   537 //*****************************************************************************
   539 NS_IMETHODIMP 
   540 nsSHEntry::GetChildCount(int32_t * aCount)
   541 {
   542   *aCount = mChildren.Count();
   543   return NS_OK;
   544 }
   546 NS_IMETHODIMP
   547 nsSHEntry::AddChild(nsISHEntry * aChild, int32_t aOffset)
   548 {
   549   if (aChild) {
   550     NS_ENSURE_SUCCESS(aChild->SetParent(this), NS_ERROR_FAILURE);
   551   }
   553   if (aOffset < 0) {
   554     mChildren.AppendObject(aChild);
   555     return NS_OK;
   556   }
   558   //
   559   // Bug 52670: Ensure children are added in order.
   560   //
   561   //  Later frames in the child list may load faster and get appended
   562   //  before earlier frames, causing session history to be scrambled.
   563   //  By growing the list here, they are added to the right position.
   564   //
   565   //  Assert that aOffset will not be so high as to grow us a lot.
   566   //
   567   NS_ASSERTION(aOffset < (mChildren.Count()+1023), "Large frames array!\n");
   569   bool newChildIsDyn = false;
   570   if (aChild) {
   571     aChild->IsDynamicallyAdded(&newChildIsDyn);
   572   }
   574   // If the new child is dynamically added, try to add it to aOffset, but if
   575   // there are non-dynamically added children, the child must be after those.
   576   if (newChildIsDyn) {
   577     int32_t lastNonDyn = aOffset - 1;
   578     for (int32_t i = aOffset; i < mChildren.Count(); ++i) {
   579       nsISHEntry* entry = mChildren[i];
   580       if (entry) {
   581         bool dyn = false;
   582         entry->IsDynamicallyAdded(&dyn);
   583         if (dyn) {
   584           break;
   585         } else {
   586           lastNonDyn = i;
   587         }
   588       }
   589     }
   590     // InsertObjectAt allows only appending one object.
   591     // If aOffset is larger than Count(), we must first manually
   592     // set the capacity.
   593     if (aOffset > mChildren.Count()) {
   594       mChildren.SetCount(aOffset);
   595     }
   596     if (!mChildren.InsertObjectAt(aChild, lastNonDyn + 1)) {
   597       NS_WARNING("Adding a child failed!");
   598       aChild->SetParent(nullptr);
   599       return NS_ERROR_FAILURE;
   600     }
   601   } else {
   602     // If the new child isn't dynamically added, it should be set to aOffset.
   603     // If there are dynamically added children before that, those must be
   604     // moved to be after aOffset.
   605     if (mChildren.Count() > 0) {
   606       int32_t start = std::min(mChildren.Count() - 1, aOffset);
   607       int32_t dynEntryIndex = -1;
   608       nsISHEntry* dynEntry = nullptr;
   609       for (int32_t i = start; i >= 0; --i) {
   610         nsISHEntry* entry = mChildren[i];
   611         if (entry) {
   612           bool dyn = false;
   613           entry->IsDynamicallyAdded(&dyn);
   614           if (dyn) {
   615             dynEntryIndex = i;
   616             dynEntry = entry;
   617           } else {
   618             break;
   619           }
   620         }
   621       }
   623       if (dynEntry) {
   624         nsCOMArray<nsISHEntry> tmp;
   625         tmp.SetCount(aOffset - dynEntryIndex + 1);
   626         mChildren.InsertObjectsAt(tmp, dynEntryIndex);
   627         NS_ASSERTION(mChildren[aOffset + 1] == dynEntry, "Whaat?");
   628       }
   629     }
   632     // Make sure there isn't anything at aOffset.
   633     if (aOffset < mChildren.Count()) {
   634       nsISHEntry* oldChild = mChildren[aOffset];
   635       if (oldChild && oldChild != aChild) {
   636         NS_ERROR("Adding a child where we already have a child? This may misbehave");
   637         oldChild->SetParent(nullptr);
   638       }
   639     }
   641     if (!mChildren.ReplaceObjectAt(aChild, aOffset)) {
   642       NS_WARNING("Adding a child failed!");
   643       aChild->SetParent(nullptr);
   644       return NS_ERROR_FAILURE;
   645     }
   646   }
   648   return NS_OK;
   649 }
   651 NS_IMETHODIMP
   652 nsSHEntry::RemoveChild(nsISHEntry * aChild)
   653 {
   654   NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE);
   655   bool childRemoved = false;
   656   bool dynamic = false;
   657   aChild->IsDynamicallyAdded(&dynamic);
   658   if (dynamic) {
   659     childRemoved = mChildren.RemoveObject(aChild);
   660   } else {
   661     int32_t index = mChildren.IndexOfObject(aChild);
   662     if (index >= 0) {
   663       childRemoved = mChildren.ReplaceObjectAt(nullptr, index);
   664     }
   665   }
   666   if (childRemoved) {
   667     aChild->SetParent(nullptr);
   669     // reduce the child count, i.e. remove empty children at the end
   670     for (int32_t i = mChildren.Count() - 1; i >= 0 && !mChildren[i]; --i) {
   671       if (!mChildren.RemoveObjectAt(i)) {
   672         break;
   673       }
   674     }
   675   }
   676   return NS_OK;
   677 }
   679 NS_IMETHODIMP
   680 nsSHEntry::GetChildAt(int32_t aIndex, nsISHEntry ** aResult)
   681 {
   682   if (aIndex >= 0 && aIndex < mChildren.Count()) {
   683     *aResult = mChildren[aIndex];
   684     // yes, mChildren can have holes in it.  AddChild's offset parameter makes
   685     // that possible.
   686     NS_IF_ADDREF(*aResult);
   687   } else {
   688     *aResult = nullptr;
   689   }
   690   return NS_OK;
   691 }
   693 NS_IMETHODIMP
   694 nsSHEntry::AddChildShell(nsIDocShellTreeItem *aShell)
   695 {
   696   NS_ASSERTION(aShell, "Null child shell added to history entry");
   697   mShared->mChildShells.AppendObject(aShell);
   698   return NS_OK;
   699 }
   701 NS_IMETHODIMP
   702 nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem **aShell)
   703 {
   704   NS_IF_ADDREF(*aShell = mShared->mChildShells.SafeObjectAt(aIndex));
   705   return NS_OK;
   706 }
   708 NS_IMETHODIMP
   709 nsSHEntry::ClearChildShells()
   710 {
   711   mShared->mChildShells.Clear();
   712   return NS_OK;
   713 }
   715 NS_IMETHODIMP
   716 nsSHEntry::GetRefreshURIList(nsISupportsArray **aList)
   717 {
   718   NS_IF_ADDREF(*aList = mShared->mRefreshURIList);
   719   return NS_OK;
   720 }
   722 NS_IMETHODIMP
   723 nsSHEntry::SetRefreshURIList(nsISupportsArray *aList)
   724 {
   725   mShared->mRefreshURIList = aList;
   726   return NS_OK;
   727 }
   729 NS_IMETHODIMP
   730 nsSHEntry::SyncPresentationState()
   731 {
   732   return mShared->SyncPresentationState();
   733 }
   735 void
   736 nsSHEntry::RemoveFromBFCacheSync()
   737 {
   738   mShared->RemoveFromBFCacheSync();
   739 }
   741 void
   742 nsSHEntry::RemoveFromBFCacheAsync()
   743 {
   744   mShared->RemoveFromBFCacheAsync();
   745 }
   747 nsDocShellEditorData*
   748 nsSHEntry::ForgetEditorData()
   749 {
   750   // XXX jlebar Check how this is used.
   751   return mShared->mEditorData.forget();
   752 }
   754 void
   755 nsSHEntry::SetEditorData(nsDocShellEditorData* aData)
   756 {
   757   NS_ASSERTION(!(aData && mShared->mEditorData),
   758                "We're going to overwrite an owning ref!");
   759   if (mShared->mEditorData != aData) {
   760     mShared->mEditorData = aData;
   761   }
   762 }
   764 bool
   765 nsSHEntry::HasDetachedEditor()
   766 {
   767   return mShared->mEditorData != nullptr;
   768 }
   770 NS_IMETHODIMP
   771 nsSHEntry::GetStateData(nsIStructuredCloneContainer **aContainer)
   772 {
   773   NS_ENSURE_ARG_POINTER(aContainer);
   774   NS_IF_ADDREF(*aContainer = mStateData);
   775   return NS_OK;
   776 }
   778 NS_IMETHODIMP
   779 nsSHEntry::SetStateData(nsIStructuredCloneContainer *aContainer)
   780 {
   781   mStateData = aContainer;
   782   return NS_OK;
   783 }
   785 NS_IMETHODIMP
   786 nsSHEntry::IsDynamicallyAdded(bool* aAdded)
   787 {
   788   *aAdded = mShared->mDynamicallyCreated;
   789   return NS_OK;
   790 }
   792 NS_IMETHODIMP
   793 nsSHEntry::HasDynamicallyAddedChild(bool* aAdded)
   794 {
   795   *aAdded = false;
   796   for (int32_t i = 0; i < mChildren.Count(); ++i) {
   797     nsISHEntry* entry = mChildren[i];
   798     if (entry) {
   799       entry->IsDynamicallyAdded(aAdded);
   800       if (*aAdded) {
   801         break;
   802       }
   803     }
   804   }
   805   return NS_OK;
   806 }
   808 NS_IMETHODIMP
   809 nsSHEntry::GetDocshellID(uint64_t* aID)
   810 {
   811   *aID = mShared->mDocShellID;
   812   return NS_OK;
   813 }
   815 NS_IMETHODIMP
   816 nsSHEntry::SetDocshellID(uint64_t aID)
   817 {
   818   mShared->mDocShellID = aID;
   819   return NS_OK;
   820 }
   823 NS_IMETHODIMP
   824 nsSHEntry::GetLastTouched(uint32_t *aLastTouched)
   825 {
   826   *aLastTouched = mShared->mLastTouched;
   827   return NS_OK;
   828 }
   830 NS_IMETHODIMP
   831 nsSHEntry::SetLastTouched(uint32_t aLastTouched)
   832 {
   833   mShared->mLastTouched = aLastTouched;
   834   return NS_OK;
   835 }

mercurial