Bug 1323064 - Remove Flash from navigator.plugins when Flash is blacklisted in the document draft
authorKirk Steuber <ksteuber@mozilla.com>
Thu, 02 Feb 2017 10:03:51 -0800
changeset 469802 7be014e105a81c8249a38cccb50a97c36d0301b6
parent 469801 292c1bedbc6cef9f84a2de04f3424ff6b687276c
child 469825 27e6b3245214be5ab8f4613a6a145ed8752625b4
child 470400 33a5a2258bfe85bb409dc35bc96e35b4effa04da
push id43842
push userksteuber@mozilla.com
push dateThu, 02 Feb 2017 19:25:19 +0000
bugs1323064
milestone54.0a1
Bug 1323064 - Remove Flash from navigator.plugins when Flash is blacklisted in the document MozReview-Commit-ID: LKjCORgaecI
dom/base/nsDocument.cpp
toolkit/components/url-classifier/tests/browser/browser_flash_block_lists.js
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3153,16 +3153,21 @@ nsDocument::GetAllowPlugins(bool * aAllo
     docShell->GetAllowPlugins(aAllowPlugins);
 
     // If the docshell allows plugins, we check whether
     // we are sandboxed and plugins should not be allowed.
     if (*aAllowPlugins)
       *aAllowPlugins = !(mSandboxFlags & SANDBOXED_PLUGINS);
   }
 
+  if (*aAllowPlugins) {
+    FlashClassification classification = DocumentFlashClassification();
+    *aAllowPlugins = (classification != FlashClassification::Denied);
+  }
+
   return NS_OK;
 }
 
 bool
 nsDocument::IsElementAnimateEnabled(JSContext* aCx, JSObject* /*unused*/)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/toolkit/components/url-classifier/tests/browser/browser_flash_block_lists.js
+++ b/toolkit/components/url-classifier/tests/browser/browser_flash_block_lists.js
@@ -70,126 +70,143 @@ registerCleanupFunction(unsetDBPrefs);
 // domain in the list is the domain of the most deeply nested iframe.
 // Only the plugin in the most deeply nested document will be checked.
 var testCases = [
   {
     name: "Unknown domain",
     domains: ["http://example.com"],
     expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: true
   },
   {
     name: "Nested unknown domains",
     domains: ["http://example.com", "http://example.org"],
     expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: true
   },
   {
     name: "Allowed domain",
     domains: ["http://flashallow.example.com"],
     expectedActivated: true,
-    expectedHasRunningPlugin: true
+    expectedHasRunningPlugin: true,
+    pluginListed: true
   },
   {
     name: "Allowed nested domain",
     domains: ["http://example.com", "http://flashallow.example.com"],
     expectedActivated: true,
-    expectedHasRunningPlugin: true
+    expectedHasRunningPlugin: true,
+    pluginListed: true
   },
   {
     name: "Subdocument of allowed domain",
     domains: ["http://flashallow.example.com", "http://example.com"],
     expectedActivated: true,
-    expectedHasRunningPlugin: true
+    expectedHasRunningPlugin: true,
+    pluginListed: true
   },
   {
     name: "Exception to allowed domain",
     domains: ["http://exception.flashallow.example.com"],
     expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: true
   },
   {
     name: "Blocked domain",
     domains: ["http://flashblock.example.com"],
-    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_SUPPRESSED,
+    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: false
   },
   {
     name: "Nested blocked domain",
     domains: ["http://example.com", "http://flashblock.example.com"],
-    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_SUPPRESSED,
+    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: false
   },
   {
     name: "Subdocument of blocked subdocument",
     domains: ["http://example.com", "http://flashblock.example.com", "http://example.com"],
-    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_SUPPRESSED,
+    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: false
   },
   {
     name: "Blocked subdocument nested among in allowed documents",
     domains: ["http://flashallow.example.com", "http://flashblock.example.com", "http://flashallow.example.com"],
-    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_SUPPRESSED,
+    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: false
   },
   {
     name: "Exception to blocked domain",
     domains: ["http://exception.flashblock.example.com"],
     expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: true
   },
   {
     name: "Sub-document blocked domain in top-level context",
     domains: ["http://subdocument.example.com"],
     expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: true
   },
   {
     name: "Sub-document blocked domain",
     domains: ["http://example.com", "http://subdocument.example.com"],
-    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_SUPPRESSED,
+    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: false
   },
   {
     name: "Sub-document blocked subdocument of an allowed domain",
     domains: ["http://flashallow.example.com", "http://subdocument.example.com"],
-    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_SUPPRESSED,
+    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: false
   },
   {
     name: "Subdocument of Sub-document blocked domain",
     domains: ["http://example.com", "http://subdocument.example.com", "http://example.com"],
-    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_SUPPRESSED,
+    expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: false
   },
   {
     name: "Sub-document exception in top-level context",
     domains: ["http://exception.subdocument.example.com"],
     expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: true
   },
   {
     name: "Sub-document blocked domain exception",
     domains: ["http://example.com", "http://exception.subdocument.example.com"],
     expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
     expectedActivated: false,
-    expectedHasRunningPlugin: false
+    expectedHasRunningPlugin: false,
+    pluginListed: true
   }
 ];
 
 function buildDocumentStructure(browser, iframeDomains) {
   return Task.spawn(function* () {
     let depth = 0;
     for (let domain of iframeDomains) {
       // Firefox does not like to load the same page in its own iframe. Put some
@@ -207,33 +224,37 @@ function buildDocumentStructure(browser,
       });
 
       yield domainLoaded;
       ++depth;
     }
   });
 }
 
-function getPlugin(browser, depth) {
+function getPluginInfo(browser, depth) {
   return ContentTask.spawn(browser,
                            {iframeId: IFRAME_ID, depth: depth},
                            function* ({iframeId, depth}) {
     let doc = content.document;
+    let win = content.window;
     for (let i = 0; i < depth; ++i) {
-      doc = doc.getElementById(iframeId).contentDocument;
+      let frame = doc.getElementById(iframeId);
+      doc = frame.contentDocument;
+      win = frame.contentWindow;
     }
 
     let pluginObj = doc.getElementById("testObject");
     if (!(pluginObj instanceof Ci.nsIObjectLoadingContent)) {
       throw new Error("Unable to find plugin!");
     }
     return {
       pluginFallbackType: pluginObj.pluginFallbackType,
       activated: pluginObj.activated,
-      hasRunningPlugin: pluginObj.hasRunningPlugin
+      hasRunningPlugin: pluginObj.hasRunningPlugin,
+      listed: ("Shockwave Flash" in win.navigator.plugins)
     };
   });
 }
 
 add_task(function* checkFlashBlockLists() {
   setDBPrefs();
 
   yield classifierHelper.waitForInit();
@@ -244,30 +265,34 @@ add_task(function* checkFlashBlockLists(
 
     let iframeDomains = testCase.domains.slice();
     let pageDomain = iframeDomains.shift();
     let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
                                                           pageDomain + URL_PATH);
 
     yield buildDocumentStructure(tab.linkedBrowser, iframeDomains);
 
-    let plugin = yield getPlugin(tab.linkedBrowser, iframeDomains.length);
+    let pluginInfo = yield getPluginInfo(tab.linkedBrowser, iframeDomains.length);
 
     if ("expectedPluginFallbackType" in testCase) {
-      is(plugin.pluginFallbackType, testCase.expectedPluginFallbackType,
+      is(pluginInfo.pluginFallbackType, testCase.expectedPluginFallbackType,
         "Plugin should have the correct fallback type");
     }
     if ("expectedActivated" in testCase) {
-      is(plugin.activated, testCase.expectedActivated,
+      is(pluginInfo.activated, testCase.expectedActivated,
         "Plugin should have the correct activation");
     }
     if ("expectedHasRunningPlugin" in testCase) {
-      is(plugin.hasRunningPlugin, testCase.expectedHasRunningPlugin,
+      is(pluginInfo.hasRunningPlugin, testCase.expectedHasRunningPlugin,
         "Plugin should have the correct 'plugin running' state");
     }
+    if ("pluginListed" in testCase) {
+      is(pluginInfo.listed, testCase.pluginListed,
+        "Plugin's existance in navigator.plugins should match expected")
+    }
 
     yield BrowserTestUtils.removeTab(tab);
   }
 });
 
 add_task(function* checkFlashBlockDisabled() {
   setDBPrefs();
   Services.prefs.setBoolPref(FLASHBLOCK_ENABLE_PREF, false);
@@ -280,17 +305,18 @@ add_task(function* checkFlashBlockDisabl
 
     let iframeDomains = testCase.domains.slice();
     let pageDomain = iframeDomains.shift();
     let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
                                                           pageDomain + URL_PATH);
 
     yield buildDocumentStructure(tab.linkedBrowser, iframeDomains);
 
-    let plugin = yield getPlugin(tab.linkedBrowser, iframeDomains.length);
+    let pluginInfo = yield getPluginInfo(tab.linkedBrowser, iframeDomains.length);
 
     // With flashblock disabled, all plugins should be activated.
-    ok(plugin.activated, "Plugin should be activated");
-    ok(plugin.hasRunningPlugin, "Plugin should be running");
+    ok(pluginInfo.activated, "Plugin should be activated");
+    ok(pluginInfo.hasRunningPlugin, "Plugin should be running");
+    ok(pluginInfo.listed, "Flash should be listed in navigator.plugins");
 
     yield BrowserTestUtils.removeTab(tab);
   }
 });