diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 90a4ef0da09..b242a895dda 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -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 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 diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 9df2d4eeec8..13b0f7593e8 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -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 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 item(do_QueryInterface(mContainer)); + nsCOMPtr item(do_QueryReferent(mContainer)); nsCOMPtr pwin(do_GetInterface(item)); nsCOMPtr 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 container = do_QueryReferent(mContainer); + container.swap(*aResult); return NS_OK; } @@ -815,13 +816,14 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, } } - nsCOMPtr requestor(do_QueryInterface(mContainer)); + nsCOMPtr requestor(do_QueryReferent(mContainer)); if (requestor) { if (mPresContext) { nsCOMPtr 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 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 prompt(do_GetInterface(mContainer)); + nsCOMPtr prompt = do_GetInterface(docShellNode); if (prompt) { nsXPIDLString preMsg, postMsg; @@ -1121,8 +1125,6 @@ DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload) } } - nsCOMPtr 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 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(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 webNav = do_QueryInterface(mContainer); + nsCOMPtr webNav = do_QueryReferent(mContainer); if (webNav) { nsCOMPtr 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 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 global(do_GetInterface(mContainer)); - + nsCOMPtr 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 base_win(do_QueryInterface(mContainer)); + nsCOMPtr 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 linkHandler(do_GetInterface(mContainer)); + if (mPresContext && base_win) { + nsCOMPtr 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 docShell(do_QueryInterface(mContainer)); + nsCOMPtr 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 base_win(do_QueryInterface(mContainer)); + nsCOMPtr 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 docShell(do_QueryInterface(mContainer)); + nsCOMPtr 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 ds(do_QueryInterface(mContainer)); + nsCOMPtr ds(do_QueryInterface(docShell)); nsCOMPtr chromeHandler; nsCOMPtr cssLoader( do_GetService(kCSSLoaderCID) ); nsCOMPtr 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 container(do_QueryInterface(mContainer)); + nsCOMPtr container(do_QueryReferent(mContainer)); nsCOMPtr parentContainer; PRInt32 itemType; if (nsnull == container @@ -2452,7 +2460,7 @@ NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode) void DocumentViewerImpl::CallChildren(CallChildFunc aFunc, void* aClosure) { - nsCOMPtr docShellNode(do_QueryInterface(mContainer)); + nsCOMPtr 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(do_QueryReferent(mContainer))); if (mDefaultCharacterSet.IsEmpty()) { @@ -2871,7 +2879,7 @@ NS_IMETHODIMP DocumentViewerImpl::SizeToContent() { NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); - nsCOMPtr docShellAsItem(do_QueryInterface(mContainer)); + nsCOMPtr docShellAsItem(do_QueryReferent(mContainer)); NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE); nsCOMPtr docShellParent; @@ -3232,7 +3240,7 @@ DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings, } #endif - nsCOMPtr docShell(do_QueryInterface(mContainer)); + nsCOMPtr 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(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 docShellTreeNode(do_QueryInterface(mContainer)); + nsCOMPtr 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 docShellTreeNode(do_QueryInterface(mContainer)); + nsCOMPtr 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 dstParentItem; - nsCOMPtr dstItem(do_QueryInterface(mContainer)); + nsCOMPtr dstItem(do_QueryReferent(mContainer)); if (dstItem) { dstItem->GetParent(getter_AddRefs(dstParentItem)); nsCOMPtr 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 dstParentItem; - nsCOMPtr dstItem(do_QueryInterface(mContainer)); + nsCOMPtr dstItem(do_QueryReferent(mContainer)); if (dstItem) { dstItem->GetParent(getter_AddRefs(dstParentItem)); nsCOMPtr docShell(do_QueryInterface(dstParentItem)); @@ -4023,7 +4034,8 @@ DocumentViewerImpl::OnDonePrinting() // We are done printing, now cleanup if (mDeferredWindowClose) { mDeferredWindowClose = PR_FALSE; - nsCOMPtr win = do_GetInterface(mContainer); + nsCOMPtr container = do_QueryReferent(mContainer); + nsCOMPtr win = do_GetInterface(container); if (win) win->Close(); } else if (mClosingWhilePrinting) {