nsSHEntry::~nsSHEntry() { StopTrackingEntry(this); // Since we never really remove kids from SHEntrys, we need to null // out the mParent pointers on all our kids. mChildren.EnumerateForwards(ClearParentPtr, nsnull); mChildren.Clear(); nsCOMPtr<nsIContentViewer> viewer = mContentViewer; DropPresentationState(); if (viewer) { viewer->Destroy(); } mEditorData = nsnull; #ifdef DEBUG // This is not happening as far as I can tell from breakpad as of early November 2007 nsExpirationTracker<nsSHEntry,3>::Iterator iterator(gHistoryTracker); nsSHEntry* elem; while ((elem = iterator.Next()) != nsnull) { NS_ASSERTION(elem != this, "Found dead entry still in the tracker!"); } #endif }
NS_IMETHODIMP nsSHEntry::SetContentViewer(nsIContentViewer *aViewer) { NS_PRECONDITION(!aViewer || !mContentViewer, "SHEntry already contains viewer"); if (mContentViewer || !aViewer) { DropPresentationState(); } mContentViewer = aViewer; if (mContentViewer) { gHistoryTracker->AddObject(this); nsCOMPtr<nsIDOMDocument> domDoc; mContentViewer->GetDOMDocument(getter_AddRefs(domDoc)); // Store observed document in strong pointer in case it is removed from // the contentviewer mDocument = do_QueryInterface(domDoc); if (mDocument) { mDocument->SetShellsHidden(PR_TRUE); mDocument->AddMutationObserver(this); } } return NS_OK; }
nsresult nsSHEntryShared::SetContentViewer(nsIContentViewer* aViewer) { MOZ_ASSERT(!aViewer || !mContentViewer, "SHEntryShared already contains viewer"); if (mContentViewer || !aViewer) { DropPresentationState(); } // If we're setting mContentViewer to null, state should already be cleared // in the DropPresentationState() call above; If we're setting it to a // non-null content viewer, the entry shouldn't have been tracked either. MOZ_ASSERT(!GetExpirationState()->IsTracked()); mContentViewer = aViewer; if (mContentViewer) { // mSHistory is only set for root entries, but in general bfcache only // applies to root entries as well. BFCache for subframe navigation has been // disabled since 2005 in bug 304860. if (nsCOMPtr<nsISHistory> shistory = do_QueryReferent(mSHistory)) { shistory->AddToExpirationTracker(this); } // Store observed document in strong pointer in case it is removed from // the contentviewer mDocument = mContentViewer->GetDocument(); if (mDocument) { mDocument->SetBFCacheEntry(this); mDocument->AddMutationObserver(this); } } return NS_OK; }
nsresult nsSHEntryShared::RemoveFromBFCacheSync() { MOZ_ASSERT(mContentViewer && mDocument, "we're not in the bfcache!"); // The call to DropPresentationState could drop the last reference, so hold // |this| until RemoveDynEntriesForBFCacheEntry finishes. RefPtr<nsSHEntryShared> kungFuDeathGrip = this; // DropPresentationState would clear mContentViewer. nsCOMPtr<nsIContentViewer> viewer = mContentViewer; DropPresentationState(); if (viewer) { viewer->Destroy(); } // Now that we've dropped the viewer, we have to clear associated dynamic // subframe entries. nsCOMPtr<nsISHistory> shistory = do_QueryReferent(mSHistory); if (shistory) { shistory->RemoveDynEntriesForBFCacheEntry(this); } return NS_OK; }
nsresult nsSHEntryShared::RemoveFromBFCacheAsync() { NS_ASSERTION(mContentViewer && mDocument, "we're not in the bfcache!"); // Release the reference to the contentviewer asynchronously so that the // document doesn't get nuked mid-mutation. nsCOMPtr<nsIRunnable> evt = new DestroyViewerEvent(mContentViewer, mDocument); nsresult rv = NS_DispatchToCurrentThread(evt); if (NS_FAILED(rv)) { NS_WARNING("failed to dispatch DestroyViewerEvent"); } else { // Drop presentation. Only do this if we succeeded in posting the event // since otherwise the document could be torn down mid-mutation, causing // crashes. DropPresentationState(); } // Careful! The call to DropPresentationState could have dropped the last // reference to this nsSHEntryShared, so don't access members beyond here. return NS_OK; }
void nsSHEntryShared::SyncPresentationState() { if (mContentViewer && mWindowState) { // If we have a content viewer and a window state, we should be ok. return; } DropPresentationState(); }
NS_IMETHODIMP nsSHEntry::SyncPresentationState() { if (mContentViewer && mWindowState) { // If we have a content viewer and a window state, we should be ok. return NS_OK; } DropPresentationState(); return NS_OK; }
void nsSHEntry::RemoveFromBFCacheSync() { NS_ASSERTION(mContentViewer && mDocument, "we're not in the bfcache!"); nsCOMPtr<nsIContentViewer> viewer = mContentViewer; DropPresentationState(); // Warning! The call to DropPresentationState could have dropped the last // reference to this nsSHEntry, so no accessing members beyond here. if (viewer) { viewer->Destroy(); } }
nsresult nsSHEntryShared::RemoveFromBFCacheSync() { NS_ASSERTION(mContentViewer && mDocument, "we're not in the bfcache!"); nsCOMPtr<nsIContentViewer> viewer = mContentViewer; DropPresentationState(); // Warning! The call to DropPresentationState could have dropped the last // reference to this object, so don't access members beyond here. if (viewer) { viewer->Destroy(); } return NS_OK; }
nsresult nsSHEntryShared::RemoveFromBFCacheAsync() { MOZ_ASSERT(mContentViewer && mDocument, "we're not in the bfcache!"); // Check it again to play safe in release builds. if (!mDocument) { return NS_ERROR_UNEXPECTED; } // DropPresentationState would clear mContentViewer & mDocument. Capture and // release the references asynchronously so that the document doesn't get // nuked mid-mutation. nsCOMPtr<nsIContentViewer> viewer = mContentViewer; nsCOMPtr<nsIDocument> document = mDocument; RefPtr<nsSHEntryShared> self = this; nsresult rv = mDocument->Dispatch( mozilla::TaskCategory::Other, NS_NewRunnableFunction( "nsSHEntryShared::RemoveFromBFCacheAsync", [self, viewer, document]() { if (viewer) { viewer->Destroy(); } nsCOMPtr<nsISHistory> shistory = do_QueryReferent(self->mSHistory); if (shistory) { shistory->RemoveDynEntriesForBFCacheEntry(self); } })); if (NS_FAILED(rv)) { NS_WARNING("Failed to dispatch RemoveFromBFCacheAsync runnable."); } else { // Drop presentation. Only do this if we succeeded in posting the event // since otherwise the document could be torn down mid-mutation, causing // crashes. DropPresentationState(); } return NS_OK; }
void nsSHEntry::DocumentMutated() { NS_ASSERTION(mContentViewer && mDocument, "we shouldn't still be observing the doc"); // Release the reference to the contentviewer asynchronously so that the // document doesn't get nuked mid-mutation. nsCOMPtr<nsIRunnable> evt = new DestroyViewerEvent(mContentViewer, mDocument); nsresult rv = NS_DispatchToCurrentThread(evt); if (NS_FAILED(rv)) { NS_WARNING("failed to dispatch DestroyViewerEvent"); } else { // Drop presentation. Also ensures that we don't post more then one // PLEvent. Only do this if we succeeded in posting the event since // otherwise the document could be torn down mid mutation causing crashes. DropPresentationState(); } // Warning! The call to DropPresentationState could have dropped the last // reference to this nsSHEntry, so no accessing members beyond here. }