bug 1186948 - remove plugins that are click-to-play from navigator.plugins (restricted to Flash) r=jst

This commit is contained in:
Brad Lassey 2015-08-03 19:24:35 -04:00
parent bab285064e
commit e680d73b96
7 changed files with 124 additions and 7 deletions

View File

@ -53,6 +53,8 @@ PluginContent.prototype = {
global.addMessageListener("BrowserPlugins:NPAPIPluginProcessCrashed", this);
global.addMessageListener("BrowserPlugins:CrashReportSubmitted", this);
global.addMessageListener("BrowserPlugins:Test:ClearCrashData", this);
Services.obs.addObserver(this, "Plugin::HiddenPluginTouched", false);
},
uninit: function() {
@ -75,6 +77,8 @@ PluginContent.prototype = {
global.removeMessageListener("BrowserPlugins:Test:ClearCrashData", this);
delete this.global;
delete this.content;
Services.obs.removeObserver(this, "Plugin::HiddenPluginTouched");
},
receiveMessage: function (msg) {
@ -116,6 +120,15 @@ PluginContent.prototype = {
}
},
observe: function observe(aSubject, aTopic, aData) {
let pluginTag = aSubject;
if (aTopic == "Plugin::HiddenPluginTouched") {
this._showClickToPlayNotification(pluginTag, false);
} else {
Cu.reportError("unknown topic observed: " + aTopic);
}
},
onPageShow: function (event) {
// Ignore events that aren't from the main document.
if (!this.content || event.target != this.content.document) {
@ -194,6 +207,45 @@ PluginContent.prototype = {
};
},
_getPluginInfoForTag: function (pluginTag, tagMimetype, fallbackType) {
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
let pluginName = gNavigatorBundle.GetStringFromName("pluginInfo.unknownPlugin");
let permissionString = null;
let blocklistState = null;
if (pluginTag) {
pluginName = BrowserUtils.makeNicePluginName(pluginTag.name);
permissionString = pluginHost.getPermissionStringForTag(pluginTag);
blocklistState = pluginTag.blocklistState;
// Convert this from nsIPluginTag so it can be serialized.
let properties = ["name", "description", "filename", "version", "enabledState", "niceName"];
let pluginTagCopy = {};
for (let prop of properties) {
pluginTagCopy[prop] = pluginTag[prop];
}
pluginTag = pluginTagCopy;
// Make state-softblocked == state-notblocked for our purposes,
// they have the same UI. STATE_OUTDATED should not exist for plugin
// items, but let's alias it anyway, just in case.
if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED ||
blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
}
}
return { mimetype: tagMimetype,
pluginName: pluginName,
pluginTag: pluginTag,
permissionString: permissionString,
fallbackType: fallbackType,
blocklistState: blocklistState,
};
},
/**
* Update the visibility of the plugin overlay.
*/

View File

@ -19,6 +19,8 @@
#include "nsIWeakReference.h"
#include "mozilla/Services.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPermissionManager.h"
#include "nsIDocument.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -66,7 +68,8 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginArray,
mWindow,
mPlugins)
mPlugins,
mCTPPlugins)
static void
GetPluginMimeTypes(const nsTArray<RefPtr<nsPluginElement> >& aPlugins,
@ -146,6 +149,7 @@ nsPluginArray::Refresh(bool aReloadDocuments)
}
mPlugins.Clear();
mCTPPlugins.Clear();
nsCOMPtr<nsIDOMNavigator> navigator = mWindow->GetNavigator();
@ -221,6 +225,13 @@ nsPluginArray::NamedGetter(const nsAString& aName, bool &aFound)
nsPluginElement* plugin = FindPlugin(mPlugins, aName);
aFound = (plugin != nullptr);
if (!aFound) {
nsPluginElement* hiddenPlugin = FindPlugin(mCTPPlugins, aName);
if (hiddenPlugin) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->NotifyObservers(hiddenPlugin->PluginTag(), "Plugin::HiddenPluginTouched", nsString(aName).get());
}
}
return plugin;
}
@ -282,7 +293,7 @@ operator<(const RefPtr<nsPluginElement>& lhs,
void
nsPluginArray::EnsurePlugins()
{
if (!mPlugins.IsEmpty()) {
if (!mPlugins.IsEmpty() || !mCTPPlugins.IsEmpty()) {
// We already have an array of plugin elements.
return;
}
@ -299,7 +310,31 @@ nsPluginArray::EnsurePlugins()
// need to wrap each of these with a nsPluginElement, which is
// scriptable.
for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
nsCOMPtr<nsPluginTag> pluginTag = do_QueryInterface(pluginTags[i]);
if (!pluginTag) {
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
} else if (pluginTag->IsActive()) {
uint32_t permission = nsIPermissionManager::ALLOW_ACTION;
if (pluginTag->IsClicktoplay()) {
nsCString name;
pluginTag->GetName(name);
if (NS_LITERAL_CSTRING("Shockwave Flash").Equals(name)) {
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
nsCString permString;
nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString);
if (rv == NS_OK) {
nsIPrincipal* principal = mWindow->GetExtantDoc()->NodePrincipal();
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission);
}
}
}
if (permission == nsIPermissionManager::ALLOW_ACTION) {
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
} else {
mCTPPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
}
}
}
// Alphabetize the enumeration order of non-hidden plugins to reduce

View File

@ -60,6 +60,10 @@ private:
nsCOMPtr<nsPIDOMWindowInner> mWindow;
nsTArray<RefPtr<nsPluginElement> > mPlugins;
/* A separate list of click-to-play plugins that we don't tell content
* about but keep track of so we can still prompt the user to click to play.
*/
nsTArray<RefPtr<nsPluginElement> > mCTPPlugins;
};
class nsPluginElement final : public nsISupports,

View File

@ -99,6 +99,18 @@ interface nsIPluginHost : nsISupports
ACString getPermissionStringForType(in AUTF8String mimeType,
[optional] in uint32_t excludeFlags);
/**
* Get the "permission string" for the plugin. This is a string that can be
* passed to the permission manager to see whether the plugin is allowed to
* run, for example. This will typically be based on the plugin's "nice name"
* and its blocklist state.
*
* @tag The tage we're interested in
* @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
*/
ACString getPermissionStringForTag(in nsIPluginTag tag,
[optional] in uint32_t excludeFlags);
/**
* Get the nsIPluginTag for this MIME type. This method works with both
* enabled and disabled/blocklisted plugins, but an enabled plugin will

View File

@ -1110,11 +1110,19 @@ nsPluginHost::GetPermissionStringForType(const nsACString &aMimeType,
nsresult rv = GetPluginTagForType(aMimeType, aExcludeFlags,
getter_AddRefs(tag));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(tag, NS_ERROR_FAILURE);
return GetPermissionStringForTag(tag, aExcludeFlags, aPermissionString);
}
NS_IMETHODIMP
nsPluginHost::GetPermissionStringForTag(nsIPluginTag* aTag,
uint32_t aExcludeFlags,
nsACString &aPermissionString)
{
NS_ENSURE_TRUE(aTag, NS_ERROR_FAILURE);
aPermissionString.Truncate();
uint32_t blocklistState;
rv = tag->GetBlocklistState(&blocklistState);
nsresult rv = aTag->GetBlocklistState(&blocklistState);
NS_ENSURE_SUCCESS(rv, rv);
if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE ||
@ -1126,7 +1134,7 @@ nsPluginHost::GetPermissionStringForType(const nsACString &aMimeType,
}
nsCString niceName;
rv = tag->GetNiceName(niceName);
rv = aTag->GetNiceName(niceName);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(!niceName.IsEmpty(), NS_ERROR_FAILURE);

View File

@ -323,7 +323,7 @@ nsPluginTag::~nsPluginTag()
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
}
NS_IMPL_ISUPPORTS(nsPluginTag, nsIPluginTag, nsIInternalPluginTag)
NS_IMPL_ISUPPORTS(nsPluginTag, nsPluginTag, nsIInternalPluginTag, nsIPluginTag)
void nsPluginTag::InitMime(const char* const* aMimeTypes,
const char* const* aMimeDescriptions,

View File

@ -30,6 +30,9 @@ struct FakePluginTagInit;
{ 0xe8fdd227, 0x27da, 0x46ee, \
{ 0xbe, 0xf3, 0x1a, 0xef, 0x5a, 0x8f, 0xc5, 0xb4 } }
#define NS_PLUGINTAG_IID \
{ 0xcce2e8b9, 0x9702, 0x4d4b, \
{ 0xbe, 0xa4, 0x7c, 0x1e, 0x13, 0x1f, 0xaf, 0x78 } }
class nsIInternalPluginTag : public nsIPluginTag
{
public:
@ -90,6 +93,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIInternalPluginTag, NS_IINTERNALPLUGINTAG_IID)
class nsPluginTag final : public nsIInternalPluginTag
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PLUGINTAG_IID)
NS_DECL_ISUPPORTS
NS_DECL_NSIPLUGINTAG
@ -192,6 +197,7 @@ private:
static uint32_t sNextId;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPluginTag, NS_PLUGINTAG_IID)
// A class representing "fake" plugin tags; that is plugin tags not
// corresponding to actual NPAPI plugins. In practice these are all