From 797bf6de915bf1edc5a8c36c8c2dd700f3a6ae4a Mon Sep 17 00:00:00 2001 From: "bryner%brianryner.com" Date: Thu, 2 Jun 2005 00:57:54 +0000 Subject: [PATCH] When restoring a presentation via fast-back, where we aren't going to save the existing presentation, defer destruction on a PLEvent to avoid hangs when reentering plugin code (bug 294231). r+sr=jst, a=chofmann. git-svn-id: svn://10.0.0.236/trunk@174012 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/nsDocShell.cpp | 48 ++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index b04b4c85454..925482aa6c0 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -172,6 +172,7 @@ static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, #include "plevent.h" #include "nsGUIEvent.h" #include "nsIPrivateDOMEvent.h" +#include "nsEventQueueUtils.h" // Number of documents currently loading static PRInt32 gNumberOfDocumentsLoading = 0; @@ -4968,6 +4969,29 @@ nsDocShell::FireRestoreEvents() NS_EVENT_FLAG_INIT, &status); } +class ContentViewerDestroyEvent : public PLEvent +{ +public: + ContentViewerDestroyEvent(nsIContentViewer *aViewer) + : mViewer(aViewer) + { + } + + nsCOMPtr mViewer; +}; + +PR_STATIC_CALLBACK(void*) +HandleContentViewerDestroyEvent(PLEvent *aEvent) +{ + NS_STATIC_CAST(ContentViewerDestroyEvent*, aEvent)->mViewer->Destroy(); + return nsnull; +} + +PR_STATIC_CALLBACK(void) +DestroyContentViewerDestroyEvent(PLEvent *aEvent) +{ + delete NS_STATIC_CAST(ContentViewerDestroyEvent*, aEvent); +} nsresult nsDocShell::RestorePresentation(nsISHEntry *aSHEntry, PRBool aSavePresentation, @@ -5055,17 +5079,37 @@ nsDocShell::RestorePresentation(nsISHEntry *aSHEntry, PRBool aSavePresentation, FireUnloadNotification(); mFiredUnloadEvent = PR_FALSE; + nsresult rv; if (mContentViewer) { mContentViewer->Close(aSavePresentation ? mOSHE.get() : nsnull); - mContentViewer->Destroy(); + + // It's unsafe to actually destroy the content viewer here. + // In particular, if we're called from within a plugin's event loop, + // then attempting to tear down the plugin can cause a hang. + // So, post an event to destroy and release the viewer. + + nsCOMPtr uiThreadQueue; + NS_GetMainEventQ(getter_AddRefs(uiThreadQueue)); + NS_ENSURE_TRUE(uiThreadQueue, NS_ERROR_UNEXPECTED); + + PLEvent *evt = new ContentViewerDestroyEvent(mContentViewer); + NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY); + + PL_InitEvent(evt, this, ::HandleContentViewerDestroyEvent, + ::DestroyContentViewerDestroyEvent); + + rv = uiThreadQueue->PostEvent(evt); + if (NS_FAILED(rv)) { + PL_DestroyEvent(evt); + } } mContentViewer.swap(viewer); viewer = nsnull; // force a release to complete ownership transfer // Reattach to the window object. - nsresult rv = mContentViewer->Open(); + rv = mContentViewer->Open(); // Now remove it from the cached presentation. aSHEntry->SetContentViewer(nsnull);