Bug 1519430 - part2 : only resume AudioContext which is blocked by autoplay policy. r=padenot
authorAlastor Wu <alwu@mozilla.com>
Fri, 18 Jan 2019 18:23:58 +0000
changeset 514496 ebe7d324f3b2a546cb4745c6a6dfdca0b6a6ff11
parent 514495 737577f837bce6bb2460b0cadbf3143a66b65f44
child 514497 54a11c7a8f08d4468f2d0d15f22a43962c21a8e7
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1519430
milestone66.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 1519430 - part2 : only resume AudioContext which is blocked by autoplay policy. r=padenot We would only start the AudioContext blocked by our autoplay policy, won't resume AudioContext which is suspended explictly by page. Differential Revision: https://phabricator.services.mozilla.com/D16613
dom/media/webaudio/AudioContext.cpp
dom/media/webaudio/AudioContext.h
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -148,16 +148,17 @@ AudioContext::AudioContext(nsPIDOMWindow
       mNumberOfChannels(aNumberOfChannels),
       mIsOffline(aIsOffline),
       mIsStarted(!aIsOffline),
       mIsShutDown(false),
       mCloseCalled(false),
       mSuspendCalled(false),
       mIsDisconnecting(false),
       mWasAllowedToStart(true),
+      mSuspendedByContent(false),
       mWasEverAllowedToStart(false),
       mWasEverBlockedToStart(false),
       mWouldBeAllowedToStart(true) {
   bool mute = aWindow->AddAudioContext(this);
 
   // Note: AudioDestinationNode needs an AudioContext that must already be
   // bound to the window.
   const bool allowedToStart = AutoplayPolicy::IsAllowedToPlay(*this);
@@ -188,17 +189,21 @@ void AudioContext::StartBlockedAudioCont
   // Only try to start AudioContext when AudioContext was not allowed to start.
   if (mWasAllowedToStart) {
     return;
   }
 
   const bool isAllowedToPlay = AutoplayPolicy::IsAllowedToPlay(*this);
   AUTOPLAY_LOG("Trying to start AudioContext %p, IsAllowedToPlay=%d", this,
                isAllowedToPlay);
-  if (isAllowedToPlay) {
+
+  // Only start the AudioContext if this resume() call was initiated by content,
+  // not if it was a result of the AudioContext starting after having been
+  // blocked because of the auto-play policy.
+  if (isAllowedToPlay && !mSuspendedByContent) {
     ResumeInternal();
   } else {
     ReportBlocked();
   }
 }
 
 nsresult AudioContext::Init() {
   if (!mIsOffline) {
@@ -897,16 +902,17 @@ already_AddRefed<Promise> AudioContext::
     return promise.forget();
   }
 
   if (mAudioContextState == AudioContextState::Closed || mCloseCalled) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
+  mSuspendedByContent = true;
   mPromiseGripArray.AppendElement(promise);
   SuspendInternal(promise);
   return promise.forget();
 }
 
 void AudioContext::SuspendFromChrome() {
   // Not support suspend call for these situations.
   if (mAudioContextState == AudioContextState::Suspended || mIsOffline ||
@@ -955,16 +961,17 @@ already_AddRefed<Promise> AudioContext::
     return promise.forget();
   }
 
   if (mAudioContextState == AudioContextState::Closed || mCloseCalled) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
+  mSuspendedByContent = false;
   mPendingResumePromises.AppendElement(promise);
 
   const bool isAllowedToPlay = AutoplayPolicy::IsAllowedToPlay(*this);
   AUTOPLAY_LOG("Trying to resume AudioContext %p, IsAllowedToPlay=%d", this,
                isAllowedToPlay);
   if (isAllowedToPlay) {
     ResumeInternal();
   } else {
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -381,16 +381,19 @@ class AudioContext final : public DOMEve
   // Close has been called, reject suspend and resume call.
   bool mCloseCalled;
   // Suspend has been called with no following resume.
   bool mSuspendCalled;
   bool mIsDisconnecting;
   // This flag stores the value of previous status of `allowed-to-start`.
   bool mWasAllowedToStart;
 
+  // True if this AudioContext has been suspended by the page.
+  bool mSuspendedByContent;
+
   // These variables are used for telemetry, they're not reflect the actual
   // status of AudioContext, they are based on the "assumption" of enabling
   // blocking web audio. Because we want to record Telemetry no matter user
   // enable blocking autoplay or not.
   // - 'mWasEverAllowedToStart' would be true when AudioContext had ever been
   //   allowed to start if we enable blocking web audio.
   // - 'mWasEverBlockedToStart' would be true when AudioContext had ever been
   //   blocked to start if we enable blocking web audio.