bug 818118 - guard pluginHost.getPermissionStringForType calls r=jaws
authorDavid Keeler <dkeeler@mozilla.com>
Thu, 06 Dec 2012 13:32:23 -0800
changeset 115238 3d63a613d14a3342f5973774d76d7bc456a74b0c
parent 115237 8f0067ac46f1d182fe9732a72d49fe3bbed4d32c
child 115239 5e0647093cd7fb60b3b861cb93ebd0d78c3cfc88
push id19226
push userdkeeler@mozilla.com
push dateThu, 06 Dec 2012 21:40:57 +0000
treeherdermozilla-inbound@3d63a613d14a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs818118
milestone20.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 818118 - guard pluginHost.getPermissionStringForType calls r=jaws
browser/base/content/browser-plugins.js
browser/base/content/test/Makefile.in
browser/base/content/test/browser_bug818118.js
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -232,24 +232,32 @@ var gPluginHandler = {
     // Hide the in-content UI if it's too big. The crashed plugin handler already did this.
     if (eventType != "PluginCrashed") {
       let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
       if (overlay != null && self.isTooSmall(plugin, overlay))
           overlay.style.visibility = "hidden";
     }
   },
 
+  isKnownPlugin: function PH_isKnownPlugin(objLoadingContent) {
+    return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
+            Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
+  },
+
   canActivatePlugin: function PH_canActivatePlugin(objLoadingContent) {
+    // if this isn't a known plugin, we can't activate it
+    // (this also guards pluginHost.getPermissionStringForType against
+    // unexpected input)
+    if (!gPluginHandler.isKnownPlugin(objLoadingContent))
+      return false;
+
     let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-    let pluginPermission = Ci.nsIPermissionManager.UNKNOWN_ACTION;
-    if (objLoadingContent.actualType) {
-      let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
-      let browser = gBrowser.getBrowserForDocument(objLoadingContent.ownerDocument.defaultView.top.document);
-      pluginPermission = Services.perms.testPermission(browser.currentURI, permissionString);
-    }
+    let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
+    let browser = gBrowser.getBrowserForDocument(objLoadingContent.ownerDocument.defaultView.top.document);
+    let pluginPermission = Services.perms.testPermission(browser.currentURI, permissionString);
 
     return !objLoadingContent.activated &&
            pluginPermission != Ci.nsIPermissionManager.DENY_ACTION &&
            objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
            objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
   },
 
   activatePlugins: function PH_activatePlugins(aContentWindow) {
@@ -357,22 +365,24 @@ var gPluginHandler = {
     openHelpLink("plugin-crashed", false);
   },
 
   // Event listener for click-to-play plugins.
   _handleClickToPlayEvent: function PH_handleClickToPlayEvent(aPlugin) {
     let doc = aPlugin.ownerDocument;
     let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
     let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-    let pluginPermission = Ci.nsIPermissionManager.UNKNOWN_ACTION;
     let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
-    if (objLoadingContent.actualType) {
-      let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
-      pluginPermission = Services.perms.testPermission(browser.currentURI, permissionString);
-    }
+    // guard against giving pluginHost.getPermissionStringForType a type
+    // not associated with any known plugin
+    if (!gPluginHandler.isKnownPlugin(objLoadingContent))
+      return;
+    let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
+    let pluginPermission = Services.perms.testPermission(browser.currentURI, permissionString);
+
     let overlay = doc.getAnonymousElementByAttribute(aPlugin, "class", "mainBox");
 
     if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION) {
       if (overlay)
         overlay.style.visibility = "hidden";
       return;
     }
 
@@ -527,18 +537,19 @@ var gPluginHandler = {
 
     return centerActions;
   },
 
   _setPermissionForPlugins: function PH_setPermissionForPlugins(aBrowser, aPermission, aPluginList) {
     let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
     for (let plugin of aPluginList) {
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-      if (gPluginHandler.canActivatePlugin(objLoadingContent) &&
-          objLoadingContent.actualType) {
+      // canActivatePlugin will return false if this isn't a known plugin type,
+      // so the pluginHost.getPermissionStringForType call is protected
+      if (gPluginHandler.canActivatePlugin(objLoadingContent)) {
         let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
         Services.perms.add(aBrowser.currentURI, permissionString, aPermission);
       }
     }
   },
 
   _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser) {
     aBrowser._clickToPlayDoorhangerShown = true;
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -269,16 +269,17 @@ endif
                  browser_aboutSyncProgress.js \
                  browser_middleMouse_inherit.js \
                  redirect_bug623155.sjs \
                  browser_tabDrop.js \
                  browser_lastAccessedTab.js \
                  browser_bug734076.js \
                  browser_bug812562.js \
                  browser_bug818009.js \
+                 browser_bug818118.js \
                  blockPluginVulnerableUpdatable.xml \
                  blockPluginVulnerableNoUpdate.xml \
                  blockNoPlugins.xml \
                  browser_utilityOverlay.js \
                  browser_social.js \
                  browser_social_toolbar.js \
                  browser_social_shareButton.js \
                  browser_social_sidebar.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug818118.js
@@ -0,0 +1,41 @@
+var gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
+var gTestBrowser = null;
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+function test() {
+  waitForExplicitFinish();
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("plugins.click_to_play");
+    gTestBrowser.removeEventListener("load", pageLoad, true);
+  });
+
+  Services.prefs.setBoolPref("plugins.click_to_play", true);
+  gBrowser.selectedTab = gBrowser.addTab();
+  gTestBrowser = gBrowser.selectedBrowser;
+  gTestBrowser.addEventListener("load", pageLoad, true);
+  gTestBrowser.contentWindow.location = gHttpTestRoot + "plugin_both.html";
+}
+
+function pageLoad(aEvent) {
+  // The plugin events are async dispatched and can come after the load event
+  // This just allows the events to fire before we then go on to test the states
+  executeSoon(actualTest);
+}
+
+function actualTest() {
+  var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(popupNotification, "should have a click-to-play notification");
+  var plugin = gTestBrowser.contentDocument.getElementById("test");
+  ok(plugin, "should have known plugin in page");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
+  ok(!objLoadingContent.activated, "plugin should not be activated");
+
+  var unknown = gTestBrowser.contentDocument.getElementById("unknown");
+  ok(unknown, "should have unknown plugin in page");
+
+  gBrowser.removeCurrentTab();
+  window.focus();
+  finish();
+}