Bug 1282484 - Write structure for pref-configurable fallback rules list, and include initial set of rules. r=qDot draft
authorFelipe Gomes <felipc@gmail.com>
Wed, 09 Nov 2016 17:24:54 -0200
changeset 436807 d417fbfd7a1bb9d71fe4546da9ec4fbf36110338
parent 436806 5d2e1e5b2457bbdf2f9b6c73517120aa849bc93d
child 536435 cea62b71e35a47ccd9e9f50745fcc9e189ef4001
push id35191
push userfelipc@gmail.com
push dateWed, 09 Nov 2016 19:25:33 +0000
reviewersqDot
bugs1282484, 1282485, 1316102, 1282487, 1282486
milestone52.0a1
Bug 1282484 - Write structure for pref-configurable fallback rules list, and include initial set of rules. r=qDot * * * Bug 1282485 - Plugin fallback rule - don't use fallback when the descendant has an embed element * * * Bug 1316102 - Plugin fallback rule - use fallback when it contains a <video> element * * * Bug 1282487 - Plugin fallback rule - don't use fallback when it contains links to adobe.com * * * Bug 1282486 - Plugin fallback rule - don't use fallback when it contains 'install Flash' instructions MozReview-Commit-ID: 5NtjdYDMtpl
browser/app/profile/firefox.js
dom/base/nsObjectLoadingContent.cpp
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -643,16 +643,20 @@ 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");
 
+// A comma-separated list of rules to follow when deciding
+// whether an object has been provided with good fallback content.
+pref("plugins.favorfallback.rules", "");
+
 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
@@ -105,16 +105,17 @@
 #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";
+static const char *kPrefFavorFallbackRules = "plugins.favorfallback.rules";
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::net;
 
 static LogModule*
 GetObjectLog()
 {
@@ -3584,17 +3585,99 @@ nsObjectLoadingContent::HasGoodFallback(
     // determined type should always just be alternate content
     return false;
   }
 
   if (!thisContent->IsHTMLElement(nsGkAtoms::object)) {
     return false;
   }
 
-  // xxx to be filled
+  nsTArray<nsCString> rulesList;
+  nsCString prefString;
+  if (NS_SUCCEEDED(Preferences::GetCString(kPrefFavorFallbackRules, &prefString))) {
+      ParseString(prefString, ',', rulesList);
+  }
+
+  for (uint32_t i = 0; i < rulesList.Length(); ++i) {
+    // RULE "embed":
+    // Don't use fallback content if the object contains an <embed> inside its
+    // fallback content.
+    if (rulesList[i].EqualsLiteral("embed")) {
+      nsTArray<nsINodeList*> childNodes;
+      for (nsIContent* child = thisContent->GetFirstChild();
+           child;
+           child = child->GetNextNode(thisContent)) {
+        if (child->IsHTMLElement(nsGkAtoms::embed)) {
+          return false;
+        }
+      }
+    }
+
+    // RULE "video":
+    // Use fallback content if the object contains a <video> inside its
+    // fallback content.
+    if (rulesList[i].EqualsLiteral("video")) {
+      nsTArray<nsINodeList*> childNodes;
+      for (nsIContent* child = thisContent->GetFirstChild();
+           child;
+           child = child->GetNextNode(thisContent)) {
+        if (child->IsHTMLElement(nsGkAtoms::video)) {
+          return true;
+        }
+      }
+    }
+
+    // RULE "adobelink":
+    // Don't use fallback content when it has a link to adobe's website.
+    if (rulesList[i].EqualsLiteral("adobelink")) {
+      nsTArray<nsINodeList*> childNodes;
+      for (nsIContent* child = thisContent->GetFirstChild();
+           child;
+           child = child->GetNextNode(thisContent)) {
+        if (child->IsHTMLElement(nsGkAtoms::a)) {
+          nsCOMPtr<nsIURI> href = child->GetHrefURI();
+          if (href) {
+            nsAutoCString asciiHost;
+            nsresult rv = href->GetAsciiHost(asciiHost);
+            if (NS_SUCCEEDED(rv) &&
+                !asciiHost.IsEmpty() &&
+                (asciiHost.EqualsLiteral("adobe.com") ||
+                 StringEndsWith(asciiHost, NS_LITERAL_CSTRING(".adobe.com")))) {
+              return false;
+            }
+          }
+        }
+      }
+    }
+
+    // RULE "installinstructions":
+    // Don't use fallback content when the text content on the fallback appears
+    // to contain instructions to install or download Flash.
+    if (rulesList[i].EqualsLiteral("installinstructions")) {
+      nsAutoString textContent;
+      ErrorResult rv;
+      thisContent->GetTextContent(textContent, rv);
+      bool hasText =
+        !rv.Failed() &&
+        (CaseInsensitiveFindInReadable(NS_LITERAL_STRING("Flash"), textContent) ||
+         CaseInsensitiveFindInReadable(NS_LITERAL_STRING("Install"), textContent) ||
+         CaseInsensitiveFindInReadable(NS_LITERAL_STRING("Download"), textContent));
+
+      if (hasText) {
+        return false;
+      }
+    }
+
+    // RULE "true":
+    // By having a rule that returns true, we can put it at the end of the rules list
+    // to change the default-to-false behavior to be default-to-true.
+    if (rulesList[i].EqualsLiteral("true")) {
+      return true;
+    }
+  }
 
   return false;
 }
 
 bool
 nsObjectLoadingContent::PreferFallback(bool aIsPluginClickToPlay) {
   if (mPreferFallbackKnown) {
     return mPreferFallback;