Bug 772590 - The plugin category manager registration should account for multiple plugins per MIME, r=josh

This commit is contained in:
John Schoenick 2012-06-29 15:28:45 -07:00
parent 3a8e7786bd
commit 6630c58f4e
6 changed files with 98 additions and 106 deletions

View File

@ -1085,13 +1085,11 @@ var gApplicationsPane = {
* enabledPlugin property. But if there's a plugin for a type, we need
* to know about it even if it isn't enabled, since we're going to give
* the user an option to enable it.
*
* I'll also note that my reading of nsPluginTag::RegisterWithCategoryManager
* suggests that enabledPlugin is only determined during registration
* and does not get updated when plugin.disable_full_page_plugin_for_types
* changes (unless modification of that preference spawns reregistration).
* So even if we could use enabledPlugin to get the plugin that would be used,
* we'd still need to check the pref ourselves to find out if it's enabled.
*
* Also note that enabledPlugin does not get updated when
* plugin.disable_full_page_plugin_for_types changes, so even if we could use
* enabledPlugin to get the plugin that would be used, we'd still need to
* check the pref ourselves to find out if it's enabled.
*/
_loadPluginHandlers: function() {
for (let i = 0; i < navigator.plugins.length; ++i) {

View File

@ -1072,13 +1072,11 @@ var gApplicationsPane = {
* enabledPlugin property. But if there's a plugin for a type, we need
* to know about it even if it isn't enabled, since we're going to give
* the user an option to enable it.
*
* I'll also note that my reading of nsPluginTag::RegisterWithCategoryManager
* suggests that enabledPlugin is only determined during registration
* and does not get updated when plugin.disable_full_page_plugin_for_types
* changes (unless modification of that preference spawns reregistration).
* So even if we could use enabledPlugin to get the plugin that would be used,
* we'd still need to check the pref ourselves to find out if it's enabled.
*
* Also note that enabledPlugin does not get updated when
* plugin.disable_full_page_plugin_for_types changes, so even if we could use
* enabledPlugin to get the plugin that would be used, we'd still need to
* check the pref ourselves to find out if it's enabled.
*/
_loadPluginHandlers: function() {
for (let i = 0; i < navigator.plugins.length; ++i) {

View File

@ -54,6 +54,7 @@
#include "nsVersionComparator.h"
#include "nsIObjectLoadingContent.h"
#include "nsIWritablePropertyBag2.h"
#include "nsICategoryManager.h"
#include "nsPluginStreamListenerPeer.h"
#include "mozilla/Preferences.h"
@ -153,6 +154,7 @@ using mozilla::TimeStamp;
#define kPluginTmpDirName NS_LITERAL_CSTRING("plugtmp")
static const char *kPrefWhitelist = "plugin.allowed_types";
static const char *kPrefDisableFullPage = "plugin.disable_full_page_plugin_for_types";
// Version of cached plugin info
// 0.01 first implementation
@ -1517,6 +1519,11 @@ nsPluginTag*
nsPluginHost::FindPreferredPlugin(const InfallibleTArray<nsPluginTag*>& matches)
{
// We prefer the plugin with the highest version number.
/// XXX(johns): This seems to assume the only time multiple plugins will have
/// the same MIME type is if they're multiple versions of the same
/// plugin -- but since plugin filenames and pretty names can both
/// update, it's probably less arbitrary than just going at it
/// alphabetically.
if (matches.IsEmpty()) {
return nsnull;
@ -2130,7 +2137,14 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
}
if (pluginTag->IsEnabled()) {
pluginTag->RegisterWithCategoryManager(mOverrideInternalTypes);
nsAdoptingCString disableFullPage =
Preferences::GetCString(kPrefDisableFullPage);
for (PRUint32 i = 0; i < pluginTag->mMimeTypes.Length(); i++) {
if (!IsTypeInList(pluginTag->mMimeTypes[i], disableFullPage)) {
RegisterWithCategoryManager(pluginTag->mMimeTypes[i],
ePluginRegister);
}
}
}
}
@ -2382,8 +2396,31 @@ nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsInvalidPluginTag>, mInvalidPlugins, mNext);
if (!aPluginTag || aPluginTag->IsEnabled())
if (!aPluginTag) {
return NS_OK;
}
// Update types with category manager
nsAdoptingCString disableFullPage =
Preferences::GetCString(kPrefDisableFullPage);
for (PRUint32 i = 0; i < aPluginTag->mMimeTypes.Length(); i++) {
nsRegisterType shouldRegister;
if (IsTypeInList(aPluginTag->mMimeTypes[i], disableFullPage)) {
shouldRegister = ePluginUnregister;
} else {
nsPluginTag *plugin = FindPluginForType(aPluginTag->mMimeTypes[i].get(),
true);
shouldRegister = plugin ? ePluginRegister : ePluginUnregister;
}
RegisterWithCategoryManager(aPluginTag->mMimeTypes[i], shouldRegister);
}
// Reload instances if needed
if (aPluginTag->IsEnabled()) {
return NS_OK;
}
nsCOMPtr<nsISupportsArray> instsToReload;
NS_NewISupportsArray(getter_AddRefs(instsToReload));
@ -2410,6 +2447,44 @@ nsPluginHost::IsTypeWhitelisted(const char *aMimeType)
return IsTypeInList(wrap, whitelist);
}
void
nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType,
nsRegisterType aType)
{
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginTag::RegisterWithCategoryManager type = %s, removing = %s\n",
aMimeType.get(), aType == ePluginUnregister ? "yes" : "no"));
nsCOMPtr<nsICategoryManager> catMan =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
if (!catMan) {
return;
}
const char *contractId =
"@mozilla.org/content/plugin/document-loader-factory;1";
if (aType == ePluginRegister) {
catMan->AddCategoryEntry("Gecko-Content-Viewers",
aMimeType.get(),
contractId,
false, /* persist: broken by bug 193031 */
mOverrideInternalTypes,
nsnull);
} else {
// Only delete the entry if a plugin registered for it
nsXPIDLCString value;
nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers",
aMimeType.get(),
getter_Copies(value));
if (NS_SUCCEEDED(rv) && strcmp(value, contractId) == 0) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers",
aMimeType.get(),
true);
}
}
}
nsresult
nsPluginHost::WritePluginInfo()
{

View File

@ -233,6 +233,11 @@ private:
nsresult
FindPlugins(bool aCreatePluginList, bool * aPluginsChanged);
// Registers or unregisters the given mime type with the category manager
// (performs no checks - see UpdateCategoryManager)
enum nsRegisterType { ePluginRegister, ePluginUnregister };
void RegisterWithCategoryManager(nsCString &aMimeType, nsRegisterType aType);
nsresult
ScanPluginsDirectory(nsIFile *pluginsDir,
bool aCreatePluginList,

View File

@ -15,7 +15,6 @@
#include "nsIPlatformCharset.h"
#include "nsICharsetConverterManager.h"
#include "nsPluginLogging.h"
#include "nsICategoryManager.h"
#include "nsNPAPIPlugin.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Preferences.h"
@ -296,8 +295,7 @@ nsPluginTag::SetDisabled(bool aDisabled)
UnMark(NS_PLUGIN_FLAG_ENABLED);
else
Mark(NS_PLUGIN_FLAG_ENABLED);
mPluginHost->UpdatePluginInfo(this);
return NS_OK;
}
@ -318,89 +316,17 @@ nsPluginTag::SetBlocklisted(bool aBlocklisted)
Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
else
UnMark(NS_PLUGIN_FLAG_BLOCKLISTED);
mPluginHost->UpdatePluginInfo(nsnull);
return NS_OK;
}
void
nsPluginTag::RegisterWithCategoryManager(bool aOverrideInternalTypes,
nsPluginTag::nsRegisterType aType)
{
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginTag::RegisterWithCategoryManager plugin=%s, removing = %s\n",
mFileName.get(), aType == ePluginUnregister ? "yes" : "no"));
nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
if (!catMan)
return;
const char *contractId = "@mozilla.org/content/plugin/document-loader-factory;1";
// A preference controls whether or not the full page plugin is disabled for
// a particular type. The string must be in the form:
// type1,type2,type3,type4
// Note: need an actual interface to control this and subsequent disabling
// (and other plugin host settings) so applications can reliably disable
// plugins - without relying on implementation details such as prefs/category
// manager entries.
nsCAutoString overrideTypesFormatted;
if (aType != ePluginUnregister) {
overrideTypesFormatted.Assign(',');
nsAdoptingCString overrideTypes =
Preferences::GetCString("plugin.disable_full_page_plugin_for_types");
overrideTypesFormatted += overrideTypes;
overrideTypesFormatted.Append(',');
}
nsACString::const_iterator start, end;
for (PRUint32 i = 0; i < mMimeTypes.Length(); i++) {
if (aType == ePluginUnregister) {
nsXPIDLCString value;
if (NS_SUCCEEDED(catMan->GetCategoryEntry("Gecko-Content-Viewers",
mMimeTypes[i].get(),
getter_Copies(value)))) {
// Only delete the entry if a plugin registered for it
if (strcmp(value, contractId) == 0) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers",
mMimeTypes[i].get(),
true);
}
}
} else {
overrideTypesFormatted.BeginReading(start);
overrideTypesFormatted.EndReading(end);
nsCAutoString commaSeparated;
commaSeparated.Assign(',');
commaSeparated += mMimeTypes[i];
commaSeparated.Append(',');
if (!FindInReadable(commaSeparated, start, end)) {
catMan->AddCategoryEntry("Gecko-Content-Viewers",
mMimeTypes[i].get(),
contractId,
false, /* persist: broken by bug 193031 */
aOverrideInternalTypes, /* replace if we're told to */
nsnull);
}
}
PLUGIN_LOG(PLUGIN_LOG_NOISY,
("nsPluginTag::RegisterWithCategoryManager mime=%s, plugin=%s\n",
mMimeTypes[i].get(), mFileName.get()));
}
return NS_OK;
}
void nsPluginTag::Mark(PRUint32 mask)
{
bool wasEnabled = IsEnabled();
mFlags |= mask;
// Update entries in the category manager if necessary.
if (mPluginHost && wasEnabled != IsEnabled()) {
if (wasEnabled)
RegisterWithCategoryManager(false, nsPluginTag::ePluginUnregister);
else
RegisterWithCategoryManager(false, nsPluginTag::ePluginRegister);
mPluginHost->UpdatePluginInfo(this);
}
}
@ -408,12 +334,9 @@ void nsPluginTag::UnMark(PRUint32 mask)
{
bool wasEnabled = IsEnabled();
mFlags &= ~mask;
// Update entries in the category manager if necessary.
if (mPluginHost && wasEnabled != IsEnabled()) {
if (wasEnabled)
RegisterWithCategoryManager(false, nsPluginTag::ePluginUnregister);
else
RegisterWithCategoryManager(false, nsPluginTag::ePluginRegister);
mPluginHost->UpdatePluginInfo(this);
}
}

View File

@ -33,11 +33,6 @@ struct nsPluginInfo;
class nsPluginTag : public nsIPluginTag
{
public:
enum nsRegisterType {
ePluginRegister,
ePluginUnregister
};
NS_DECL_ISUPPORTS
NS_DECL_NSIPLUGINTAG
@ -63,8 +58,6 @@ public:
bool HasFlag(PRUint32 flag);
PRUint32 Flags();
bool IsEnabled();
void RegisterWithCategoryManager(bool aOverrideInternalTypes,
nsRegisterType aType = ePluginRegister);
nsRefPtr<nsPluginTag> mNext;
nsPluginHost *mPluginHost;