Bug 1347791 - part3 : update block stauts to front-end side.
When the block stauts of the window was changed, we would notify front-end side
to update the vaule, so that we can save it for session restore.
MozReview-Commit-ID: FyclKmAxZHf
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -5076,17 +5076,17 @@
} else if (tab._overPlayingIcon) {
let stringID;
if (tab.selected) {
stringID = tab.linkedBrowser.audioMuted ?
"tabs.unmuteAudio.tooltip" :
"tabs.muteAudio.tooltip";
label = stringWithShortcut(stringID, "key_toggleMute");
} else {
- if (tab.linkedBrowser.audioBlocked) {
+ if (tab.hasAttribute("activemedia-blocked")) {
stringID = "tabs.unblockAudio.tooltip";
} else {
stringID = tab.linkedBrowser.audioMuted ?
"tabs.unmuteAudio.background.tooltip" :
"tabs.muteAudio.background.tooltip";
}
label = this.mStringBundle.getString(stringID);
@@ -7577,17 +7577,17 @@
return;
}
let tabContainer = this.parentNode;
let browser = this.linkedBrowser;
let modifiedAttrs = [];
let hist = Services.telemetry.getHistogramById("TAB_AUDIO_INDICATOR_USED");
- if (browser.audioBlocked) {
+ if (this.hasAttribute("activemedia-blocked")) {
this.removeAttribute("activemedia-blocked");
modifiedAttrs.push("activemedia-blocked");
browser.resumeMedia();
hist.add(3 /* unblockByClickingIcon */);
this.finishMediaBlockTimer();
} else {
if (browser.audioMuted) {
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -651,20 +651,16 @@ AudioChannelService::NotifyMediaResumedF
return;
}
AudioChannelWindow* winData = GetWindowData(topWindow->WindowID());
if (!winData) {
return;
}
- if (!winData->mShouldSendBlockStopEvent) {
- return;
- }
-
winData->NotifyMediaBlockStop(aWindow);
}
void
AudioChannelService::AudioChannelWindow::RequestAudioFocus(AudioChannelAgent* aAgent)
{
MOZ_ASSERT(aAgent);
@@ -855,32 +851,50 @@ AudioChannelService::AudioChannelWindow:
AudioAudibleChanged(aAgent,
AudibleState::eNotAudible,
AudibleChangedReasons::ePauseStateChanged);
}
void
AudioChannelService::AudioChannelWindow::NotifyMediaBlockStop(nsPIDOMWindowOuter* aWindow)
{
- mShouldSendBlockStopEvent = false;
// Can't use raw pointer for lamba variable capturing, use smart ptr.
nsCOMPtr<nsPIDOMWindowOuter> window = aWindow;
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"dom::AudioChannelService::AudioChannelWindow::NotifyMediaBlockStop",
[window]() -> void {
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (NS_WARN_IF(!observerService)) {
return;
}
observerService->NotifyObservers(ToSupports(window),
"audio-playback",
- u"blockStop");
- }));
+ u"mediaBlockStop");
+ })
+ );
+
+ if (mShouldSendActiveMediaBlockStopEvent) {
+ mShouldSendActiveMediaBlockStopEvent = false;
+ NS_DispatchToCurrentThread(NS_NewRunnableFunction(
+ "dom::AudioChannelService::AudioChannelWindow::NotifyMediaBlockStop",
+ [window]() -> void {
+ nsCOMPtr<nsIObserverService> observerService =
+ services::GetObserverService();
+ if (NS_WARN_IF(!observerService)) {
+ return;
+ }
+
+ observerService->NotifyObservers(ToSupports(window),
+ "audio-playback",
+ u"activeMediaBlockStop");
+ })
+ );
+ }
}
void
AudioChannelService::AudioChannelWindow::AppendAgentAndIncreaseAgentsNum(AudioChannelAgent* aAgent)
{
MOZ_ASSERT(aAgent);
MOZ_ASSERT(!mAgents.Contains(aAgent));
@@ -1032,29 +1046,29 @@ AudioChannelService::AudioChannelWindow:
return;
}
if (window->GetMediaSuspend() != nsISuspendedTypes::SUSPENDED_BLOCK ||
!doc->Hidden()) {
return;
}
- if (!mShouldSendBlockStopEvent) {
- mShouldSendBlockStopEvent = true;
+ if (!mShouldSendActiveMediaBlockStopEvent) {
+ mShouldSendActiveMediaBlockStopEvent = true;
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"dom::AudioChannelService::AudioChannelWindow::"
"MaybeNotifyMediaBlockStart",
[window]() -> void {
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (NS_WARN_IF(!observerService)) {
return;
}
observerService->NotifyObservers(
- ToSupports(window), "audio-playback", u"blockStart");
+ ToSupports(window), "audio-playback", u"activeMediaBlockStart");
}));
}
}
} // namespace dom
} // namespace mozilla
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -177,17 +177,17 @@ private:
class AudioChannelWindow final
{
public:
explicit AudioChannelWindow(uint64_t aWindowID)
: mWindowID(aWindowID)
, mIsAudioCaptured(false)
, mOwningAudioFocus(!AudioChannelService::IsEnableAudioCompeting())
- , mShouldSendBlockStopEvent(false)
+ , mShouldSendActiveMediaBlockStopEvent(false)
{}
void AudioFocusChanged(AudioChannelAgent* aNewPlayingAgent);
void AudioAudibleChanged(AudioChannelAgent* aAgent,
AudibleState aAudible,
AudibleChangedReasons aReason);
void AppendAgent(AudioChannelAgent* aAgent, AudibleState aAudible);
@@ -202,19 +202,20 @@ private:
// Raw pointer because the AudioChannelAgent must unregister itself.
nsTObserverArray<AudioChannelAgent*> mAgents;
nsTObserverArray<AudioChannelAgent*> mAudibleAgents;
// Owning audio focus when the window starts playing audible sound, and
// lose audio focus when other windows starts playing.
bool mOwningAudioFocus;
- // If we've dispatched "blockStart" event, we must dispatch another event
- // "blockStop" when the window is resumed from suspend-block.
- bool mShouldSendBlockStopEvent;
+ // If we've dispatched "activeMediaBlockStart" event, we must dispatch
+ // another event "activeMediablockStop" when the window is resumed from
+ // suspend-block.
+ bool mShouldSendActiveMediaBlockStopEvent;
private:
void AudioCapturedChanged(AudioChannelAgent* aAgent,
AudioCaptureState aCapture);
void AppendAudibleAgentIfNotContained(AudioChannelAgent* aAgent,
AudibleChangedReasons aReason);
void RemoveAudibleAgentIfContained(AudioChannelAgent* aAgent,
AudibleChangedReasons aReason);
--- a/toolkit/content/browser-content.js
+++ b/toolkit/content/browser-content.js
@@ -1017,20 +1017,22 @@ var AudioPlaybackListener = {
break;
}
},
observe(subject, topic, data) {
if (topic === "audio-playback") {
if (subject && subject.top == global.content) {
let name = "AudioPlayback:";
- if (data === "blockStart") {
- name += "BlockStart";
- } else if (data === "blockStop") {
- name += "BlockStop";
+ if (data === "activeMediaBlockStart") {
+ name += "ActiveMediaBlockStart";
+ } else if (data === "activeMediaBlockStop") {
+ name += "ActiveMediaBlockStop";
+ } else if (data == "mediaBlockStop") {
+ name += "MediaBlockStop";
} else {
name += (data === "active") ? "Start" : "Stop";
}
sendAsyncMessage(name);
}
}
},
--- a/toolkit/content/tests/browser/browser_mediaPlayback_suspended.js
+++ b/toolkit/content/tests/browser/browser_mediaPlayback_suspended.js
@@ -151,17 +151,18 @@ async function suspended_block(url, brow
info("- resume blocked audio -");
browser.resumeMedia();
await ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED,
check_audio_suspended);
}
add_task(async function setup_test_preference() {
await SpecialPowers.pushPrefEnv({"set": [
- ["media.useAudioChannelService.testing", true]
+ ["media.useAudioChannelService.testing", true],
+ ["media.block-autoplay-until-in-foreground", true]
]});
});
add_task(async function test_suspended_pause() {
await BrowserTestUtils.withNewTab({
gBrowser,
url: "about:blank"
}, suspended_pause.bind(this, PAGE));
--- a/toolkit/content/tests/browser/browser_mediaPlayback_suspended_multipleAudio.js
+++ b/toolkit/content/tests/browser/browser_mediaPlayback_suspended_multipleAudio.js
@@ -271,17 +271,18 @@ async function suspended_block(url, brow
info("- both audio should be resumed at the same time -");
browser.resumeMedia();
await ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED,
check_all_audio_suspended);
}
add_task(async function setup_test_preference() {
await SpecialPowers.pushPrefEnv({"set": [
- ["media.useAudioChannelService.testing", true]
+ ["media.useAudioChannelService.testing", true],
+ ["media.block-autoplay-until-in-foreground", true]
]});
});
add_task(async function test_suspended_pause() {
await BrowserTestUtils.withNewTab({
gBrowser,
url: "about:blank"
}, suspended_pause.bind(this, PAGE));
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -715,51 +715,80 @@
<![CDATA[
let event = document.createEvent("Events");
event.initEvent("DOMAudioPlaybackStopped", true, false);
this.dispatchEvent(event);
]]>
</body>
</method>
- <method name="audioPlaybackBlockStarted">
+ <!--
+ When the pref "media.block-autoplay-until-in-foreground" is on, all
+ windows would be blocked by default in gecko. The "block" means the
+ autoplay media can't be started in that tab unless the tab has been
+ visited or resumed by tab's play tab icon. Since the window is blocked
+ by default, there's no method to signal entering that state.
+ (1) If the window is resumed, no matter it has autoplay media or not
+ - will call mediaBlockStopped()
+ (2) If the window has blocked any autoplay media
+ - will call activeMediaBlockStarted()
+ (3) If the window has resumed any autoplay media
+ - will call activeMediaBlockStopped()
+ -->
+ <method name="activeMediaBlockStarted">
<body>
<![CDATA[
- this._audioBlocked = true;
+ this._hasAnyPlayingMediaBeenBlocked = true;
let event = document.createEvent("Events");
event.initEvent("DOMAudioPlaybackBlockStarted", true, false);
this.dispatchEvent(event);
]]>
</body>
</method>
- <method name="audioPlaybackBlockStopped">
+ <method name="activeMediaBlockStopped">
<body>
<![CDATA[
- if (!this._audioBlocked) {
+ if (!this._hasAnyPlayingMediaBeenBlocked) {
return;
}
- this._audioBlocked = false;
+ this._hasAnyPlayingMediaBeenBlocked = false;
let event = document.createEvent("Events");
event.initEvent("DOMAudioPlaybackBlockStopped", true, false);
this.dispatchEvent(event);
]]>
</body>
</method>
+ <method name="mediaBlockStopped">
+ <body>
+ <![CDATA[
+ this._mediaBlocked = false;
+ ]]>
+ </body>
+ </method>
+
<field name="_audioMuted">false</field>
<property name="audioMuted"
onget="return this._audioMuted;"
readonly="true"/>
+ <field name="_mediaBlocked">true</field>
+ <property name="mediaBlocked" readonly="true">
+ <getter>
+ <![CDATA[
+ if (this.mPrefs.getBoolPref("media.block-autoplay-until-in-foreground", true)) {
+ return this._mediaBlocked;
+ }
+ return false;
+ ]]>
+ </getter>
+ </property>
- <field name="_audioBlocked">false</field>
- <property name="audioBlocked"
- onget="return this._audioBlocked;"
- readonly="true"/>
+ <field name="_hasAnyPlayingMediaBeenBlocked">false</field>
<method name="mute">
<parameter name="transientState"/>
<body>
<![CDATA[
if (!transientState) {
this._audioMuted = true;
}
@@ -803,32 +832,38 @@
{type: "mediaControlStopped"});
]]>
</body>
</method>
<method name="blockMedia">
<body>
<![CDATA[
- this._audioBlocked = true;
+ if (!this.mPrefs.getBoolPref("media.block-autoplay-until-in-foreground", true)) {
+ return;
+ }
+ this._mediaBlocked = true;
this.messageManager.sendAsyncMessage("AudioPlayback",
{type: "blockInactivePageMedia"});
]]>
</body>
</method>
<method name="resumeMedia">
<body>
<![CDATA[
- this._audioBlocked = false;
+ this._mediaBlocked = false;
this.messageManager.sendAsyncMessage("AudioPlayback",
{type: "resumeMedia"});
- let event = document.createEvent("Events");
- event.initEvent("DOMAudioPlaybackBlockStopped", true, false);
- this.dispatchEvent(event);
+ if (this._hasAnyPlayingMediaBeenBlocked) {
+ this._hasAnyPlayingMediaBeenBlocked = false;
+ let event = document.createEvent("Events");
+ event.initEvent("DOMAudioPlaybackBlockStopped", true, false);
+ this.dispatchEvent(event);
+ }
]]>
</body>
</method>
<property name="securityUI">
<getter>
<![CDATA[
if (!this.docShell.securityUI) {
@@ -951,18 +986,19 @@
}
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:BlockStart", this);
- this.messageManager.addMessageListener("AudioPlayback:BlockStop", this);
+ this.messageManager.addMessageListener("AudioPlayback:ActiveMediaBlockStart", this);
+ this.messageManager.addMessageListener("AudioPlayback:ActiveMediaBlockStop", this);
+ this.messageManager.addMessageListener("AudioPlayback:MediaBlockStop", this);
if (this.hasAttribute("selectmenulist")) {
this.messageManager.addMessageListener("Forms:ShowDropDown", this);
this.messageManager.addMessageListener("Forms:HideDropDown", this);
}
}
]]>
@@ -1050,21 +1086,24 @@
this._autoScrollPopup.hidePopup();
break;
case "AudioPlayback:Start":
this.audioPlaybackStarted();
break;
case "AudioPlayback:Stop":
this.audioPlaybackStopped();
break;
- case "AudioPlayback:BlockStart":
- this.audioPlaybackBlockStarted();
+ case "AudioPlayback:ActiveMediaBlockStart":
+ this.activeMediaBlockStarted();
break;
- case "AudioPlayback:BlockStop":
- this.audioPlaybackBlockStopped();
+ case "AudioPlayback:ActiveMediaBlockStop":
+ this.activeMediaBlockStopped();
+ break;
+ case "AudioPlayback:MediaBlockStop":
+ this.mediaBlockStopped();
break;
case "Forms:ShowDropDown": {
if (!this._selectParentHelper) {
this._selectParentHelper =
Cu.import("resource://gre/modules/SelectParentHelper.jsm", {}).SelectParentHelper;
}
let menulist = document.getElementById(this.getAttribute("selectmenulist"));