Bug 1778959 - Tweaks to PermissionUI to delegate gated site permissions request flows to synthetic SitePermsAddon install flow. r=permissions-reviewers,pbz
authornchevobbe <nchevobbe@mozilla.com>
Fri, 30 Sep 2022 22:07:19 +0000
changeset 636748 3913eb81b66817ab32bedc32a77f66a951320041
parent 636747 2f1a9eb03661ee7a529eb26fd8ec3e9d8f767e6f
child 636749 21a65ff1007c4de321095da30660c34a1b022e03
push id170482
push usernchevobbe@mozilla.com
push dateFri, 30 Sep 2022 22:10:01 +0000
treeherderautoland@1ef96ac13291 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspermissions-reviewers, pbz
bugs1778959
milestone107.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 1778959 - Tweaks to PermissionUI to delegate gated site permissions request flows to synthetic SitePermsAddon install flow. r=permissions-reviewers,pbz This patch includes a new `PermissionUI.SitePermsAddonInstallRequestPrototype` helper, it inherits from `PermissionPromptForRequestPrototype` and override the `prompt` method to trigger the synthetic `SitePermsAddon` install flow when a addon gated site permissions is requested (currently only "midi" and "midi-sysex"). The new `SitePermsAddonInstallRequestPrototype` helper is then set as the `__proto__` for the `MIDIPermissionPrompt.prototype`, which makes sure that every time the MIDI site permissions are being requested, the user is prompted to install a synthetic addon as part of the site permission request. When the `dom.sitepermsaddon-provider.enabled` pref is set to `false`, or when we're dealing with a `file` scheme, we fall back to `PermissionPromptForRequestPrototype.prompt`. Differential Revision: https://phabricator.services.mozilla.com/D151478
browser/modules/PermissionUI.jsm
browser/modules/test/browser/browser_PermissionUI_prompts.js
--- a/browser/modules/PermissionUI.jsm
+++ b/browser/modules/PermissionUI.jsm
@@ -62,16 +62,21 @@ var EXPORTED_SYMBOLS = ["PermissionUI"];
  * the caller having called into createPermissionPrompt.
  */
 const { XPCOMUtils } = ChromeUtils.importESModule(
   "resource://gre/modules/XPCOMUtils.sys.mjs"
 );
 const lazy = {};
 ChromeUtils.defineModuleGetter(
   lazy,
+  "AddonManager",
+  "resource://gre/modules/AddonManager.jsm"
+);
+ChromeUtils.defineModuleGetter(
+  lazy,
   "SitePermissions",
   "resource:///modules/SitePermissions.jsm"
 );
 ChromeUtils.defineModuleGetter(
   lazy,
   "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm"
 );
@@ -91,16 +96,26 @@ XPCOMUtils.defineLazyServiceGetter(
 );
 
 XPCOMUtils.defineLazyGetter(lazy, "gBrowserBundle", function() {
   return Services.strings.createBundle(
     "chrome://browser/locale/browser.properties"
   );
 });
 
+const { SITEPERMS_ADDON_PROVIDER_PREF } = ChromeUtils.importESModule(
+  "resource://gre/modules/addons/siteperms-addon-utils.sys.mjs"
+);
+XPCOMUtils.defineLazyPreferenceGetter(
+  lazy,
+  "sitePermsAddonsProviderEnabled",
+  SITEPERMS_ADDON_PROVIDER_PREF,
+  false
+);
+
 var PermissionUI = {};
 
 /**
  * PermissionPromptPrototype should be subclassed by callers that
  * want to display prompts to the user. See each method and property
  * below for guidance on what to override.
  *
  * Note that if you're creating a prompt for an
@@ -683,16 +698,51 @@ var PermissionPromptForRequestPrototype 
   allow(choices) {
     this.request.allow(choices);
   },
 };
 
 PermissionUI.PermissionPromptForRequestPrototype = PermissionPromptForRequestPrototype;
 
 /**
+ * A subclass of PermissionPromptForRequestPrototype that prompts
+ * for a Synthetic SitePermsAddon addon type and starts a synthetic
+ * addon install flow.
+ */
+var SitePermsAddonInstallRequestPrototype = {
+  __proto__: PermissionPromptForRequestPrototype,
+
+  prompt() {
+    // fallback to regular permission prompt for localhost,
+    // or when the SitePermsAddonProvider is not enabled.
+    if (this.principal.isLoopbackHost || !lazy.sitePermsAddonsProviderEnabled) {
+      PermissionPromptForRequestPrototype.prompt.call(this);
+      return;
+    }
+
+    // Otherwise, we'll use the addon install flow.
+    lazy.AddonManager.installSitePermsAddonFromWebpage(
+      this.browser,
+      this.principal,
+      this.permName
+    ).then(
+      () => {
+        this.allow();
+      },
+      err => {
+        Cu.reportError(err);
+        this.cancel();
+      }
+    );
+  },
+};
+
+PermissionUI.SitePermsAddonInstallRequestPrototype = SitePermsAddonInstallRequestPrototype;
+
+/**
  * Creates a PermissionPrompt for a nsIContentPermissionRequest for
  * the GeoLocation API.
  *
  * @param request (nsIContentPermissionRequest)
  *        The request for a permission from content.
  */
 function GeolocationPermissionPrompt(request) {
   this.request = request;
@@ -1169,18 +1219,17 @@ function MIDIPermissionPrompt(request) {
     perm.options.queryElementAt(0, Ci.nsISupportsString) == "sysex";
   this.permName = "midi";
   if (this.isSysexPerm) {
     this.permName = "midi-sysex";
   }
 }
 
 MIDIPermissionPrompt.prototype = {
-  __proto__: PermissionPromptForRequestPrototype,
-
+  __proto__: SitePermsAddonInstallRequestPrototype,
   get type() {
     return "midi";
   },
 
   get permissionKey() {
     return this.permName;
   },
 
--- a/browser/modules/test/browser/browser_PermissionUI_prompts.js
+++ b/browser/modules/test/browser/browser_PermissionUI_prompts.js
@@ -7,18 +7,18 @@
 "use strict";
 
 const { Integration } = ChromeUtils.importESModule(
   "resource://gre/modules/Integration.sys.mjs"
 );
 const { PermissionUI } = ChromeUtils.import(
   "resource:///modules/PermissionUI.jsm"
 );
-const { SitePermissions } = ChromeUtils.import(
-  "resource:///modules/SitePermissions.jsm"
+const { SITEPERMS_ADDON_PROVIDER_PREF } = ChromeUtils.importESModule(
+  "resource://gre/modules/addons/siteperms-addon-utils.sys.mjs"
 );
 
 // Tests that GeolocationPermissionPrompt works as expected
 add_task(async function test_geo_permission_prompt() {
   await testPrompt(PermissionUI.GeolocationPermissionPrompt);
 });
 
 // Tests that XRPermissionPrompt works as expected
@@ -45,16 +45,23 @@ add_task(async function test_desktop_not
 
 // Tests that PersistentStoragePermissionPrompt works as expected
 add_task(async function test_persistent_storage_permission_prompt() {
   await testPrompt(PermissionUI.PersistentStoragePermissionPrompt);
 });
 
 // Tests that MidiPrompt works as expected
 add_task(async function test_midi_permission_prompt() {
+  if (Services.prefs.getBoolPref(SITEPERMS_ADDON_PROVIDER_PREF, false)) {
+    ok(
+      true,
+      "PermissionUI.MIDIPermissionPrompt uses SitePermsAddon install flow"
+    );
+    return;
+  }
   await testPrompt(PermissionUI.MIDIPermissionPrompt);
 });
 
 // Tests that StoragePermissionPrompt works as expected
 add_task(async function test_storage_access_permission_prompt() {
   Services.prefs.setBoolPref("dom.storage_access.auto_grants", false);
   await testPrompt(PermissionUI.StorageAccessPermissionPrompt);
   Services.prefs.clearUserPref("dom.storage_access.auto_grants");