From 499adb6a0ee0622a59047ae3da16fc6124c456f6 Mon Sep 17 00:00:00 2001 From: "flamingice%sourmilk.net" Date: Sat, 14 Jul 2007 00:28:06 +0000 Subject: [PATCH] Bug 330511, Plugin-in blocklisting, r+sr=jst git-svn-id: svn://10.0.0.236/trunk@229935 18797224-902f-48f8-a5cc-f745e15eee43 --- .../base/src/nsObjectLoadingContent.cpp | 51 +++++--- .../content/base/src/nsObjectLoadingContent.h | 3 +- .../plugin/base/public/nsIPluginTag.idl | 3 +- .../plugin/base/public/nsPluginError.h | 1 + .../plugin/base/src/nsPluginHostImpl.cpp | 120 ++++++++++++------ .../plugin/base/src/nsPluginHostImpl.h | 19 ++- 6 files changed, 128 insertions(+), 69 deletions(-) diff --git a/mozilla/content/base/src/nsObjectLoadingContent.cpp b/mozilla/content/base/src/nsObjectLoadingContent.cpp index 9d3661e6a37..0bb9a0af925 100644 --- a/mozilla/content/base/src/nsObjectLoadingContent.cpp +++ b/mozilla/content/base/src/nsObjectLoadingContent.cpp @@ -152,29 +152,37 @@ nsAsyncInstantiateEvent::Run() } /** - * A task for firing PluginNotFound DOM Events. + * A task for firing PluginNotFound and PluginBlocklisted DOM Events. */ -class nsPluginNotFoundEvent : public nsRunnable { +class nsPluginErrorEvent : public nsRunnable { public: nsCOMPtr mContent; + PRBool mBlocklisted; - nsPluginNotFoundEvent(nsIContent* aContent) - : mContent(aContent) + nsPluginErrorEvent(nsIContent* aContent, PRBool aBlocklisted) + : mContent(aContent), + mBlocklisted(aBlocklisted) {} - ~nsPluginNotFoundEvent() {} + ~nsPluginErrorEvent() {} NS_IMETHOD Run(); }; NS_IMETHODIMP -nsPluginNotFoundEvent::Run() +nsPluginErrorEvent::Run() { LOG(("OBJLC []: Firing plugin not found event for content %p\n", mContent.get())); - nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent, - NS_LITERAL_STRING("PluginNotFound"), - PR_TRUE, PR_TRUE); + if (mBlocklisted) + nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent, + NS_LITERAL_STRING("PluginBlocklisted"), + PR_TRUE, PR_TRUE); + else + nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent, + NS_LITERAL_STRING("PluginNotFound"), + PR_TRUE, PR_TRUE); + return NS_OK; } @@ -426,8 +434,9 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest, nsISupports *aConte PluginSupportState pluginState = GetPluginSupportState(thisContent, mContentType); // Do nothing, but fire the plugin not found event if needed - if (pluginState == ePluginUnsupported) { - FirePluginNotFound(thisContent); + if (pluginState == ePluginUnsupported || + pluginState == ePluginBlocklisted) { + FirePluginError(thisContent, pluginState == ePluginBlocklisted); } if (pluginState != ePluginDisabled) { mTypeUnsupported = PR_TRUE; @@ -887,8 +896,9 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI, // No need to load anything PluginSupportState pluginState = GetPluginSupportState(thisContent, aTypeHint); - if (pluginState == ePluginUnsupported) { - FirePluginNotFound(thisContent); + if (pluginState == ePluginUnsupported || + pluginState == ePluginBlocklisted) { + FirePluginError(thisContent, pluginState == ePluginBlocklisted); } if (pluginState != ePluginDisabled) { fallback.TypeUnsupported(); @@ -1193,15 +1203,16 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType, } /* static */ void -nsObjectLoadingContent::FirePluginNotFound(nsIContent* thisContent) +nsObjectLoadingContent::FirePluginError(nsIContent* thisContent, + PRBool blocklisted) { - LOG(("OBJLC []: Dispatching PluginNotFound event for content %p\n", + LOG(("OBJLC []: Dispatching nsPluginErrorEvent for content %p\n", thisContent)); - nsCOMPtr ev = new nsPluginNotFoundEvent(thisContent); + nsCOMPtr ev = new nsPluginErrorEvent(thisContent, blocklisted); nsresult rv = NS_DispatchToCurrentThread(ev); if (NS_FAILED(rv)) { - NS_WARNING("failed to dispatch nsPluginNotFoundEvent"); + NS_WARNING("failed to dispatch nsPluginErrorEvent"); } } @@ -1437,5 +1448,9 @@ nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType) return ePluginUnsupported; } nsresult rv = host->IsPluginEnabledForType(aContentType.get()); - return rv == NS_ERROR_PLUGIN_DISABLED ? ePluginDisabled : ePluginUnsupported; + if (rv == NS_ERROR_PLUGIN_DISABLED) + return ePluginDisabled; + if (rv == NS_ERROR_PLUGIN_BLOCKLISTED) + return ePluginBlocklisted; + return ePluginUnsupported; } diff --git a/mozilla/content/base/src/nsObjectLoadingContent.h b/mozilla/content/base/src/nsObjectLoadingContent.h index 4c47f3b86f3..915222a45bf 100644 --- a/mozilla/content/base/src/nsObjectLoadingContent.h +++ b/mozilla/content/base/src/nsObjectLoadingContent.h @@ -256,7 +256,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent * Fires the "Plugin not found" event. This function doesn't do any checks * whether it should be fired, the caller should do that. */ - static void FirePluginNotFound(nsIContent* thisContent); + static void FirePluginError(nsIContent* thisContent, PRBool blocklisted); ObjectType GetTypeOfContent(const nsCString& aMIMEType); @@ -300,6 +300,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent ePluginUnsupported, // The plugin is not supported (not installed, say) ePluginDisabled, // The plugin has been explicitly disabled by the // user. + ePluginBlocklisted, // The plugin is blocklisted and disabled ePluginOtherState // Something else (e.g. not a plugin at all as far // as we can tell). }; diff --git a/mozilla/modules/plugin/base/public/nsIPluginTag.idl b/mozilla/modules/plugin/base/public/nsIPluginTag.idl index 97182e5b764..67353ef271a 100644 --- a/mozilla/modules/plugin/base/public/nsIPluginTag.idl +++ b/mozilla/modules/plugin/base/public/nsIPluginTag.idl @@ -38,11 +38,12 @@ #include "nsISupports.idl" -[scriptable, uuid(42f9c725-e13d-47d5-bf1d-f9b0a9ee5cf7)] +[scriptable, uuid(e8b85cb4-6281-40b1-b54d-da825487b73a)] interface nsIPluginTag : nsISupports { readonly attribute ACString description; readonly attribute ACString filename; readonly attribute ACString name; attribute boolean disabled; + attribute boolean blocklisted; }; diff --git a/mozilla/modules/plugin/base/public/nsPluginError.h b/mozilla/modules/plugin/base/public/nsPluginError.h index 1cddcb61332..470aa4ad3b4 100644 --- a/mozilla/modules/plugin/base/public/nsPluginError.h +++ b/mozilla/modules/plugin/base/public/nsPluginError.h @@ -44,5 +44,6 @@ #define NS_ERROR_PLUGINS_PLUGINSNOTCHANGED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PLUGINS,1000) #define NS_ERROR_PLUGIN_DISABLED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PLUGINS,1001) +#define NS_ERROR_PLUGIN_BLOCKLISTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PLUGINS,1002) #endif // nsPluginError_h__ diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index f727c3349a3..14a035fbb22 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -531,7 +531,9 @@ PRBool nsActivePluginList::remove(nsActivePlugin * plugin) // 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 aPluginTag is given, then only that plugin is terminated +void nsActivePluginList::stopRunning(nsISupportsArray* aReloadDocs, + nsPluginTag* aPluginTag) { if(mFirst == nsnull) return; @@ -540,7 +542,8 @@ void nsActivePluginList::stopRunning(nsISupportsArray* aReloadDocs) for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext) { - if(!p->mStopped && p->mInstance) + if(!p->mStopped && p->mInstance && + (!aPluginTag || aPluginTag == p->mPluginTag)) { // then determine if the plugin wants Destroy to be called after // Set Window. This is for bug 50547. @@ -989,13 +992,36 @@ nsPluginTag::SetDisabled(PRBool aDisabled) if (HasFlag(NS_PLUGIN_FLAG_ENABLED) == !aDisabled) return NS_OK; - /* TODO: stop plugin if it's currently running */ if (aDisabled) UnMark(NS_PLUGIN_FLAG_ENABLED); else Mark(NS_PLUGIN_FLAG_ENABLED); - mPluginHost->UpdatePluginInfo(); + mPluginHost->UpdatePluginInfo(this); + return NS_OK; +} + +NS_IMETHODIMP +nsPluginTag::GetBlocklisted(PRBool* aBlocklisted) +{ + *aBlocklisted = HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED); + return NS_OK; +} + +NS_IMETHODIMP +nsPluginTag::SetBlocklisted(PRBool aBlocklisted) +{ + if (HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED) == aBlocklisted) + return NS_OK; + + if (aBlocklisted) { + Mark(NS_PLUGIN_FLAG_BLOCKLISTED); + if (HasFlag(NS_PLUGIN_FLAG_ENABLED)) + UnMark(NS_PLUGIN_FLAG_ENABLED); + } else + UnMark(NS_PLUGIN_FLAG_BLOCKLISTED); + + mPluginHost->UpdatePluginInfo(nsnull); return NS_OK; } @@ -2753,7 +2779,7 @@ nsresult nsPluginHostImpl::ReloadPlugins(PRBool reloadPages) // 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); + mActivePluginList.stopRunning(instsToReload, nsnull); } // clean active plugin list @@ -3250,7 +3276,7 @@ NS_IMETHODIMP nsPluginHostImpl::Destroy(void) // we should call nsIPluginInstance::Stop and nsIPluginInstance::SetWindow // for those plugins who want it - mActivePluginList.stopRunning(nsnull); + mActivePluginList.stopRunning(nsnull, nsnull); // at this point nsIPlugin::Shutdown calls will be performed if needed mActivePluginList.shut(); @@ -4107,12 +4133,6 @@ nsPluginHostImpl::SetUpDefaultPluginInstance(const char *aMimeType, NS_IMETHODIMP nsPluginHostImpl::IsPluginEnabledForType(const char* aMimeType) { - if (!mJavaEnabled && IsJavaMIMEType(aMimeType)) { - // Return DISABLED whether we have a java plugin or not -- if it's - // disabled, it's disabled. - return NS_ERROR_PLUGIN_DISABLED; - } - // Pass PR_FALSE as the second arg so we can return NS_ERROR_PLUGIN_DISABLED // for disabled plug-ins. nsPluginTag *plugin = FindPluginForType(aMimeType, PR_FALSE); @@ -4120,10 +4140,19 @@ nsPluginHostImpl::IsPluginEnabledForType(const char* aMimeType) return NS_ERROR_FAILURE; } - if (!plugin->HasFlag(NS_PLUGIN_FLAG_ENABLED)) { + if (!mJavaEnabled && IsJavaMIMEType(aMimeType)) { + // Return DISABLED whether we have a java plugin or not -- if it's + // disabled, it's disabled. return NS_ERROR_PLUGIN_DISABLED; } + if (!plugin->HasFlag(NS_PLUGIN_FLAG_ENABLED)) { + if (plugin->HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED)) + return NS_ERROR_PLUGIN_BLOCKLISTED; + else + return NS_ERROR_PLUGIN_DISABLED; + } + return NS_OK; } @@ -5035,12 +5064,13 @@ nsresult nsPluginHostImpl::ScanPluginsDirectory(nsIFile * pluginsDir, RemoveCachedPluginsInfo(NS_ConvertUTF16toUTF8(pfd->mFilename).get(), getter_AddRefs(pluginTag)); - PRBool pluginEnabled = PR_TRUE; + PRUint32 oldFlags = NS_PLUGIN_FLAG_ENABLED; if (pluginTag) { // If plugin changed, delete cachedPluginTag and don't use cache if (LL_NE(fileModTime, pluginTag->mLastModifiedTime)) { // Plugins has changed. Don't use cached plugin info. - pluginEnabled = pluginTag->HasFlag(NS_PLUGIN_FLAG_ENABLED); + oldFlags = pluginTag->Flags() & + (NS_PLUGIN_FLAG_ENABLED | NS_PLUGIN_FLAG_BLOCKLISTED); pluginTag = nsnull; // plugin file changed, flag this fact @@ -5117,9 +5147,13 @@ nsresult nsPluginHostImpl::ScanPluginsDirectory(nsIFile * pluginsDir, pluginTag->mLibrary = pluginLibrary; pluginTag->mLastModifiedTime = fileModTime; - if (!pluginEnabled || (IsJavaPluginTag(pluginTag) && !mJavaEnabled)) + if (!(oldFlags & NS_PLUGIN_FLAG_ENABLED) || + (IsJavaPluginTag(pluginTag) && !mJavaEnabled)) pluginTag->UnMark(NS_PLUGIN_FLAG_ENABLED); + if (oldFlags & NS_PLUGIN_FLAG_BLOCKLISTED) + pluginTag->Mark(NS_PLUGIN_FLAG_BLOCKLISTED); + // if this is unwanted plugin we are checkin for, or this is a duplicate plugin, // add it to our cache info list so we can cache the unwantedness of this plugin // when we sync cached plugins to registry @@ -5223,6 +5257,11 @@ NS_IMETHODIMP nsPluginHostImpl::LoadPlugins() if (iim) iim->AutoRegisterInterfaces(); + + nsCOMPtr + obsService(do_GetService("@mozilla.org/observer-service;1")); + if (obsService) + obsService->NotifyObservers(nsnull, "plugins-list-updated", nsnull); } return NS_OK; @@ -5284,7 +5323,7 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi // if we are just looking for possible changes, // no need to proceed if changes are detected if (!aCreatePluginList && *aPluginsChanged) { - ClearCachedPluginInfoList(); + mCachedPlugins = nsnull; return NS_OK; } } @@ -5311,7 +5350,7 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi // if we are just looking for possible changes, // no need to proceed if changes are detected if (!aCreatePluginList && *aPluginsChanged) { - ClearCachedPluginInfoList(); + mCachedPlugins = nsnull; return NS_OK; } } @@ -5359,7 +5398,7 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi // if we are just looking for possible changes, // no need to proceed if changes are detected if (!aCreatePluginList && *aPluginsChanged) { - ClearCachedPluginInfoList(); + mCachedPlugins = nsnull; return NS_OK; } } @@ -5387,7 +5426,7 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi // if we are not creating the list, there is no need to proceed if (!aCreatePluginList) { - ClearCachedPluginInfoList(); + mCachedPlugins = nsnull; return NS_OK; } @@ -5397,7 +5436,7 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi WritePluginInfo(); // No more need for cached plugins. Clear it up. - ClearCachedPluginInfoList(); + mCachedPlugins = nsnull; /* * XXX Big time hack alert!!!! @@ -5425,11 +5464,6 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi return NS_OK; } -void nsPluginHostImpl::ClearCachedPluginInfoList() -{ - mCachedPlugins = nsnull; -} - //////////////////////////////////////////////////////////////////////// nsresult nsPluginHostImpl::LoadXPCOMPlugins(nsIComponentManager* aComponentManager) @@ -5449,11 +5483,28 @@ nsPluginHostImpl::LoadXPCOMPlugins(nsIComponentManager* aComponentManager) } nsresult -nsPluginHostImpl::UpdatePluginInfo() +nsPluginHostImpl::UpdatePluginInfo(nsPluginTag* aPluginTag) { ReadPluginInfo(); WritePluginInfo(); - ClearCachedPluginInfoList(); + mCachedPlugins = nsnull; + + if (!aPluginTag || aPluginTag->HasFlag(NS_PLUGIN_FLAG_ENABLED)) + return NS_OK; + + nsCOMPtr instsToReload; + NS_NewISupportsArray(getter_AddRefs(instsToReload)); + mActivePluginList.stopRunning(instsToReload, aPluginTag); + mActivePluginList.removeAllStopped(); + + PRUint32 c; + if (instsToReload && + NS_SUCCEEDED(instsToReload->Count(&c)) && + c > 0) { + nsCOMPtr ev = new nsPluginDocReframeEvent(instsToReload); + if (ev) + NS_DispatchToCurrentThread(ev); + } return NS_OK; } @@ -6378,18 +6429,9 @@ NS_IMETHODIMP nsPluginHostImpl::Observe(nsISupports *aSubject, // disabled so at least FindPluginForType/Extension doesn't return // anything. for (nsPluginTag* cur = mPlugins; cur; cur = cur->mNext) { - if (IsJavaPluginTag(cur)) { - if (mJavaEnabled) { - cur->Mark(NS_PLUGIN_FLAG_ENABLED); - } else { - cur->UnMark(NS_PLUGIN_FLAG_ENABLED); - } - } + if (IsJavaPluginTag(cur)) + cur->SetDisabled(!mJavaEnabled); } - - // Pass PR_TRUE for reloadPages because otherwise if there is a java - // plugin running somewhere it won't get turned off - return ReloadPlugins(PR_TRUE); } } return NS_OK; diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h index 1aeb2ed8e77..5ef2c110580 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h @@ -75,10 +75,11 @@ class nsIChannel; class nsIRegistry; class nsPluginHostImpl; -#define NS_PLUGIN_FLAG_ENABLED 0x0001 // is this plugin enabled? -#define NS_PLUGIN_FLAG_OLDSCHOOL 0x0002 // is this a pre-xpcom plugin? -#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache -#define NS_PLUGIN_FLAG_UNWANTED 0x0008 // this is an unwanted plugin +#define NS_PLUGIN_FLAG_ENABLED 0x0001 // is this plugin enabled? +#define NS_PLUGIN_FLAG_OLDSCHOOL 0x0002 // is this a pre-xpcom plugin? +#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache +#define NS_PLUGIN_FLAG_UNWANTED 0x0008 // this is an unwanted plugin +#define NS_PLUGIN_FLAG_BLOCKLISTED 0x0010 // this is a blocklisted plugin /** * A linked-list of plugin information that is used for @@ -198,7 +199,7 @@ public: PRUint32 getStoppedCount(); nsActivePlugin * findOldestStopped(); void removeAllStopped(); - void stopRunning(nsISupportsArray* aReloadDocs); + void stopRunning(nsISupportsArray* aReloadDocs, nsPluginTag* aPluginTag); PRBool IsLastInstance(nsActivePlugin * plugin); }; @@ -319,8 +320,9 @@ public: static nsresult GetPluginTempDir(nsIFile **aDir); - // Writes updated plugins settings to disk - nsresult UpdatePluginInfo(); + // Writes updated plugins settings to disk and unloads the plugin + // if it is now disabled + nsresult UpdatePluginInfo(nsPluginTag* aPluginTag); private: NS_IMETHOD @@ -409,9 +411,6 @@ private: // that does Java) PRBool IsJavaMIMEType(const char *aType); - // destroys plugin info list - void ClearCachedPluginInfoList(); - nsresult EnsurePrivateDirServiceProvider(); nsresult GetPrompt(nsIPluginInstanceOwner *aOwner, nsIPrompt **aPrompt);