Bugs 292962 and 311269: Make pages in bf cache not behave as if they have a presentation, and evict pages from the bf cache synchronously if they are modified.

r/sr=bryner


git-svn-id: svn://10.0.0.236/trunk@181785 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
cvshook%sicking.cc 2005-10-07 20:20:52 +00:00
parent f8250e3905
commit 103f17eb41
7 changed files with 103 additions and 82 deletions

View File

@ -93,8 +93,8 @@ class nsILayoutHistoryState;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0x6a524f45, 0x4e21, 0x4049, \
{ 0xb3, 0x57, 0x2d, 0x29, 0x75, 0x76, 0x7a, 0x43 } }
{ 0x977a6eea, 0xd06f, 0x43fd, \
{ 0xa5, 0x7e, 0xe8, 0xad, 0x4d, 0x64, 0x02, 0x43 } }
// The base value for the content ID counter.
// This counter is used by the document to
@ -290,6 +290,7 @@ public:
virtual PRBool DeleteShell(nsIPresShell* aShell) = 0;
virtual PRUint32 GetNumberOfShells() const = 0;
virtual nsIPresShell *GetShellAt(PRUint32 aIndex) const = 0;
virtual void SetShellsHidden(PRBool aHide) = 0;
/**
* Return the parent document of this document. Will return null

View File

@ -1042,8 +1042,8 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
PRBool applicable;
sheet->GetApplicable(applicable);
if (applicable) {
for (PRInt32 i = 0, i_end = mPresShells.Count(); i < i_end; ++i) {
NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(i))->StyleSet()->
for (PRInt32 i = 0, i_end = GetNumberOfShells(); i < i_end; ++i) {
GetShellAt(i)->StyleSet()->
RemoveStyleSheet(nsStyleSet::eAgentSheet, sheet);
}
}
@ -1063,9 +1063,9 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
nsStyleSet::sheetType attrSheetType = GetAttrSheetType();
if (mAttrStyleSheet) {
// Remove this sheet from all style sets
PRInt32 count = mPresShells.Count();
PRInt32 count = GetNumberOfShells();
for (indx = 0; indx < count; ++indx) {
NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(indx))->StyleSet()->
GetShellAt(indx)->StyleSet()->
RemoveStyleSheet(attrSheetType, mAttrStyleSheet);
}
rv = mAttrStyleSheet->Reset(aURI);
@ -1080,9 +1080,9 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
if (mStyleAttrStyleSheet) {
// Remove this sheet from all style sets
PRInt32 count = mPresShells.Count();
PRInt32 count = GetNumberOfShells();
for (indx = 0; indx < count; ++indx) {
NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(indx))->StyleSet()->
GetShellAt(indx)->StyleSet()->
RemoveStyleSheet(nsStyleSet::eStyleAttrSheet, mStyleAttrStyleSheet);
}
rv = mStyleAttrStyleSheet->Reset(aURI);
@ -1097,10 +1097,9 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
mStyleAttrStyleSheet->SetOwningDocument(this);
// Now set up our style sets
PRInt32 count = mPresShells.Count();
PRInt32 count = GetNumberOfShells();
for (indx = 0; indx < count; ++indx) {
FillStyleSet(NS_STATIC_CAST(nsIPresShell*,
mPresShells.ElementAt(indx))->StyleSet());
FillStyleSet(GetShellAt(indx)->StyleSet());
}
return rv;
@ -1485,7 +1484,9 @@ nsDocument::doCreateShell(nsPresContext* aContext,
nsIPresShell** aInstancePtrResult)
{
*aInstancePtrResult = nsnull;
NS_ENSURE_FALSE(mShellsAreHidden, NS_ERROR_FAILURE);
FillStyleSet(aStyleSet);
nsCOMPtr<nsIPresShell> shell;
@ -1513,13 +1514,20 @@ nsDocument::DeleteShell(nsIPresShell* aShell)
PRUint32
nsDocument::GetNumberOfShells() const
{
return mPresShells.Count();
return mShellsAreHidden ? 0 : mPresShells.Count();
}
nsIPresShell *
nsDocument::GetShellAt(PRUint32 aIndex) const
{
return (nsIPresShell*)mPresShells.SafeElementAt(aIndex);
return mShellsAreHidden ? nsnull :
NS_STATIC_CAST(nsIPresShell*, mPresShells.SafeElementAt(aIndex));
}
void
nsDocument::SetShellsHidden(PRBool aHide)
{
mShellsAreHidden = aHide;
}
PR_STATIC_CALLBACK(void)
@ -1738,11 +1746,10 @@ nsDocument::GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const
void
nsDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet)
{
PRInt32 count = mPresShells.Count();
PRInt32 count = GetNumberOfShells();
PRInt32 indx;
for (indx = 0; indx < count; ++indx) {
NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(indx))->StyleSet()->
AddDocStyleSheet(aSheet, this);
GetShellAt(indx)->StyleSet()->AddDocStyleSheet(aSheet, this);
}
}
@ -1773,8 +1780,8 @@ nsDocument::AddStyleSheet(nsIStyleSheet* aSheet)
void
nsDocument::RemoveStyleSheetFromStyleSets(nsIStyleSheet* aSheet)
{
for (PRInt32 i = 0, i_end = mPresShells.Count(); i < i_end; ++i)
NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(i))->StyleSet()->
for (PRInt32 i = 0, i_end = GetNumberOfShells(); i < i_end; ++i)
GetShellAt(i)->StyleSet()->
RemoveStyleSheet(nsStyleSet::eDocSheet, aSheet);
}
@ -1949,8 +1956,8 @@ nsDocument::AddCatalogStyleSheet(nsIStyleSheet* aSheet)
if (applicable) {
// This is like |AddStyleSheetToStyleSets|, but for an agent sheet.
for (PRInt32 i = 0, i_end = mPresShells.Count(); i < i_end; ++i)
NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(i))->StyleSet()->
for (PRInt32 i = 0, i_end = GetNumberOfShells(); i < i_end; ++i)
GetShellAt(i)->StyleSet()->
AppendStyleSheet(nsStyleSet::eAgentSheet, aSheet);
}
@ -3157,9 +3164,8 @@ nsDocument::GetTitle(nsAString& aTitle)
NS_IMETHODIMP
nsDocument::SetTitle(const nsAString& aTitle)
{
for (PRInt32 i = mPresShells.Count() - 1; i >= 0; --i) {
nsCOMPtr<nsIPresShell> shell =
NS_STATIC_CAST(nsIPresShell*, mPresShells[i]);
for (PRInt32 i = GetNumberOfShells() - 1; i >= 0; --i) {
nsCOMPtr<nsIPresShell> shell = GetShellAt(i);
nsCOMPtr<nsISupports> container = shell->GetPresContext()->GetContainer();
if (!container)
@ -3312,7 +3318,7 @@ static const DirTable dirAttributes[] = {
NS_IMETHODIMP
nsDocument::GetDir(nsAString& aDirection)
{
nsCOMPtr<nsIPresShell> shell = (nsIPresShell*)mPresShells.SafeElementAt(0);
nsCOMPtr<nsIPresShell> shell = GetShellAt(0);
if (shell) {
nsPresContext *context = shell->GetPresContext();
if (context) {
@ -3337,8 +3343,7 @@ nsDocument::GetDir(nsAString& aDirection)
NS_IMETHODIMP
nsDocument::SetDir(const nsAString& aDirection)
{
nsIPresShell *shell =
NS_STATIC_CAST(nsIPresShell *, mPresShells.SafeElementAt(0));
nsIPresShell *shell = GetShellAt(0);
if (!shell) {
return NS_OK;
@ -4283,11 +4288,10 @@ nsDocument::FlushPendingNotifications(mozFlushType aType)
}
}
PRInt32 i, count = mPresShells.Count();
PRInt32 i, count = GetNumberOfShells();
for (i = 0; i < count; i++) {
nsCOMPtr<nsIPresShell> shell =
NS_STATIC_CAST(nsIPresShell*, mPresShells[i]);
nsCOMPtr<nsIPresShell> shell = GetShellAt(i);
if (shell) {
shell->FlushPendingNotifications(aType);
@ -4720,10 +4724,9 @@ PRBool
nsDocument::IsSafeToFlush() const
{
PRBool isSafeToFlush = PR_TRUE;
PRInt32 i = 0, n = mPresShells.Count();
PRInt32 i = 0, n = GetNumberOfShells();
while (i < n && isSafeToFlush) {
nsCOMPtr<nsIPresShell> shell =
NS_STATIC_CAST(nsIPresShell*, mPresShells[i]);
nsCOMPtr<nsIPresShell> shell = GetShellAt(i);
if (shell) {
shell->IsSafeToFlush(isSafeToFlush);
@ -4953,9 +4956,8 @@ nsDocument::Destroy()
// content as well. This ensures that there aren't any accidental references
// left in anonymous content keeping the document alive. (While not strictly
// necessary -- the PresShell owns us -- it's tidy.)
for (count = mPresShells.Count() - 1; count >= 0; --count) {
nsCOMPtr<nsIPresShell> shell =
NS_STATIC_CAST(nsIPresShell*, mPresShells[count]);
for (count = GetNumberOfShells() - 1; count >= 0; --count) {
nsCOMPtr<nsIPresShell> shell = GetShellAt(count);
if (!shell)
continue;
@ -5116,7 +5118,7 @@ nsDocument::OnPageShow(PRBool aPersisted)
}
}
nsIPresShell *shell = NS_STATIC_CAST(nsIPresShell*, mPresShells[0]);
nsIPresShell *shell = GetShellAt(0);
if (shell && mScriptGlobalObject) {
nsPresContext *pc = shell->GetPresContext();
if (pc) {
@ -5152,7 +5154,7 @@ nsDocument::OnPageHide(PRBool aPersisted)
}
// Now send out a PageHide event.
nsIPresShell *shell = NS_STATIC_CAST(nsIPresShell*, mPresShells[0]);
nsIPresShell *shell = GetShellAt(0);
if (shell && mScriptGlobalObject) {
nsPresContext *pc = shell->GetPresContext();
if (pc) {

View File

@ -383,6 +383,7 @@ public:
virtual PRBool DeleteShell(nsIPresShell* aShell);
virtual PRUint32 GetNumberOfShells() const;
virtual nsIPresShell *GetShellAt(PRUint32 aIndex) const;
virtual void SetShellsHidden(PRBool aHide);
virtual nsresult SetSubDocumentFor(nsIContent *aContent,
nsIDocument* aSubDoc);
@ -698,8 +699,6 @@ protected:
PLDHashTable *mSubDocuments;
nsSmallVoidArray mPresShells;
// Array of owning references to all children
nsAttrAndChildArray mChildren;
@ -734,6 +733,8 @@ protected:
// True if the document "page" is not hidden
PRPackedBool mVisible:1;
PRPackedBool mShellsAreHidden:1;
PRUint8 mXMLDeclarationBits;
PRUint8 mDefaultElementType;
@ -762,6 +763,8 @@ private:
nsDocument(const nsDocument& aOther);
nsDocument& operator=(const nsDocument& aOther);
nsSmallVoidArray mPresShells;
nsXPathDocumentTearoff* mXPathDocument;
// The layout history state that should be used by nodes in this

View File

@ -1074,7 +1074,7 @@ nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode)
mCompatMode = aMode;
CSSLoader()->SetCompatibilityMode(mCompatMode);
nsCOMPtr<nsIPresShell> shell = (nsIPresShell*)mPresShells.SafeElementAt(0);
nsCOMPtr<nsIPresShell> shell = GetShellAt(0);
if (shell) {
nsPresContext *pc = shell->GetPresContext();
if (pc) {

View File

@ -1055,10 +1055,9 @@ nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster,
// |onbroadcast| event handler
nsEvent event(PR_TRUE, NS_XUL_BROADCAST);
PRInt32 j = mPresShells.Count();
PRInt32 j = GetNumberOfShells();
while (--j >= 0) {
nsCOMPtr<nsIPresShell> shell =
NS_STATIC_CAST(nsIPresShell*, mPresShells[j]);
nsCOMPtr<nsIPresShell> shell = GetShellAt(j);
nsCOMPtr<nsPresContext> aPresContext = shell->GetPresContext();

View File

@ -114,9 +114,12 @@ nsSHEntry::~nsSHEntry()
// out the mParent pointers on all our kids.
mChildren.EnumerateForwards(ClearParentPtr, nsnull);
mChildren.Clear();
RemoveDocumentObserver();
if (mContentViewer)
mContentViewer->Destroy();
nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
DropPresentationState();
if (viewer) {
viewer->Destroy();
}
}
//*****************************************************************************
@ -173,10 +176,14 @@ NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
NS_IMETHODIMP
nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
{
RemoveDocumentObserver();
NS_PRECONDITION(!aViewer || !mContentViewer, "SHEntry already contains viewer");
if (!aViewer) {
DropPresentationState();
}
mContentViewer = aViewer;
mDocument = nsnull;
if (mContentViewer) {
nsCOMPtr<nsIDOMDocument> domDoc;
mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
@ -184,6 +191,7 @@ nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
// the contentviewer
mDocument = do_QueryInterface(domDoc);
if (mDocument) {
mDocument->SetShellsHidden(PR_TRUE);
mDocument->AddObserver(this);
}
}
@ -606,12 +614,17 @@ nsSHEntry::SyncPresentationState()
void
nsSHEntry::DropPresentationState()
{
RemoveDocumentObserver();
nsRefPtr<nsSHEntry> kungFuDeathGrip = this;
if (mDocument) {
mDocument->SetShellsHidden(PR_FALSE);
mDocument->RemoveObserver(this);
mDocument = nsnull;
}
if (mContentViewer)
mContentViewer->ClearHistoryEntry();
mContentViewer = nsnull;
mDocument = nsnull;
mSticky = PR_TRUE;
mWindowState = nsnull;
mViewerBounds.SetRect(0, 0, 0, 0);
@ -619,15 +632,6 @@ nsSHEntry::DropPresentationState()
mRefreshURIList = nsnull;
}
void
nsSHEntry::RemoveDocumentObserver()
{
if (mDocument) {
mDocument->RemoveObserver(this);
mDocument = nsnull;
}
}
//*****************************************************************************
// nsSHEntry: nsIDocumentObserver
//*****************************************************************************
@ -682,39 +686,39 @@ nsSHEntry::ContentRemoved(nsIDocument* aDocument,
DocumentMutated();
}
class DropPresentationEvent : public PLEvent
class DestroyViewerEvent : public PLEvent
{
public:
DropPresentationEvent(nsSHEntry* aSHEntry);
DestroyViewerEvent(nsIContentViewer* aViewer, nsIDocument* aDocument);
nsRefPtr<nsSHEntry> mSHEntry;
nsCOMPtr<nsIContentViewer> mViewer;
nsCOMPtr<nsIDocument> mDocument;
};
PR_STATIC_CALLBACK(void*)
HandleDropPresentationEvent(PLEvent *aEvent)
HandleDestroyViewerEvent(PLEvent *aEvent)
{
nsSHEntry* entry = NS_STATIC_CAST(DropPresentationEvent*, aEvent)->mSHEntry;
nsCOMPtr<nsIContentViewer> viewer;
entry->GetContentViewer(getter_AddRefs(viewer));
nsIContentViewer* viewer = NS_STATIC_CAST(DestroyViewerEvent*, aEvent)->mViewer;
if (viewer) {
viewer->Destroy();
}
entry->DropPresentationState();
return nsnull;
}
PR_STATIC_CALLBACK(void)
DestroyDropPresentationEvent(PLEvent *aEvent)
DestroyDestroyViewerEvent(PLEvent *aEvent)
{
delete NS_STATIC_CAST(DropPresentationEvent*, aEvent);
delete NS_STATIC_CAST(DestroyViewerEvent*, aEvent);
}
DropPresentationEvent::DropPresentationEvent(nsSHEntry* aSHEntry)
: mSHEntry(aSHEntry)
DestroyViewerEvent::DestroyViewerEvent(nsIContentViewer* aViewer,
nsIDocument* aDocument)
: mViewer(aViewer),
mDocument(aDocument)
{
PL_InitEvent(this, mSHEntry, ::HandleDropPresentationEvent,
::DestroyDropPresentationEvent);
PL_InitEvent(this, mViewer, ::HandleDestroyViewerEvent,
::DestroyDestroyViewerEvent);
}
void
@ -731,7 +735,7 @@ nsSHEntry::DocumentMutated()
return;
}
PLEvent *evt = new DropPresentationEvent(this);
PLEvent *evt = new DestroyViewerEvent(mContentViewer, mDocument);
if (!evt) {
return;
}
@ -740,7 +744,12 @@ nsSHEntry::DocumentMutated()
if (NS_FAILED(rv)) {
PL_DestroyEvent(evt);
}
// Ensure that we don't post more then one PLEvent
RemoveDocumentObserver();
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.
}

View File

@ -1344,7 +1344,7 @@ DocumentViewerImpl::Destroy()
mSHEntry->SetSticky(mIsSticky);
mIsSticky = PR_TRUE;
mSHEntry->SetContentViewer(this);
PRBool savePresentation = PR_TRUE;
// Remove our root view from the view hierarchy.
if (mPresShell) {
@ -1371,13 +1371,20 @@ DocumentViewerImpl::Destroy()
if (mDocument) {
nsresult rv = mDocument->Sanitize();
if (NS_FAILED(rv)) {
// If we failed to sanitize, remove the document immediately.
mSHEntry->SetContentViewer(nsnull);
mSHEntry->SyncPresentationState();
// If we failed to sanitize, don't save presentation.
savePresentation = PR_FALSE;
}
}
// Reverse ownership. Do this *after* calling sanitize so that sanitize
// doesn't cause mutations that make the SHEntry drop the presentation
if (savePresentation) {
mSHEntry->SetContentViewer(this);
}
else {
mSHEntry->SyncPresentationState();
}
mSHEntry = nsnull;
// Break the link from the document/presentation to the docshell, so that