Bug 1595647 - fix flash permissions so they get set for the toplevel page's principal instead of the subframe, r=mconley
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Mon, 18 Nov 2019 18:56:08 +0000
changeset 502453 57308405ef981e915faa3493c44207eb7a25cef7
parent 502452 a35dac1f4cf947996f3a6356b6b4e7200989d86a
child 502454 d8bdee06190fa6b2df2625dcfb3241c69ac1914b
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1595647, 1305232, 853855
milestone72.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 1595647 - fix flash permissions so they get set for the toplevel page's principal instead of the subframe, r=mconley This is the historical behaviour here (cf. bug 1305232, bug 853855). I accidentally broke it when I refactored this code for fission. This restores the "old" behaviour. Differential Revision: https://phabricator.services.mozilla.com/D53351
browser/actors/PluginParent.jsm
browser/base/content/test/plugins/browser.ini
browser/base/content/test/plugins/browser_plugin_framed_domain.js
--- a/browser/actors/PluginParent.jsm
+++ b/browser/actors/PluginParent.jsm
@@ -527,25 +527,31 @@ class PluginParent extends JSWindowActor
     let { id, fallbackType } = plugin;
     let pluginTag = PluginManager.getPluginTagById(id);
     if (!pluginTag) {
       return;
     }
     let permissionString = gPluginHost.getPermissionStringForTag(pluginTag);
     let active = fallbackType == PLUGIN_ACTIVE;
 
+    let { top } = this.browsingContext;
+    if (!top.currentWindowGlobal) {
+      return;
+    }
+    let principal = top.currentWindowGlobal.documentPrincipal;
+
     let options = {
       dismissed: !showNow,
       hideClose: true,
       persistent: showNow,
       eventCallback: this._clickToPlayNotificationEventCallback,
       showNow,
       popupIconClass: "plugin-icon",
       extraAttr: active ? "active" : "inactive",
-      principal: this.browsingContext.currentWindowGlobal.documentPrincipal,
+      principal,
     };
 
     let description;
     if (
       fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE
     ) {
       description = gNavigatorBundle.GetStringFromName(
         "flashActivate.outdated.message"
--- a/browser/base/content/test/plugins/browser.ini
+++ b/browser/base/content/test/plugins/browser.ini
@@ -80,16 +80,17 @@ tags = blocklist
 [browser_CTP_resize.js]
 tags = blocklist
 [browser_CTP_shouldShowOverlay.js]
 [browser_CTP_zoom.js]
 tags = blocklist
 [browser_blocking.js]
 tags = blocklist
 [browser_iterate_hidden_plugins.js]
+[browser_plugin_framed_domain.js]
 [browser_pluginnotification.js]
 tags = blocklist
 [browser_plugin_reloading.js]
 tags = blocklist
 [browser_blocklist_content.js]
 skip-if = !e10s
 tags = blocklist
 [browser_enable_DRM_prompt.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/plugins/browser_plugin_framed_domain.js
@@ -0,0 +1,60 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var rootDir = getRootDirectory(gTestPath);
+const gTestRoot = rootDir.replace(
+  "chrome://mochitests/content/",
+  "https://example.com/"
+);
+
+/**
+ * Verify that giving permission to a plugin works based on the toplevel
+ * page's principal, so that permissions meant for framed plugins persist
+ * correctly for the duration of the session.
+ */
+add_task(async function test_toplevel_frame_permission() {
+  await BrowserTestUtils.withNewTab(
+    gTestRoot + "empty_file.html",
+    async browser => {
+      // Add a cross-origin iframe and return when it's loaded.
+      await SpecialPowers.spawn(browser.browsingContext, [], async function() {
+        let doc = content.document;
+        let iframe = doc.createElement("iframe");
+        let loadPromise = ContentTaskUtils.waitForEvent(iframe, "load");
+        iframe.src = doc.location.href.replace(".com/", ".org/");
+        doc.body.appendChild(iframe);
+        // Note that we cannot return (rather than await) loadPromise, because
+        // it resolves with the event, which isn't structured-clonable.
+        await loadPromise;
+      });
+
+      // Show a plugin notification from the iframe's actor:
+      let { currentWindowGlobal } = browser.browsingContext.getChildren()[0];
+      let actor = currentWindowGlobal.getActor("Plugin");
+      const kHost = Cc["@mozilla.org/plugin/host;1"].getService(
+        Ci.nsIPluginHost
+      );
+      const { PLUGIN_CLICK_TO_PLAY } = Ci.nsIObjectLoadingContent;
+      let plugin = kHost.getPluginTags()[0];
+      actor.showClickToPlayNotification(
+        browser,
+        { id: plugin.id, fallbackType: PLUGIN_CLICK_TO_PLAY },
+        false /* showNow */
+      );
+
+      // Check that it is associated with the toplevel origin (.com), not
+      // the subframe's origin (.org):
+      let notification = PopupNotifications.getNotification(
+        "click-to-play-plugins",
+        browser
+      );
+      is(
+        notification.options.principal.URI.host,
+        "example.com",
+        "Should use top host for permission prompt!"
+      );
+    }
+  );
+});