Bug 1192927 - Remove plugins specific code and initialize the flash plugin row in Page Info and support flash in Site Identity. r?johannh,felipe draft
authorPrathiksha <prathikshaprasadsuman@gmail.com>
Sun, 18 Feb 2018 00:20:11 +0530
changeset 762534 3f2cc7493231975ef36503bd4f04c9efcf740846
parent 761894 426ef843d356879b3d1079d0ea7d867ff5a71b8c
push id101202
push userbmo:prathikshaprasadsuman@gmail.com
push dateFri, 02 Mar 2018 17:27:34 +0000
reviewersjohannh, felipe
bugs1192927
milestone60.0a1
Bug 1192927 - Remove plugins specific code and initialize the flash plugin row in Page Info and support flash in Site Identity. r?johannh,felipe MozReview-Commit-ID: 7CLfN4Io0ez
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/pageinfo/pageInfo.xul
browser/base/content/pageinfo/permissions.js
browser/base/content/test/plugins/browser.ini
browser/base/content/test/plugins/browser_pageInfo_plugins.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/browser.properties
browser/locales/en-US/chrome/browser/pageInfo.dtd
browser/locales/en-US/chrome/browser/sitePermissions.properties
browser/modules/SitePermissions.jsm
browser/modules/test/unit/test_SitePermissions.js
browser/themes/shared/notification-icons.inc.css
testing/runtimes/mochitest-browser-chrome-e10s.runtimes.json
testing/runtimes/mochitest-browser-chrome.runtimes.json
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -8056,24 +8056,29 @@ var gIdentityHandler = {
   },
 
   _createPermissionItem(aPermission) {
     let container = document.createElement("hbox");
     container.setAttribute("class", "identity-popup-permission-item");
     container.setAttribute("align", "center");
 
     let img = document.createElement("image");
-    let classes = "identity-popup-permission-icon " + aPermission.id + "-icon";
+    img.classList.add("identity-popup-permission-icon");
+    if (aPermission.id == "plugin:flash") {
+      img.classList.add("plugin-icon");
+    } else {
+      img.classList.add(aPermission.id + "-icon");
+    }
     if (aPermission.state == SitePermissions.BLOCK)
-      classes += " blocked-permission-icon";
+      img.classList.add("blocked-permission-icon");
 
     if (aPermission.sharingState == Ci.nsIMediaManagerService.STATE_CAPTURE_ENABLED ||
        (aPermission.id == "screen" && aPermission.sharingState &&
         !aPermission.sharingState.includes("Paused"))) {
-      classes += " in-use";
+      img.classList.add("in-use");
 
       // Synchronize control center and identity block blinking animations.
       window.promiseDocumentFlushed(() => {}).then(() => {
         let sharingIconBlink = document.getElementById("sharing-icon").getAnimations()[0];
         if (sharingIconBlink) {
           let startTime = sharingIconBlink.startTime;
           window.requestAnimationFrame(() => {
             // TODO(Bug 1440607): This could cause a style flush, but putting
@@ -8081,17 +8086,16 @@ var gIdentityHandler = {
             let imgBlink = img.getAnimations()[0];
             if (imgBlink) {
               imgBlink.startTime = startTime;
             }
           });
         }
       });
     }
-    img.setAttribute("class", classes);
 
     let nameLabel = document.createElement("label");
     nameLabel.setAttribute("flex", "1");
     nameLabel.setAttribute("class", "identity-popup-permission-label");
     nameLabel.textContent = SitePermissions.getPermissionLabel(aPermission.id);
 
     let isPolicyPermission = aPermission.scope == SitePermissions.SCOPE_POLICY;
 
@@ -8143,17 +8147,17 @@ var gIdentityHandler = {
     stateLabel.setAttribute("class", "identity-popup-permission-state-label");
     let {state, scope} = aPermission;
     // If the user did not permanently allow this device but it is currently
     // used, set the variables to display a "temporarily allowed" info.
     if (state != SitePermissions.ALLOW && aPermission.sharingState) {
       state = SitePermissions.ALLOW;
       scope = SitePermissions.SCOPE_REQUEST;
     }
-    stateLabel.textContent = SitePermissions.getCurrentStateLabel(state, scope);
+    stateLabel.textContent = SitePermissions.getCurrentStateLabel(state, aPermission.id, scope);
 
     container.appendChild(img);
     container.appendChild(nameLabel);
     container.appendChild(stateLabel);
 
     /* We return the permission item here without a remove button if the permission is a
        SCOPE_POLICY permission. Policy permissions cannot be removed/changed for the duration
        of the browser session. */
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -811,16 +811,18 @@
                   <image data-permission-id="screen" class="blocked-permission-icon screen-icon" role="button"
                          tooltiptext="&urlbar.screenBlocked.tooltip;"/>
                   <image data-permission-id="persistent-storage" class="blocked-permission-icon persistent-storage-icon" role="button"
                          tooltiptext="&urlbar.persistentStorageBlocked.tooltip;"/>
                   <image data-permission-id="popup" class="blocked-permission-icon popup-icon" role="button"
                          tooltiptext="&urlbar.popupBlocked.tooltip;"/>
                   <image data-permission-id="canvas" class="blocked-permission-icon canvas-icon" role="button"
                          tooltiptext="&urlbar.canvasBlocked.tooltip;"/>
+                  <image data-permission-id="plugin:flash" class="blocked-permission-icon plugin-icon" role="button"
+                         tooltiptext="&urlbar.flashPluginBlocked.tooltip;"/>
                   <image data-permission-id="midi" class="blocked-permission-icon midi-icon" role="button"
                          tooltiptext="&urlbar.midiBlocked.tooltip;"/>
                 </box>
                 <box id="notification-popup-box"
                      hidden="true"
                      onmouseover="document.getElementById('identity-box').classList.add('no-hover');"
                      onmouseout="document.getElementById('identity-box').classList.remove('no-hover');"
                      align="center">
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -40,20 +40,16 @@
     <stringbundle id="browserBundle" src="chrome://browser/locale/browser.properties"/>
   </stringbundleset>
 
   <commandset id="pageInfoCommandSet">
     <command id="cmd_close"     oncommand="window.close();"/>
     <command id="cmd_help"      oncommand="doHelpButton();"/>
     <command id="cmd_copy"      oncommand="doCopy();"/>
     <command id="cmd_selectall" oncommand="doSelectAll();"/>
-
-    <!-- permissions tab -->
-    <command id="cmd_pluginsDef"    oncommand="onCheckboxClick('plugins');"/>
-    <command id="cmd_pluginsToggle" oncommand="onPluginRadioClick(event);"/>
   </commandset>
 
   <keyset id="pageInfoKeySet">
     <key key="&closeWindow.key;" modifiers="accel" command="cmd_close"/>
     <key keycode="VK_ESCAPE"                       command="cmd_close"/>
 #ifdef XP_MACOSX
     <key key="."                 modifiers="meta"  command="cmd_close"/>
 #else
@@ -273,33 +269,17 @@
     <!-- Permissions -->
     <vbox id="permPanel">
       <hbox id="permHostBox">
         <label value="&permissionsFor;" control="hostText" />
         <textbox id="hostText" class="header" readonly="true"
                  crop="end" flex="1"/>
       </hbox>
 
-      <vbox id="permList" flex="1">
-        <vbox class="permission" id="perm-plugins-row">
-          <label class="permissionLabel" id="permPluginsLabel"
-                 value="&permPlugins;" control="pluginsRadioGroup"/>
-          <hbox id="permPluginTemplate" role="group" aria-labelledby="permPluginsLabel" align="baseline">
-            <label class="permPluginTemplateLabel"/>
-            <spacer flex="1"/>
-            <radiogroup class="permPluginTemplateRadioGroup" orient="horizontal" command="cmd_pluginsToggle">
-              <radio class="permPluginTemplateRadioDefault" label="&permUseDefault;"/>
-              <radio class="permPluginTemplateRadioAsk" label="&permAskAlways;"/>
-              <radio class="permPluginTemplateRadioAllow" label="&permAllow;"/>
-              <radio class="permPluginTemplateRadioHide" label="&permHide;"/>
-              <radio class="permPluginTemplateRadioBlock" label="&permBlock;"/>
-            </radiogroup>
-          </hbox>
-        </vbox>
-      </vbox>
+      <vbox id="permList" flex="1"/>
       <hbox pack="end">
         <button command="cmd_help" label="&helpButton.label;" dlgtype="help"/>
       </hbox>
     </vbox>
 
     <!-- Security & Privacy -->
     <vbox id="securityPanel">
       <!-- Identity Section -->
--- a/browser/base/content/pageinfo/permissions.js
+++ b/browser/base/content/pageinfo/permissions.js
@@ -12,27 +12,23 @@ var gPermPrincipal;
 var gUsageRequest;
 
 // Array of permissionIDs sorted alphabetically by label.
 var gPermissions = SitePermissions.listPermissions().sort((a, b) => {
   let firstLabel = SitePermissions.getPermissionLabel(a);
   let secondLabel = SitePermissions.getPermissionLabel(b);
   return firstLabel.localeCompare(secondLabel);
 });
-gPermissions.push("plugins");
 
 var permissionObserver = {
   observe(aSubject, aTopic, aData) {
     if (aTopic == "perm-changed") {
       var permission = aSubject.QueryInterface(Ci.nsIPermission);
-      if (permission.matchesURI(gPermURI, true)) {
-        if (gPermissions.indexOf(permission.type) > -1)
+      if (permission.matchesURI(gPermURI, true) && gPermissions.includes(permission.type)) {
           initRow(permission.type);
-        else if (permission.type.startsWith("plugin"))
-          setPluginsRadioState();
       }
     }
   }
 };
 
 function onLoadPermission(uri, principal) {
   var permTab = document.getElementById("permTab");
   if (SitePermissions.isSupportedURI(uri)) {
@@ -55,28 +51,28 @@ function onUnloadPermission() {
 
   if (gUsageRequest) {
     gUsageRequest.cancel();
     gUsageRequest = null;
   }
 }
 
 function initRow(aPartId) {
-  if (aPartId == "plugins") {
-    initPluginsRow();
-    return;
-  }
-
   createRow(aPartId);
 
   var checkbox = document.getElementById(aPartId + "Def");
   var command  = document.getElementById("cmd_" + aPartId + "Toggle");
   var {state, scope} = SitePermissions.get(gPermURI, aPartId);
   let defaultState = SitePermissions.getDefault(aPartId);
 
+  // When flash permission state is "Hide", we show it as "Always Ask" in page info.
+  if (aPartId.startsWith("plugin") && state == SitePermissions.PROMPT_HIDE) {
+    defaultState == SitePermissions.UNKNOWN ? state = defaultState : state = SitePermissions.PROMPT;
+  }
+
   if (state != defaultState) {
     checkbox.checked = false;
     command.removeAttribute("disabled");
   } else {
     checkbox.checked = true;
     command.setAttribute("disabled", "true");
   }
 
@@ -153,112 +149,21 @@ function onCheckboxClick(aPartId) {
     var perm = SitePermissions.getDefault(aPartId);
     setRadioState(aPartId, perm);
   } else {
     onRadioClick(aPartId);
     command.removeAttribute("disabled");
   }
 }
 
-function onPluginRadioClick(aEvent) {
-  onRadioClick(aEvent.originalTarget.getAttribute("id").split("#")[0]);
-}
-
 function onRadioClick(aPartId) {
   var radioGroup = document.getElementById(aPartId + "RadioGroup");
   var id = radioGroup.selectedItem.id;
   var permission = parseInt(id.split("#")[1]);
   SitePermissions.set(gPermURI, aPartId, permission);
 }
 
 function setRadioState(aPartId, aValue) {
   var radio = document.getElementById(aPartId + "#" + aValue);
   if (radio) {
     radio.radioGroup.selectedItem = radio;
   }
 }
-
-function fillInPluginPermissionTemplate(aPluginName, aPermissionString) {
-  let permPluginTemplate = document.getElementById("permPluginTemplate").cloneNode(true);
-  permPluginTemplate.setAttribute("permString", aPermissionString);
-  let attrs = [
-    [ ".permPluginTemplateLabel", "value", aPluginName ],
-    [ ".permPluginTemplateRadioGroup", "id", aPermissionString + "RadioGroup" ],
-    [ ".permPluginTemplateRadioDefault", "id", aPermissionString + "#0" ],
-    [ ".permPluginTemplateRadioAsk", "id", aPermissionString + "#3" ],
-    [ ".permPluginTemplateRadioAllow", "id", aPermissionString + "#1" ],
-    // #8 comes from Ci.nsIObjectLoadingContent.PLUGIN_PERMISSION_PROMPT_ACTION_QUIET
-    [ ".permPluginTemplateRadioHide", "id", aPermissionString + "#8"],
-    [ ".permPluginTemplateRadioBlock", "id", aPermissionString + "#2" ]
-  ];
-
-  for (let attr of attrs) {
-    permPluginTemplate.querySelector(attr[0]).setAttribute(attr[1], attr[2]);
-  }
-
-  return permPluginTemplate;
-}
-
-function clearPluginPermissionTemplate() {
-  let permPluginTemplate = document.getElementById("permPluginTemplate");
-  permPluginTemplate.hidden = true;
-  permPluginTemplate.removeAttribute("permString");
-  document.querySelector(".permPluginTemplateLabel").removeAttribute("value");
-  document.querySelector(".permPluginTemplateRadioGroup").removeAttribute("id");
-  document.querySelector(".permPluginTemplateRadioAsk").removeAttribute("id");
-  document.querySelector(".permPluginTemplateRadioAllow").removeAttribute("id");
-  document.querySelector(".permPluginTemplateRadioBlock").removeAttribute("id");
-}
-
-function initPluginsRow() {
-  let vulnerableLabel = document.getElementById("browserBundle").getString("pluginActivateVulnerable.label");
-  let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-
-  let permissionMap = new Map();
-
-  for (let plugin of pluginHost.getPluginTags()) {
-    if (plugin.disabled) {
-      continue;
-    }
-    for (let mimeType of plugin.getMimeTypes()) {
-      let permString = pluginHost.getPermissionStringForType(mimeType);
-      if (!permissionMap.has(permString)) {
-        let name = BrowserUtils.makeNicePluginName(plugin.name);
-        if (permString.startsWith("plugin-vulnerable:")) {
-          name += " \u2014 " + vulnerableLabel;
-        }
-        permissionMap.set(permString, name);
-      }
-    }
-  }
-
-  let entries = Array.from(permissionMap, item => ({ name: item[1], permission: item[0] }));
-
-  entries.sort(function(a, b) {
-    return a.name.localeCompare(b.name);
-  });
-
-  let permissionEntries = entries.map(p => fillInPluginPermissionTemplate(p.name, p.permission));
-
-  let permPluginsRow = document.getElementById("perm-plugins-row");
-  clearPluginPermissionTemplate();
-  if (permissionEntries.length < 1) {
-    permPluginsRow.hidden = true;
-    return;
-  }
-
-  for (let permissionEntry of permissionEntries) {
-    permPluginsRow.appendChild(permissionEntry);
-  }
-
-  setPluginsRadioState();
-}
-
-function setPluginsRadioState() {
-  let box = document.getElementById("perm-plugins-row");
-  for (let permissionEntry of box.childNodes) {
-    if (permissionEntry.hasAttribute("permString")) {
-      let permString = permissionEntry.getAttribute("permString");
-      let permission = SitePermissions.get(gPermURI, permString);
-      setRadioState(permString, permission.state);
-    }
-  }
-}
--- a/browser/base/content/test/plugins/browser.ini
+++ b/browser/base/content/test/plugins/browser.ini
@@ -91,13 +91,12 @@ tags = blocklist
 skip-if = !e10s
 tags = blocklist
 [browser_enable_DRM_prompt.js]
 [browser_private_browsing_eme_persistent_state.js]
 [browser_globalplugin_crashinfobar.js]
 skip-if = !crashreporter
 [browser_pluginCrashCommentAndURL.js]
 skip-if = !crashreporter
-[browser_pageInfo_plugins.js]
 [browser_pluginCrashReportNonDeterminism.js]
 skip-if = !crashreporter
 [browser_private_clicktoplay.js]
 [browser_subframe_access_hidden_plugins.js]
deleted file mode 100644
--- a/browser/base/content/test/plugins/browser_pageInfo_plugins.js
+++ /dev/null
@@ -1,187 +0,0 @@
-var gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
-var gPageInfo = null;
-var gNextTest = null;
-var gTestBrowser = null;
-var gPluginHost = Cc["@mozilla.org/plugin/host;1"]
-                    .getService(Ci.nsIPluginHost);
-var gTestPermissionString = gPluginHost.getPermissionStringForType("application/x-test");
-var gSecondTestPermissionString = gPluginHost.getPermissionStringForType("application/x-second-test");
-
-function doOnPageLoad(url, continuation) {
-  gNextTest = continuation;
-  BrowserTestUtils.browserLoaded(gTestBrowser).then(pageLoad);
-  gTestBrowser.loadURI(url);
-}
-
-function pageLoad() {
-  // 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(gNextTest);
-}
-
-function doOnOpenPageInfo(continuation) {
-  Services.obs.addObserver(pageInfoObserve, "page-info-dialog-loaded");
-  gNextTest = continuation;
-  // An explanation: it looks like the test harness complains about leaked
-  // windows if we don't keep a reference to every window we've opened.
-  // So, don't reuse pointers to opened Page Info windows - simply append
-  // to this list.
-  gPageInfo = BrowserPageInfo(null, "permTab");
-}
-
-function pageInfoObserve(win, topic, data) {
-  Services.obs.removeObserver(pageInfoObserve, "page-info-dialog-loaded");
-  gPageInfo.onFinished.push(() => executeSoon(gNextTest));
-}
-
-function finishTest() {
-  Services.perms.remove(makeURI("http://127.0.0.1:8888/"), gTestPermissionString);
-  Services.perms.remove(makeURI("http://127.0.0.1:8888/"), gSecondTestPermissionString);
-  Services.prefs.clearUserPref("plugins.click_to_play");
-  gBrowser.removeCurrentTab();
-
-  gPageInfo = null;
-  gNextTest = null;
-  gTestBrowser = null;
-  gPluginHost = null;
-
-  executeSoon(finish);
-}
-
-function test() {
-  waitForExplicitFinish();
-  Services.prefs.setBoolPref("plugins.click_to_play", true);
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in");
-  gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
-  gTestBrowser = gBrowser.selectedBrowser;
-  Services.perms.remove(makeURI("http://127.0.0.1:8888/"), gTestPermissionString);
-  Services.perms.remove(makeURI("http://127.0.0.1:8888/"), gSecondTestPermissionString);
-  doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart1a);
-}
-
-// The first test plugin is CtP and the second test plugin is enabled.
-function testPart1a() {
-  let testElement = gTestBrowser.contentDocumentAsCPOW.getElementById("test");
-  let objLoadingContent = testElement.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(!objLoadingContent.activated, "part 1a: Test plugin should not be activated");
-  let secondtest = gTestBrowser.contentDocumentAsCPOW.getElementById("secondtestA");
-  objLoadingContent = secondtest.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(objLoadingContent.activated, "part 1a: Second Test plugin should be activated");
-
-  doOnOpenPageInfo(testPart1b);
-}
-
-function testPart1b() {
-  let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
-  let testRadioDefault = gPageInfo.document.getElementById(gTestPermissionString + "#0");
-
-  is(testRadioGroup.selectedItem, testRadioDefault, "part 1b: Test radio group should be set to 'Default'");
-  let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1");
-  testRadioGroup.selectedItem = testRadioAllow;
-  testRadioAllow.doCommand();
-
-  let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
-  let secondtestRadioDefault = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0");
-  is(secondtestRadioGroup.selectedItem, secondtestRadioDefault, "part 1b: Second Test radio group should be set to 'Default'");
-  let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#3");
-  secondtestRadioGroup.selectedItem = secondtestRadioAsk;
-  secondtestRadioAsk.doCommand();
-
-  doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart2);
-}
-
-// Now, the Test plugin should be allowed, and the Test2 plugin should be CtP
-function testPart2() {
-  let testElement = gTestBrowser.contentDocumentAsCPOW.getElementById("test").
-    QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(testElement.activated, "part 2: Test plugin should be activated");
-
-  let secondtest = gTestBrowser.contentDocumentAsCPOW.getElementById("secondtestA").
-    QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(!secondtest.activated, "part 2: Second Test plugin should not be activated");
-  is(secondtest.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
-     "part 2: Second test plugin should be click-to-play.");
-
-  let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
-  let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1");
-  is(testRadioGroup.selectedItem, testRadioAllow, "part 2: Test radio group should be set to 'Allow'");
-  let testRadioBlock = gPageInfo.document.getElementById(gTestPermissionString + "#2");
-  testRadioGroup.selectedItem = testRadioBlock;
-  testRadioBlock.doCommand();
-
-  let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
-  let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#3");
-  is(secondtestRadioGroup.selectedItem, secondtestRadioAsk, "part 2: Second Test radio group should be set to 'Always Ask'");
-  let secondtestRadioBlock = gPageInfo.document.getElementById(gSecondTestPermissionString + "#2");
-  secondtestRadioGroup.selectedItem = secondtestRadioBlock;
-  secondtestRadioBlock.doCommand();
-
-  doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart3);
-}
-
-// Now, all the things should be blocked
-function testPart3() {
-  let testElement = gTestBrowser.contentDocumentAsCPOW.getElementById("test").
-    QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(!testElement.activated, "part 3: Test plugin should not be activated");
-  is(testElement.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED,
-    "part 3: Test plugin should be marked as PLUGIN_DISABLED");
-
-  let secondtest = gTestBrowser.contentDocumentAsCPOW.getElementById("secondtestA").
-    QueryInterface(Ci.nsIObjectLoadingContent);
-
-  ok(!secondtest.activated, "part 3: Second Test plugin should not be activated");
-  is(secondtest.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED,
-     "part 3: Second test plugin should be marked as PLUGIN_DISABLED");
-
-  // reset permissions
-  Services.perms.remove(makeURI("http://127.0.0.1:8888/"), gTestPermissionString);
-  Services.perms.remove(makeURI("http://127.0.0.1:8888/"), gSecondTestPermissionString);
-  // check that changing the permissions affects the radio state in the
-  // open Page Info window
-  let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
-  let testRadioDefault = gPageInfo.document.getElementById(gTestPermissionString + "#0");
-  is(testRadioGroup.selectedItem, testRadioDefault, "part 3: Test radio group should be set to 'Default'");
-  let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
-  let secondtestRadioDefault = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0");
-  is(secondtestRadioGroup.selectedItem, secondtestRadioDefault, "part 3: Second Test radio group should be set to 'Default'");
-
-  doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart4a);
-}
-
-// Now test that setting permission directly (as from the popup notification)
-// immediately influences Page Info.
-function testPart4a() {
-  // simulate "allow" from the doorhanger
-  Services.perms.add(gTestBrowser.currentURI, gTestPermissionString, Ci.nsIPermissionManager.ALLOW_ACTION);
-  Services.perms.add(gTestBrowser.currentURI, gSecondTestPermissionString, Ci.nsIPermissionManager.ALLOW_ACTION);
-
-  // check (again) that changing the permissions affects the radio state in the
-  // open Page Info window
-  let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
-  let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1");
-  is(testRadioGroup.selectedItem, testRadioAllow, "part 4a: Test radio group should be set to 'Allow'");
-  let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
-  let secondtestRadioAllow = gPageInfo.document.getElementById(gSecondTestPermissionString + "#1");
-  is(secondtestRadioGroup.selectedItem, secondtestRadioAllow, "part 4a: Second Test radio group should be set to 'Always Allow'");
-
-  // now close Page Info and see that it opens with the right settings
-  gPageInfo.close();
-  doOnOpenPageInfo(testPart4b);
-}
-
-// check that "always allow" resulted in the radio buttons getting set to allow
-function testPart4b() {
-  let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
-  let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1");
-  is(testRadioGroup.selectedItem, testRadioAllow, "part 4b: Test radio group should be set to 'Allow'");
-
-  let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
-  let secondtestRadioAllow = gPageInfo.document.getElementById(gSecondTestPermissionString + "#1");
-  is(secondtestRadioGroup.selectedItem, secondtestRadioAllow, "part 4b: Second Test radio group should be set to 'Allow'");
-
-  Services.prefs.setBoolPref("plugins.click_to_play", false);
-  gPageInfo.close();
-  finishTest();
-}
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -230,16 +230,17 @@ These should match what Safari and other
 <!ENTITY urlbar.cameraBlocked.tooltip            "You have blocked your camera for this website.">
 <!ENTITY urlbar.microphoneBlocked.tooltip        "You have blocked your microphone for this website.">
 <!ENTITY urlbar.screenBlocked.tooltip            "You have blocked this website from sharing your screen.">
 <!ENTITY urlbar.geolocationBlocked.tooltip       "You have blocked location information for this website.">
 <!ENTITY urlbar.webNotificationsBlocked.tooltip  "You have blocked notifications for this website.">
 <!ENTITY urlbar.persistentStorageBlocked.tooltip "You have blocked persistent storage for this website.">
 <!ENTITY urlbar.popupBlocked.tooltip             "You have blocked pop-ups for this website.">
 <!ENTITY urlbar.canvasBlocked.tooltip            "You have blocked canvas data extraction for this website.">
+<!ENTITY urlbar.flashPluginBlocked.tooltip       "You have blocked this website from using the Adobe Flash plugin.">
 <!ENTITY urlbar.midiBlocked.tooltip              "You have blocked MIDI access for this website.">
 
 <!ENTITY urlbar.openHistoryPopup.tooltip                "Show history">
 
 <!ENTITY searchItem.title             "Search">
 
 <!-- Toolbar items -->
 <!ENTITY homeButton.label             "Home">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -312,31 +312,20 @@ pluginActivationWarning.message=This sit
 
 pluginActivate.learnMore=Learn More…
 # LOCALIZATION NOTE (pluginActivateOutdated.message, pluginActivateOutdated.label):
 # These strings are used when an unsafe plugin has an update available.
 # %1$S is the plugin name, %2$S is the domain, and %3$S is brandShortName.
 pluginActivateOutdated.message=%3$S has prevented the outdated plugin “%1$S” from running on %2$S.
 pluginActivateOutdated.label=Outdated plugin
 pluginActivate.updateLabel=Update now…
-# LOCALIZATION NOTE (pluginActivateVulnerable.message, pluginActivateVulnerable.label):
-# These strings are used when an unsafe plugin has no update available.
+# LOCALIZATION NOTE (pluginActivateVulnerable.message):
+# This string is used when an unsafe plugin has no update available.
 # %1$S is the plugin name, %2$S is the domain, and %3$S is brandShortName.
 pluginActivateVulnerable.message=%3$S has prevented the unsafe plugin “%1$S” from running on %2$S.
-pluginActivateVulnerable.label=Vulnerable plugin!
-pluginActivate.riskLabel=What’s the risk?
-# LOCALIZATION NOTE (pluginActivateBlocked.message): %1$S is the plugin name, %2$S is brandShortName
-pluginActivateBlocked.message=%2$S has blocked “%1$S” for your protection.
-pluginActivateBlocked.label=Blocked for your protection
-pluginActivateDisabled.message=“%S” is disabled.
-pluginActivateDisabled.label=Disabled
-pluginActivateDisabled.manage=Manage plugins…
-pluginEnabled.message=“%S” is enabled on %S.
-pluginEnabledOutdated.message=Outdated plugin “%S” is enabled on %S.
-pluginEnabledVulnerable.message=Insecure plugin “%S” is enabled on %S.
 pluginInfo.unknownPlugin=Unknown
 
 # LOCALIZATION NOTE (pluginActivateNow.label, pluginActivateAlways.label, pluginBlockNow.label): These should be the same as the matching strings in browser.dtd
 # LOCALIZATION NOTE (pluginActivateNow.label): This button will enable the
 # plugin in the current session for an short time (about an hour), auto-renewed
 # if the site keeps using the plugin.
 pluginActivateNow.label=Allow Now
 pluginActivateNow.accesskey=N
--- a/browser/locales/en-US/chrome/browser/pageInfo.dtd
+++ b/browser/locales/en-US/chrome/browser/pageInfo.dtd
@@ -44,24 +44,17 @@
 <!ENTITY  mediaSaveAs2.accesskey "e">
 <!ENTITY  mediaPreview          "Media Preview:">
 
 <!ENTITY  feedTab               "Feeds">
 <!ENTITY  feedTab.accesskey     "F">
 
 <!ENTITY  permTab               "Permissions">
 <!ENTITY  permTab.accesskey     "P">
-<!ENTITY  permUseDefault        "Use Default">
-<!ENTITY  permAskAlways         "Always ask">
-<!ENTITY  permAllow             "Allow">
-<!ENTITY  permAllowSession      "Allow for Session">
-<!ENTITY  permHide              "Hide">
-<!ENTITY  permBlock             "Block">
 <!ENTITY  permissionsFor        "Permissions for:">
-<!ENTITY  permPlugins           "Activate Plugins">
 
 <!ENTITY  securityTab           "Security">
 <!ENTITY  securityTab.accesskey "S">
 <!ENTITY  securityView.certView "View Certificate">
 <!ENTITY  securityView.accesskey "V">
 <!ENTITY  securityView.unknown   "Unknown">
 
 
--- a/browser/locales/en-US/chrome/browser/sitePermissions.properties
+++ b/browser/locales/en-US/chrome/browser/sitePermissions.properties
@@ -1,25 +1,27 @@
 # 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/.
 
 # LOCALIZATION NOTE (state.current.allowed,
 #                    state.current.allowedForSession,
 #                    state.current.allowedTemporarily,
 #                    state.current.blockedTemporarily,
-#                    state.current.blocked):
+#                    state.current.blocked,
+#                    state.current.hide):
 # This label is used to display active permission states in the site
 # identity popup (which does not have a lot of screen space).
 state.current.allowed = Allowed
 state.current.allowedForSession = Allowed for Session
 state.current.allowedTemporarily = Allowed Temporarily
 state.current.blockedTemporarily = Blocked Temporarily
 state.current.blocked = Blocked
 state.current.prompt = Always Ask
+state.current.hide = Hide Prompt
 
 # LOCALIZATION NOTE (state.multichoice.alwaysAsk,
 #                    state.multichoice.allow,
 #                    state.multichoice.allowForSession,
 #                    state.multichoice.block):
 # Used to label permission state checkboxes in the page info dialog.
 state.multichoice.alwaysAsk = Always Ask
 state.multichoice.allow = Allow
@@ -34,10 +36,11 @@ permission.microphone.label = Use the Mi
 permission.screen.label = Share the Screen
 permission.install.label = Install Add-ons
 permission.popup.label = Open Pop-up Windows
 permission.geo.label = Access Your Location
 permission.shortcuts.label = Override Keyboard Shortcuts
 permission.focus-tab-by-prompt.label = Switch to this Tab
 permission.persistent-storage.label = Store Data in Persistent Storage
 permission.canvas.label = Extract Canvas Data
+permission.flash-plugin.label = Run Adobe Flash
 permission.midi.label = Access MIDI Devices
 permission.midi-sysex.label = Access MIDI Devices with SysEx Support
\ No newline at end of file
--- a/browser/modules/SitePermissions.jsm
+++ b/browser/modules/SitePermissions.jsm
@@ -133,21 +133,24 @@ const TemporaryBlockedPermissions = {
  * A module to manage permanent and temporary permissions
  * by URI and browser.
  *
  * Some methods have the side effect of dispatching a "PermissionStateChange"
  * event on changes to temporary permissions, as mentioned in the respective docs.
  */
 var SitePermissions = {
   // Permission states.
+  // PROMPT_HIDE state is only used to show the "Hide Prompt" state in the identity panel
+  // for the "plugin:flash" permission and not in pageinfo.
   UNKNOWN: Services.perms.UNKNOWN_ACTION,
   ALLOW: Services.perms.ALLOW_ACTION,
   BLOCK: Services.perms.DENY_ACTION,
   PROMPT: Services.perms.PROMPT_ACTION,
   ALLOW_COOKIES_FOR_SESSION: Ci.nsICookiePermission.ACCESS_SESSION,
+  PROMPT_HIDE: Ci.nsIObjectLoadingContent.PLUGIN_PERMISSION_PROMPT_ACTION_QUIET,
 
   // Permission scopes.
   SCOPE_REQUEST: "{SitePermissions.SCOPE_REQUEST}",
   SCOPE_TEMPORARY: "{SitePermissions.SCOPE_TEMPORARY}",
   SCOPE_SESSION: "{SitePermissions.SCOPE_SESSION}",
   SCOPE_PERSISTENT: "{SitePermissions.SCOPE_PERSISTENT}",
   SCOPE_POLICY: "{SitePermissions.SCOPE_POLICY}",
 
@@ -533,23 +536,31 @@ var SitePermissions = {
     }
   },
 
   /**
    * Returns the localized label for a permission's current state.
    *
    * @param {SitePermissions state} state
    *        The state to get the label for.
+   * @param {string} id
+   *        The permission to get the state label for.
    * @param {SitePermissions scope} scope (optional)
    *        The scope to get the label for.
    *
    * @return {String|null} the localized label or null if an
    *         unknown state was passed.
    */
-  getCurrentStateLabel(state, scope = null) {
+  getCurrentStateLabel(state, id, scope = null) {
+    // We try to avoid a collision between SitePermissions.PROMPT_HIDE
+    // and SitePermissions.ALLOW_COOKIES_FOR_SESSION which share the same const value.
+    if (id.startsWith("plugin") && state == SitePermissions.PROMPT_HIDE) {
+      return gStringBundle.GetStringFromName("state.current.hide");
+    }
+
     switch (state) {
       case this.PROMPT:
         return gStringBundle.GetStringFromName("state.current.prompt");
       case this.ALLOW:
         if (scope && scope != this.SCOPE_PERSISTENT && scope != this.SCOPE_POLICY)
           return gStringBundle.GetStringFromName("state.current.allowedTemporarily");
         return gStringBundle.GetStringFromName("state.current.allowed");
       case this.ALLOW_COOKIES_FOR_SESSION:
@@ -580,16 +591,18 @@ var gPermissionObject = {
    *
    *  - labelID
    *    Use the given ID instead of the permission name for looking up strings.
    *    e.g. "desktop-notification2" to use permission.desktop-notification2.label
    *
    *  - states
    *    Array of permission states to be exposed to the user.
    *    Defaults to ALLOW, BLOCK and the default state (see getDefault).
+   *    The PROMPT_HIDE state is deliberately excluded from "plugin:flash" since we
+   *    don't want to expose a "Hide Prompt" button to the user through pageinfo.
    */
 
   "image": {
     states: [ SitePermissions.ALLOW, SitePermissions.BLOCK ],
   },
 
   "cookie": {
     states: [ SitePermissions.ALLOW, SitePermissions.ALLOW_COOKIES_FOR_SESSION, SitePermissions.BLOCK ],
@@ -652,16 +665,21 @@ var gPermissionObject = {
 
   "shortcuts": {
     states: [ SitePermissions.ALLOW, SitePermissions.BLOCK ],
   },
 
   "canvas": {
   },
 
+  "plugin:flash": {
+    labelID: "flash-plugin",
+    states: [ SitePermissions.UNKNOWN, SitePermissions.ALLOW, SitePermissions.BLOCK ],
+  },
+
   "midi": {
     exactHostMatch: true
   },
 
   "midi-sysex": {
     exactHostMatch: true
   }
 };
--- a/browser/modules/test/unit/test_SitePermissions.js
+++ b/browser/modules/test/unit/test_SitePermissions.js
@@ -7,17 +7,17 @@ ChromeUtils.import("resource:///modules/
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 const STORAGE_MANAGER_ENABLED = Services.prefs.getBoolPref("browser.storageManager.enabled");
 const RESIST_FINGERPRINTING_ENABLED = Services.prefs.getBoolPref("privacy.resistFingerprinting");
 const MIDI_ENABLED = Services.prefs.getBoolPref("dom.webmidi.enabled");
 
 add_task(async function testPermissionsListing() {
   let expectedPermissions = ["camera", "cookie", "desktop-notification", "focus-tab-by-prompt",
-     "geo", "image", "install", "microphone", "popup", "screen", "shortcuts"];
+     "geo", "image", "install", "microphone", "plugin:flash", "popup", "screen", "shortcuts"];
   if (STORAGE_MANAGER_ENABLED) {
     // The persistent-storage permission is still only pref-on on Nightly
     // so we add it only when it's pref-on.
     // Should remove this checking and add it as default after it is fully pref-on.
     expectedPermissions.push("persistent-storage");
   }
   if (RESIST_FINGERPRINTING_ENABLED) {
     // Canvas permission should be hidden unless privacy.resistFingerprinting
@@ -126,17 +126,17 @@ add_task(async function testExactHostMat
     exactHostMatched.push("canvas");
   }
   if (MIDI_ENABLED) {
     // WebMIDI is only pref'd on in nightly.
     // Should remove this checking and add it as default after it is fully pref-on.
     exactHostMatched.push("midi");
     exactHostMatched.push("midi-sysex");
   }
-  let nonExactHostMatched = ["image", "cookie", "popup", "install", "shortcuts"];
+  let nonExactHostMatched = ["image", "cookie", "plugin:flash", "popup", "install", "shortcuts"];
 
   let permissions = SitePermissions.listPermissions();
   for (let permission of permissions) {
     SitePermissions.set(uri, permission, SitePermissions.ALLOW);
 
     if (exactHostMatched.includes(permission)) {
       // Check that the sub-origin does not inherit the permission from its parent.
       Assert.equal(SitePermissions.get(subUri, permission).state, SitePermissions.UNKNOWN,
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -234,19 +234,18 @@ html|*#webRTC-previewVideo {
 
 /* PLUGINS */
 
 .plugin-icon {
   list-style-image: url(chrome://mozapps/skin/plugins/plugin.svg);
   transition: fill 1.5s;
 }
 
-.plugin-blocked-icon {
+.plugin-icon.blocked-permission-icon {
   list-style-image: url(chrome://mozapps/skin/plugins/plugin-blocked.svg);
-  transition: fill 1.5s;
 }
 
 #plugin-icon-badge {
   list-style-image: url(chrome://browser/skin/notification-icons/plugin-badge.svg);
   opacity: 0;
   transition: opacity 1.5s;
 }
 
--- a/testing/runtimes/mochitest-browser-chrome-e10s.runtimes.json
+++ b/testing/runtimes/mochitest-browser-chrome-e10s.runtimes.json
@@ -163,17 +163,16 @@
     "browser/base/content/test/plugins/browser_CTP_drag_drop.js": 5737,
     "browser/base/content/test/plugins/browser_CTP_favorfallback.js": 4197,
     "browser/base/content/test/plugins/browser_CTP_notificationBar.js": 4022,
     "browser/base/content/test/plugins/browser_CTP_remove_navigate.js": 2812,
     "browser/base/content/test/plugins/browser_blocking.js": 8271,
     "browser/base/content/test/plugins/browser_blocklist_content.js": 3470,
     "browser/base/content/test/plugins/browser_clearplugindata.js": 2972,
     "browser/base/content/test/plugins/browser_iterate_hidden_plugins.js": 3683,
-    "browser/base/content/test/plugins/browser_pageInfo_plugins.js": 3850,
     "browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js": 4903,
     "browser/base/content/test/plugins/browser_pluginnotification.js": 10941,
     "browser/base/content/test/plugins/browser_plugins_added_dynamically.js": 2627,
     "browser/base/content/test/plugins/browser_private_browsing_eme_persistent_state.js": 4030,
     "browser/base/content/test/plugins/browser_private_clicktoplay.js": 7605,
     "browser/base/content/test/popupNotifications/browser_popupNotification.js": 2717,
     "browser/base/content/test/popupNotifications/browser_popupNotification_2.js": 5048,
     "browser/base/content/test/popupNotifications/browser_popupNotification_3.js": 4707,
--- a/testing/runtimes/mochitest-browser-chrome.runtimes.json
+++ b/testing/runtimes/mochitest-browser-chrome.runtimes.json
@@ -166,17 +166,16 @@
     "browser/base/content/test/plugins/browser_CTP_multi_allow.js": 2872,
     "browser/base/content/test/plugins/browser_CTP_notificationBar.js": 4215,
     "browser/base/content/test/plugins/browser_CTP_outsideScrollArea.js": 1716,
     "browser/base/content/test/plugins/browser_CTP_remove_navigate.js": 2099,
     "browser/base/content/test/plugins/browser_CTP_zoom.js": 2291,
     "browser/base/content/test/plugins/browser_blocking.js": 6301,
     "browser/base/content/test/plugins/browser_clearplugindata.js": 1970,
     "browser/base/content/test/plugins/browser_iterate_hidden_plugins.js": 2260,
-    "browser/base/content/test/plugins/browser_pageInfo_plugins.js": 2521,
     "browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js": 3550,
     "browser/base/content/test/plugins/browser_pluginCrashReportNonDeterminism.js": 3141,
     "browser/base/content/test/plugins/browser_pluginnotification.js": 8135,
     "browser/base/content/test/plugins/browser_plugins_added_dynamically.js": 2075,
     "browser/base/content/test/plugins/browser_private_browsing_eme_persistent_state.js": 3061,
     "browser/base/content/test/plugins/browser_private_clicktoplay.js": 5946,
     "browser/base/content/test/popupNotifications/browser_popupNotification.js": 2262,
     "browser/base/content/test/popupNotifications/browser_popupNotification_2.js": 5117,