From 2acd95d9aa56f9cc077ef3c5d24780769748d32e Mon Sep 17 00:00:00 2001 From: "dbaron%fas.harvard.edu" Date: Wed, 1 Aug 2001 03:15:50 +0000 Subject: [PATCH] Split nsIContentViewer::destroy into close and destroy so we can trigger teardown both at the beginning and at the end of paint suppression. Move the PresShell's teardown from its destructor into new Destroy method so it happens at the end of paint suppression. Also clean up nsDocumentViewer.cpp a bit. b=80203,89626 r=hyatt sr=waterson git-svn-id: svn://10.0.0.236/trunk@100081 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsDocumentViewer.cpp | 304 +++++++++--------- mozilla/docshell/base/nsDocShell.cpp | 3 +- mozilla/docshell/base/nsIContentViewer.idl | 17 +- mozilla/layout/base/nsDocumentViewer.cpp | 304 +++++++++--------- mozilla/layout/base/nsIPresShell.h | 9 + mozilla/layout/base/nsPresShell.cpp | 225 +++++++------ mozilla/layout/base/public/nsIPresShell.h | 9 + mozilla/layout/generic/nsObjectFrame.cpp | 2 +- .../layout/html/base/src/nsObjectFrame.cpp | 2 +- mozilla/layout/html/base/src/nsPresShell.cpp | 225 +++++++------ .../plugin/base/src/nsPluginViewer.cpp | 31 +- .../modules/plugin/nglsrc/nsPluginViewer.cpp | 31 +- 12 files changed, 593 insertions(+), 569 deletions(-) diff --git a/mozilla/content/base/src/nsDocumentViewer.cpp b/mozilla/content/base/src/nsDocumentViewer.cpp index de6a7aed964..2a02d87d4d0 100644 --- a/mozilla/content/base/src/nsDocumentViewer.cpp +++ b/mozilla/content/base/src/nsDocumentViewer.cpp @@ -275,17 +275,17 @@ struct PrintObject public: PrintObject(); - virtual ~PrintObject(); + ~PrintObject(); // non-virtual // Methods PRBool IsPrintable() { return !mDontPrint; } nsIWebShell *mWebShell; PrintObjectType mFrameType; - nsIPresContext *mPresContext; - nsIStyleSet *mStyleSet; - nsIPresShell *mPresShell; - nsIViewManager *mViewManager; + nsCOMPtr mPresContext; + nsCOMPtr mStyleSet; + nsCOMPtr mPresShell; + nsCOMPtr mViewManager; nsIView *mView; nsIView *mRootView; @@ -305,6 +305,9 @@ public: nsRect mClipRect; +private: + PrintObject& operator=(const PrintObject& aOther); // not implemented + }; //--------------------------------------------------- @@ -314,17 +317,17 @@ struct PrintData { public: PrintData(); - virtual ~PrintData(); + ~PrintData(); // non-virtual // Listener Helper Methods void OnEndPrinting(nsresult aResult); void OnStartPrinting(); - nsIDeviceContext *mPrintDC; - nsIPresContext *mPrintPC; - nsIStyleSet *mPrintSS; - nsIPresShell *mPrintPS; - nsIViewManager *mPrintVM; + nsCOMPtr mPrintDC; + nsCOMPtr mPrintPC; + nsCOMPtr mPrintSS; + nsCOMPtr mPrintPS; + nsCOMPtr mPrintVM; nsIView *mPrintView; FILE *mFilePointer; // a file where information can go to when printing @@ -351,6 +354,9 @@ public: FILE * mDebugFD; #endif +private: + PrintData& operator=(const PrintData& aOther); // not implemented + }; //------------------------------------------------------------- @@ -372,30 +378,7 @@ public: NS_DECL_ISUPPORTS // nsIContentViewer interface... - NS_IMETHOD Init(nsIWidget* aParentWidget, - nsIDeviceContext* aDeviceContext, - const nsRect& aBounds); - NS_IMETHOD SetContainer(nsISupports* aContainer); - NS_IMETHOD GetContainer(nsISupports** aContainerResult); - NS_IMETHOD LoadStart(nsISupports* aDoc); - NS_IMETHOD LoadComplete(nsresult aStatus); - NS_IMETHOD Unload(void); - NS_IMETHOD Destroy(void); - NS_IMETHOD Stop(void); - NS_IMETHOD GetDOMDocument(nsIDOMDocument **aResult); - NS_IMETHOD SetDOMDocument(nsIDOMDocument *aDocument); - NS_IMETHOD GetBounds(nsRect& aResult); - NS_IMETHOD SetBounds(const nsRect& aBounds); - - NS_IMETHOD GetPreviousViewer(nsIContentViewer** aResult); - NS_IMETHOD SetPreviousViewer(nsIContentViewer* aViewer); - - NS_IMETHOD Move(PRInt32 aX, PRInt32 aY); - NS_IMETHOD Show(); - NS_IMETHOD Hide(); - NS_IMETHOD Validate(); - NS_IMETHOD SetEnableRendering(PRBool aOn); - NS_IMETHOD GetEnableRendering(PRBool* aResult); + NS_DECL_NSICONTENTVIEWER // nsIDocumentViewer interface... NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet); @@ -667,9 +650,7 @@ private: PrintObject * mPrintObj; }; -NS_IMPL_ADDREF(nsPagePrintTimer) -NS_IMPL_RELEASE(nsPagePrintTimer) -NS_IMPL_QUERY_INTERFACE1(nsPagePrintTimer, nsITimerCallback) +NS_IMPL_ISUPPORTS1(nsPagePrintTimer, nsITimerCallback) nsresult NS_NewUpdateTimer(nsPagePrintTimer **aResult) { @@ -690,7 +671,6 @@ nsresult NS_NewUpdateTimer(nsPagePrintTimer **aResult) //-- PrintData Class Impl //--------------------------------------------------- PrintData::PrintData() : - mPrintDC(nsnull), mPrintPC(nsnull), mPrintSS(nsnull), mPrintPS(nsnull), mPrintVM(nsnull), mPrintView(nsnull), mFilePointer(nsnull), mPrintObject(nsnull), mSelectedPO(nsnull), mPrintDocList(nsnull), mIsIFrameSelected(PR_FALSE), mIsParentAFrameSet(PR_FALSE), mPrintingAsIsSubDoc(PR_FALSE), @@ -708,7 +688,9 @@ PrintData::~PrintData() // printing is complete, clean up now if (mPrintPS) { + // XXX we never call BeginObservingDocument on this pres shell. mPrintPS->EndObservingDocument(); + mPrintPS->Destroy(); } OnEndPrinting(NS_OK); // removes listener @@ -725,12 +707,6 @@ PrintData::~PrintData() mPrintDocList->Clear(); delete mPrintDocList; - NS_IF_RELEASE(mPrintPS); - NS_IF_RELEASE(mPrintVM); - NS_IF_RELEASE(mPrintSS); - NS_IF_RELEASE(mPrintDC); - NS_IF_RELEASE(mPrintPC); - #ifdef DEBUG_PRINTING fclose(mDebugFD); #endif @@ -754,7 +730,7 @@ void PrintData::OnEndPrinting(nsresult aResult) } mPrintListener->OnEndPrinting(aResult); // clear the lister so the destructor doesn't send the - mPrintListener = do_QueryInterface(nsnull); + mPrintListener = nsnull; } } @@ -763,8 +739,7 @@ void PrintData::OnEndPrinting(nsresult aResult) //-- PrintObject Class Impl //--------------------------------------------------- PrintObject::PrintObject() : - mWebShell(nsnull), mFrameType(eFrame), mPresContext(nsnull), - mStyleSet(nsnull), mPresShell(nsnull), mViewManager(nsnull), + mWebShell(nsnull), mFrameType(eFrame), mView(nsnull), mRootView(nsnull), mContent(nsnull), mSeqFrame(nsnull), mPageFrame(nsnull), mPageNum(-1), mRect(0,0,0,0), mReflowRect(0,0,0,0), @@ -776,16 +751,13 @@ PrintObject::PrintObject() : PrintObject::~PrintObject() { - NS_IF_RELEASE(mPresShell); - NS_IF_RELEASE(mStyleSet); - NS_IF_RELEASE(mViewManager); - NS_IF_RELEASE(mPresContext); - for (PRInt32 i=0;iDestroy(); } //------------------------------------------------------------------ @@ -809,7 +781,7 @@ NS_NewDocumentViewer(nsIDocumentViewer** aResult) *aResult = nsnull; return NS_ERROR_OUT_OF_MEMORY; } - return it->QueryInterface(NS_GET_IID(nsIDocumentViewer), (void**) aResult); + return CallQueryInterface(it, aResult); } // Note: operator new zeros our memory @@ -828,7 +800,7 @@ void DocumentViewerImpl::PrepareToStartLoad() { } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) - : mPresContext(dont_QueryInterface(aPresContext)) + : mPresContext(aPresContext) { NS_INIT_ISUPPORTS(); mHintCharsetSource = kCharsetUninitialized; @@ -845,20 +817,16 @@ NS_IMPL_ISUPPORTS5(DocumentViewerImpl, DocumentViewerImpl::~DocumentViewerImpl() { - if (mPagePrintTimer != nsnull) { - mPagePrintTimer->Stop(); - delete mPagePrintTimer; - } - - if (mPrt != nsnull) { - mPrt->OnEndPrinting(NS_ERROR_FAILURE); - delete mPrt; - } - // Revoke pending invalidate events - NS_ASSERTION(!mDocument, "User did not call nsIContentViewer::Destroy"); + NS_ASSERTION(!mDocument, "User did not call nsIContentViewer::Close"); if (mDocument) + Close(); + + NS_ASSERTION(!mPresShell, "User did not call nsIContentViewer::Destroy"); + if (mPresShell) Destroy(); + // XXX(?) Revoke pending invalidate events + // clear weak references before we go away if (mPresContext) { mPresContext->SetContainer(nsnull); @@ -870,10 +838,6 @@ DocumentViewerImpl::~DocumentViewerImpl() // stop everything but the chrome. mPresContext->Stop(); } - - // Avoid leaking the old viewer. - if (mPreviousViewer) - SetPreviousViewer(nsnull); } /* @@ -1037,7 +1001,7 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, // this is the owning reference. The nsCOMPtr will take care of releasing // our ref to the listener on destruction. NS_ADDREF(selectionListener); - rv = selectionListener->QueryInterface(NS_GET_IID(nsISelectionListener), getter_AddRefs(mSelectionListener)); + mSelectionListener = do_QueryInterface(selectionListener); NS_RELEASE(selectionListener); if (NS_FAILED(rv)) return rv; @@ -1060,7 +1024,7 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, // this is the owning reference. The nsCOMPtr will take care of releasing // our ref to the listener on destruction. NS_ADDREF(focusListener); - rv = focusListener->QueryInterface(NS_GET_IID(nsIDOMFocusListener), getter_AddRefs(mFocusListener)); + mFocusListener = do_QueryInterface(focusListener); NS_RELEASE(focusListener); if (NS_FAILED(rv)) return rv; @@ -1068,8 +1032,7 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, if(mDocument) { // get the DOM event receiver - nsCOMPtr erP; - rv = mDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP)); + nsCOMPtr erP (do_QueryInterface(mDocument, &rv)); if(NS_FAILED(rv) || !erP) return rv?rv:NS_ERROR_FAILURE; @@ -1166,13 +1129,19 @@ DocumentViewerImpl::Unload() } NS_IMETHODIMP -DocumentViewerImpl::Destroy() +DocumentViewerImpl::Close() { - // All callers are supposed to call destroy to break circular + // All callers are supposed to call close to break circular // references. If we do this stuff in the destructor, the // destructor might never be called (especially if we're being // used from JS. + // Close is also needed to disable scripts during paint suppression, + // since we transfer the existing global object to the new document + // that is loaded. In the future, the global object may become a proxy + // for an object that can be switched in and out so that we don't need + // to disable scripts during paint suppression. + nsresult rv; if (mDocument) { @@ -1187,13 +1156,41 @@ DocumentViewerImpl::Destroy() mDocument->SetScriptGlobalObject(nsnull); if (mFocusListener) { // get the DOM event receiver - nsCOMPtr erP; - rv = mDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP)); + nsCOMPtr erP( do_QueryInterface(mDocument, &rv) ); if(NS_SUCCEEDED(rv) && erP) erP->RemoveEventListenerByIID(mFocusListener, NS_GET_IID(nsIDOMFocusListener)); } } + mDocument = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +DocumentViewerImpl::Destroy() +{ + // All callers are supposed to call destroy to break circular + // references. If we do this stuff in the destructor, the + // destructor might never be called (especially if we're being + // used from JS. + + if (mPagePrintTimer != nsnull) { + mPagePrintTimer->Stop(); + delete mPagePrintTimer; + } + + if (mPrt) { + mPrt->OnEndPrinting(NS_ERROR_FAILURE); + delete mPrt; + mPrt = nsnull; + } + + // Avoid leaking the old viewer. + if (mPreviousViewer) { + mPreviousViewer->Destroy(); + mPreviousViewer = nsnull; + } + if (mDeviceContext) mDeviceContext->FlushFontCache(); @@ -1201,13 +1198,14 @@ DocumentViewerImpl::Destroy() // Break circular reference (or something) mPresShell->EndObservingDocument(); nsCOMPtr selection; - rv = GetDocumentSelection(getter_AddRefs(selection)); + nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); nsCOMPtr selPrivate(do_QueryInterface(selection)); if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) selPrivate->RemoveSelectionListener(mSelectionListener); + mPresShell->Destroy(); + mPresShell = nsnull; } - mDocument = nsnull; return NS_OK; } @@ -1291,6 +1289,7 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) // 3) Replace the current pres shell with a new shell for the new document mPresShell->EndObservingDocument(); + mPresShell->Destroy(); mPresShell = nsnull; rv = newDoc->CreateShell(mPresContext, mViewManager, styleSet, @@ -1302,8 +1301,7 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) // 4) Register the focus listener on the new document if(mDocument) { - nsCOMPtr erP; - rv = mDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP)); + nsCOMPtr erP = do_QueryInterface(mDocument, &rv); if(NS_FAILED(rv) || !erP) return rv ? rv : NS_ERROR_FAILURE; @@ -1370,17 +1368,13 @@ DocumentViewerImpl::GetPreviousViewer(nsIContentViewer** aViewer) NS_IMETHODIMP DocumentViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer) { - if (!aViewer) { - // Clearing it out. - mPreviousViewer = nsnull; + // NOTE: |Show| sets |mPreviousViewer| to null without calling this + // function. + + if (aViewer) { + NS_ASSERTION(!mPreviousViewer, + "can't set previous viewer when there already is one"); - // Now we can show, but only if we aren't dead already (which - // can occasionally happen when one page moves to another during the onload - // handler.) - if (mDocument) - Show(); - } - else { // In a multiple chaining situation (which occurs when running a thrashing // test like i-bench or jrgm's tests with no delay), we can build up a // whole chain of viewers. In order to avoid this, we always set our previous @@ -1392,9 +1386,9 @@ DocumentViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer) nsCOMPtr prevViewer; aViewer->GetPreviousViewer(getter_AddRefs(prevViewer)); if (prevViewer) { - SetPreviousViewer(prevViewer); - prevViewer->SetPreviousViewer(nsnull); - return NS_OK; + aViewer->SetPreviousViewer(nsnull); + aViewer->Destroy(); + return SetPreviousViewer(prevViewer); } } @@ -1432,6 +1426,17 @@ DocumentViewerImpl::Show(void) { NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); NS_PRECONDITION(mWindow, "null window"); + + // We don't need the previous viewer anymore since we're not + // displaying it. + if (mPreviousViewer) { + // This little dance *may* only be to keep + // PresShell::EndObservingDocument happy, but I'm not sure. + nsCOMPtr prevViewer(mPreviousViewer); + mPreviousViewer = nsnull; + prevViewer->Destroy(); + } + if (mWindow) { mWindow->Show(PR_TRUE); } @@ -1491,7 +1496,7 @@ GetPresShellFor(nsIDocShell* aDocShell) aDocShell->GetContentViewer(&cv); if (nsnull != cv) { nsIDocumentViewer* docv = nsnull; - cv->QueryInterface(NS_GET_IID(nsIDocumentViewer), (void**) &docv); + CallQueryInterface(cv, &docv); if (nsnull != docv) { nsIPresContext* cx; docv->GetPresContext(cx); @@ -1537,7 +1542,7 @@ static void DumpFrames(FILE* out, nsAutoString tmp; nsIFrameDebug* frameDebug; - if (NS_SUCCEEDED(child->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) { + if (NS_SUCCEEDED(CallQueryInterface(child, &frameDebug))) { frameDebug->GetFrameName(tmp); } fputs(tmp, out); @@ -1665,7 +1670,7 @@ static void DumpPrintObjectsList(nsVoidArray * aDocList, FILE* aFD = nsnull) po->mPresShell->GetRootFrame(&rootFrame); while (rootFrame != nsnull) { nsIPageSequenceFrame * sqf = nsnull; - if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIPageSequenceFrame), (void**)&sqf)) && sqf) { + if (NS_SUCCEEDED(CallQueryInterface(rootFrame, &sqf)) && sqf) { break; } rootFrame->FirstChild(po->mPresContext, nsnull, &rootFrame); @@ -1721,7 +1726,7 @@ static void DumpPrintObjectsTreeLayout(PrintObject * aPO, } if (fd) { nsIFrame* rootFrame = nsnull; - if (aPO->mPresShell != nsnull) { + if (aPO->mPresShell) { aPO->mPresShell->GetRootFrame(&rootFrame); } for (PRInt32 k=0;kQueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_FAILED(CallQueryInterface(aPageSeqFrame, &seqFrame))) { return NS_ERROR_FAILURE; } @@ -2268,7 +2273,7 @@ DocumentViewerImpl::PrintPage(nsIPresContext* aPresContext, // page num of it's parent doc curPageSeq->GetCurrentPageNum(&pageNum); nsIFrame* fr; - curPageSeq->QueryInterface(NS_GET_IID(nsIFrame), (void**)&fr); + CallQueryInterface(curPageSeq, &fr); if (fr == po->mSeqFrame && pageNum == po->mPageNum) { PRBool donePrintingSubDoc; @@ -2425,7 +2430,7 @@ void DocumentViewerImpl::CalcPageFrameLocation(nsIPresShell * aPresShell, // Keep a pointer to the Seq and Page frames nsIPageSequenceFrame * sqf = nsnull; if (parent != nsnull && - NS_SUCCEEDED(parent->QueryInterface(NS_GET_IID(nsIPageSequenceFrame), (void**)&sqf)) && sqf) { + NS_SUCCEEDED(CallQueryInterface(parent, &sqf)) && sqf) { pageFrame = temp; seqFrame = parent; } @@ -2482,7 +2487,7 @@ DocumentViewerImpl::MapSubDocFrameLocations(PrintObject* aPO) CalcPageFrameLocation(aPO->mParent->mPresShell, aPO); } - if (aPO->mPresShell != nsnull) { + if (aPO->mPresShell) { for (PRInt32 i=0;imKids.Count();i++) { MapSubDocFrameLocations((PrintObject*)aPO->mKids[i]); } @@ -2732,7 +2737,7 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) if (NS_FAILED(rv)) { return rv; } else { - rv = printcon->QueryInterface(NS_GET_IID(nsIPresContext), (void**)&aPO->mPresContext); + aPO->mPresContext = do_QueryInterface(printcon); if (NS_FAILED(rv)) { return rv; } @@ -2741,16 +2746,14 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) // init it with the DC (aPO->mPresContext)->Init(mPrt->mPrintDocDC); - CreateStyleSet(document, &aPO->mStyleSet); + CreateStyleSet(document, getter_AddRefs(aPO->mStyleSet)); - rv = nsComponentManager::CreateInstance(kPresShellCID,nsnull, - NS_GET_IID(nsIPresShell),(void **)&aPO->mPresShell); + aPO->mPresShell = do_CreateInstance(kPresShellCID, &rv); if (NS_FAILED(rv)) { return rv; } - rv = nsComponentManager::CreateInstance(kViewManagerCID,nsnull, - NS_GET_IID(nsIViewManager),(void **)&aPO->mViewManager); + aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); if (NS_FAILED(rv)) { return rv; } @@ -2796,7 +2799,7 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) nsRect tbounds = nsRect(0, 0, width, height); // Create a child window of the parent that is our "root view/window" - rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&(aPO->mRootView)); + rv = CallCreateInstance(kViewCID, &aPO->mRootView); if (NS_FAILED(rv)) { return rv; } @@ -2807,7 +2810,8 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) // Setup hierarchical relationship in view manager aPO->mViewManager->SetRootView(aPO->mRootView); - aPO->mPresShell->Init(document, aPO->mPresContext, aPO->mViewManager,aPO->mStyleSet); + aPO->mPresShell->Init(document, aPO->mPresContext, + aPO->mViewManager, aPO->mStyleSet); nsCompatibility mode; mPresContext->GetCompatibilityMode(&mode); @@ -3435,7 +3439,7 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a nsIFrame* root; poPresShell->GetRootFrame(&root); - if (NS_SUCCEEDED(root->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**) &fdbg))) { + if (NS_SUCCEEDED(CallQueryInterface(root, &fdbg))) { fdbg->DumpRegressionData(poPresContext, mPrt->mFilePointer, 0, PR_TRUE); } fclose(mPrt->mFilePointer); @@ -3501,7 +3505,7 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a if (startPageNum == endPageNum) { nsIFrame * seqFrame; - if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { gCurrentlyPrinting = PR_FALSE; return NS_ERROR_FAILURE; } @@ -3518,7 +3522,7 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a } nsIFrame * seqFrame; - if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { gCurrentlyPrinting = PR_FALSE; return NS_ERROR_FAILURE; } @@ -3582,11 +3586,13 @@ DocumentViewerImpl::CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNu PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); NS_ASSERTION(po, "PrintObject can't be null!"); if (po->IsPrintable()) { - if (po->mPresShell != nsnull && (po->mFrameType != eIFrame && po->mFrameType != eFrameSet)) { + if (po->mPresShell && + po->mFrameType != eIFrame && + po->mFrameType != eFrameSet) { nsIPageSequenceFrame* pageSequence; po->mPresShell->GetPageSequenceFrame(&pageSequence); nsIFrame * seqFrame; - if (NS_SUCCEEDED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_SUCCEEDED(CallQueryInterface(pageSequence, &seqFrame))) { nsIFrame* frame; seqFrame->FirstChild(po->mPresContext, nsnull, &frame); while (frame) { @@ -3765,7 +3771,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, NS_WARNING("unable to load UA style sheet"); } - rv = nsComponentManager::CreateInstance(kStyleSetCID,nsnull,NS_GET_IID(nsIStyleSet),(void**)aStyleSet); + rv = CallCreateInstance(kStyleSetCID, aStyleSet); if (NS_OK == rv) { PRInt32 index = 0; aDocument->GetNumberOfStyleSheets(&index); @@ -3838,10 +3844,9 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, { nsresult rv; - rv = nsComponentManager::CreateInstance(kViewManagerCID, - nsnull, - NS_GET_IID(nsIViewManager), - getter_AddRefs(mViewManager)); + mViewManager = do_CreateInstance(kViewManagerCID, &rv); + if (NS_FAILED(rv)) + return rv; nsCOMPtr dx; mPresContext->GetDeviceContext(getter_AddRefs(dx)); @@ -3852,11 +3857,12 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, mPresContext->GetPixelsToTwips(&p2t); tbounds *= p2t; - // Initialize the view manager with an offset. This allows the viewmanager - // to manage a coordinate space offset from (0,0) - if ((NS_OK != rv) || (NS_OK != mViewManager->Init(dx, tbounds.x, tbounds.y))) { + // Initialize the view manager with an offset. This allows the viewmanager + // to manage a coordinate space offset from (0,0) + rv = mViewManager->Init(dx, tbounds.x, tbounds.y); + if (NS_FAILED(rv)) return rv; - } + // Reset the bounds offset so the root view is set to 0,0. The offset is // specified in nsIViewManager::Init above. // Besides, layout will reset the root view to (0,0) during reflow, @@ -3867,15 +3873,12 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, // Create a child window of the parent that is our "root view/window" // Create a view - rv = nsComponentManager::CreateInstance(kViewCID, - nsnull, - NS_GET_IID(nsIView), - (void**)&mView); - if ((NS_OK != rv) || (NS_OK != mView->Init(mViewManager, - tbounds, - nsnull))) { + rv = CallCreateInstance(kViewCID, &mView); + if (NS_FAILED(rv)) + return rv; + rv = mView->Init(mViewManager, tbounds, nsnull); + if (NS_FAILED(rv)) return rv; - } rv = mView->CreateWidget(kWidgetCID, nsnull, aParentWidget->GetNativeData(NS_NATIVE_WIDGET)); @@ -4064,10 +4067,7 @@ NS_IMETHODIMP DocumentViewerImpl::SelectAll() if (NS_FAILED(rv)) return rv; static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID); - nsCOMPtr range; - rv = nsComponentManager::CreateInstance(kCDOMRangeCID, nsnull, - NS_GET_IID(nsIDOMRange), - getter_AddRefs(range)); + nsCOMPtr range = do_CreateInstance(kCDOMRangeCID, &rv); rv = range->SelectNodeContents(bodyNode); if (NS_FAILED(rv)) return rv; @@ -4320,10 +4320,7 @@ nsresult rv; // another is still in here (the printing dialog is a good example). if(gCurrentlyPrinting) { // Beep at the user, let them know we are not ready to print. - nsCOMPtr soundInterface; - rv = nsComponentManager::CreateInstance(kSoundCID, - nsnull, NS_GET_IID(nsISound), - getter_AddRefs(soundInterface)); + nsCOMPtr soundInterface( do_CreateInstance(kSoundCID, &rv) ); if (NS_SUCCEEDED(rv) && (soundInterface != nsnull)){ soundInterface->Beep(); } @@ -4425,11 +4422,8 @@ nsresult rv; } #endif - nsCOMPtr factory; - nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, - nsnull, - NS_GET_IID(nsIDeviceContextSpecFactory), - (void **)getter_AddRefs(factory)); + nsCOMPtr factory = + do_CreateInstance(kDeviceContextSpecFactoryCID); if (factory) { @@ -4439,13 +4433,13 @@ nsresult rv; nsIDeviceContextSpec *devspec = nsnull; nsCOMPtr dx; - mPrt->mPrintDC = nsnull; + mPrt->mPrintDC = nsnull; // XXX why? mPrt->mFilePointer = aFile; factory->CreateDeviceContextSpec(mWindow, devspec, aSilent); if (nsnull != devspec) { mPresContext->GetDeviceContext(getter_AddRefs(dx)); - rv = dx->GetDeviceContextFor(devspec, mPrt->mPrintDC); + rv = dx->GetDeviceContextFor(devspec, *getter_AddRefs(mPrt->mPrintDC)); if (NS_SUCCEEDED(rv)) { NS_RELEASE(devspec); @@ -4457,7 +4451,7 @@ nsresult rv; gCurrentlyPrinting = PR_FALSE; return rv; } else { - rv = printcon->QueryInterface(NS_GET_IID(nsIPresContext), (void**)&mPrt->mPrintPC); + mPrt->mPrintPC = do_QueryInterface(printcon, &rv); if (NS_FAILED(rv)) { gCurrentlyPrinting = PR_FALSE; return rv; @@ -4478,15 +4472,15 @@ nsresult rv; mPrt->mPrintPC->Init(mPrt->mPrintDC); mPrt->mPrintPC->SetContainer(webContainer); - CreateStyleSet(mDocument,&mPrt->mPrintSS); + CreateStyleSet(mDocument, getter_AddRefs(mPrt->mPrintSS)); - rv = nsComponentManager::CreateInstance(kPresShellCID, nsnull, NS_GET_IID(nsIPresShell),(void**)&mPrt->mPrintPS); + mPrt->mPrintPS = do_CreateInstance(kPresShellCID, &rv); if(NS_FAILED(rv)){ gCurrentlyPrinting = PR_FALSE; return rv; } - rv = nsComponentManager::CreateInstance(kViewManagerCID, nsnull, NS_GET_IID(nsIViewManager),(void**)&mPrt->mPrintVM); + mPrt->mPrintVM = do_CreateInstance(kViewManagerCID, &rv); if(NS_FAILED(rv)) { gCurrentlyPrinting = PR_FALSE; return rv; @@ -4498,7 +4492,7 @@ nsresult rv; return rv; } - rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView),(void**)&mPrt->mPrintView); + rv = CallCreateInstance(kViewCID, &mPrt->mPrintView); if(NS_FAILED(rv)) { gCurrentlyPrinting = PR_FALSE; return rv; @@ -5146,7 +5140,7 @@ NS_IMETHODIMP DocumentViewerImpl::SizeToContent() #pragma mark - #endif -NS_IMPL_ISUPPORTS(nsDocViewerSelectionListener, NS_GET_IID(nsISelectionListener)); +NS_IMPL_ISUPPORTS1(nsDocViewerSelectionListener, nsISelectionListener); nsresult nsDocViewerSelectionListener::Init(DocumentViewerImpl *aDocViewer) { @@ -5368,7 +5362,7 @@ NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocumen } //nsDocViewerFocusListener -NS_IMPL_ISUPPORTS(nsDocViewerFocusListener, NS_GET_IID(nsIDOMFocusListener)); +NS_IMPL_ISUPPORTS1(nsDocViewerFocusListener, nsIDOMFocusListener); nsDocViewerFocusListener::nsDocViewerFocusListener() :mDocViewer(nsnull) diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 04c47b0dd33..74cce7a6253 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -2451,6 +2451,7 @@ nsDocShell::Destroy() docShellParentAsNode->RemoveChild(this); if (mContentViewer) { + mContentViewer->Close(); mContentViewer->Destroy(); mContentViewer = nsnull; } @@ -4106,7 +4107,7 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer) } } - mContentViewer->Destroy(); + mContentViewer->Close(); aNewViewer->SetPreviousViewer(mContentViewer); mContentViewer = nsnull; } diff --git a/mozilla/docshell/base/nsIContentViewer.idl b/mozilla/docshell/base/nsIContentViewer.idl index de6e6b39807..f6d85a30568 100644 --- a/mozilla/docshell/base/nsIContentViewer.idl +++ b/mozilla/docshell/base/nsIContentViewer.idl @@ -27,7 +27,17 @@ interface nsIContentViewer : nsISupports void loadComplete(in unsigned long aStatus); void unload(); + /** + * All users of a content viewer are responsible for calling both + * close() and destroy(), in that order. + * + * close() should be called when the load of a new page for the next + * content viewer begins, and destroy() should be called when the next + * content viewer replaces this one. + */ + void close(); void destroy(); + void stop(); attribute nsIDOMDocument DOMDocument; @@ -35,8 +45,11 @@ interface nsIContentViewer : nsISupports [noscript] void getBounds(in nsRectRef aBounds); [noscript] void setBounds([const] in nsRectRef aBounds); - [noscript] void setPreviousViewer(in nsIContentViewer aViewer); - [noscript] nsIContentViewer getPreviousViewer(); + /** + * The previous content viewer, which has been |close|d but not + * |destroy|ed. + */ + [noscript] attribute nsIContentViewer previousViewer; void move(in long aX, in long aY); diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index de6a7aed964..2a02d87d4d0 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -275,17 +275,17 @@ struct PrintObject public: PrintObject(); - virtual ~PrintObject(); + ~PrintObject(); // non-virtual // Methods PRBool IsPrintable() { return !mDontPrint; } nsIWebShell *mWebShell; PrintObjectType mFrameType; - nsIPresContext *mPresContext; - nsIStyleSet *mStyleSet; - nsIPresShell *mPresShell; - nsIViewManager *mViewManager; + nsCOMPtr mPresContext; + nsCOMPtr mStyleSet; + nsCOMPtr mPresShell; + nsCOMPtr mViewManager; nsIView *mView; nsIView *mRootView; @@ -305,6 +305,9 @@ public: nsRect mClipRect; +private: + PrintObject& operator=(const PrintObject& aOther); // not implemented + }; //--------------------------------------------------- @@ -314,17 +317,17 @@ struct PrintData { public: PrintData(); - virtual ~PrintData(); + ~PrintData(); // non-virtual // Listener Helper Methods void OnEndPrinting(nsresult aResult); void OnStartPrinting(); - nsIDeviceContext *mPrintDC; - nsIPresContext *mPrintPC; - nsIStyleSet *mPrintSS; - nsIPresShell *mPrintPS; - nsIViewManager *mPrintVM; + nsCOMPtr mPrintDC; + nsCOMPtr mPrintPC; + nsCOMPtr mPrintSS; + nsCOMPtr mPrintPS; + nsCOMPtr mPrintVM; nsIView *mPrintView; FILE *mFilePointer; // a file where information can go to when printing @@ -351,6 +354,9 @@ public: FILE * mDebugFD; #endif +private: + PrintData& operator=(const PrintData& aOther); // not implemented + }; //------------------------------------------------------------- @@ -372,30 +378,7 @@ public: NS_DECL_ISUPPORTS // nsIContentViewer interface... - NS_IMETHOD Init(nsIWidget* aParentWidget, - nsIDeviceContext* aDeviceContext, - const nsRect& aBounds); - NS_IMETHOD SetContainer(nsISupports* aContainer); - NS_IMETHOD GetContainer(nsISupports** aContainerResult); - NS_IMETHOD LoadStart(nsISupports* aDoc); - NS_IMETHOD LoadComplete(nsresult aStatus); - NS_IMETHOD Unload(void); - NS_IMETHOD Destroy(void); - NS_IMETHOD Stop(void); - NS_IMETHOD GetDOMDocument(nsIDOMDocument **aResult); - NS_IMETHOD SetDOMDocument(nsIDOMDocument *aDocument); - NS_IMETHOD GetBounds(nsRect& aResult); - NS_IMETHOD SetBounds(const nsRect& aBounds); - - NS_IMETHOD GetPreviousViewer(nsIContentViewer** aResult); - NS_IMETHOD SetPreviousViewer(nsIContentViewer* aViewer); - - NS_IMETHOD Move(PRInt32 aX, PRInt32 aY); - NS_IMETHOD Show(); - NS_IMETHOD Hide(); - NS_IMETHOD Validate(); - NS_IMETHOD SetEnableRendering(PRBool aOn); - NS_IMETHOD GetEnableRendering(PRBool* aResult); + NS_DECL_NSICONTENTVIEWER // nsIDocumentViewer interface... NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet); @@ -667,9 +650,7 @@ private: PrintObject * mPrintObj; }; -NS_IMPL_ADDREF(nsPagePrintTimer) -NS_IMPL_RELEASE(nsPagePrintTimer) -NS_IMPL_QUERY_INTERFACE1(nsPagePrintTimer, nsITimerCallback) +NS_IMPL_ISUPPORTS1(nsPagePrintTimer, nsITimerCallback) nsresult NS_NewUpdateTimer(nsPagePrintTimer **aResult) { @@ -690,7 +671,6 @@ nsresult NS_NewUpdateTimer(nsPagePrintTimer **aResult) //-- PrintData Class Impl //--------------------------------------------------- PrintData::PrintData() : - mPrintDC(nsnull), mPrintPC(nsnull), mPrintSS(nsnull), mPrintPS(nsnull), mPrintVM(nsnull), mPrintView(nsnull), mFilePointer(nsnull), mPrintObject(nsnull), mSelectedPO(nsnull), mPrintDocList(nsnull), mIsIFrameSelected(PR_FALSE), mIsParentAFrameSet(PR_FALSE), mPrintingAsIsSubDoc(PR_FALSE), @@ -708,7 +688,9 @@ PrintData::~PrintData() // printing is complete, clean up now if (mPrintPS) { + // XXX we never call BeginObservingDocument on this pres shell. mPrintPS->EndObservingDocument(); + mPrintPS->Destroy(); } OnEndPrinting(NS_OK); // removes listener @@ -725,12 +707,6 @@ PrintData::~PrintData() mPrintDocList->Clear(); delete mPrintDocList; - NS_IF_RELEASE(mPrintPS); - NS_IF_RELEASE(mPrintVM); - NS_IF_RELEASE(mPrintSS); - NS_IF_RELEASE(mPrintDC); - NS_IF_RELEASE(mPrintPC); - #ifdef DEBUG_PRINTING fclose(mDebugFD); #endif @@ -754,7 +730,7 @@ void PrintData::OnEndPrinting(nsresult aResult) } mPrintListener->OnEndPrinting(aResult); // clear the lister so the destructor doesn't send the - mPrintListener = do_QueryInterface(nsnull); + mPrintListener = nsnull; } } @@ -763,8 +739,7 @@ void PrintData::OnEndPrinting(nsresult aResult) //-- PrintObject Class Impl //--------------------------------------------------- PrintObject::PrintObject() : - mWebShell(nsnull), mFrameType(eFrame), mPresContext(nsnull), - mStyleSet(nsnull), mPresShell(nsnull), mViewManager(nsnull), + mWebShell(nsnull), mFrameType(eFrame), mView(nsnull), mRootView(nsnull), mContent(nsnull), mSeqFrame(nsnull), mPageFrame(nsnull), mPageNum(-1), mRect(0,0,0,0), mReflowRect(0,0,0,0), @@ -776,16 +751,13 @@ PrintObject::PrintObject() : PrintObject::~PrintObject() { - NS_IF_RELEASE(mPresShell); - NS_IF_RELEASE(mStyleSet); - NS_IF_RELEASE(mViewManager); - NS_IF_RELEASE(mPresContext); - for (PRInt32 i=0;iDestroy(); } //------------------------------------------------------------------ @@ -809,7 +781,7 @@ NS_NewDocumentViewer(nsIDocumentViewer** aResult) *aResult = nsnull; return NS_ERROR_OUT_OF_MEMORY; } - return it->QueryInterface(NS_GET_IID(nsIDocumentViewer), (void**) aResult); + return CallQueryInterface(it, aResult); } // Note: operator new zeros our memory @@ -828,7 +800,7 @@ void DocumentViewerImpl::PrepareToStartLoad() { } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) - : mPresContext(dont_QueryInterface(aPresContext)) + : mPresContext(aPresContext) { NS_INIT_ISUPPORTS(); mHintCharsetSource = kCharsetUninitialized; @@ -845,20 +817,16 @@ NS_IMPL_ISUPPORTS5(DocumentViewerImpl, DocumentViewerImpl::~DocumentViewerImpl() { - if (mPagePrintTimer != nsnull) { - mPagePrintTimer->Stop(); - delete mPagePrintTimer; - } - - if (mPrt != nsnull) { - mPrt->OnEndPrinting(NS_ERROR_FAILURE); - delete mPrt; - } - // Revoke pending invalidate events - NS_ASSERTION(!mDocument, "User did not call nsIContentViewer::Destroy"); + NS_ASSERTION(!mDocument, "User did not call nsIContentViewer::Close"); if (mDocument) + Close(); + + NS_ASSERTION(!mPresShell, "User did not call nsIContentViewer::Destroy"); + if (mPresShell) Destroy(); + // XXX(?) Revoke pending invalidate events + // clear weak references before we go away if (mPresContext) { mPresContext->SetContainer(nsnull); @@ -870,10 +838,6 @@ DocumentViewerImpl::~DocumentViewerImpl() // stop everything but the chrome. mPresContext->Stop(); } - - // Avoid leaking the old viewer. - if (mPreviousViewer) - SetPreviousViewer(nsnull); } /* @@ -1037,7 +1001,7 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, // this is the owning reference. The nsCOMPtr will take care of releasing // our ref to the listener on destruction. NS_ADDREF(selectionListener); - rv = selectionListener->QueryInterface(NS_GET_IID(nsISelectionListener), getter_AddRefs(mSelectionListener)); + mSelectionListener = do_QueryInterface(selectionListener); NS_RELEASE(selectionListener); if (NS_FAILED(rv)) return rv; @@ -1060,7 +1024,7 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, // this is the owning reference. The nsCOMPtr will take care of releasing // our ref to the listener on destruction. NS_ADDREF(focusListener); - rv = focusListener->QueryInterface(NS_GET_IID(nsIDOMFocusListener), getter_AddRefs(mFocusListener)); + mFocusListener = do_QueryInterface(focusListener); NS_RELEASE(focusListener); if (NS_FAILED(rv)) return rv; @@ -1068,8 +1032,7 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, if(mDocument) { // get the DOM event receiver - nsCOMPtr erP; - rv = mDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP)); + nsCOMPtr erP (do_QueryInterface(mDocument, &rv)); if(NS_FAILED(rv) || !erP) return rv?rv:NS_ERROR_FAILURE; @@ -1166,13 +1129,19 @@ DocumentViewerImpl::Unload() } NS_IMETHODIMP -DocumentViewerImpl::Destroy() +DocumentViewerImpl::Close() { - // All callers are supposed to call destroy to break circular + // All callers are supposed to call close to break circular // references. If we do this stuff in the destructor, the // destructor might never be called (especially if we're being // used from JS. + // Close is also needed to disable scripts during paint suppression, + // since we transfer the existing global object to the new document + // that is loaded. In the future, the global object may become a proxy + // for an object that can be switched in and out so that we don't need + // to disable scripts during paint suppression. + nsresult rv; if (mDocument) { @@ -1187,13 +1156,41 @@ DocumentViewerImpl::Destroy() mDocument->SetScriptGlobalObject(nsnull); if (mFocusListener) { // get the DOM event receiver - nsCOMPtr erP; - rv = mDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP)); + nsCOMPtr erP( do_QueryInterface(mDocument, &rv) ); if(NS_SUCCEEDED(rv) && erP) erP->RemoveEventListenerByIID(mFocusListener, NS_GET_IID(nsIDOMFocusListener)); } } + mDocument = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +DocumentViewerImpl::Destroy() +{ + // All callers are supposed to call destroy to break circular + // references. If we do this stuff in the destructor, the + // destructor might never be called (especially if we're being + // used from JS. + + if (mPagePrintTimer != nsnull) { + mPagePrintTimer->Stop(); + delete mPagePrintTimer; + } + + if (mPrt) { + mPrt->OnEndPrinting(NS_ERROR_FAILURE); + delete mPrt; + mPrt = nsnull; + } + + // Avoid leaking the old viewer. + if (mPreviousViewer) { + mPreviousViewer->Destroy(); + mPreviousViewer = nsnull; + } + if (mDeviceContext) mDeviceContext->FlushFontCache(); @@ -1201,13 +1198,14 @@ DocumentViewerImpl::Destroy() // Break circular reference (or something) mPresShell->EndObservingDocument(); nsCOMPtr selection; - rv = GetDocumentSelection(getter_AddRefs(selection)); + nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); nsCOMPtr selPrivate(do_QueryInterface(selection)); if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) selPrivate->RemoveSelectionListener(mSelectionListener); + mPresShell->Destroy(); + mPresShell = nsnull; } - mDocument = nsnull; return NS_OK; } @@ -1291,6 +1289,7 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) // 3) Replace the current pres shell with a new shell for the new document mPresShell->EndObservingDocument(); + mPresShell->Destroy(); mPresShell = nsnull; rv = newDoc->CreateShell(mPresContext, mViewManager, styleSet, @@ -1302,8 +1301,7 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) // 4) Register the focus listener on the new document if(mDocument) { - nsCOMPtr erP; - rv = mDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP)); + nsCOMPtr erP = do_QueryInterface(mDocument, &rv); if(NS_FAILED(rv) || !erP) return rv ? rv : NS_ERROR_FAILURE; @@ -1370,17 +1368,13 @@ DocumentViewerImpl::GetPreviousViewer(nsIContentViewer** aViewer) NS_IMETHODIMP DocumentViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer) { - if (!aViewer) { - // Clearing it out. - mPreviousViewer = nsnull; + // NOTE: |Show| sets |mPreviousViewer| to null without calling this + // function. + + if (aViewer) { + NS_ASSERTION(!mPreviousViewer, + "can't set previous viewer when there already is one"); - // Now we can show, but only if we aren't dead already (which - // can occasionally happen when one page moves to another during the onload - // handler.) - if (mDocument) - Show(); - } - else { // In a multiple chaining situation (which occurs when running a thrashing // test like i-bench or jrgm's tests with no delay), we can build up a // whole chain of viewers. In order to avoid this, we always set our previous @@ -1392,9 +1386,9 @@ DocumentViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer) nsCOMPtr prevViewer; aViewer->GetPreviousViewer(getter_AddRefs(prevViewer)); if (prevViewer) { - SetPreviousViewer(prevViewer); - prevViewer->SetPreviousViewer(nsnull); - return NS_OK; + aViewer->SetPreviousViewer(nsnull); + aViewer->Destroy(); + return SetPreviousViewer(prevViewer); } } @@ -1432,6 +1426,17 @@ DocumentViewerImpl::Show(void) { NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); NS_PRECONDITION(mWindow, "null window"); + + // We don't need the previous viewer anymore since we're not + // displaying it. + if (mPreviousViewer) { + // This little dance *may* only be to keep + // PresShell::EndObservingDocument happy, but I'm not sure. + nsCOMPtr prevViewer(mPreviousViewer); + mPreviousViewer = nsnull; + prevViewer->Destroy(); + } + if (mWindow) { mWindow->Show(PR_TRUE); } @@ -1491,7 +1496,7 @@ GetPresShellFor(nsIDocShell* aDocShell) aDocShell->GetContentViewer(&cv); if (nsnull != cv) { nsIDocumentViewer* docv = nsnull; - cv->QueryInterface(NS_GET_IID(nsIDocumentViewer), (void**) &docv); + CallQueryInterface(cv, &docv); if (nsnull != docv) { nsIPresContext* cx; docv->GetPresContext(cx); @@ -1537,7 +1542,7 @@ static void DumpFrames(FILE* out, nsAutoString tmp; nsIFrameDebug* frameDebug; - if (NS_SUCCEEDED(child->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) { + if (NS_SUCCEEDED(CallQueryInterface(child, &frameDebug))) { frameDebug->GetFrameName(tmp); } fputs(tmp, out); @@ -1665,7 +1670,7 @@ static void DumpPrintObjectsList(nsVoidArray * aDocList, FILE* aFD = nsnull) po->mPresShell->GetRootFrame(&rootFrame); while (rootFrame != nsnull) { nsIPageSequenceFrame * sqf = nsnull; - if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIPageSequenceFrame), (void**)&sqf)) && sqf) { + if (NS_SUCCEEDED(CallQueryInterface(rootFrame, &sqf)) && sqf) { break; } rootFrame->FirstChild(po->mPresContext, nsnull, &rootFrame); @@ -1721,7 +1726,7 @@ static void DumpPrintObjectsTreeLayout(PrintObject * aPO, } if (fd) { nsIFrame* rootFrame = nsnull; - if (aPO->mPresShell != nsnull) { + if (aPO->mPresShell) { aPO->mPresShell->GetRootFrame(&rootFrame); } for (PRInt32 k=0;kQueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_FAILED(CallQueryInterface(aPageSeqFrame, &seqFrame))) { return NS_ERROR_FAILURE; } @@ -2268,7 +2273,7 @@ DocumentViewerImpl::PrintPage(nsIPresContext* aPresContext, // page num of it's parent doc curPageSeq->GetCurrentPageNum(&pageNum); nsIFrame* fr; - curPageSeq->QueryInterface(NS_GET_IID(nsIFrame), (void**)&fr); + CallQueryInterface(curPageSeq, &fr); if (fr == po->mSeqFrame && pageNum == po->mPageNum) { PRBool donePrintingSubDoc; @@ -2425,7 +2430,7 @@ void DocumentViewerImpl::CalcPageFrameLocation(nsIPresShell * aPresShell, // Keep a pointer to the Seq and Page frames nsIPageSequenceFrame * sqf = nsnull; if (parent != nsnull && - NS_SUCCEEDED(parent->QueryInterface(NS_GET_IID(nsIPageSequenceFrame), (void**)&sqf)) && sqf) { + NS_SUCCEEDED(CallQueryInterface(parent, &sqf)) && sqf) { pageFrame = temp; seqFrame = parent; } @@ -2482,7 +2487,7 @@ DocumentViewerImpl::MapSubDocFrameLocations(PrintObject* aPO) CalcPageFrameLocation(aPO->mParent->mPresShell, aPO); } - if (aPO->mPresShell != nsnull) { + if (aPO->mPresShell) { for (PRInt32 i=0;imKids.Count();i++) { MapSubDocFrameLocations((PrintObject*)aPO->mKids[i]); } @@ -2732,7 +2737,7 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) if (NS_FAILED(rv)) { return rv; } else { - rv = printcon->QueryInterface(NS_GET_IID(nsIPresContext), (void**)&aPO->mPresContext); + aPO->mPresContext = do_QueryInterface(printcon); if (NS_FAILED(rv)) { return rv; } @@ -2741,16 +2746,14 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) // init it with the DC (aPO->mPresContext)->Init(mPrt->mPrintDocDC); - CreateStyleSet(document, &aPO->mStyleSet); + CreateStyleSet(document, getter_AddRefs(aPO->mStyleSet)); - rv = nsComponentManager::CreateInstance(kPresShellCID,nsnull, - NS_GET_IID(nsIPresShell),(void **)&aPO->mPresShell); + aPO->mPresShell = do_CreateInstance(kPresShellCID, &rv); if (NS_FAILED(rv)) { return rv; } - rv = nsComponentManager::CreateInstance(kViewManagerCID,nsnull, - NS_GET_IID(nsIViewManager),(void **)&aPO->mViewManager); + aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); if (NS_FAILED(rv)) { return rv; } @@ -2796,7 +2799,7 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) nsRect tbounds = nsRect(0, 0, width, height); // Create a child window of the parent that is our "root view/window" - rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&(aPO->mRootView)); + rv = CallCreateInstance(kViewCID, &aPO->mRootView); if (NS_FAILED(rv)) { return rv; } @@ -2807,7 +2810,8 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) // Setup hierarchical relationship in view manager aPO->mViewManager->SetRootView(aPO->mRootView); - aPO->mPresShell->Init(document, aPO->mPresContext, aPO->mViewManager,aPO->mStyleSet); + aPO->mPresShell->Init(document, aPO->mPresContext, + aPO->mViewManager, aPO->mStyleSet); nsCompatibility mode; mPresContext->GetCompatibilityMode(&mode); @@ -3435,7 +3439,7 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a nsIFrame* root; poPresShell->GetRootFrame(&root); - if (NS_SUCCEEDED(root->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**) &fdbg))) { + if (NS_SUCCEEDED(CallQueryInterface(root, &fdbg))) { fdbg->DumpRegressionData(poPresContext, mPrt->mFilePointer, 0, PR_TRUE); } fclose(mPrt->mFilePointer); @@ -3501,7 +3505,7 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a if (startPageNum == endPageNum) { nsIFrame * seqFrame; - if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { gCurrentlyPrinting = PR_FALSE; return NS_ERROR_FAILURE; } @@ -3518,7 +3522,7 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a } nsIFrame * seqFrame; - if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { gCurrentlyPrinting = PR_FALSE; return NS_ERROR_FAILURE; } @@ -3582,11 +3586,13 @@ DocumentViewerImpl::CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNu PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); NS_ASSERTION(po, "PrintObject can't be null!"); if (po->IsPrintable()) { - if (po->mPresShell != nsnull && (po->mFrameType != eIFrame && po->mFrameType != eFrameSet)) { + if (po->mPresShell && + po->mFrameType != eIFrame && + po->mFrameType != eFrameSet) { nsIPageSequenceFrame* pageSequence; po->mPresShell->GetPageSequenceFrame(&pageSequence); nsIFrame * seqFrame; - if (NS_SUCCEEDED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + if (NS_SUCCEEDED(CallQueryInterface(pageSequence, &seqFrame))) { nsIFrame* frame; seqFrame->FirstChild(po->mPresContext, nsnull, &frame); while (frame) { @@ -3765,7 +3771,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, NS_WARNING("unable to load UA style sheet"); } - rv = nsComponentManager::CreateInstance(kStyleSetCID,nsnull,NS_GET_IID(nsIStyleSet),(void**)aStyleSet); + rv = CallCreateInstance(kStyleSetCID, aStyleSet); if (NS_OK == rv) { PRInt32 index = 0; aDocument->GetNumberOfStyleSheets(&index); @@ -3838,10 +3844,9 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, { nsresult rv; - rv = nsComponentManager::CreateInstance(kViewManagerCID, - nsnull, - NS_GET_IID(nsIViewManager), - getter_AddRefs(mViewManager)); + mViewManager = do_CreateInstance(kViewManagerCID, &rv); + if (NS_FAILED(rv)) + return rv; nsCOMPtr dx; mPresContext->GetDeviceContext(getter_AddRefs(dx)); @@ -3852,11 +3857,12 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, mPresContext->GetPixelsToTwips(&p2t); tbounds *= p2t; - // Initialize the view manager with an offset. This allows the viewmanager - // to manage a coordinate space offset from (0,0) - if ((NS_OK != rv) || (NS_OK != mViewManager->Init(dx, tbounds.x, tbounds.y))) { + // Initialize the view manager with an offset. This allows the viewmanager + // to manage a coordinate space offset from (0,0) + rv = mViewManager->Init(dx, tbounds.x, tbounds.y); + if (NS_FAILED(rv)) return rv; - } + // Reset the bounds offset so the root view is set to 0,0. The offset is // specified in nsIViewManager::Init above. // Besides, layout will reset the root view to (0,0) during reflow, @@ -3867,15 +3873,12 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, // Create a child window of the parent that is our "root view/window" // Create a view - rv = nsComponentManager::CreateInstance(kViewCID, - nsnull, - NS_GET_IID(nsIView), - (void**)&mView); - if ((NS_OK != rv) || (NS_OK != mView->Init(mViewManager, - tbounds, - nsnull))) { + rv = CallCreateInstance(kViewCID, &mView); + if (NS_FAILED(rv)) + return rv; + rv = mView->Init(mViewManager, tbounds, nsnull); + if (NS_FAILED(rv)) return rv; - } rv = mView->CreateWidget(kWidgetCID, nsnull, aParentWidget->GetNativeData(NS_NATIVE_WIDGET)); @@ -4064,10 +4067,7 @@ NS_IMETHODIMP DocumentViewerImpl::SelectAll() if (NS_FAILED(rv)) return rv; static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID); - nsCOMPtr range; - rv = nsComponentManager::CreateInstance(kCDOMRangeCID, nsnull, - NS_GET_IID(nsIDOMRange), - getter_AddRefs(range)); + nsCOMPtr range = do_CreateInstance(kCDOMRangeCID, &rv); rv = range->SelectNodeContents(bodyNode); if (NS_FAILED(rv)) return rv; @@ -4320,10 +4320,7 @@ nsresult rv; // another is still in here (the printing dialog is a good example). if(gCurrentlyPrinting) { // Beep at the user, let them know we are not ready to print. - nsCOMPtr soundInterface; - rv = nsComponentManager::CreateInstance(kSoundCID, - nsnull, NS_GET_IID(nsISound), - getter_AddRefs(soundInterface)); + nsCOMPtr soundInterface( do_CreateInstance(kSoundCID, &rv) ); if (NS_SUCCEEDED(rv) && (soundInterface != nsnull)){ soundInterface->Beep(); } @@ -4425,11 +4422,8 @@ nsresult rv; } #endif - nsCOMPtr factory; - nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, - nsnull, - NS_GET_IID(nsIDeviceContextSpecFactory), - (void **)getter_AddRefs(factory)); + nsCOMPtr factory = + do_CreateInstance(kDeviceContextSpecFactoryCID); if (factory) { @@ -4439,13 +4433,13 @@ nsresult rv; nsIDeviceContextSpec *devspec = nsnull; nsCOMPtr dx; - mPrt->mPrintDC = nsnull; + mPrt->mPrintDC = nsnull; // XXX why? mPrt->mFilePointer = aFile; factory->CreateDeviceContextSpec(mWindow, devspec, aSilent); if (nsnull != devspec) { mPresContext->GetDeviceContext(getter_AddRefs(dx)); - rv = dx->GetDeviceContextFor(devspec, mPrt->mPrintDC); + rv = dx->GetDeviceContextFor(devspec, *getter_AddRefs(mPrt->mPrintDC)); if (NS_SUCCEEDED(rv)) { NS_RELEASE(devspec); @@ -4457,7 +4451,7 @@ nsresult rv; gCurrentlyPrinting = PR_FALSE; return rv; } else { - rv = printcon->QueryInterface(NS_GET_IID(nsIPresContext), (void**)&mPrt->mPrintPC); + mPrt->mPrintPC = do_QueryInterface(printcon, &rv); if (NS_FAILED(rv)) { gCurrentlyPrinting = PR_FALSE; return rv; @@ -4478,15 +4472,15 @@ nsresult rv; mPrt->mPrintPC->Init(mPrt->mPrintDC); mPrt->mPrintPC->SetContainer(webContainer); - CreateStyleSet(mDocument,&mPrt->mPrintSS); + CreateStyleSet(mDocument, getter_AddRefs(mPrt->mPrintSS)); - rv = nsComponentManager::CreateInstance(kPresShellCID, nsnull, NS_GET_IID(nsIPresShell),(void**)&mPrt->mPrintPS); + mPrt->mPrintPS = do_CreateInstance(kPresShellCID, &rv); if(NS_FAILED(rv)){ gCurrentlyPrinting = PR_FALSE; return rv; } - rv = nsComponentManager::CreateInstance(kViewManagerCID, nsnull, NS_GET_IID(nsIViewManager),(void**)&mPrt->mPrintVM); + mPrt->mPrintVM = do_CreateInstance(kViewManagerCID, &rv); if(NS_FAILED(rv)) { gCurrentlyPrinting = PR_FALSE; return rv; @@ -4498,7 +4492,7 @@ nsresult rv; return rv; } - rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView),(void**)&mPrt->mPrintView); + rv = CallCreateInstance(kViewCID, &mPrt->mPrintView); if(NS_FAILED(rv)) { gCurrentlyPrinting = PR_FALSE; return rv; @@ -5146,7 +5140,7 @@ NS_IMETHODIMP DocumentViewerImpl::SizeToContent() #pragma mark - #endif -NS_IMPL_ISUPPORTS(nsDocViewerSelectionListener, NS_GET_IID(nsISelectionListener)); +NS_IMPL_ISUPPORTS1(nsDocViewerSelectionListener, nsISelectionListener); nsresult nsDocViewerSelectionListener::Init(DocumentViewerImpl *aDocViewer) { @@ -5368,7 +5362,7 @@ NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocumen } //nsDocViewerFocusListener -NS_IMPL_ISUPPORTS(nsDocViewerFocusListener, NS_GET_IID(nsIDOMFocusListener)); +NS_IMPL_ISUPPORTS1(nsDocViewerFocusListener, nsIDOMFocusListener); nsDocViewerFocusListener::nsDocViewerFocusListener() :mDocViewer(nsnull) diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 34035caad1f..61b91b030d4 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -125,6 +125,15 @@ public: nsIViewManager* aViewManager, nsIStyleSet* aStyleSet) = 0; + /** + * All callers are responsible for calling |Destroy| after calling + * |EndObservingDocument|. It needs to be separate only because form + * controls incorrectly store their data in the frames rather than the + * content model and printing calls |EndObservingDocument| multiple + * times to make form controls behave nicely when printed. + */ + NS_IMETHOD Destroy() = 0; + // All frames owned by the shell are allocated from an arena. They are also recycled // using free lists (separate free lists being maintained for each size_t). // Methods for recycling frames. diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 7fa3ba333fa..dc85987a70e 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -807,6 +807,7 @@ public: nsIPresContext* aPresContext, nsIViewManager* aViewManager, nsIStyleSet* aStyleSet); + NS_IMETHOD Destroy(); NS_IMETHOD AllocateFrame(size_t aSize, void** aResult); NS_IMETHOD FreeFrame(size_t aSize, void* aFreeChunk); @@ -1482,111 +1483,20 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr) PresShell::~PresShell() { -#ifdef MOZ_REFLOW_PERF - DumpReflows(); - if (mReflowCountMgr) { - delete mReflowCountMgr; - mReflowCountMgr = nsnull; + if (mStyleSet) { + NS_NOTREACHED("Someone did not call nsIPresShell::destroy"); + Destroy(); } -#endif - - // If our paint suppression timer is still active, kill it. - if (mPaintSuppressionTimer) { - mPaintSuppressionTimer->Cancel(); - mPaintSuppressionTimer = nsnull; - } - - nsCOMPtr container; - mPresContext->GetContainer(getter_AddRefs(container)); - if (container) { - nsCOMPtr cvc(do_QueryInterface(container)); - if (cvc) { - nsCOMPtr cv; - cvc->GetContentViewer(getter_AddRefs(cv)); - if (cv) - cv->SetPreviousViewer(nsnull); - } - } - - // release our pref style sheet, if we have one still - ClearPreferenceStyleRules(); // if we allocated any stack memory free it. FreeDynamicStack(); - - // free our table of anonymous content - ReleaseAnonymousContent(); - - mIsDestroying = PR_TRUE; - - // Clobber weak leaks in case of re-entrancy during tear down - mHistoryState = nsnull; - - // kill subshell map, if any. It holds only weak references - if (mSubShellMap) - { - delete mSubShellMap; - mSubShellMap = nsnull; - } - - // release current event content and any content on event stack - NS_IF_RELEASE(mCurrentEventContent); - - PRInt32 i, count = mCurrentEventContentStack.Count(); - nsIContent* currentEventContent; - for (i = 0; i < count; i++) { - currentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(i); - NS_IF_RELEASE(currentEventContent); - } - - if (mViewManager) { - // Disable paints during tear down of the frame tree - mViewManager->DisableRefresh(); - mViewManager = nsnull; - } - - // This shell must be removed from the document before the frame - // hierarchy is torn down to avoid finding deleted frames through - // this presshell while the frames are being torn down - if (mDocument) { - mDocument->DeleteShell(this); - } - - // Destroy the frame manager. This will destroy the frame hierarchy - if (mFrameManager) { - mFrameManager->Destroy(); - NS_RELEASE(mFrameManager); - } - - // Let the style set do its cleanup. - mStyleSet->Shutdown(); - - // We hold a reference to the pres context, and it holds a weak link back - // to us. To avoid the pres context having a dangling reference, set its - // pres shell to NULL - if (mPresContext) { - mPresContext->SetShell(nsnull); - } - - if (mViewEventListener) { - mViewEventListener->SetPresShell((nsIPresShell*)nsnull); - NS_RELEASE(mViewEventListener); - } - - // Revoke pending reflow events - if (mPendingReflowEvent) { - mPendingReflowEvent = PR_FALSE; - mEventQueue->RevokeEvents(this); - } - - KillResizeEventTimer(); } /** * Initialize the presentation shell. Create view manager and style * manager. */ -nsresult +NS_IMETHODIMP PresShell::Init(nsIDocument* aDocument, nsIPresContext* aPresContext, nsIViewManager* aViewManager, @@ -1614,7 +1524,7 @@ PresShell::Init(nsIDocument* aDocument, mPresContext = dont_QueryInterface(aPresContext); aPresContext->SetShell(this); - mStyleSet = dont_QueryInterface(aStyleSet); + mStyleSet = aStyleSet; mHistoryState = nsnull; @@ -1719,6 +1629,116 @@ PresShell::Init(nsIDocument* aDocument, } #endif + return NS_OK; +} + +NS_IMETHODIMP +PresShell::Destroy() +{ +#ifdef MOZ_REFLOW_PERF + DumpReflows(); + if (mReflowCountMgr) { + delete mReflowCountMgr; + mReflowCountMgr = nsnull; + } +#endif + + // If our paint suppression timer is still active, kill it. + if (mPaintSuppressionTimer) { + mPaintSuppressionTimer->Cancel(); + mPaintSuppressionTimer = nsnull; + } + +#ifdef DEBUG + { + nsCOMPtr container; + mPresContext->GetContainer(getter_AddRefs(container)); + if (container) { + nsCOMPtr cvc(do_QueryInterface(container)); + if (cvc) { + nsCOMPtr cv; + cvc->GetContentViewer(getter_AddRefs(cv)); + if (cv) { + nsCOMPtr prevViewer; + cv->GetPreviousViewer(getter_AddRefs(prevViewer)); + NS_ASSERTION(!prevViewer, "still have a previous viewer!"); + } + } + } + } +#endif + + // release our pref style sheet, if we have one still + ClearPreferenceStyleRules(); + + // free our table of anonymous content + ReleaseAnonymousContent(); + + mIsDestroying = PR_TRUE; + + // Clobber weak leaks in case of re-entrancy during tear down + mHistoryState = nsnull; + + // kill subshell map, if any. It holds only weak references + if (mSubShellMap) + { + delete mSubShellMap; + mSubShellMap = nsnull; + } + + // release current event content and any content on event stack + NS_IF_RELEASE(mCurrentEventContent); + + PRInt32 i, count = mCurrentEventContentStack.Count(); + nsIContent* currentEventContent; + for (i = 0; i < count; i++) { + currentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(i); + NS_IF_RELEASE(currentEventContent); + } + + if (mViewManager) { + // Disable paints during tear down of the frame tree + mViewManager->DisableRefresh(); + mViewManager = nsnull; + } + + // This shell must be removed from the document before the frame + // hierarchy is torn down to avoid finding deleted frames through + // this presshell while the frames are being torn down + if (mDocument) { + mDocument->DeleteShell(this); + } + + // Destroy the frame manager. This will destroy the frame hierarchy + if (mFrameManager) { + mFrameManager->Destroy(); + NS_RELEASE(mFrameManager); + } + + // Let the style set do its cleanup. + mStyleSet->Shutdown(); + mStyleSet = nsnull; + + // We hold a reference to the pres context, and it holds a weak link back + // to us. To avoid the pres context having a dangling reference, set its + // pres shell to NULL + if (mPresContext) { + mPresContext->SetShell(nsnull); + } + + if (mViewEventListener) { + mViewEventListener->SetPresShell((nsIPresShell*)nsnull); + NS_RELEASE(mViewEventListener); + } + + // Revoke pending reflow events + if (mPendingReflowEvent) { + mPendingReflowEvent = PR_FALSE; + mEventQueue->RevokeEvents(this); + } + + KillResizeEventTimer(); + return NS_OK; } @@ -2447,6 +2467,7 @@ PresShell::EndObservingDocument() return NS_ERROR_UNEXPECTED; mSelection->ShutDown(); } + return NS_OK; } @@ -4579,23 +4600,17 @@ PresShell::UnsuppressAndInvalidate() focusController->SetSuppressFocus(PR_TRUE, "PresShell suppression on Web page loads"); nsCOMPtr container; - nsCOMPtr cv; - nsCOMPtr dv; mPresContext->GetContainer(getter_AddRefs(container)); if (container) { nsCOMPtr cvc(do_QueryInterface(container)); if (cvc) { + nsCOMPtr cv; cvc->GetContentViewer(getter_AddRefs(cv)); - dv = do_QueryInterface(cv); + if (cv) + cv->Show(); } } - if (dv) - dv->Show(); - - if (cv) - cv->SetPreviousViewer(nsnull); - mPaintingSuppressed = PR_FALSE; nsIFrame* rootFrame; mFrameManager->GetRootFrame(&rootFrame); diff --git a/mozilla/layout/base/public/nsIPresShell.h b/mozilla/layout/base/public/nsIPresShell.h index 34035caad1f..61b91b030d4 100644 --- a/mozilla/layout/base/public/nsIPresShell.h +++ b/mozilla/layout/base/public/nsIPresShell.h @@ -125,6 +125,15 @@ public: nsIViewManager* aViewManager, nsIStyleSet* aStyleSet) = 0; + /** + * All callers are responsible for calling |Destroy| after calling + * |EndObservingDocument|. It needs to be separate only because form + * controls incorrectly store their data in the frames rather than the + * content model and printing calls |EndObservingDocument| multiple + * times to make form controls behave nicely when printed. + */ + NS_IMETHOD Destroy() = 0; + // All frames owned by the shell are allocated from an arena. They are also recycled // using free lists (separate free lists being maintained for each size_t). // Methods for recycling frames. diff --git a/mozilla/layout/generic/nsObjectFrame.cpp b/mozilla/layout/generic/nsObjectFrame.cpp index 10c0d52b6cd..3ce4aab8f7a 100644 --- a/mozilla/layout/generic/nsObjectFrame.cpp +++ b/mozilla/layout/generic/nsObjectFrame.cpp @@ -440,7 +440,7 @@ nsObjectFrame::Init(nsIPresContext* aPresContext, nsCOMPtr cv; cvc->GetContentViewer(getter_AddRefs(cv)); if (cv) - cv->SetPreviousViewer(nsnull); + cv->Show(); } } diff --git a/mozilla/layout/html/base/src/nsObjectFrame.cpp b/mozilla/layout/html/base/src/nsObjectFrame.cpp index 10c0d52b6cd..3ce4aab8f7a 100644 --- a/mozilla/layout/html/base/src/nsObjectFrame.cpp +++ b/mozilla/layout/html/base/src/nsObjectFrame.cpp @@ -440,7 +440,7 @@ nsObjectFrame::Init(nsIPresContext* aPresContext, nsCOMPtr cv; cvc->GetContentViewer(getter_AddRefs(cv)); if (cv) - cv->SetPreviousViewer(nsnull); + cv->Show(); } } diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 7fa3ba333fa..dc85987a70e 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -807,6 +807,7 @@ public: nsIPresContext* aPresContext, nsIViewManager* aViewManager, nsIStyleSet* aStyleSet); + NS_IMETHOD Destroy(); NS_IMETHOD AllocateFrame(size_t aSize, void** aResult); NS_IMETHOD FreeFrame(size_t aSize, void* aFreeChunk); @@ -1482,111 +1483,20 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr) PresShell::~PresShell() { -#ifdef MOZ_REFLOW_PERF - DumpReflows(); - if (mReflowCountMgr) { - delete mReflowCountMgr; - mReflowCountMgr = nsnull; + if (mStyleSet) { + NS_NOTREACHED("Someone did not call nsIPresShell::destroy"); + Destroy(); } -#endif - - // If our paint suppression timer is still active, kill it. - if (mPaintSuppressionTimer) { - mPaintSuppressionTimer->Cancel(); - mPaintSuppressionTimer = nsnull; - } - - nsCOMPtr container; - mPresContext->GetContainer(getter_AddRefs(container)); - if (container) { - nsCOMPtr cvc(do_QueryInterface(container)); - if (cvc) { - nsCOMPtr cv; - cvc->GetContentViewer(getter_AddRefs(cv)); - if (cv) - cv->SetPreviousViewer(nsnull); - } - } - - // release our pref style sheet, if we have one still - ClearPreferenceStyleRules(); // if we allocated any stack memory free it. FreeDynamicStack(); - - // free our table of anonymous content - ReleaseAnonymousContent(); - - mIsDestroying = PR_TRUE; - - // Clobber weak leaks in case of re-entrancy during tear down - mHistoryState = nsnull; - - // kill subshell map, if any. It holds only weak references - if (mSubShellMap) - { - delete mSubShellMap; - mSubShellMap = nsnull; - } - - // release current event content and any content on event stack - NS_IF_RELEASE(mCurrentEventContent); - - PRInt32 i, count = mCurrentEventContentStack.Count(); - nsIContent* currentEventContent; - for (i = 0; i < count; i++) { - currentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(i); - NS_IF_RELEASE(currentEventContent); - } - - if (mViewManager) { - // Disable paints during tear down of the frame tree - mViewManager->DisableRefresh(); - mViewManager = nsnull; - } - - // This shell must be removed from the document before the frame - // hierarchy is torn down to avoid finding deleted frames through - // this presshell while the frames are being torn down - if (mDocument) { - mDocument->DeleteShell(this); - } - - // Destroy the frame manager. This will destroy the frame hierarchy - if (mFrameManager) { - mFrameManager->Destroy(); - NS_RELEASE(mFrameManager); - } - - // Let the style set do its cleanup. - mStyleSet->Shutdown(); - - // We hold a reference to the pres context, and it holds a weak link back - // to us. To avoid the pres context having a dangling reference, set its - // pres shell to NULL - if (mPresContext) { - mPresContext->SetShell(nsnull); - } - - if (mViewEventListener) { - mViewEventListener->SetPresShell((nsIPresShell*)nsnull); - NS_RELEASE(mViewEventListener); - } - - // Revoke pending reflow events - if (mPendingReflowEvent) { - mPendingReflowEvent = PR_FALSE; - mEventQueue->RevokeEvents(this); - } - - KillResizeEventTimer(); } /** * Initialize the presentation shell. Create view manager and style * manager. */ -nsresult +NS_IMETHODIMP PresShell::Init(nsIDocument* aDocument, nsIPresContext* aPresContext, nsIViewManager* aViewManager, @@ -1614,7 +1524,7 @@ PresShell::Init(nsIDocument* aDocument, mPresContext = dont_QueryInterface(aPresContext); aPresContext->SetShell(this); - mStyleSet = dont_QueryInterface(aStyleSet); + mStyleSet = aStyleSet; mHistoryState = nsnull; @@ -1719,6 +1629,116 @@ PresShell::Init(nsIDocument* aDocument, } #endif + return NS_OK; +} + +NS_IMETHODIMP +PresShell::Destroy() +{ +#ifdef MOZ_REFLOW_PERF + DumpReflows(); + if (mReflowCountMgr) { + delete mReflowCountMgr; + mReflowCountMgr = nsnull; + } +#endif + + // If our paint suppression timer is still active, kill it. + if (mPaintSuppressionTimer) { + mPaintSuppressionTimer->Cancel(); + mPaintSuppressionTimer = nsnull; + } + +#ifdef DEBUG + { + nsCOMPtr container; + mPresContext->GetContainer(getter_AddRefs(container)); + if (container) { + nsCOMPtr cvc(do_QueryInterface(container)); + if (cvc) { + nsCOMPtr cv; + cvc->GetContentViewer(getter_AddRefs(cv)); + if (cv) { + nsCOMPtr prevViewer; + cv->GetPreviousViewer(getter_AddRefs(prevViewer)); + NS_ASSERTION(!prevViewer, "still have a previous viewer!"); + } + } + } + } +#endif + + // release our pref style sheet, if we have one still + ClearPreferenceStyleRules(); + + // free our table of anonymous content + ReleaseAnonymousContent(); + + mIsDestroying = PR_TRUE; + + // Clobber weak leaks in case of re-entrancy during tear down + mHistoryState = nsnull; + + // kill subshell map, if any. It holds only weak references + if (mSubShellMap) + { + delete mSubShellMap; + mSubShellMap = nsnull; + } + + // release current event content and any content on event stack + NS_IF_RELEASE(mCurrentEventContent); + + PRInt32 i, count = mCurrentEventContentStack.Count(); + nsIContent* currentEventContent; + for (i = 0; i < count; i++) { + currentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(i); + NS_IF_RELEASE(currentEventContent); + } + + if (mViewManager) { + // Disable paints during tear down of the frame tree + mViewManager->DisableRefresh(); + mViewManager = nsnull; + } + + // This shell must be removed from the document before the frame + // hierarchy is torn down to avoid finding deleted frames through + // this presshell while the frames are being torn down + if (mDocument) { + mDocument->DeleteShell(this); + } + + // Destroy the frame manager. This will destroy the frame hierarchy + if (mFrameManager) { + mFrameManager->Destroy(); + NS_RELEASE(mFrameManager); + } + + // Let the style set do its cleanup. + mStyleSet->Shutdown(); + mStyleSet = nsnull; + + // We hold a reference to the pres context, and it holds a weak link back + // to us. To avoid the pres context having a dangling reference, set its + // pres shell to NULL + if (mPresContext) { + mPresContext->SetShell(nsnull); + } + + if (mViewEventListener) { + mViewEventListener->SetPresShell((nsIPresShell*)nsnull); + NS_RELEASE(mViewEventListener); + } + + // Revoke pending reflow events + if (mPendingReflowEvent) { + mPendingReflowEvent = PR_FALSE; + mEventQueue->RevokeEvents(this); + } + + KillResizeEventTimer(); + return NS_OK; } @@ -2447,6 +2467,7 @@ PresShell::EndObservingDocument() return NS_ERROR_UNEXPECTED; mSelection->ShutDown(); } + return NS_OK; } @@ -4579,23 +4600,17 @@ PresShell::UnsuppressAndInvalidate() focusController->SetSuppressFocus(PR_TRUE, "PresShell suppression on Web page loads"); nsCOMPtr container; - nsCOMPtr cv; - nsCOMPtr dv; mPresContext->GetContainer(getter_AddRefs(container)); if (container) { nsCOMPtr cvc(do_QueryInterface(container)); if (cvc) { + nsCOMPtr cv; cvc->GetContentViewer(getter_AddRefs(cv)); - dv = do_QueryInterface(cv); + if (cv) + cv->Show(); } } - if (dv) - dv->Show(); - - if (cv) - cv->SetPreviousViewer(nsnull); - mPaintingSuppressed = PR_FALSE; nsIFrame* rootFrame; mFrameManager->GetRootFrame(&rootFrame); diff --git a/mozilla/modules/plugin/base/src/nsPluginViewer.cpp b/mozilla/modules/plugin/base/src/nsPluginViewer.cpp index c0f908419a8..6873cbe5de1 100644 --- a/mozilla/modules/plugin/base/src/nsPluginViewer.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginViewer.cpp @@ -169,28 +169,7 @@ public: NS_IMETHOD StartLoad(nsIRequest* request, nsIStreamListener*& aResult); // nsIContentViewer - NS_IMETHOD Init(nsIWidget* aParentWidget, - nsIDeviceContext* aDeviceContext, - const nsRect& aBounds); - NS_IMETHOD SetContainer(nsISupports* aContainer); - NS_IMETHOD GetContainer(nsISupports** aContainerResult); - NS_IMETHOD LoadStart(nsISupports* aDoc); - NS_IMETHOD LoadComplete(nsresult aStatus); - NS_IMETHOD Unload(void); - NS_IMETHOD Destroy(void); - NS_IMETHOD Stop(void); - NS_IMETHOD GetDOMDocument(nsIDOMDocument **aResult); - NS_IMETHOD SetDOMDocument(nsIDOMDocument *aDocument); - NS_IMETHOD GetBounds(nsRect& aResult); - NS_IMETHOD SetBounds(const nsRect& aBounds); - NS_IMETHOD GetPreviousViewer(nsIContentViewer** aViewer); - NS_IMETHOD SetPreviousViewer(nsIContentViewer* aViewer); - NS_IMETHOD Move(PRInt32 aX, PRInt32 aY); - NS_IMETHOD Show(); - NS_IMETHOD Hide(); - NS_IMETHOD Validate(); - NS_IMETHOD SetEnableRendering(PRBool aOn); - NS_IMETHOD GetEnableRendering(PRBool* aResult); + NS_DECL_NSICONTENTVIEWER // nsIContentViewerEdit NS_DECL_NSICONTENTVIEWEREDIT @@ -435,6 +414,12 @@ PluginViewerImpl::Unload(void) return NS_OK; } +NS_IMETHODIMP +PluginViewerImpl::Close(void) +{ + return NS_OK; +} + NS_IMETHODIMP PluginViewerImpl::Destroy(void) { @@ -558,6 +543,8 @@ PluginViewerImpl::GetPreviousViewer(nsIContentViewer** aViewer) NS_IMETHODIMP PluginViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer) { + if (aViewer) + aViewer->Destroy(); return NS_OK; } diff --git a/mozilla/modules/plugin/nglsrc/nsPluginViewer.cpp b/mozilla/modules/plugin/nglsrc/nsPluginViewer.cpp index c0f908419a8..6873cbe5de1 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginViewer.cpp +++ b/mozilla/modules/plugin/nglsrc/nsPluginViewer.cpp @@ -169,28 +169,7 @@ public: NS_IMETHOD StartLoad(nsIRequest* request, nsIStreamListener*& aResult); // nsIContentViewer - NS_IMETHOD Init(nsIWidget* aParentWidget, - nsIDeviceContext* aDeviceContext, - const nsRect& aBounds); - NS_IMETHOD SetContainer(nsISupports* aContainer); - NS_IMETHOD GetContainer(nsISupports** aContainerResult); - NS_IMETHOD LoadStart(nsISupports* aDoc); - NS_IMETHOD LoadComplete(nsresult aStatus); - NS_IMETHOD Unload(void); - NS_IMETHOD Destroy(void); - NS_IMETHOD Stop(void); - NS_IMETHOD GetDOMDocument(nsIDOMDocument **aResult); - NS_IMETHOD SetDOMDocument(nsIDOMDocument *aDocument); - NS_IMETHOD GetBounds(nsRect& aResult); - NS_IMETHOD SetBounds(const nsRect& aBounds); - NS_IMETHOD GetPreviousViewer(nsIContentViewer** aViewer); - NS_IMETHOD SetPreviousViewer(nsIContentViewer* aViewer); - NS_IMETHOD Move(PRInt32 aX, PRInt32 aY); - NS_IMETHOD Show(); - NS_IMETHOD Hide(); - NS_IMETHOD Validate(); - NS_IMETHOD SetEnableRendering(PRBool aOn); - NS_IMETHOD GetEnableRendering(PRBool* aResult); + NS_DECL_NSICONTENTVIEWER // nsIContentViewerEdit NS_DECL_NSICONTENTVIEWEREDIT @@ -435,6 +414,12 @@ PluginViewerImpl::Unload(void) return NS_OK; } +NS_IMETHODIMP +PluginViewerImpl::Close(void) +{ + return NS_OK; +} + NS_IMETHODIMP PluginViewerImpl::Destroy(void) { @@ -558,6 +543,8 @@ PluginViewerImpl::GetPreviousViewer(nsIContentViewer** aViewer) NS_IMETHODIMP PluginViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer) { + if (aViewer) + aViewer->Destroy(); return NS_OK; }