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
--- 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;