Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
void nsSHEntryShared::SyncPresentationState() {
  if (mContentViewer && mWindowState) {
    // If we have a content viewer and a window state, we should be ok.
    return;
  }

  DropPresentationState();
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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();
  }
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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.
}