LCOV - code coverage report
Current view: directory - docshell/shistory/src - nsSHEntry.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 352 0 0.0 %
Date: 2012-06-02 Functions: 79 0 0.0 %

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

Generated by: LCOV version 1.7