Bug 1526044 - part2 : resume from Chrome should only take effect when the AudioContext was suspended from Chrome. r=padenot
authoralwu <alwu@mozilla.com>
Fri, 15 Feb 2019 14:41:46 +0000
changeset 459597 53830102bf765ff8d8fb28953bea2ab177d39d6d
parent 459596 506828839f9fd9d97ad06e2afa668604c415006d
child 459598 e4f973a6f8a06e7a9669faee23eb1c1799f6e860
push id35563
push userccoroiu@mozilla.com
push dateSat, 16 Feb 2019 09:36:04 +0000
treeherdermozilla-central@1cfd69d05aa1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1526044
milestone67.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 1526044 - part2 : resume from Chrome should only take effect when the AudioContext was suspended from Chrome. r=padenot If the AudioContext is suspended by content or by Autoplay policy, it shouldn't be resumed by chrome. Differential Revision: https://phabricator.services.mozilla.com/D19451
dom/media/webaudio/AudioContext.cpp
dom/media/webaudio/AudioContext.h
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -151,16 +151,17 @@ AudioContext::AudioContext(nsPIDOMWindow
       mIsOffline(aIsOffline),
       mIsStarted(!aIsOffline),
       mIsShutDown(false),
       mCloseCalled(false),
       mSuspendCalled(false),
       mIsDisconnecting(false),
       mWasAllowedToStart(true),
       mSuspendedByContent(false),
+      mSuspendedByChrome(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);
@@ -930,16 +931,17 @@ already_AddRefed<Promise> AudioContext::
 void AudioContext::SuspendFromChrome() {
   // Not support suspend call for these situations.
   if (mAudioContextState == AudioContextState::Suspended || mIsOffline ||
       (mAudioContextState == AudioContextState::Closed || mCloseCalled) ||
       mIsShutDown) {
     return;
   }
   SuspendInternal(nullptr);
+  mSuspendedByChrome = true;
 }
 
 void AudioContext::SuspendInternal(void* aPromise) {
   Destination()->Suspend();
 
   nsTArray<MediaStream*> streams;
   // If mSuspendCalled is true then we already suspended all our streams,
   // so don't suspend them again (since suspend(); suspend(); resume(); should
@@ -953,20 +955,21 @@ void AudioContext::SuspendInternal(void*
 
   mSuspendCalled = true;
 }
 
 void AudioContext::ResumeFromChrome() {
   // Not support resume call for these situations.
   if (mAudioContextState == AudioContextState::Running || mIsOffline ||
       (mAudioContextState == AudioContextState::Closed || mCloseCalled) ||
-      mIsShutDown) {
+      mIsShutDown || !mSuspendedByChrome) {
     return;
   }
   ResumeInternal();
+  mSuspendedByChrome = false;
 }
 
 already_AddRefed<Promise> AudioContext::Resume(ErrorResult& aRv) {
   nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject());
   RefPtr<Promise> promise;
   promise = Promise::Create(parentObject, aRv);
   if (aRv.Failed()) {
     return nullptr;
@@ -1011,16 +1014,20 @@ void AudioContext::ResumeInternal() {
   // be OK). But we still need to do ApplyAudioContextOperation
   // to ensure our new promise is resolved.
   if (mSuspendCalled) {
     streams = GetAllStreams();
   }
   Graph()->ApplyAudioContextOperation(DestinationStream(), streams,
                                       AudioContextOperation::Resume, nullptr);
   mSuspendCalled = false;
+  // AudioContext will be resumed later, so we have no need to keep the suspend
+  // flag from Chrome, in case to avoid to resume the suspended Audio Context
+  // which is requested by content.
+  mSuspendedByChrome = false;
 }
 
 void AudioContext::UpdateAutoplayAssumptionStatus() {
   if (AutoplayPolicy::WouldBeAllowedToPlayIfAutoplayDisabled(*this)) {
     mWasEverAllowedToStart |= true;
     mWouldBeAllowedToStart = true;
   } else {
     mWasEverBlockedToStart |= true;
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -383,16 +383,18 @@ class AudioContext final : public DOMEve
   // 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;
+  // True if this AudioContext has been suspended by the chrome.
+  bool mSuspendedByChrome;
 
   // 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