Bug 1169945 - Remove unused plugins.enumerable_names whitelist. r=bsmedberg
authorChris Peterson <cpeterson@mozilla.com>
Fri, 29 May 2015 22:42:23 -0700
changeset 247324 882f1779b4d8c2a428a5cde9a04f82453a5c4bbf
parent 247323 1e76ec5ebbb5b7db36d2d97101eff458bad1269f
child 247325 bc305c9b5d050cfd348fd4be7ce3b5178b7d9901
push id28864
push userkwierso@gmail.com
push dateFri, 05 Jun 2015 21:49:37 +0000
treeherdermozilla-central@97a39c939c51 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs1169945
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1169945 - Remove unused plugins.enumerable_names whitelist. r=bsmedberg
dom/base/nsMimeTypeArray.cpp
dom/base/nsMimeTypeArray.h
dom/base/nsPluginArray.cpp
dom/base/nsPluginArray.h
dom/plugins/test/mochitest/test_secondPlugin.html
modules/libpref/init/all.js
--- a/dom/base/nsMimeTypeArray.cpp
+++ b/dom/base/nsMimeTypeArray.cpp
@@ -22,18 +22,17 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsMimeTy
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsMimeTypeArray)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsMimeTypeArray)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsMimeTypeArray,
                                       mWindow,
-                                      mMimeTypes,
-                                      mHiddenMimeTypes)
+                                      mMimeTypes)
 
 nsMimeTypeArray::nsMimeTypeArray(nsPIDOMWindow* aWindow)
   : mWindow(aWindow)
 {
 }
 
 nsMimeTypeArray::~nsMimeTypeArray()
 {
@@ -44,17 +43,16 @@ nsMimeTypeArray::WrapObject(JSContext* a
 {
   return MimeTypeArrayBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 nsMimeTypeArray::Refresh()
 {
   mMimeTypes.Clear();
-  mHiddenMimeTypes.Clear();
 }
 
 nsPIDOMWindow*
 nsMimeTypeArray::GetParentObject() const
 {
   MOZ_ASSERT(mWindow);
   return mWindow;
 }
@@ -109,20 +107,16 @@ nsMimeTypeArray::NamedGetter(const nsASt
   aFound = false;
 
   EnsurePluginMimeTypes();
 
   nsString lowerName(aName);
   ToLowerCase(lowerName);
 
   nsMimeType* mimeType = FindMimeType(mMimeTypes, lowerName);
-  if (!mimeType) {
-    mimeType = FindMimeType(mHiddenMimeTypes, lowerName);
-  }
-
   if (mimeType) {
     aFound = true;
     return mimeType;
   }
 
   // Now let's check with the MIME service.
   nsCOMPtr<nsIMIMEService> mimeSrv = do_GetService("@mozilla.org/mime;1");
   if (!mimeSrv) {
@@ -159,21 +153,18 @@ nsMimeTypeArray::NamedGetter(const nsASt
         }
       }
     }
   }
 
   // If we got here, we support this type!  Say so.
   aFound = true;
 
-  // We don't want navigator.mimeTypes enumeration to expose MIME types with
-  // application handlers, so add them to the list of hidden MIME types.
   nsMimeType *mt = new nsMimeType(mWindow, lowerName);
-  mHiddenMimeTypes.AppendElement(mt);
-
+  mMimeTypes.AppendElement(mt);
   return mt;
 }
 
 bool
 nsMimeTypeArray::NameIsEnumerable(const nsAString& aName)
 {
   return true;
 }
@@ -194,17 +185,17 @@ nsMimeTypeArray::GetSupportedNames(unsig
   for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
     aRetval.AppendElement(mMimeTypes[i]->Type());
   }
 }
 
 void
 nsMimeTypeArray::EnsurePluginMimeTypes()
 {
-  if (!mMimeTypes.IsEmpty() || !mHiddenMimeTypes.IsEmpty() || !mWindow) {
+  if (!mMimeTypes.IsEmpty() || !mWindow) {
     return;
   }
 
   nsCOMPtr<nsIDOMNavigator> navigator;
   mWindow->GetNavigator(getter_AddRefs(navigator));
 
   if (!navigator) {
     return;
@@ -212,17 +203,17 @@ nsMimeTypeArray::EnsurePluginMimeTypes()
 
   ErrorResult rv;
   nsPluginArray *pluginArray =
     static_cast<Navigator*>(navigator.get())->GetPlugins(rv);
   if (!pluginArray) {
     return;
   }
 
-  pluginArray->GetMimeTypes(mMimeTypes, mHiddenMimeTypes);
+  pluginArray->GetMimeTypes(mMimeTypes);
 }
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsMimeType, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsMimeType, Release)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsMimeType, mWindow, mPluginElement)
 
 nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, nsPluginElement* aPluginElement,
--- a/dom/base/nsMimeTypeArray.h
+++ b/dom/base/nsMimeTypeArray.h
@@ -42,26 +42,19 @@ public:
 protected:
   virtual ~nsMimeTypeArray();
 
   void EnsurePluginMimeTypes();
   void Clear();
 
   nsCOMPtr<nsPIDOMWindow> mWindow;
 
-  // mMimeTypes contains MIME types handled by non-hidden plugins, those
-  // popular plugins that must be exposed in navigator.plugins enumeration to
-  // avoid breaking web content. Likewise, mMimeTypes are exposed in
-  // navigator.mimeTypes enumeration.
+  // mMimeTypes contains MIME types handled by plugins or by an OS
+  // PreferredApplicationHandler.
   nsTArray<nsRefPtr<nsMimeType> > mMimeTypes;
-
-  // mHiddenMimeTypes contains MIME types handled by plugins hidden from
-  // navigator.plugins enumeration or by an OS PreferredApplicationHandler.
-  // mHiddenMimeTypes are hidden from navigator.mimeTypes enumeration.
-  nsTArray<nsRefPtr<nsMimeType> > mHiddenMimeTypes;
 };
 
 class nsMimeType final : public nsWrapperCache
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsMimeType)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsMimeType)
 
--- a/dom/base/nsPluginArray.cpp
+++ b/dom/base/nsPluginArray.cpp
@@ -1,21 +1,19 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsPluginArray.h"
 
-#include "mozilla/Preferences.h"
 #include "mozilla/dom/PluginArrayBinding.h"
 #include "mozilla/dom/PluginBinding.h"
 
-#include "nsCharSeparatedTokenizer.h"
 #include "nsMimeTypeArray.h"
 #include "Navigator.h"
 #include "nsIDocShell.h"
 #include "nsIWebNavigation.h"
 #include "nsPluginHost.h"
 #include "nsPluginTags.h"
 #include "nsIObserverService.h"
 #include "nsIWeakReference.h"
@@ -63,18 +61,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginArray,
                                       mWindow,
-                                      mPlugins,
-                                      mHiddenPlugins)
+                                      mPlugins)
 
 static void
 GetPluginMimeTypes(const nsTArray<nsRefPtr<nsPluginElement> >& aPlugins,
                    nsTArray<nsRefPtr<nsMimeType> >& aMimeTypes)
 {
   for (uint32_t i = 0; i < aPlugins.Length(); ++i) {
     nsPluginElement *plugin = aPlugins[i];
     aMimeTypes.AppendElements(plugin->MimeTypes());
@@ -84,30 +81,27 @@ GetPluginMimeTypes(const nsTArray<nsRefP
 static bool
 operator<(const nsRefPtr<nsMimeType>& lhs, const nsRefPtr<nsMimeType>& rhs)
 {
   // Sort MIME types alphabetically by type name.
   return lhs->Type() < rhs->Type();
 }
 
 void
-nsPluginArray::GetMimeTypes(nsTArray<nsRefPtr<nsMimeType> >& aMimeTypes,
-                            nsTArray<nsRefPtr<nsMimeType> >& aHiddenMimeTypes)
+nsPluginArray::GetMimeTypes(nsTArray<nsRefPtr<nsMimeType>>& aMimeTypes)
 {
   aMimeTypes.Clear();
-  aHiddenMimeTypes.Clear();
 
   if (!AllowPlugins()) {
     return;
   }
 
   EnsurePlugins();
 
   GetPluginMimeTypes(mPlugins, aMimeTypes);
-  GetPluginMimeTypes(mHiddenPlugins, aHiddenMimeTypes);
 
   // Alphabetize the enumeration order of non-hidden MIME types to reduce
   // fingerprintable entropy based on plugins' installation file times.
   aMimeTypes.Sort();
 }
 
 nsPluginElement*
 nsPluginArray::Item(uint32_t aIndex)
@@ -141,24 +135,22 @@ nsPluginArray::Refresh(bool aReloadDocum
 
     // Check if the number of plugins we know about are different from
     // the number of plugin tags the plugin host knows about. If the
     // lengths are different, we refresh. This is safe because we're
     // notified for every plugin enabling/disabling event that
     // happens, and therefore the lengths will be in sync only when
     // the both arrays contain the same plugin tags (though as
     // different types).
-    uint32_t pluginCount = mPlugins.Length() + mHiddenPlugins.Length();
-    if (newPluginTags.Length() == pluginCount) {
+    if (newPluginTags.Length() == mPlugins.Length()) {
       return;
     }
   }
 
   mPlugins.Clear();
-  mHiddenPlugins.Clear();
 
   nsCOMPtr<nsIDOMNavigator> navigator;
   mWindow->GetNavigator(getter_AddRefs(navigator));
 
   if (!navigator) {
     return;
   }
 
@@ -220,20 +212,16 @@ nsPluginArray::NamedGetter(const nsAStri
 
   if (!AllowPlugins()) {
     return nullptr;
   }
 
   EnsurePlugins();
 
   nsPluginElement* plugin = FindPlugin(mPlugins, aName);
-  if (!plugin) {
-    plugin = FindPlugin(mHiddenPlugins, aName);
-  }
-
   aFound = (plugin != nullptr);
   return plugin;
 }
 
 bool
 nsPluginArray::NameIsEnumerable(const nsAString& aName)
 {
   return true;
@@ -282,92 +270,45 @@ bool
 nsPluginArray::AllowPlugins() const
 {
   nsCOMPtr<nsIDocShell> docShell = mWindow ? mWindow->GetDocShell() : nullptr;
 
   return docShell && docShell->PluginsAllowedInCurrentDoc();
 }
 
 static bool
-HasStringPrefix(const nsCString& str, const nsACString& prefix) {
-  return str.Compare(prefix.BeginReading(), false, prefix.Length()) == 0;
-}
-
-static bool
-IsPluginEnumerable(const nsTArray<nsCString>& enumerableNames,
-                   const nsPluginTag* pluginTag)
-{
-  const nsCString& pluginName = pluginTag->mName;
-
-  const uint32_t length = enumerableNames.Length();
-  for (uint32_t i = 0; i < length; i++) {
-    const nsCString& name = enumerableNames[i];
-    if (HasStringPrefix(pluginName, name)) {
-      return true; // don't hide plugin
-    }
-  }
-
-  return false; // hide plugin!
-}
-
-static bool
 operator<(const nsRefPtr<nsPluginElement>& lhs,
           const nsRefPtr<nsPluginElement>& rhs)
 {
   // Sort plugins alphabetically by name.
   return lhs->PluginTag()->mName < rhs->PluginTag()->mName;
 }
 
 void
 nsPluginArray::EnsurePlugins()
 {
-  if (!mPlugins.IsEmpty() || !mHiddenPlugins.IsEmpty()) {
+  if (!mPlugins.IsEmpty()) {
     // We already have an array of plugin elements.
     return;
   }
 
   nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
   if (!pluginHost) {
     // We have no plugin host.
     return;
   }
 
   nsTArray<nsRefPtr<nsPluginTag> > pluginTags;
   pluginHost->GetPlugins(pluginTags);
 
-  nsTArray<nsCString> enumerableNames;
-
-  const nsAdoptingCString& enumerableNamesPref =
-      Preferences::GetCString("plugins.enumerable_names");
-
-  bool disablePluginHiding = !enumerableNamesPref ||
-                             enumerableNamesPref.EqualsLiteral("*");
-
-  if (!disablePluginHiding) {
-    nsCCharSeparatedTokenizer tokens(enumerableNamesPref, ',');
-    while (tokens.hasMoreTokens()) {
-      const nsCSubstring& token = tokens.nextToken();
-      if (!token.IsEmpty()) {
-        enumerableNames.AppendElement(token);
-      }
-    }
-  }
-
   // need to wrap each of these with a nsPluginElement, which is
   // scriptable.
   for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
     nsPluginTag* pluginTag = pluginTags[i];
-
-    // Add the plugin to the list of hidden plugins or non-hidden plugins?
-    nsTArray<nsRefPtr<nsPluginElement> >& pluginArray =
-        (disablePluginHiding || IsPluginEnumerable(enumerableNames, pluginTag))
-        ? mPlugins
-        : mHiddenPlugins;
-
-    pluginArray.AppendElement(new nsPluginElement(mWindow, pluginTag));
+    mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTag));
   }
 
   // Alphabetize the enumeration order of non-hidden plugins to reduce
   // fingerprintable entropy based on plugins' installation file times.
   mPlugins.Sort();
 }
 
 // nsPluginElement implementation.
--- a/dom/base/nsPluginArray.h
+++ b/dom/base/nsPluginArray.h
@@ -35,18 +35,17 @@ public:
 
   // nsPluginArray registers itself as an observer with a weak reference.
   // This can't be done in the constructor, because at that point its
   // refcount is 0 (and it gets destroyed upon registration). So, Init()
   // must be called after construction.
   void Init();
   void Invalidate();
 
-  void GetMimeTypes(nsTArray<nsRefPtr<nsMimeType> >& aMimeTypes,
-                    nsTArray<nsRefPtr<nsMimeType> >& aHiddenMimeTypes);
+  void GetMimeTypes(nsTArray<nsRefPtr<nsMimeType>>& aMimeTypes);
 
   // PluginArray WebIDL methods
 
   nsPluginElement* Item(uint32_t aIndex);
   nsPluginElement* NamedItem(const nsAString& aName);
   void Refresh(bool aReloadDocuments);
   nsPluginElement* IndexedGetter(uint32_t aIndex, bool &aFound);
   nsPluginElement* NamedGetter(const nsAString& aName, bool &aFound);
@@ -56,28 +55,17 @@ public:
 
 private:
   virtual ~nsPluginArray();
 
   bool AllowPlugins() const;
   void EnsurePlugins();
 
   nsCOMPtr<nsPIDOMWindow> mWindow;
-
-  // Many sites check whether a particular plugin is installed by enumerating
-  // all navigator.plugins, checking each plugin's name. These sites should
-  // just check navigator.plugins["Popular Plugin Name"] instead. mPlugins
-  // contains those popular plugins that must be exposed in navigator.plugins
-  // enumeration to avoid breaking web content.
   nsTArray<nsRefPtr<nsPluginElement> > mPlugins;
-
-  // mHiddenPlugins contains plugins that can be queried by
-  // navigator.plugins["Hidden Plugin Name"] but do not need to be exposed in
-  // navigator.plugins enumeration.
-  nsTArray<nsRefPtr<nsPluginElement> > mHiddenPlugins;
 };
 
 class nsPluginElement final : public nsISupports,
                               public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPluginElement)
--- a/dom/plugins/test/mochitest/test_secondPlugin.html
+++ b/dom/plugins/test/mochitest/test_secondPlugin.html
@@ -8,17 +8,18 @@
   </head>
 
   <body onload="run()">
     <script class="testbody" type="application/javascript">
       "use strict";
 
       SimpleTest.waitForExplicitFinish();
       setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
-      setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in");
+      setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_DISABLED, "Second Test Plug-in");
+      setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Java Test Plug-in");
 
       function findPlugin(pluginName) {
           for (var i = 0; i < navigator.plugins.length; i++) {
             var plugin = navigator.plugins[i];
             if (plugin.name === pluginName) {
               return plugin;
             }
           }
@@ -31,43 +32,42 @@
             if (mimeType.type === mimeTypeType) {
               return mimeType;
             }
           }
           return null;
       }
 
       function run() {
-        // Add "Test Plug-in" (but not "Second Test Plug-in") to the list of
-        // unhidden plugins. This test must modify the "plugins.enumerable_names"
-        // pref BEFORE accessing the navigator.plugins or navigator.mimeTypes
-        // arrays because they only read the pref when they first initialize
-        // their internal arrays!
-        var prefs = SpecialPowers.Cc["@mozilla.org/preferences-service;1"].getService(SpecialPowers.Ci.nsIPrefBranch);
-        var defaultEnumerableNamesPref = prefs.getCharPref("plugins.enumerable_names");
-        SpecialPowers.pushPrefEnv(
-          {'set': [["plugins.enumerable_names", defaultEnumerableNamesPref + ",Test Plug-in"]]},
-          finishRun
-        );
-      }
-      function finishRun() {
         var pluginElement = document.getElementById("plugin");
         is(pluginElement.identifierToStringTest("foo"), "foo", "Should be able to call a function provided by the plugin");
 
-        ok(navigator.plugins["Test Plug-in"], "Should have queried a non-hidden plugin named 'Test Plug-in'");
-        ok(navigator.plugins["Second Test Plug-in"], "Should have queried a hidden plugin named 'Test Plug-in'");
+        pluginElement = document.getElementById("disabledPlugin");
+        is(typeof pluginElement.identifierToStringTest, "undefined", "Should NOT be able to call a function on a disabled plugin");
 
-        ok(findPlugin("Test Plug-in"), "Should have found a non-hidden plugin named 'Test Plug-in'");
-        ok(!findPlugin("Second Test Plug-in"), "Should NOT found a hidden plugin named 'Test Plug-in'");
+        pluginElement = document.getElementById("clickToPlayPlugin");
+        is(typeof pluginElement.identifierToStringTest, "undefined", "Should NOT be able to call a function on a click-to-play plugin");
+
+        ok(navigator.plugins["Test Plug-in"], "Should have queried a plugin named 'Test Plug-in'");
+        ok(!navigator.plugins["Second Test Plug-in"], "Should NOT have queried a disabled plugin named 'Second Test Plug-in'");
+        ok(navigator.plugins["Java Test Plug-in"], "Should have queried a click-to-play plugin named 'Java Test Plug-in'");
 
-        ok(navigator.mimeTypes["application/x-test"], "Should have queried a non-hidden MIME type named 'application/x-test'");
-        ok(navigator.mimeTypes["application/x-second-test"], "Should have queried a MIME type named 'application/x-second-test'");
+        ok(findPlugin("Test Plug-in"), "Should have found a plugin named 'Test Plug-in'");
+        ok(!findPlugin("Second Test Plug-in"), "Should NOT found a disabled plugin named 'Second Test Plug-in'");
+        ok(findPlugin("Java Test Plug-in"), "Should have found a click-to-play plugin named 'Java Test Plug-in'");
 
-        ok(findMimeType("application/x-test"), "Should have found a non-hidden MIME type named 'application/x-test'");
-        ok(!findMimeType("application/x-second-test"), "Should NOT have found a MIME type named 'application/x-second-test'");
+        ok(navigator.mimeTypes["application/x-test"], "Should have queried a MIME type named 'application/x-test'");
+        ok(!navigator.mimeTypes["application/x-second-test"], "Should NOT have queried a disabled type named 'application/x-second-test'");
+        ok(navigator.mimeTypes["application/x-java-test"], "Should have queried a click-to-play MIME type named 'application/x-java-test'");
+
+        ok(findMimeType("application/x-test"), "Should have found a MIME type named 'application/x-test'");
+        ok(!findMimeType("application/x-second-test"), "Should NOT have found a disabled MIME type named 'application/x-second-test'");
+        ok(findMimeType("application/x-java-test"), "Should have found a click-to-play MIME type named 'application/x-java-test'");
 
         SimpleTest.finish();
       }
     </script>
 
-    <object id="plugin" type="application/x-second-test" width=200 height=200></object>
+    <object id="plugin" type="application/x-test" width=200 height=200></object>
+    <object id="disabledPlugin" type="application/x-second-test" width=200 height=200></object>
+    <object id="clickToPlayPlugin" type="application/x-java-test" width=200 height=200></object>
   </body>
 </html>
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2389,24 +2389,16 @@ pref("dom.archivereader.enabled", false)
 // Disabled on all platforms per bug 705748 until the found issues are
 // resolved.
 pref("hangmonitor.timeout", 0);
 
 pref("plugins.load_appdir_plugins", false);
 // If true, plugins will be click to play
 pref("plugins.click_to_play", false);
 
-// A comma-delimited list of plugin name prefixes matching plugins that will be
-// exposed when enumerating navigator.plugins[]. For example, prefix "Shockwave"
-// matches both Adobe Flash Player ("Shockwave Flash") and Adobe Shockwave
-// Player ("Shockwave for Director"). To hide all plugins from enumeration, use
-// the empty string "" to match no plugin names. To allow all plugins to be
-// enumerated, use the string "*" to match all plugin names.
-pref("plugins.enumerable_names", "*");
-
 // The default value for nsIPluginTag.enabledState (STATE_ENABLED = 2)
 pref("plugin.default.state", 2);
 
 // The MIME type that should bind to legacy java-specific invocations like
 // <applet> and <object data="java:foo">. Setting this to a non-java MIME type
 // is undefined behavior.
 pref("plugin.java.mime", "application/x-java-vm");