Bug 1192927 - Remove plugins specific code and initialize the flash plugin row in Page Info and support flash in Site Identity. r=Felipe,johannh
authorPrathiksha <prathikshaprasadsuman@gmail.com>
Sun, 18 Feb 2018 00:20:11 +0530
changeset 461425 2d3065417d04bec4d600f506d3e8169485314586
parent 461424 e48e3c46e0dae1e03f914bb661d7f3f9ffa56913
child 461426 5da62e6df5f36c7b3669f7f751d9af63c4697224
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFelipe, johannh
bugs1192927
milestone60.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 1192927 - Remove plugins specific code and initialize the flash plugin row in Page Info and support flash in Site Identity. r=Felipe,johannh 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
@@ -8067,37 +8067,41 @@ 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(() => {
         let sharingIconBlink = document.getElementById("sharing-icon").getAnimations()[0];
         let imgBlink = img.getAnimations()[0];
         return [sharingIconBlink, imgBlink];
       }).then(([sharingIconBlink, imgBlink]) => {
         if (sharingIconBlink && imgBlink) {
           imgBlink.startTime = sharingIconBlink.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;
 
@@ -8149,17 +8153,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
@@ -810,16 +810,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
@@ -44,20 +44,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
@@ -277,33 +273,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
@@ -313,31 +313,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,