LCOV - code coverage report
Current view: top level - docshell/shistory - nsSHEntryShared.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 8 126 6.3 %
Date: 2017-07-14 16:53:18 Functions: 5 28 17.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsSHEntryShared.h"
       8             : 
       9             : #include "nsArray.h"
      10             : #include "nsDocShellEditorData.h"
      11             : #include "nsIContentViewer.h"
      12             : #include "nsIDocShell.h"
      13             : #include "nsIDocShellTreeItem.h"
      14             : #include "nsIDocument.h"
      15             : #include "nsIDOMDocument.h"
      16             : #include "nsILayoutHistoryState.h"
      17             : #include "nsISHistory.h"
      18             : #include "nsISHistoryInternal.h"
      19             : #include "nsIWebNavigation.h"
      20             : #include "nsThreadUtils.h"
      21             : 
      22             : #include "mozilla/Attributes.h"
      23             : #include "mozilla/Preferences.h"
      24             : 
      25             : namespace dom = mozilla::dom;
      26             : 
      27             : namespace {
      28             : 
      29             : uint64_t gSHEntrySharedID = 0;
      30             : 
      31             : } // namespace
      32             : 
      33             : void
      34           0 : nsSHEntryShared::Shutdown()
      35             : {
      36           0 : }
      37             : 
      38           1 : nsSHEntryShared::nsSHEntryShared()
      39             :   : mDocShellID({0})
      40             :   , mLastTouched(0)
      41           1 :   , mID(gSHEntrySharedID++)
      42             :   , mViewerBounds(0, 0, 0, 0)
      43             :   , mIsFrameNavigation(false)
      44             :   , mSaveLayoutState(true)
      45             :   , mSticky(true)
      46             :   , mDynamicallyCreated(false)
      47           2 :   , mExpired(false)
      48             : {
      49           1 : }
      50             : 
      51           0 : nsSHEntryShared::~nsSHEntryShared()
      52             : {
      53           0 :   RemoveFromExpirationTracker();
      54           0 :   if (mContentViewer) {
      55           0 :     RemoveFromBFCacheSync();
      56             :   }
      57           0 : }
      58             : 
      59          22 : NS_IMPL_ISUPPORTS(nsSHEntryShared, nsIBFCacheEntry, nsIMutationObserver)
      60             : 
      61             : already_AddRefed<nsSHEntryShared>
      62           0 : nsSHEntryShared::Duplicate(nsSHEntryShared* aEntry)
      63             : {
      64           0 :   RefPtr<nsSHEntryShared> newEntry = new nsSHEntryShared();
      65             : 
      66           0 :   newEntry->mDocShellID = aEntry->mDocShellID;
      67           0 :   newEntry->mChildShells.AppendObjects(aEntry->mChildShells);
      68           0 :   newEntry->mTriggeringPrincipal = aEntry->mTriggeringPrincipal;
      69           0 :   newEntry->mPrincipalToInherit = aEntry->mPrincipalToInherit;
      70           0 :   newEntry->mContentType.Assign(aEntry->mContentType);
      71           0 :   newEntry->mIsFrameNavigation = aEntry->mIsFrameNavigation;
      72           0 :   newEntry->mSaveLayoutState = aEntry->mSaveLayoutState;
      73           0 :   newEntry->mSticky = aEntry->mSticky;
      74           0 :   newEntry->mDynamicallyCreated = aEntry->mDynamicallyCreated;
      75           0 :   newEntry->mCacheKey = aEntry->mCacheKey;
      76           0 :   newEntry->mLastTouched = aEntry->mLastTouched;
      77             : 
      78           0 :   return newEntry.forget();
      79             : }
      80             : 
      81             : void
      82           0 : nsSHEntryShared::RemoveFromExpirationTracker()
      83             : {
      84           0 :   nsCOMPtr<nsISHistoryInternal> shistory = do_QueryReferent(mSHistory);
      85           0 :   if (shistory && GetExpirationState()->IsTracked()) {
      86           0 :     shistory->RemoveFromExpirationTracker(this);
      87             :   }
      88           0 : }
      89             : 
      90             : nsresult
      91           0 : nsSHEntryShared::SyncPresentationState()
      92             : {
      93           0 :   if (mContentViewer && mWindowState) {
      94             :     // If we have a content viewer and a window state, we should be ok.
      95           0 :     return NS_OK;
      96             :   }
      97             : 
      98           0 :   DropPresentationState();
      99             : 
     100           0 :   return NS_OK;
     101             : }
     102             : 
     103             : void
     104           0 : nsSHEntryShared::DropPresentationState()
     105             : {
     106           0 :   RefPtr<nsSHEntryShared> kungFuDeathGrip = this;
     107             : 
     108           0 :   if (mDocument) {
     109           0 :     mDocument->SetBFCacheEntry(nullptr);
     110           0 :     mDocument->RemoveMutationObserver(this);
     111           0 :     mDocument = nullptr;
     112             :   }
     113           0 :   if (mContentViewer) {
     114           0 :     mContentViewer->ClearHistoryEntry();
     115             :   }
     116             : 
     117           0 :   RemoveFromExpirationTracker();
     118           0 :   mContentViewer = nullptr;
     119           0 :   mSticky = true;
     120           0 :   mWindowState = nullptr;
     121           0 :   mViewerBounds.SetRect(0, 0, 0, 0);
     122           0 :   mChildShells.Clear();
     123           0 :   mRefreshURIList = nullptr;
     124           0 :   mEditorData = nullptr;
     125           0 : }
     126             : 
     127             : nsresult
     128           0 : nsSHEntryShared::SetContentViewer(nsIContentViewer* aViewer)
     129             : {
     130           0 :   NS_PRECONDITION(!aViewer || !mContentViewer,
     131             :                   "SHEntryShared already contains viewer");
     132             : 
     133           0 :   if (mContentViewer || !aViewer) {
     134           0 :     DropPresentationState();
     135             :   }
     136             : 
     137             :   // If we're setting mContentViewer to null, state should already be cleared
     138             :   // in the DropPresentationState() call above; If we're setting it to a
     139             :   // non-null content viewer, the entry shouldn't have been tracked either.
     140           0 :   MOZ_ASSERT(!GetExpirationState()->IsTracked());
     141           0 :   mContentViewer = aViewer;
     142             : 
     143           0 :   if (mContentViewer) {
     144             :     // mSHistory is only set for root entries, but in general bfcache only
     145             :     // applies to root entries as well. BFCache for subframe navigation has been
     146             :     // disabled since 2005 in bug 304860.
     147           0 :     nsCOMPtr<nsISHistoryInternal> shistory = do_QueryReferent(mSHistory);
     148           0 :     if (shistory) {
     149           0 :       shistory->AddToExpirationTracker(this);
     150             :     }
     151             : 
     152           0 :     nsCOMPtr<nsIDOMDocument> domDoc;
     153           0 :     mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
     154             :     // Store observed document in strong pointer in case it is removed from
     155             :     // the contentviewer
     156           0 :     mDocument = do_QueryInterface(domDoc);
     157           0 :     if (mDocument) {
     158           0 :       mDocument->SetBFCacheEntry(this);
     159           0 :       mDocument->AddMutationObserver(this);
     160             :     }
     161             :   }
     162             : 
     163           0 :   return NS_OK;
     164             : }
     165             : 
     166             : nsresult
     167           0 : nsSHEntryShared::RemoveFromBFCacheSync()
     168             : {
     169           0 :   MOZ_ASSERT(mContentViewer && mDocument, "we're not in the bfcache!");
     170             : 
     171           0 :   nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
     172           0 :   DropPresentationState();
     173             : 
     174             :   // Warning! The call to DropPresentationState could have dropped the last
     175             :   // reference to this object, so don't access members beyond here.
     176             : 
     177           0 :   if (viewer) {
     178           0 :     viewer->Destroy();
     179             :   }
     180             : 
     181           0 :   return NS_OK;
     182             : }
     183             : 
     184           0 : class DestroyViewerEvent : public mozilla::Runnable
     185             : {
     186             : public:
     187           0 :   DestroyViewerEvent(nsIContentViewer* aViewer, nsIDocument* aDocument)
     188           0 :     : mozilla::Runnable("DestroyViewerEvent")
     189             :     , mViewer(aViewer)
     190           0 :     , mDocument(aDocument)
     191             :   {
     192           0 :   }
     193             : 
     194           0 :   NS_IMETHOD Run() override
     195             :   {
     196           0 :     if (mViewer) {
     197           0 :       mViewer->Destroy();
     198             :     }
     199           0 :     return NS_OK;
     200             :   }
     201             : 
     202             :   nsCOMPtr<nsIContentViewer> mViewer;
     203             :   nsCOMPtr<nsIDocument> mDocument;
     204             : };
     205             : 
     206             : nsresult
     207           0 : nsSHEntryShared::RemoveFromBFCacheAsync()
     208             : {
     209           0 :   MOZ_ASSERT(mContentViewer && mDocument, "we're not in the bfcache!");
     210             : 
     211             :   // Release the reference to the contentviewer asynchronously so that the
     212             :   // document doesn't get nuked mid-mutation.
     213             : 
     214           0 :   if (!mDocument) {
     215           0 :     return NS_ERROR_UNEXPECTED;
     216             :   }
     217           0 :   nsCOMPtr<nsIRunnable> evt = new DestroyViewerEvent(mContentViewer, mDocument);
     218           0 :   nsresult rv = mDocument->Dispatch("nsSHEntryShared::DestroyViewerEvent",
     219           0 :                                     mozilla::TaskCategory::Other, evt.forget());
     220           0 :   if (NS_FAILED(rv)) {
     221           0 :     NS_WARNING("failed to dispatch DestroyViewerEvent");
     222             :   } else {
     223             :     // Drop presentation. Only do this if we succeeded in posting the event
     224             :     // since otherwise the document could be torn down mid-mutation, causing
     225             :     // crashes.
     226           0 :     DropPresentationState();
     227             :   }
     228             : 
     229             :   // Careful! The call to DropPresentationState could have dropped the last
     230             :   // reference to this nsSHEntryShared, so don't access members beyond here.
     231             : 
     232           0 :   return NS_OK;
     233             : }
     234             : 
     235             : nsresult
     236           2 : nsSHEntryShared::GetID(uint64_t* aID)
     237             : {
     238           2 :   *aID = mID;
     239           2 :   return NS_OK;
     240             : }
     241             : 
     242             : void
     243           0 : nsSHEntryShared::NodeWillBeDestroyed(const nsINode* aNode)
     244             : {
     245           0 :   NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
     246           0 : }
     247             : 
     248             : void
     249           0 : nsSHEntryShared::CharacterDataWillChange(nsIDocument* aDocument,
     250             :                                          nsIContent* aContent,
     251             :                                          CharacterDataChangeInfo* aInfo)
     252             : {
     253           0 : }
     254             : 
     255             : void
     256           0 : nsSHEntryShared::CharacterDataChanged(nsIDocument* aDocument,
     257             :                                       nsIContent* aContent,
     258             :                                       CharacterDataChangeInfo* aInfo)
     259             : {
     260           0 :   RemoveFromBFCacheAsync();
     261           0 : }
     262             : 
     263             : void
     264           0 : nsSHEntryShared::AttributeWillChange(nsIDocument* aDocument,
     265             :                                      dom::Element* aContent,
     266             :                                      int32_t aNameSpaceID,
     267             :                                      nsIAtom* aAttribute,
     268             :                                      int32_t aModType,
     269             :                                      const nsAttrValue* aNewValue)
     270             : {
     271           0 : }
     272             : 
     273             : void
     274           0 : nsSHEntryShared::NativeAnonymousChildListChange(nsIDocument* aDocument,
     275             :                                                 nsIContent* aContent,
     276             :                                                 bool aIsRemove)
     277             : {
     278           0 : }
     279             : 
     280             : void
     281           0 : nsSHEntryShared::AttributeChanged(nsIDocument* aDocument,
     282             :                                   dom::Element* aElement,
     283             :                                   int32_t aNameSpaceID,
     284             :                                   nsIAtom* aAttribute,
     285             :                                   int32_t aModType,
     286             :                                   const nsAttrValue* aOldValue)
     287             : {
     288           0 :   RemoveFromBFCacheAsync();
     289           0 : }
     290             : 
     291             : void
     292           0 : nsSHEntryShared::ContentAppended(nsIDocument* aDocument,
     293             :                                  nsIContent* aContainer,
     294             :                                  nsIContent* aFirstNewContent,
     295             :                                  int32_t /* unused */)
     296             : {
     297           0 :   RemoveFromBFCacheAsync();
     298           0 : }
     299             : 
     300             : void
     301           0 : nsSHEntryShared::ContentInserted(nsIDocument* aDocument,
     302             :                                  nsIContent* aContainer,
     303             :                                  nsIContent* aChild,
     304             :                                  int32_t /* unused */)
     305             : {
     306           0 :   RemoveFromBFCacheAsync();
     307           0 : }
     308             : 
     309             : void
     310           0 : nsSHEntryShared::ContentRemoved(nsIDocument* aDocument,
     311             :                                 nsIContent* aContainer,
     312             :                                 nsIContent* aChild,
     313             :                                 int32_t aIndexInContainer,
     314             :                                 nsIContent* aPreviousSibling)
     315             : {
     316           0 :   RemoveFromBFCacheAsync();
     317           0 : }
     318             : 
     319             : void
     320           0 : nsSHEntryShared::ParentChainChanged(nsIContent* aContent)
     321             : {
     322           0 : }

Generated by: LCOV version 1.13