diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp index f8691d6eca8..eed2188e8c1 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp @@ -679,6 +679,9 @@ NS_IMETHODIMP ns4xPluginInstance::Print(nsPluginPrint* platformPrint) NS_IMETHODIMP ns4xPluginInstance::HandleEvent(nsPluginEvent* event, PRBool* handled) { + if(!mStarted) + return NS_OK; + if (fNPP.pdata == nsnull) return NS_ERROR_FAILURE; diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index c15a5249355..f538e140c09 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -27,9 +27,11 @@ #include "ns4xPlugin.h" #include "nsPluginInstancePeer.h" +#include "nsIPlugin.h" #include "nsIPluginStreamListener.h" #include "nsIHTTPHeaderListener.h" #include "nsIHTTPHeader.h" +#include "nsIObserverService.h" #include "nsIHTTPProtocolHandler.h" #include "nsIStreamListener.h" #include "nsIInputStream.h" @@ -46,7 +48,6 @@ #include "nsIHTTPChannel.h" #include "nsIStreamAsFile.h" #include "nsIFileStream.h" // for nsIRandomAccessStore -#include "nsCOMPtr.h" #include "nsNetUtil.h" #include "nsIProgressEventSink.h" #include "nsIDocument.h" @@ -159,26 +160,20 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); void DisplayNoDefaultPluginDialog(const char *mimeType); /** - * Used in DisplayNoDefaultPlugindialog to prevent showing the dialog twice * for the same mimetype. - */ static nsHashtable *mimeTypesSeen = nsnull; /** - * placeholder value for mimeTypesSeen hashtable - */ static const char *hashValue = "value"; /** - * Default number of entries in the mimeTypesSeen hashtable - */ #define NS_MIME_TYPES_HASH_NUM (20) @@ -293,10 +288,14 @@ void DisplayNoDefaultPluginDialog(const char *mimeType) return; } -nsActivePlugin::nsActivePlugin(nsIPluginInstance* aInstance, char * url, PRBool aDefaultPlugin) +nsActivePlugin::nsActivePlugin(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, + char * url, + PRBool aDefaultPlugin) { mNext = nsnull; mPeer = nsnull; + mPlugin = aPlugin; mURL = PL_strdup(url); mInstance = aInstance; @@ -312,6 +311,7 @@ nsActivePlugin::nsActivePlugin(nsIPluginInstance* aInstance, char * url, PRBool nsActivePlugin::~nsActivePlugin() { + mPlugin = nsnull; if(mInstance != nsnull) { mInstance->Destroy(); @@ -377,6 +377,19 @@ PRInt32 nsActivePluginList::add(nsActivePlugin * plugin) return mCount; } +PRBool nsActivePluginList::IsLastInstance(nsActivePlugin * plugin) +{ + if(!plugin) + return PR_FALSE; + + for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext) + { + if((p->mPlugin.get() == plugin->mPlugin.get()) && (p != plugin)) + return PR_FALSE; + } + return PR_TRUE; +} + PRBool nsActivePluginList::remove(nsActivePlugin * plugin) { if(mFirst == nsnull) @@ -395,7 +408,19 @@ PRBool nsActivePluginList::remove(nsActivePlugin * plugin) if((prev != nsnull) && (prev->mNext == nsnull)) mLast = prev; - delete p; + // see if this is going to be the last instance of a plugin + if(IsLastInstance(p)) + { + nsIPlugin *nsiplugin = p->mPlugin.get(); + + delete p; // plugin instance is destroyed here + + if(nsiplugin) + nsiplugin->Shutdown(); + } + else + delete p; + mCount--; return PR_TRUE; } @@ -458,7 +483,14 @@ nsActivePlugin * nsActivePluginList::find(nsIPluginInstance* instance) for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext) { if(p->mInstance == instance) + { +#ifdef NS_DEBUG + PRBool doCache = PR_TRUE; + p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(!p->mStopped || doCache, "This plugin is not supposed to be cached!"); +#endif return p; + } } return nsnull; } @@ -485,7 +517,14 @@ nsActivePlugin * nsActivePluginList::find(char * mimetype) continue; if(PL_strcasecmp(mt, mimetype) == 0) - return p; + { +#ifdef NS_DEBUG + PRBool doCache = PR_TRUE; + p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(!p->mStopped || doCache, "This plugin is not supposed to be cached!"); +#endif + return p; + } } return nsnull; } @@ -495,7 +534,14 @@ nsActivePlugin * nsActivePluginList::findStopped(char * url) for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext) { if(!PL_strcmp(url, p->mURL) && p->mStopped) - return p; + { +#ifdef NS_DEBUG + PRBool doCache = PR_TRUE; + p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(doCache, "This plugin is not supposed to be cached!"); +#endif + return p; + } } return nsnull; } @@ -526,6 +572,16 @@ nsActivePlugin * nsActivePluginList::findOldestStopped() res = p; } } + +#ifdef NS_DEBUG + if(res) + { + PRBool doCache = PR_TRUE; + res->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(doCache, "This plugin is not supposed to be cached!"); + } +#endif + return res; } @@ -1613,7 +1669,12 @@ nsPluginHostImpl::nsPluginHostImpl() NS_INIT_REFCNT(); mPluginsLoaded = PR_FALSE; mDontShowBadPluginMessage = PR_FALSE; + mIsDestroyed = PR_FALSE; mUnloadedLibraries = nsnull; + + nsCOMPtr obsService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID); + if (obsService) + obsService->AddObserver(this, NS_LITERAL_STRING("quit-application")); } nsPluginHostImpl::~nsPluginHostImpl() @@ -1638,12 +1699,13 @@ printf("killing plugin host\n"); CleanUnloadedLibraries(); } -NS_IMPL_ISUPPORTS5(nsPluginHostImpl, +NS_IMPL_ISUPPORTS6(nsPluginHostImpl, nsIPluginManager, nsIPluginManager2, nsIPluginHost, nsIFileUtilities, - nsICookieStorage); + nsICookieStorage, + nsIObserver); NS_METHOD nsPluginHostImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) @@ -2282,23 +2344,18 @@ NS_IMETHODIMP nsPluginHostImpl::Init(void) NS_IMETHODIMP nsPluginHostImpl::Destroy(void) { - nsPluginTag *plug = mPlugins; + if (mIsDestroyed) + return NS_OK; + mIsDestroyed = PR_TRUE; + + // at this point nsIPlugin::Shutdown calls will be performed if needed mActivePluginList.shut(); - while (nsnull != plug) - { - if (nsnull != plug->mEntryPoint) - plug->mEntryPoint->Shutdown(); - - plug = plug->mNext; - } - return NS_OK; } /* Called by nsPluginInstanceOwner (nsObjectFrame.cpp - embeded case) */ - NS_IMETHODIMP nsPluginHostImpl::InstantiateEmbededPlugin(const char *aMimeType, nsIURI* aURL, nsIPluginInstanceOwner *aOwner) @@ -2577,7 +2634,8 @@ nsresult nsPluginHostImpl::FindStoppedPluginForURL(nsIURI* aURL, return NS_ERROR_FAILURE; } -void nsPluginHostImpl::AddInstanceToActiveList(nsIPluginInstance* aInstance, +void nsPluginHostImpl::AddInstanceToActiveList(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, nsIURI* aURL, PRBool aDefaultPlugin) @@ -2593,7 +2651,7 @@ void nsPluginHostImpl::AddInstanceToActiveList(nsIPluginInstance* aInstance, (void)aURL->GetSpec(&url); - nsActivePlugin * plugin = new nsActivePlugin(aInstance, url, aDefaultPlugin); + nsActivePlugin * plugin = new nsActivePlugin(aPlugin, aInstance, url, aDefaultPlugin); if(plugin == nsnull) return; @@ -2632,42 +2690,47 @@ nsresult nsPluginHostImpl::RegisterPluginMimeTypesWithLayout(nsPluginTag * plugi } NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, - nsIURI *aURL, - nsIPluginInstanceOwner *aOwner) + nsIURI *aURL, + nsIPluginInstanceOwner *aOwner) { - nsresult result = NS_ERROR_FAILURE; - nsIPluginInstance* instance = NULL; - nsIPlugin* plugin = NULL; - const char* mimetype; - nsString strContractID; strContractID.AssignWithConversion (NS_INLINE_PLUGIN_CONTRACTID_PREFIX); - char buf[255]; // todo: need to use a const + nsresult result = NS_ERROR_FAILURE; + nsIPluginInstance* instance = NULL; + nsCOMPtr plugin; + const char* mimetype; + nsString strContractID; strContractID.AssignWithConversion (NS_INLINE_PLUGIN_CONTRACTID_PREFIX); + char buf[255]; // todo: need to use a const - if(!aURL) - return NS_ERROR_FAILURE; + if(!aURL) + return NS_ERROR_FAILURE; // if don't have a mimetype, check by file extension - if(!aMimeType) - { - char* extension; - - char* filename; - aURL->GetPath(&filename); - extension = PL_strrchr(filename, '.'); - if(extension) - ++extension; - else - return NS_ERROR_FAILURE; + if(!aMimeType) + { + char* extension; - if(IsPluginEnabledForExtension(extension, mimetype) != NS_OK) - return NS_ERROR_FAILURE; - nsCRT::free(filename); + char* filename; + aURL->GetPath(&filename); + extension = PL_strrchr(filename, '.'); + if(extension) + ++extension; + else + return NS_ERROR_FAILURE; + + if(IsPluginEnabledForExtension(extension, mimetype) != NS_OK) + { + nsCRT::free(filename); + return NS_ERROR_FAILURE; + } + nsCRT::free(filename); } - else - mimetype = aMimeType; + else + mimetype = aMimeType; strContractID.AppendWithConversion(mimetype); strContractID.ToCString(buf, 255); // todo: need to use a const - + + GetPluginFactory(mimetype, getter_AddRefs(plugin)); + result = nsComponentManager::CreateInstance(buf, nsnull, nsIPluginInstance::GetIID(), @@ -2675,25 +2738,28 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, // couldn't create an XPCOM plugin, try to create wrapper for a legacy plugin - if (NS_FAILED(result)) { - result = GetPluginFactory(mimetype, &plugin); - if(!NS_FAILED(result)){ + if (NS_FAILED(result)) + { + if(plugin) result = plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance); - NS_RELEASE(plugin); - } - if (NS_FAILED(result)) { - NS_WITH_SERVICE(nsIPlugin, plugin, "@mozilla.org/blackwood/pluglet-engine;1",&result); - if (NS_SUCCEEDED(result)) { - result = plugin->CreatePluginInstance(NULL, kIPluginInstanceIID, aMimeType,(void **)&instance); - } + + if (NS_FAILED(result)) + { + NS_WITH_SERVICE(nsIPlugin, bwPlugin, "@mozilla.org/blackwood/pluglet-engine;1",&result); + if (NS_SUCCEEDED(result)) + { + result = bwPlugin->CreatePluginInstance(NULL, + kIPluginInstanceIID, + aMimeType, + (void **)&instance); + } } } // neither an XPCOM or legacy plugin could be instantiated, // so return the failure - if (NS_FAILED(result)){ + if (NS_FAILED(result)) return result; - } // it is adreffed here aOwner->SetInstance(instance); @@ -2718,7 +2784,7 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, NS_RELEASE(pi); // we should addref here - AddInstanceToActiveList(instance, aURL); + AddInstanceToActiveList(plugin, instance, aURL, PR_FALSE); //release what was addreffed in Create(Plugin)Instance NS_RELEASE(instance); @@ -2731,7 +2797,7 @@ nsresult nsPluginHostImpl::SetUpDefaultPluginInstance(const char *aMimeType, nsI { nsresult result = NS_ERROR_FAILURE; nsIPluginInstance* instance = NULL; - nsIPlugin* plugin = NULL; + nsCOMPtr plugin = NULL; const char* mimetype; nsString strContractID; strContractID.AssignWithConversion (NS_INLINE_PLUGIN_CONTRACTID_PREFIX); char buf[255]; // todo: need to use a const @@ -2744,17 +2810,15 @@ nsresult nsPluginHostImpl::SetUpDefaultPluginInstance(const char *aMimeType, nsI strContractID.AppendWithConversion("*"); strContractID.ToCString(buf, 255); // todo: need to use a const + GetPluginFactory("*", getter_AddRefs(plugin)); + result = nsComponentManager::CreateInstance(buf, nsnull, nsIPluginInstance::GetIID(), (void**)&instance); // couldn't create an XPCOM plugin, try to create wrapper for a legacy plugin if (NS_FAILED(result)) { - result = GetPluginFactory("*", &plugin); - if(!NS_FAILED(result)) - { + if(plugin) result = plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance); - NS_RELEASE(plugin); - } } // neither an XPCOM or legacy plugin could be instantiated, so return the failure @@ -2808,7 +2872,7 @@ nsresult nsPluginHostImpl::SetUpDefaultPluginInstance(const char *aMimeType, nsI NS_RELEASE(pi); // we should addref here - AddInstanceToActiveList(instance, aURL, PR_TRUE); + AddInstanceToActiveList(plugin, instance, aURL, PR_TRUE); //release what was addreffed in Create(Plugin)Instance NS_RELEASE(instance); @@ -4160,10 +4224,20 @@ NS_IMETHODIMP nsPluginHostImpl::SetCookie(const char* inCookieURL, const void* i return rv; } +NS_IMETHODIMP nsPluginHostImpl::Observe(nsISupports *aSubject, + const PRUnichar *aTopic, + const PRUnichar *someData) +{ + Destroy(); + return NS_OK; +} + NS_IMETHODIMP nsPluginHostImpl::HandleBadPlugin(PRLibrary* aLibrary) { nsresult rv = NS_OK; + NS_ASSERTION(PR_FALSE, "Plugin performed illegal operation"); + if(mDontShowBadPluginMessage) return rv; diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h index 41f13125d9b..0c92e2ac413 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h @@ -27,7 +27,9 @@ #include "nsIPluginManager.h" #include "nsIPluginManager2.h" #include "nsIPluginHost.h" +#include "nsIObserver.h" #include "nsCRT.h" +#include "nsCOMPtr.h" #include "prlink.h" #include "nsIFileUtilities.h" #include "nsICookieStorage.h" @@ -80,18 +82,21 @@ struct nsActivePlugin nsActivePlugin* mNext; char* mURL; nsIPluginInstancePeer* mPeer; + nsCOMPtr mPlugin; nsIPluginInstance* mInstance; PRBool mStopped; PRTime mllStopTime; PRBool mDefaultPlugin; - nsActivePlugin(nsIPluginInstance* aInstance, char * url, PRBool aDefaultPlugin); + nsActivePlugin(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, + char * url, + PRBool aDefaultPlugin); ~nsActivePlugin(); void setStopped(PRBool stopped); }; - class nsActivePluginList { public: @@ -112,6 +117,7 @@ public: nsActivePlugin * findOldestStopped(); void removeAllStopped(); void stopRunning(); + PRBool IsLastInstance(nsActivePlugin * plugin); }; // The purpose of this list is to keep track of unloaded plugin libs @@ -137,7 +143,8 @@ public: class nsPluginHostImpl : public nsIPluginManager2, public nsIPluginHost, public nsIFileUtilities, - public nsICookieStorage + public nsICookieStorage, + public nsIObserver { public: nsPluginHostImpl(); @@ -316,6 +323,10 @@ public: NS_IMETHOD SetCookie(const char* inCookieURL, const void* inCookieBuffer, PRUint32 inCookieSize); + // Methods from nsIObserver + NS_IMETHOD + Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData); + /* Called by GetURL and PostURL */ NS_IMETHOD @@ -374,7 +385,9 @@ private: SetUpDefaultPluginInstance(const char *aMimeType, nsIURI *aURL, nsIPluginInstanceOwner *aOwner); void - AddInstanceToActiveList(nsIPluginInstance* aInstance, nsIURI* aURL, PRBool aDefaultPlugin = PR_FALSE); + AddInstanceToActiveList(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, + nsIURI* aURL, PRBool aDefaultPlugin); nsresult RegisterPluginMimeTypesWithLayout(nsPluginTag *pluginTag, nsIComponentManager * compManager, nsIFile * layoutPath); @@ -392,6 +405,7 @@ private: nsPluginTag *mPlugins; PRBool mPluginsLoaded; PRBool mDontShowBadPluginMessage; + PRBool mIsDestroyed; nsActivePluginList mActivePluginList; nsUnloadedLibrary *mUnloadedLibraries; diff --git a/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp b/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp index f8691d6eca8..eed2188e8c1 100644 --- a/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp +++ b/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp @@ -679,6 +679,9 @@ NS_IMETHODIMP ns4xPluginInstance::Print(nsPluginPrint* platformPrint) NS_IMETHODIMP ns4xPluginInstance::HandleEvent(nsPluginEvent* event, PRBool* handled) { + if(!mStarted) + return NS_OK; + if (fNPP.pdata == nsnull) return NS_ERROR_FAILURE; diff --git a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp index c15a5249355..f538e140c09 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp @@ -27,9 +27,11 @@ #include "ns4xPlugin.h" #include "nsPluginInstancePeer.h" +#include "nsIPlugin.h" #include "nsIPluginStreamListener.h" #include "nsIHTTPHeaderListener.h" #include "nsIHTTPHeader.h" +#include "nsIObserverService.h" #include "nsIHTTPProtocolHandler.h" #include "nsIStreamListener.h" #include "nsIInputStream.h" @@ -46,7 +48,6 @@ #include "nsIHTTPChannel.h" #include "nsIStreamAsFile.h" #include "nsIFileStream.h" // for nsIRandomAccessStore -#include "nsCOMPtr.h" #include "nsNetUtil.h" #include "nsIProgressEventSink.h" #include "nsIDocument.h" @@ -159,26 +160,20 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); void DisplayNoDefaultPluginDialog(const char *mimeType); /** - * Used in DisplayNoDefaultPlugindialog to prevent showing the dialog twice * for the same mimetype. - */ static nsHashtable *mimeTypesSeen = nsnull; /** - * placeholder value for mimeTypesSeen hashtable - */ static const char *hashValue = "value"; /** - * Default number of entries in the mimeTypesSeen hashtable - */ #define NS_MIME_TYPES_HASH_NUM (20) @@ -293,10 +288,14 @@ void DisplayNoDefaultPluginDialog(const char *mimeType) return; } -nsActivePlugin::nsActivePlugin(nsIPluginInstance* aInstance, char * url, PRBool aDefaultPlugin) +nsActivePlugin::nsActivePlugin(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, + char * url, + PRBool aDefaultPlugin) { mNext = nsnull; mPeer = nsnull; + mPlugin = aPlugin; mURL = PL_strdup(url); mInstance = aInstance; @@ -312,6 +311,7 @@ nsActivePlugin::nsActivePlugin(nsIPluginInstance* aInstance, char * url, PRBool nsActivePlugin::~nsActivePlugin() { + mPlugin = nsnull; if(mInstance != nsnull) { mInstance->Destroy(); @@ -377,6 +377,19 @@ PRInt32 nsActivePluginList::add(nsActivePlugin * plugin) return mCount; } +PRBool nsActivePluginList::IsLastInstance(nsActivePlugin * plugin) +{ + if(!plugin) + return PR_FALSE; + + for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext) + { + if((p->mPlugin.get() == plugin->mPlugin.get()) && (p != plugin)) + return PR_FALSE; + } + return PR_TRUE; +} + PRBool nsActivePluginList::remove(nsActivePlugin * plugin) { if(mFirst == nsnull) @@ -395,7 +408,19 @@ PRBool nsActivePluginList::remove(nsActivePlugin * plugin) if((prev != nsnull) && (prev->mNext == nsnull)) mLast = prev; - delete p; + // see if this is going to be the last instance of a plugin + if(IsLastInstance(p)) + { + nsIPlugin *nsiplugin = p->mPlugin.get(); + + delete p; // plugin instance is destroyed here + + if(nsiplugin) + nsiplugin->Shutdown(); + } + else + delete p; + mCount--; return PR_TRUE; } @@ -458,7 +483,14 @@ nsActivePlugin * nsActivePluginList::find(nsIPluginInstance* instance) for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext) { if(p->mInstance == instance) + { +#ifdef NS_DEBUG + PRBool doCache = PR_TRUE; + p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(!p->mStopped || doCache, "This plugin is not supposed to be cached!"); +#endif return p; + } } return nsnull; } @@ -485,7 +517,14 @@ nsActivePlugin * nsActivePluginList::find(char * mimetype) continue; if(PL_strcasecmp(mt, mimetype) == 0) - return p; + { +#ifdef NS_DEBUG + PRBool doCache = PR_TRUE; + p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(!p->mStopped || doCache, "This plugin is not supposed to be cached!"); +#endif + return p; + } } return nsnull; } @@ -495,7 +534,14 @@ nsActivePlugin * nsActivePluginList::findStopped(char * url) for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext) { if(!PL_strcmp(url, p->mURL) && p->mStopped) - return p; + { +#ifdef NS_DEBUG + PRBool doCache = PR_TRUE; + p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(doCache, "This plugin is not supposed to be cached!"); +#endif + return p; + } } return nsnull; } @@ -526,6 +572,16 @@ nsActivePlugin * nsActivePluginList::findOldestStopped() res = p; } } + +#ifdef NS_DEBUG + if(res) + { + PRBool doCache = PR_TRUE; + res->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache); + NS_ASSERTION(doCache, "This plugin is not supposed to be cached!"); + } +#endif + return res; } @@ -1613,7 +1669,12 @@ nsPluginHostImpl::nsPluginHostImpl() NS_INIT_REFCNT(); mPluginsLoaded = PR_FALSE; mDontShowBadPluginMessage = PR_FALSE; + mIsDestroyed = PR_FALSE; mUnloadedLibraries = nsnull; + + nsCOMPtr obsService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID); + if (obsService) + obsService->AddObserver(this, NS_LITERAL_STRING("quit-application")); } nsPluginHostImpl::~nsPluginHostImpl() @@ -1638,12 +1699,13 @@ printf("killing plugin host\n"); CleanUnloadedLibraries(); } -NS_IMPL_ISUPPORTS5(nsPluginHostImpl, +NS_IMPL_ISUPPORTS6(nsPluginHostImpl, nsIPluginManager, nsIPluginManager2, nsIPluginHost, nsIFileUtilities, - nsICookieStorage); + nsICookieStorage, + nsIObserver); NS_METHOD nsPluginHostImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) @@ -2282,23 +2344,18 @@ NS_IMETHODIMP nsPluginHostImpl::Init(void) NS_IMETHODIMP nsPluginHostImpl::Destroy(void) { - nsPluginTag *plug = mPlugins; + if (mIsDestroyed) + return NS_OK; + mIsDestroyed = PR_TRUE; + + // at this point nsIPlugin::Shutdown calls will be performed if needed mActivePluginList.shut(); - while (nsnull != plug) - { - if (nsnull != plug->mEntryPoint) - plug->mEntryPoint->Shutdown(); - - plug = plug->mNext; - } - return NS_OK; } /* Called by nsPluginInstanceOwner (nsObjectFrame.cpp - embeded case) */ - NS_IMETHODIMP nsPluginHostImpl::InstantiateEmbededPlugin(const char *aMimeType, nsIURI* aURL, nsIPluginInstanceOwner *aOwner) @@ -2577,7 +2634,8 @@ nsresult nsPluginHostImpl::FindStoppedPluginForURL(nsIURI* aURL, return NS_ERROR_FAILURE; } -void nsPluginHostImpl::AddInstanceToActiveList(nsIPluginInstance* aInstance, +void nsPluginHostImpl::AddInstanceToActiveList(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, nsIURI* aURL, PRBool aDefaultPlugin) @@ -2593,7 +2651,7 @@ void nsPluginHostImpl::AddInstanceToActiveList(nsIPluginInstance* aInstance, (void)aURL->GetSpec(&url); - nsActivePlugin * plugin = new nsActivePlugin(aInstance, url, aDefaultPlugin); + nsActivePlugin * plugin = new nsActivePlugin(aPlugin, aInstance, url, aDefaultPlugin); if(plugin == nsnull) return; @@ -2632,42 +2690,47 @@ nsresult nsPluginHostImpl::RegisterPluginMimeTypesWithLayout(nsPluginTag * plugi } NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, - nsIURI *aURL, - nsIPluginInstanceOwner *aOwner) + nsIURI *aURL, + nsIPluginInstanceOwner *aOwner) { - nsresult result = NS_ERROR_FAILURE; - nsIPluginInstance* instance = NULL; - nsIPlugin* plugin = NULL; - const char* mimetype; - nsString strContractID; strContractID.AssignWithConversion (NS_INLINE_PLUGIN_CONTRACTID_PREFIX); - char buf[255]; // todo: need to use a const + nsresult result = NS_ERROR_FAILURE; + nsIPluginInstance* instance = NULL; + nsCOMPtr plugin; + const char* mimetype; + nsString strContractID; strContractID.AssignWithConversion (NS_INLINE_PLUGIN_CONTRACTID_PREFIX); + char buf[255]; // todo: need to use a const - if(!aURL) - return NS_ERROR_FAILURE; + if(!aURL) + return NS_ERROR_FAILURE; // if don't have a mimetype, check by file extension - if(!aMimeType) - { - char* extension; - - char* filename; - aURL->GetPath(&filename); - extension = PL_strrchr(filename, '.'); - if(extension) - ++extension; - else - return NS_ERROR_FAILURE; + if(!aMimeType) + { + char* extension; - if(IsPluginEnabledForExtension(extension, mimetype) != NS_OK) - return NS_ERROR_FAILURE; - nsCRT::free(filename); + char* filename; + aURL->GetPath(&filename); + extension = PL_strrchr(filename, '.'); + if(extension) + ++extension; + else + return NS_ERROR_FAILURE; + + if(IsPluginEnabledForExtension(extension, mimetype) != NS_OK) + { + nsCRT::free(filename); + return NS_ERROR_FAILURE; + } + nsCRT::free(filename); } - else - mimetype = aMimeType; + else + mimetype = aMimeType; strContractID.AppendWithConversion(mimetype); strContractID.ToCString(buf, 255); // todo: need to use a const - + + GetPluginFactory(mimetype, getter_AddRefs(plugin)); + result = nsComponentManager::CreateInstance(buf, nsnull, nsIPluginInstance::GetIID(), @@ -2675,25 +2738,28 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, // couldn't create an XPCOM plugin, try to create wrapper for a legacy plugin - if (NS_FAILED(result)) { - result = GetPluginFactory(mimetype, &plugin); - if(!NS_FAILED(result)){ + if (NS_FAILED(result)) + { + if(plugin) result = plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance); - NS_RELEASE(plugin); - } - if (NS_FAILED(result)) { - NS_WITH_SERVICE(nsIPlugin, plugin, "@mozilla.org/blackwood/pluglet-engine;1",&result); - if (NS_SUCCEEDED(result)) { - result = plugin->CreatePluginInstance(NULL, kIPluginInstanceIID, aMimeType,(void **)&instance); - } + + if (NS_FAILED(result)) + { + NS_WITH_SERVICE(nsIPlugin, bwPlugin, "@mozilla.org/blackwood/pluglet-engine;1",&result); + if (NS_SUCCEEDED(result)) + { + result = bwPlugin->CreatePluginInstance(NULL, + kIPluginInstanceIID, + aMimeType, + (void **)&instance); + } } } // neither an XPCOM or legacy plugin could be instantiated, // so return the failure - if (NS_FAILED(result)){ + if (NS_FAILED(result)) return result; - } // it is adreffed here aOwner->SetInstance(instance); @@ -2718,7 +2784,7 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, NS_RELEASE(pi); // we should addref here - AddInstanceToActiveList(instance, aURL); + AddInstanceToActiveList(plugin, instance, aURL, PR_FALSE); //release what was addreffed in Create(Plugin)Instance NS_RELEASE(instance); @@ -2731,7 +2797,7 @@ nsresult nsPluginHostImpl::SetUpDefaultPluginInstance(const char *aMimeType, nsI { nsresult result = NS_ERROR_FAILURE; nsIPluginInstance* instance = NULL; - nsIPlugin* plugin = NULL; + nsCOMPtr plugin = NULL; const char* mimetype; nsString strContractID; strContractID.AssignWithConversion (NS_INLINE_PLUGIN_CONTRACTID_PREFIX); char buf[255]; // todo: need to use a const @@ -2744,17 +2810,15 @@ nsresult nsPluginHostImpl::SetUpDefaultPluginInstance(const char *aMimeType, nsI strContractID.AppendWithConversion("*"); strContractID.ToCString(buf, 255); // todo: need to use a const + GetPluginFactory("*", getter_AddRefs(plugin)); + result = nsComponentManager::CreateInstance(buf, nsnull, nsIPluginInstance::GetIID(), (void**)&instance); // couldn't create an XPCOM plugin, try to create wrapper for a legacy plugin if (NS_FAILED(result)) { - result = GetPluginFactory("*", &plugin); - if(!NS_FAILED(result)) - { + if(plugin) result = plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance); - NS_RELEASE(plugin); - } } // neither an XPCOM or legacy plugin could be instantiated, so return the failure @@ -2808,7 +2872,7 @@ nsresult nsPluginHostImpl::SetUpDefaultPluginInstance(const char *aMimeType, nsI NS_RELEASE(pi); // we should addref here - AddInstanceToActiveList(instance, aURL, PR_TRUE); + AddInstanceToActiveList(plugin, instance, aURL, PR_TRUE); //release what was addreffed in Create(Plugin)Instance NS_RELEASE(instance); @@ -4160,10 +4224,20 @@ NS_IMETHODIMP nsPluginHostImpl::SetCookie(const char* inCookieURL, const void* i return rv; } +NS_IMETHODIMP nsPluginHostImpl::Observe(nsISupports *aSubject, + const PRUnichar *aTopic, + const PRUnichar *someData) +{ + Destroy(); + return NS_OK; +} + NS_IMETHODIMP nsPluginHostImpl::HandleBadPlugin(PRLibrary* aLibrary) { nsresult rv = NS_OK; + NS_ASSERTION(PR_FALSE, "Plugin performed illegal operation"); + if(mDontShowBadPluginMessage) return rv; diff --git a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h index 41f13125d9b..0c92e2ac413 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h +++ b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h @@ -27,7 +27,9 @@ #include "nsIPluginManager.h" #include "nsIPluginManager2.h" #include "nsIPluginHost.h" +#include "nsIObserver.h" #include "nsCRT.h" +#include "nsCOMPtr.h" #include "prlink.h" #include "nsIFileUtilities.h" #include "nsICookieStorage.h" @@ -80,18 +82,21 @@ struct nsActivePlugin nsActivePlugin* mNext; char* mURL; nsIPluginInstancePeer* mPeer; + nsCOMPtr mPlugin; nsIPluginInstance* mInstance; PRBool mStopped; PRTime mllStopTime; PRBool mDefaultPlugin; - nsActivePlugin(nsIPluginInstance* aInstance, char * url, PRBool aDefaultPlugin); + nsActivePlugin(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, + char * url, + PRBool aDefaultPlugin); ~nsActivePlugin(); void setStopped(PRBool stopped); }; - class nsActivePluginList { public: @@ -112,6 +117,7 @@ public: nsActivePlugin * findOldestStopped(); void removeAllStopped(); void stopRunning(); + PRBool IsLastInstance(nsActivePlugin * plugin); }; // The purpose of this list is to keep track of unloaded plugin libs @@ -137,7 +143,8 @@ public: class nsPluginHostImpl : public nsIPluginManager2, public nsIPluginHost, public nsIFileUtilities, - public nsICookieStorage + public nsICookieStorage, + public nsIObserver { public: nsPluginHostImpl(); @@ -316,6 +323,10 @@ public: NS_IMETHOD SetCookie(const char* inCookieURL, const void* inCookieBuffer, PRUint32 inCookieSize); + // Methods from nsIObserver + NS_IMETHOD + Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData); + /* Called by GetURL and PostURL */ NS_IMETHOD @@ -374,7 +385,9 @@ private: SetUpDefaultPluginInstance(const char *aMimeType, nsIURI *aURL, nsIPluginInstanceOwner *aOwner); void - AddInstanceToActiveList(nsIPluginInstance* aInstance, nsIURI* aURL, PRBool aDefaultPlugin = PR_FALSE); + AddInstanceToActiveList(nsCOMPtr aPlugin, + nsIPluginInstance* aInstance, + nsIURI* aURL, PRBool aDefaultPlugin); nsresult RegisterPluginMimeTypesWithLayout(nsPluginTag *pluginTag, nsIComponentManager * compManager, nsIFile * layoutPath); @@ -392,6 +405,7 @@ private: nsPluginTag *mPlugins; PRBool mPluginsLoaded; PRBool mDontShowBadPluginMessage; + PRBool mIsDestroyed; nsActivePluginList mActivePluginList; nsUnloadedLibrary *mUnloadedLibraries;