Bug 1282484 - Add a mechanism to control plugin fallback content. r=qDot
MozReview-Commit-ID: Aabu5bvgvhb
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -635,16 +635,24 @@ pref("findbar.modalHighlight", true);
#endif
// Tracks when accessibility is loaded into the previous session.
pref("accessibility.loadedInLastSession", false);
pref("plugins.click_to_play", true);
pref("plugins.testmode", false);
+// This pref can take 3 possible string values:
+// "always" - always use favor fallback mode
+// "follow-ctp" - activate if ctp is active for the given
+// plugin object (could be due to a plugin-wide
+// setting or a site-specific setting)
+// "never" - never use favor fallback mode
+pref("plugins.favorfallback.mode", "follow-ctp");
+
pref("plugin.default.state", 1);
// Plugins bundled in XPIs are enabled by default.
pref("plugin.defaultXpi.state", 2);
// Flash is enabled by default, and Java is click-to-activate by default on
// all channels.
pref("plugin.state.flash", 2);
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -104,16 +104,17 @@
#include "mozilla/dom/HTMLObjectElement.h"
#endif
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
static const char *kPrefJavaMIME = "plugin.java.mime";
static const char *kPrefYoutubeRewrite = "plugins.rewrite_youtube_embeds";
static const char *kPrefBlockURIs = "browser.safebrowsing.blockedURIs.enabled";
+static const char *kPrefFavorFallbackMode = "plugins.favorfallback.mode";
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::net;
static LogModule*
GetObjectLog()
{
@@ -3499,45 +3500,108 @@ nsObjectLoadingContent::ShouldPlay(Fallb
uint64_t nowms = PR_Now() / 1000;
permissionManager->UpdateExpireTime(
topDoc->NodePrincipal(), permissionString.Data(), false,
nowms + sSessionTimeoutMinutes * 60 * 1000,
nowms / 1000 + uint64_t(sPersistentTimeoutDays) * 24 * 60 * 60 * 1000);
}
switch (permission) {
case nsIPermissionManager::ALLOW_ACTION:
+ if (PreferFallback(false /* isPluginClickToPlay */)) {
+ aReason = eFallbackAlternate;
+ return false;
+ }
+
return true;
case nsIPermissionManager::DENY_ACTION:
aReason = eFallbackDisabled;
return false;
case nsIPermissionManager::PROMPT_ACTION:
+ if (PreferFallback(true /* isPluginClickToPlay */)) {
+ // False is already returned in this case, but
+ // it's important to correctly set aReason too.
+ aReason = eFallbackAlternate;
+ }
+
return false;
case nsIPermissionManager::UNKNOWN_ACTION:
break;
default:
MOZ_ASSERT(false);
return false;
}
}
// No site-specific permissions. Vulnerable plugins are automatically CtP
if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE ||
blocklistState == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
return false;
}
+ if (PreferFallback(enabledState == nsIPluginTag::STATE_CLICKTOPLAY)) {
+ aReason = eFallbackAlternate;
+ return false;
+ }
+
switch (enabledState) {
case nsIPluginTag::STATE_ENABLED:
return true;
case nsIPluginTag::STATE_CLICKTOPLAY:
return false;
}
MOZ_CRASH("Unexpected enabledState");
}
+bool
+nsObjectLoadingContent::FavorFallbackMode(bool aIsPluginClickToPlay) {
+ if (!IsFlashMIME(mContentType)) {
+ return false;
+ }
+
+ nsCString prefString;
+ if (NS_SUCCEEDED(Preferences::GetCString(kPrefFavorFallbackMode, &prefString))) {
+ if (aIsPluginClickToPlay &&
+ prefString.EqualsLiteral("follow-ctp")) {
+ return true;
+ }
+
+ if (prefString.EqualsLiteral("always")) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+nsObjectLoadingContent::HasGoodFallback() {
+ nsCOMPtr<nsIContent> thisContent =
+ do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+ NS_ASSERTION(thisContent, "must be a content");
+
+ if (!thisContent->IsHTMLElement() || mContentType.IsEmpty()) {
+ // Don't let custom fallback handlers run outside HTML, tags without a
+ // determined type should always just be alternate content
+ return false;
+ }
+
+ if (!thisContent->IsHTMLElement(nsGkAtoms::object)) {
+ return false;
+ }
+
+ // xxx to be filled
+
+ return false;
+}
+
+bool
+nsObjectLoadingContent::PreferFallback(bool aIsPluginClickToPlay) {
+ return FavorFallbackMode(aIsPluginClickToPlay) && HasGoodFallback();
+}
+
nsIDocument*
nsObjectLoadingContent::GetContentDocument(nsIPrincipal& aSubjectPrincipal)
{
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
if (!thisContent->IsInComposedDoc()) {
return nullptr;
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -456,16 +456,42 @@ class nsObjectLoadingContent : public ns
/**
* If this object is allowed to play plugin content, or if it would display
* click-to-play instead.
* NOTE that this does not actually check if the object is a loadable plugin
* NOTE This ignores the current activated state. The caller should check this if appropriate.
*/
bool ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentType);
+ /**
+ * This method tells if the fallback content should be attempted to be used
+ * over the original object content.
+ * It will look at prefs and this plugin's CTP state to make a decision.
+ *
+ * NOTE that this doesn't say whether the fallback _will_ be used, only whether
+ * we should look into it to possibly use it. The final answer will be
+ * given by the PreferFallback method.
+ *
+ * @param aIsPluginClickToPlay Whether this object instance is CTP.
+ */
+ bool FavorFallbackMode(bool aIsPluginClickToPlay);
+
+ /**
+ * Whether the page has provided good fallback content to this object.
+ */
+ bool HasGoodFallback();
+
+ /**
+ * This method tells the final answer on whether this object's fallback
+ * content should be used instead of the original plugin content.
+ *
+ * @param aIsPluginClickToPlay Whether this object instance is CTP.
+ */
+ bool PreferFallback(bool aIsPluginClickToPlay);
+
/*
* Helper to check if mBaseURI can be used by java as a codebase
*/
bool CheckJavaCodebase();
/**
* Helper to check if our current URI passes policy
*