Fix crash with fast-back enabled when a reload wipes out a cached docshell (bug 293534). r+sr=bzbarsky, a=brendan.

git-svn-id: svn://10.0.0.236/trunk@173450 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bryner%brianryner.com 2005-05-15 00:30:02 +00:00
parent faa0771d5c
commit b3fad70a54
2 changed files with 68 additions and 40 deletions

View File

@ -4993,6 +4993,22 @@ nsDocShell::RestorePresentation(nsISHEntry *aSHEntry, PRBool aSavePresentation,
return NS_OK;
}
// We need to make sure the content viewer's container is this docshell.
// In subframe navigation, it's possible for the docshell that the
// content viewer was originally loaded into to be replaced with a
// different one. We don't currently support restoring the presentation
// in that case.
nsCOMPtr<nsISupports> container;
viewer->GetContainer(getter_AddRefs(container));
if (!::SameCOMIdentity(container, GetAsSupports(this))) {
#ifdef DEBUG_PAGE_CACHE
printf("No valid container, clearing presentation\n");
#endif
aSHEntry->SetContentViewer(nsnull);
return NS_OK;
}
NS_ASSERTION(mContentViewer != viewer, "Restoring existing presentation");
#ifdef DEBUG_PAGE_CACHE

View File

@ -192,6 +192,7 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
#include "nsISHistory.h"
#include "nsISHistoryInternal.h"
#include "nsIWebNavigation.h"
#include "nsWeakPtr.h"
//paint forcing
#include "prenv.h"
@ -383,7 +384,7 @@ protected:
// (ie, non owning) references. If you add any members to this
// class, please make the ownership explicit (pinkerton, scc).
nsISupports* mContainer; // [WEAK] it owns me!
nsWeakPtr mContainer; // it owns me!
nsCOMPtr<nsIDeviceContext> mDeviceContext; // ??? can't hurt, but...
// the following six items are explicitly in this order
@ -561,7 +562,7 @@ DocumentViewerImpl::LoadStart(nsISupports *aDoc)
nsresult
DocumentViewerImpl::SyncParentSubDocMap()
{
nsCOMPtr<nsIDocShellTreeItem> item(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeItem> item(do_QueryReferent(mContainer));
nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(item));
nsCOMPtr<nsIContent> content;
@ -593,7 +594,7 @@ DocumentViewerImpl::SyncParentSubDocMap()
NS_IMETHODIMP
DocumentViewerImpl::SetContainer(nsISupports* aContainer)
{
mContainer = aContainer;
mContainer = do_GetWeakReference(aContainer);
if (mPresContext) {
mPresContext->SetContainer(aContainer);
}
@ -610,9 +611,9 @@ DocumentViewerImpl::GetContainer(nsISupports** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mContainer;
NS_IF_ADDREF(*aResult);
*aResult = nsnull;
nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
container.swap(*aResult);
return NS_OK;
}
@ -815,13 +816,14 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
}
}
nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryInterface(mContainer));
nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryReferent(mContainer));
if (requestor) {
if (mPresContext) {
nsCOMPtr<nsILinkHandler> linkHandler;
requestor->GetInterface(NS_GET_IID(nsILinkHandler),
getter_AddRefs(linkHandler));
mPresContext->SetContainer(mContainer);
mPresContext->SetContainer(requestor);
mPresContext->SetLinkHandler(linkHandler);
}
@ -1083,11 +1085,13 @@ DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
mInPermitUnload = PR_FALSE;
}
nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
if (NS_SUCCEEDED(rv) && (event.flags & NS_EVENT_FLAG_NO_DEFAULT ||
!event.text.IsEmpty())) {
// Ask the user if it's ok to unload the current page
nsCOMPtr<nsIPrompt> prompt(do_GetInterface(mContainer));
nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShellNode);
if (prompt) {
nsXPIDLString preMsg, postMsg;
@ -1121,8 +1125,6 @@ DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
}
}
nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryInterface(mContainer));
if (docShellNode) {
PRInt32 childCount;
docShellNode->GetChildCount(&childCount);
@ -1180,6 +1182,12 @@ DocumentViewerImpl::Open()
{
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
// Our container might have gone away while we were closed.
// If this is the case, we must fail to open so we don't crash.
nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
if (!container)
return NS_ERROR_NOT_AVAILABLE;
nsRect bounds;
mWindow->GetBounds(bounds);
@ -1188,7 +1196,7 @@ DocumentViewerImpl::Open()
NS_ENSURE_SUCCESS(rv, rv);
if (mDocument)
mDocument->SetContainer(mContainer);
mDocument->SetContainer(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
SyncParentSubDocMap();
@ -1339,7 +1347,7 @@ DocumentViewerImpl::Destroy()
// too many content viewers around. Note: if max_viewers is set to 0,
// this can reenter Destroy() and dispose of this content viewer!
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mContainer);
nsCOMPtr<nsIWebNavigation> webNav = do_QueryReferent(mContainer);
if (webNav) {
nsCOMPtr<nsISHistory> history;
webNav->GetSessionHistory(getter_AddRefs(history));
@ -1466,14 +1474,14 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
if (NS_FAILED(rv)) return rv;
// Set new container
newDoc->SetContainer(mContainer);
nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
newDoc->SetContainer(container);
// Replace the old document with the new one
mDocument = newDoc;
// Set the script global object on the new document
nsCOMPtr<nsIScriptGlobalObject> global(do_GetInterface(mContainer));
nsCOMPtr<nsIScriptGlobalObject> global = do_GetInterface(container);
if (global) {
mDocument->SetScriptGlobalObject(global);
global->SetNewDocument(aDocument, PR_TRUE, PR_TRUE);
@ -1675,7 +1683,7 @@ DocumentViewerImpl::Show(void)
if (mDocument && !mPresShell && !mWindow) {
nsresult rv;
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mContainer));
nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
NS_ENSURE_TRUE(base_win, NS_ERROR_UNEXPECTED);
base_win->GetParentWidget(&mParentWidget);
@ -1714,14 +1722,14 @@ DocumentViewerImpl::Show(void)
if (NS_FAILED(rv))
return rv;
if (mPresContext && mContainer) {
nsCOMPtr<nsILinkHandler> linkHandler(do_GetInterface(mContainer));
if (mPresContext && base_win) {
nsCOMPtr<nsILinkHandler> linkHandler(do_GetInterface(base_win));
if (linkHandler) {
mPresContext->SetLinkHandler(linkHandler);
}
mPresContext->SetContainer(mContainer);
mPresContext->SetContainer(base_win);
}
if (mPresContext) {
@ -1818,7 +1826,7 @@ DocumentViewerImpl::Hide(void)
}
#endif
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
if (docShell) {
PRBool saveLayoutState = PR_FALSE;
docShell->GetShouldSaveLayoutState(&saveLayoutState);
@ -1840,7 +1848,7 @@ DocumentViewerImpl::Hide(void)
mDeviceContext = nsnull;
mParentWidget = nsnull;
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mContainer));
nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
if (base_win) {
base_win->SetParentWidget(nsnull);
@ -1955,7 +1963,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
// The document will fill in the document sheets when we create the presshell
// Handle the user sheets.
nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
PRInt32 shellType;
docShell->GetItemType(&shellType);
nsICSSStyleSheet* sheet = nsnull;
@ -1971,7 +1979,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
// Append chrome sheets (scrollbars + forms).
PRBool shouldOverride = PR_FALSE;
nsCOMPtr<nsIDocShell> ds(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShell> ds(do_QueryInterface(docShell));
nsCOMPtr<nsIChromeEventHandler> chromeHandler;
nsCOMPtr<nsICSSLoader> cssLoader( do_GetService(kCSSLoaderCID) );
nsCOMPtr<nsIURI> uri;
@ -2094,7 +2102,7 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget,
// but is really just for peace of mind. This check can be removed if we want to support fancy
// chrome effects like transparent controls floating over content, transparent Web browsers, and
// things like that, and the perf bugs are fixed.
nsCOMPtr<nsIDocShellTreeItem> container(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeItem> container(do_QueryReferent(mContainer));
nsCOMPtr<nsIDocShellTreeItem> parentContainer;
PRInt32 itemType;
if (nsnull == container
@ -2452,7 +2460,7 @@ NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode)
void
DocumentViewerImpl::CallChildren(CallChildFunc aFunc, void* aClosure)
{
nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
if (docShellNode)
{
PRInt32 i;
@ -2569,7 +2577,7 @@ DocumentViewerImpl::GetAuthorStyleDisabled(PRBool* aStyleDisabled)
NS_IMETHODIMP
DocumentViewerImpl::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
{
NS_ENSURE_STATE(mContainer);
NS_ENSURE_STATE(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
if (mDefaultCharacterSet.IsEmpty())
{
@ -2871,7 +2879,7 @@ NS_IMETHODIMP DocumentViewerImpl::SizeToContent()
{
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryReferent(mContainer));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShellTreeItem> docShellParent;
@ -3232,7 +3240,7 @@ DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings,
}
#endif
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
NS_ASSERTION(docShell, "This has to be a docshell");
// Check to see if this document is still busy
@ -3285,10 +3293,10 @@ DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings,
NS_ADDREF(mPrintEngine);
#ifdef NS_DEBUG
mPrintEngine->Initialize(this, this, mContainer, mDocument,
mPrintEngine->Initialize(this, this, docShell, mDocument,
mDeviceContext, mPresContext, mWindow, mParentWidget, mDebugFile);
#else
mPrintEngine->Initialize(this, this, mContainer, mDocument,
mPrintEngine->Initialize(this, this, docShell, mDocument,
mDeviceContext, mPresContext, mWindow, mParentWidget, nsnull);
#endif
}
@ -3339,13 +3347,16 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings,
NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(mPrintEngine);
mPrintEngine->Initialize(this, this,
nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)),
mDocument, mDeviceContext, mPresContext,
mWindow, mParentWidget,
#ifdef NS_DEBUG
mPrintEngine->Initialize(this, this, mContainer, mDocument,
mDeviceContext, mPresContext, mWindow, mParentWidget, mDebugFile);
mDebugFile
#else
mPrintEngine->Initialize(this, this, mContainer, mDocument,
mDeviceContext, mPresContext, mWindow, mParentWidget, nsnull);
nsnull
#endif
);
}
rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener);
@ -3733,7 +3744,7 @@ DocumentViewerImpl::SetIsPrinting(PRBool aIsPrinting)
// Set all the docShells in the docshell tree to be printing.
// that way if anyone of them tries to "navigate" it can't
if (mContainer) {
nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryReferent(mContainer));
NS_ASSERTION(docShellTreeNode, "mContainer has to be a nsIDocShellTreeNode");
SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrinting, PR_TRUE);
}
@ -3764,7 +3775,7 @@ DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview)
// Set all the docShells in the docshell tree to be printing.
// that way if anyone of them tries to "navigate" it can't
if (mContainer) {
nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryReferent(mContainer));
NS_ASSERTION(docShellTreeNode, "mContainer has to be a nsIDocShellTreeNode");
SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrintPreview, PR_TRUE);
}
@ -3813,7 +3824,7 @@ DocumentViewerImpl::ReturnToGalleyPresentation()
// In case we have focus focus the parent DocShell
// which in this case should always be chrome
nsCOMPtr<nsIDocShellTreeItem> dstParentItem;
nsCOMPtr<nsIDocShellTreeItem> dstItem(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeItem> dstItem(do_QueryReferent(mContainer));
if (dstItem) {
dstItem->GetParent(getter_AddRefs(dstParentItem));
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(dstParentItem));
@ -3916,7 +3927,7 @@ DocumentViewerImpl::InstallNewPresentation()
// In case we have focus focus the parent DocShell
// which in this case should always be chrome
nsCOMPtr<nsIDocShellTreeItem> dstParentItem;
nsCOMPtr<nsIDocShellTreeItem> dstItem(do_QueryInterface(mContainer));
nsCOMPtr<nsIDocShellTreeItem> dstItem(do_QueryReferent(mContainer));
if (dstItem) {
dstItem->GetParent(getter_AddRefs(dstParentItem));
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(dstParentItem));
@ -4023,7 +4034,8 @@ DocumentViewerImpl::OnDonePrinting()
// We are done printing, now cleanup
if (mDeferredWindowClose) {
mDeferredWindowClose = PR_FALSE;
nsCOMPtr<nsIDOMWindowInternal> win = do_GetInterface(mContainer);
nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
nsCOMPtr<nsIDOMWindowInternal> win = do_GetInterface(container);
if (win)
win->Close();
} else if (mClosingWhilePrinting) {