Bug 1477926 - Hide autoplay-media prompt on DOMAudioPlaybackAbortPermissionRequest. r?johannh draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 01 Aug 2018 16:10:48 +1200
changeset 826186 eb8ff7d45f82efa05bb4e55bfbef7b6ccedcf0c7
parent 826185 e0cba4a7248f9149eac60a371cc00a748ede7776
child 826187 3820a1540ef716ea284737be653c7b64d392dede
push id118257
push userbmo:cpearce@mozilla.com
push dateFri, 03 Aug 2018 04:44:24 +0000
reviewersjohannh
bugs1477926
milestone63.0a1
Bug 1477926 - Hide autoplay-media prompt on DOMAudioPlaybackAbortPermissionRequest. r?johannh Currently we're hiding the autoplay-media permission doorhanger when we detect playback in the tab via a DOMAudioPlaybackStarted event. However this only fires for audible playback in a tab; if a media element tries to play audibly, detects that it's blocked, and then switches to playing inaudibly, we'll be left still be showing the doorhanger even though it's not connected to anything. We also don't handle the case where there are multiple things waiting on the doorhanger and one of them is able to play audibly but others aren't; we'd hide the doorhanger without having a meaningful result to post to the other waiters. So the previous patch handled the above cases, and we now dispatch an observer service notification "audio-playback"/"abortPermissionRequest" when Gecko has stopped waiting on all pending "autoplay-media" requests. The front end code needs to hide the doorhanger upon receiving that instead of DOMAudioPlaybackStarted. MozReview-Commit-ID: 84RTfwtzjCv
browser/modules/PermissionUI.jsm
toolkit/content/browser-content.js
toolkit/content/widgets/browser.xml
--- a/browser/modules/PermissionUI.jsm
+++ b/browser/modules/PermissionUI.jsm
@@ -824,30 +824,30 @@ AutoplayPermissionPrompt.prototype = {
         accessKey: gBrowserBundle.GetStringFromName("autoplay.DontAllow.accesskey"),
         action: Ci.nsIPermissionManager.DENY_ACTION,
     }];
   },
 
   onAfterShow() {
     // Remove the event listener to prevent any leaks.
     this.browser.removeEventListener(
-      "DOMAudioPlaybackStarted", this.handlePlaybackStart);
+      "DOMAudioPlaybackAbortPermissionRequest", this.handlePlaybackStart);
   },
 
   onBeforeShow() {
     // Hide the prompt if the tab starts playing media.
     this.handlePlaybackStart = () => {
       let chromeWin = this.browser.ownerGlobal;
       if (!chromeWin.PopupNotifications) {
         return;
       }
       let notification = chromeWin.PopupNotifications.getNotification(
         this.notificationID, this.browser);
       if (notification) {
         chromeWin.PopupNotifications.remove(notification);
       }
     };
     this.browser.addEventListener(
-      "DOMAudioPlaybackStarted", this.handlePlaybackStart);
+      "DOMAudioPlaybackAbortPermissionRequest", this.handlePlaybackStart);
   },
 };
 
 PermissionUI.AutoplayPermissionPrompt = AutoplayPermissionPrompt;
--- a/toolkit/content/browser-content.js
+++ b/toolkit/content/browser-content.js
@@ -264,16 +264,18 @@ var AudioPlaybackListener = {
   observe(subject, topic, data) {
     if (topic === "audio-playback") {
       if (subject && subject.top == global.content) {
         let name = "AudioPlayback:";
         if (data === "activeMediaBlockStart") {
           name += "ActiveMediaBlockStart";
         } else if (data === "activeMediaBlockStop") {
           name += "ActiveMediaBlockStop";
+        } else if (data === "abortPermissionRequest") {
+          name += "AbortPermissionRequest";
         } else {
           name += (data === "active") ? "Start" : "Stop";
         }
         sendAsyncMessage(name);
       }
     }
   },
 
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -632,16 +632,26 @@
             this._hasAnyPlayingMediaBeenBlocked = false;
             let event = document.createEvent("Events");
             event.initEvent("DOMAudioPlaybackBlockStopped", true, false);
             this.dispatchEvent(event);
           ]]>
         </body>
       </method>
 
+      <method name="abortAutoplayMediaPermissionRequest">
+        <body>
+          <![CDATA[
+            let event = document.createEvent("Events");
+            event.initEvent("DOMAudioPlaybackAbortPermissionRequest", true, false);
+            this.dispatchEvent(event);
+          ]]>
+        </body>
+      </method>
+
       <field name="_audioMuted">false</field>
       <property name="audioMuted"
                 onget="return this._audioMuted;"
                 readonly="true"/>
 
       <field name="_hasAnyPlayingMediaBeenBlocked">false</field>
 
       <method name="mute">
@@ -848,16 +858,17 @@
           if (this.messageManager) {
             this.messageManager.addMessageListener("PopupBlocking:UpdateBlockedPopups", this);
             this.messageManager.addMessageListener("Autoscroll:Start", this);
             this.messageManager.addMessageListener("Autoscroll:Cancel", this);
             this.messageManager.addMessageListener("AudioPlayback:Start", this);
             this.messageManager.addMessageListener("AudioPlayback:Stop", this);
             this.messageManager.addMessageListener("AudioPlayback:ActiveMediaBlockStart", this);
             this.messageManager.addMessageListener("AudioPlayback:ActiveMediaBlockStop", this);
+            this.messageManager.addMessageListener("AudioPlayback:AbortPermissionRequest", this);
             this.messageManager.addMessageListener("UnselectedTabHover:Toggle", this);
             this.messageManager.addMessageListener("AudibleAutoplayMediaOccurred", this);
 
             if (this.hasAttribute("selectmenulist")) {
               this.messageManager.addMessageListener("Forms:ShowDropDown", this);
               this.messageManager.addMessageListener("Forms:HideDropDown", this);
             }
 
@@ -973,16 +984,19 @@
               this.audioPlaybackStopped();
               break;
             case "AudioPlayback:ActiveMediaBlockStart":
               this.activeMediaBlockStarted();
               break;
             case "AudioPlayback:ActiveMediaBlockStop":
               this.activeMediaBlockStopped();
               break;
+            case "AudioPlayback:AbortPermissionRequest":
+              this.abortAutoplayMediaPermissionRequest();
+              break;
             case "UnselectedTabHover:Toggle":
               this._shouldSendUnselectedTabHover = data.enable ?
                 ++this._unselectedTabHoverMessageListenerCount > 0 :
                 --this._unselectedTabHoverMessageListenerCount == 0;
               break;
             case "AudibleAutoplayMediaOccurred":
               this.notifyAudibleAutoplayMediaOccurred();
               break;