Fixing bug 148458: Netscape Radio crashes using Real Player if another plugin is being installed in another window because scripting any plugin in other window after plugins.refresh(1) causes this crash when plugin has been unloaded - N70PR1 [@ NPPL3260.DLL - XPTC_InvokeByIndex] r=av, sr=jst

git-svn-id: svn://10.0.0.236/trunk@124632 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
peterlubczynski%netscape.com
2002-07-03 21:03:51 +00:00
parent d05d2dcdd8
commit f760c5576b
5 changed files with 163 additions and 6 deletions

View File

@@ -55,6 +55,7 @@ REQUIRES = xpcom \
webbrwsr \
windowwatcher \
imglib2 \
layout \
$(NULL)
# for xlib port
REQUIRES += xlibxtbin xlibrgb

View File

@@ -55,6 +55,7 @@ REQUIRES = xpcom \
windowwatcher \
gfx \
imglib2 \
layout \
$(NULL)
DEFINES =-D_IMPL_NS_PLUGIN -DWIN32_LEAN_AND_MEAN

View File

@@ -154,6 +154,13 @@
#include "nsDefaultPlugin.h"
#include "nsWeakReference.h"
#include "nsIDOMElement.h"
#include "nsIStyleSet.h"
#include "nsIStyleFrameConstruction.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIWebNavigation.h"
#include "nsISupportsArray.h"
#include "nsIDocShell.h"
#ifdef XP_UNIX
#if defined(MOZ_WIDGET_GTK)
@@ -351,6 +358,96 @@ void DisplayNoDefaultPluginDialog(const char *mimeType, nsIPrompt *prompt)
return;
}
////////////////////////////////////////////////////////////////////////
// Little helper struct to asynchronously reframe any presentations (embedded)
// or reload any documents (full-page), that contained plugins
// which were shutdown as a result of a plugins.refresh(1)
struct nsPluginDocReframeEvent: public PLEvent {
nsPluginDocReframeEvent (nsISupportsArray* aDocs) { mDocs = aDocs; }
nsresult HandlePluginDocReframeEvent();
nsCOMPtr<nsISupportsArray> mDocs;
};
nsresult nsPluginDocReframeEvent::HandlePluginDocReframeEvent() {
NS_ENSURE_TRUE(mDocs, NS_ERROR_FAILURE);
PRUint32 c;
mDocs->Count(&c);
// for each document (which previously had a running instance), tell
// the frame constructor to rebuild
for (PRUint32 i = 0; i < c; i++) {
nsCOMPtr<nsIDocument> doc (do_QueryElementAt(mDocs, i));
if (doc) {
nsCOMPtr<nsIPresShell> shell;
doc->GetShellAt(0, getter_AddRefs(shell));
// if this document has a presentation shell, then it has frames and can be reframed
if (shell) {
nsCOMPtr<nsIPresContext> pc;
nsCOMPtr<nsIStyleSet> set;
shell->GetPresContext(getter_AddRefs(pc));
shell->GetStyleSet(getter_AddRefs(set));
if (pc && set) {
nsCOMPtr<nsIStyleFrameConstruction> fc;
set->GetStyleFrameConstruction(getter_AddRefs(fc));
if (fc)
/**
* A reframe will cause a fresh object frame, instance owner, and instance
* to be created. Reframing of the entire document is necessary as we may have
* recently found new plugins and we want a shot at trying to use them instead
* of leaving alternate renderings.
* We do not want to completely reload all the documents that had running plugins
* because we could possibly trigger a script to run in the unload event handler
* which may want to access our defunct plugin and cause us to crash.
*/
fc->ReconstructDocElementHierarchy(pc); // causes reframe of document
}
} else { // no pres shell --> full-page plugin
/**
* This document does not have a presentation shell. It may be a full-page plugin.
* Full-page plugins don't really have the same problem of crashing because they
* are not currently scriptable. However, they do leave a non-painting, defunct
* window which doesn't look good. A reload of the page for full-page plugins
* is needed to kickstart the instance.
*/
nsCOMPtr<nsIScriptGlobalObject> gso;
doc->GetScriptGlobalObject(getter_AddRefs(gso));
if (gso) {
nsCOMPtr<nsIDocShell> docShell;
gso->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIWebNavigation> webNav (do_QueryInterface(docShell));
if (webNav)
webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
else NS_WARNING("refreshing plugins: couldn't get webnav or docshell from gso");
} else NS_WARNING("refreshing plugins: could not get the global script object -- did the plugin set it?");
}
}
}
return mDocs->Clear();
}
//----------------------------------------------------------------------
static void* PR_CALLBACK HandlePluginDocReframePLEvent(PLEvent* aEvent)
{
nsPluginDocReframeEvent* event = NS_REINTERPRET_CAST(nsPluginDocReframeEvent*, aEvent);
event->HandlePluginDocReframeEvent();
return nsnull;
}
static void PR_CALLBACK DestroyPluginDocReframePLEvent(PLEvent* aEvent)
{
delete aEvent;
}
////////////////////////////////////////////////////////////////////////
nsActivePlugin::nsActivePlugin(nsPluginTag* aPluginTag,
@@ -566,7 +663,10 @@ PRBool nsActivePluginList::remove(nsActivePlugin * plugin)
////////////////////////////////////////////////////////////////////////
void nsActivePluginList::stopRunning()
// This method terminates all running instances of plugins and collects their
// documents to be returned through an array. This method is used
// when we are shutting down or when a plugins.refresh(1) happens.
void nsActivePluginList::stopRunning(nsISupportsArray* aReloadDocs)
{
if(mFirst == nsnull)
return;
@@ -593,6 +693,21 @@ void nsActivePluginList::stopRunning()
}
doCallSetWindowAfterDestroy = PR_FALSE;
p->setStopped(PR_TRUE);
// If we've been passed an array to return, lets collect all our documents,
// removing duplicates. These will be reframed (embedded) or reloaded (full-page) later
// to kickstart our instances.
if (aReloadDocs && p->mPeer) {
nsPluginInstancePeerImpl * peer = (nsPluginInstancePeerImpl *)p->mPeer;
nsCOMPtr<nsIPluginInstanceOwner> owner;
peer->GetOwner(*getter_AddRefs(owner));
if (owner) {
nsCOMPtr<nsIDocument> doc;
owner->GetDocument(getter_AddRefs(doc));
if (doc && aReloadDocs->IndexOf(doc) == -1) // don't allow for duplicates
aReloadDocs->AppendElement(doc);
}
}
}
}
}
@@ -2695,10 +2810,15 @@ nsresult nsPluginHostImpl::ReloadPlugins(PRBool reloadPages)
// if no changed detected, return an appropriate error code
if (!pluginschanged)
return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
nsCOMPtr<nsISupportsArray> instsToReload;
if(reloadPages) {
// stop any running plugins
mActivePluginList.stopRunning();
NS_NewISupportsArray(getter_AddRefs(instsToReload));
// Then stop any running plugin instances but hold on to the documents in the array
// We are going to need to restart the instances in these documents later
mActivePluginList.stopRunning(instsToReload);
}
// clean active plugin list
@@ -2737,6 +2857,29 @@ nsresult nsPluginHostImpl::ReloadPlugins(PRBool reloadPages)
// load them again
rv = LoadPlugins();
// If we have shut down any plugin instances, we've now got to restart them.
// Post an event to do the rest as we are going to be destroying the frame tree and we also want
// any posted unload events to finish
PRUint32 c;
if (reloadPages &&
instsToReload &&
NS_SUCCEEDED(instsToReload->Count(&c)) &&
c > 0) {
nsCOMPtr<nsIEventQueueService> eventService(do_GetService(kEventQueueServiceCID));
if (eventService) {
nsCOMPtr<nsIEventQueue> eventQueue;
eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue));
if (eventQueue) {
nsPluginDocReframeEvent * ev = new nsPluginDocReframeEvent(instsToReload);
if (ev) {
PL_InitEvent(ev, nsnull, HandlePluginDocReframePLEvent, DestroyPluginDocReframePLEvent);
eventQueue->PostEvent(ev);
}
}
}
}
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginHostImpl::ReloadPlugins End active_instance_count=%d\n",
mActivePluginList.mCount));
@@ -3256,7 +3399,7 @@ NS_IMETHODIMP nsPluginHostImpl::Destroy(void)
// we should call nsIPluginInstance::Stop and nsIPluginInstance::SetWindow
// for those plugins who want it
mActivePluginList.stopRunning();
mActivePluginList.stopRunning(nsnull);
// at this point nsIPlugin::Shutdown calls will be performed if needed
mActivePluginList.shut();

View File

@@ -61,6 +61,7 @@ class nsIFile;
class nsIChannel;
class nsIRegistry;
class nsPluginHostImpl;
class nsISupportsArray;
/**
* A linked-list of plugin information that is used for
@@ -152,7 +153,7 @@ public:
PRUint32 getStoppedCount();
nsActivePlugin * findOldestStopped();
void removeAllStopped();
void stopRunning();
void stopRunning(nsISupportsArray* aReloadDocs);
PRBool IsLastInstance(nsActivePlugin * plugin);
};

View File

@@ -65,7 +65,7 @@
#include "nsGUIEvent.h"
#include "nsIPluginViewer.h"
#include "nsContentCID.h"
#include "nsIScriptGlobalObject.h"
#include "nsITimer.h"
#include "nsITimerCallback.h"
@@ -326,6 +326,17 @@ PluginViewerImpl::StartLoad(nsIRequest* request, nsIStreamListener*& aResult)
GetURI(getter_AddRefs(uri));
if (uri)
mDocument->SetDocumentURL(uri);
// we're going to need the docshell later to reload this full-page plugin in the event of a plugins refresh
// so stuff it in the document we created
nsCOMPtr<nsIScriptGlobalObject> global (do_GetInterface(mContainer));
if (global) {
mDocument->SetScriptGlobalObject(global);
nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(mDocument));
if (domdoc)
global->SetNewDocument(domdoc, PR_TRUE);
}
}
nsRect r;