Bug 1319771 - part2 : resume foreground window if it was still be blocked. draft
authorAlastor Wu <alwu@mozilla.com>
Fri, 03 Feb 2017 10:50:07 +0800
changeset 470015 d9396bbd37cb12bc62bacea395a3fa431dbeb03a
parent 470014 94ab6ad95ab63fc4c432ae0b30ca956156083427
child 544357 8aced6291652bad19846718ef1a09a85a2a7c6a6
push id43901
push useralwu@mozilla.com
push dateFri, 03 Feb 2017 02:48:33 +0000
bugs1319771
milestone54.0a1
Bug 1319771 - part2 : resume foreground window if it was still be blocked. In previous patch, we modify the behavior of nsDocument, now it would only resume window when document has active media components. However, it causes another issue. If the tab really goes to foreground, but there is no active media component, the tab would still be blocked and it won't be resumed anymore. Therefore, we need to resume it by ourself if the tab is on the foreground but doesn't be resumed yet. MozReview-Commit-ID: EdnQ7sRkSJK
dom/audiochannel/AudioChannelAgent.cpp
dom/audiochannel/AudioChannelService.cpp
dom/audiochannel/AudioChannelService.h
dom/base/nsDocument.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsPIDOMWindow.h
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -179,16 +179,19 @@ AudioChannelAgent::InitInternal(nsPIDOMW
   mAudioChannelType = aChannelType;
 
   if (aUseWeakRef) {
     mWeakCallback = do_GetWeakReference(aCallback);
   } else {
     mCallback = aCallback;
   }
 
+  RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
+  service->NotifyCreatedNewAgent(this);
+
   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
          ("AudioChannelAgent, InitInternal, this = %p, type = %d, "
           "owner = %p, hasCallback = %d\n", this, mAudioChannelType,
           mWindow.get(), (!!mCallback || !!mWeakCallback)));
 
   return NS_OK;
 }
 
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -289,16 +289,29 @@ AudioChannelService::AudioChannelService
                                "dom.audiochannel.audioCompeting");
 }
 
 AudioChannelService::~AudioChannelService()
 {
 }
 
 void
+AudioChannelService::NotifyCreatedNewAgent(AudioChannelAgent* aAgent)
+{
+  MOZ_ASSERT(aAgent);
+
+  nsCOMPtr<nsPIDOMWindowOuter> window = aAgent->Window();
+  if (!window) {
+    return;
+  }
+
+  window->NotifyCreatedNewMediaComponent();
+}
+
+void
 AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
                                                AudibleState aAudible)
 {
   MOZ_ASSERT(aAgent);
 
   uint64_t windowID = aAgent->WindowID();
   AudioChannelWindow* winData = GetWindowData(windowID);
   if (!winData) {
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -194,16 +194,18 @@ public:
   static void GetAudioChannelString(AudioChannel aChannel, nsAString& aString);
   static void GetDefaultAudioChannelString(nsAString& aString);
 
   void Notify(uint64_t aWindowID);
 
   void ChildStatusReceived(uint64_t aChildID, bool aTelephonyChannel,
                            bool aContentOrNormalChannel, bool aAnyChannel);
 
+  void NotifyCreatedNewAgent(AudioChannelAgent* aAgent);
+
 private:
   AudioChannelService();
   ~AudioChannelService();
 
   void RefreshAgents(nsPIDOMWindowOuter* aWindow,
                      std::function<void(AudioChannelAgent*)> aFunc);
 
   static void CreateServiceIfNeeded();
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -12075,20 +12075,17 @@ nsDocument::MaybeActiveMediaComponents()
     return;
   }
 
   if (!mWindow) {
     return;
   }
 
   mEverInForeground = true;
-  if (GetWindow()->GetMediaSuspend() == nsISuspendedTypes::SUSPENDED_BLOCK &&
-      AudioChannelService::IsServiceStarted()) {
-    GetWindow()->SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED);
-  }
+  GetWindow()->MaybeActiveMediaComponents();
 }
 
 NS_IMETHODIMP
 nsDocument::GetHidden(bool* aHidden)
 {
   *aHidden = Hidden();
   return NS_OK;
 }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4167,16 +4167,55 @@ nsPIDOMWindowInner::TimeoutManager()
 }
 
 bool
 nsPIDOMWindowInner::IsRunningTimeout()
 {
   return TimeoutManager().IsRunningTimeout();
 }
 
+void
+nsPIDOMWindowOuter::NotifyCreatedNewMediaComponent()
+{
+  if (mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) {
+    return;
+  }
+
+  // If the document is already on the foreground but the suspend state is still
+  // suspend-block, that means the media component was created after calling
+  // MaybeActiveMediaComponents, so the window's suspend state doesn't be
+  // changed yet. Therefore, we need to call it again, because the state is only
+  // changed after there exists alive media within the window.
+  MaybeActiveMediaComponents();
+}
+
+void
+nsPIDOMWindowOuter::MaybeActiveMediaComponents()
+{
+  if (IsInnerWindow()) {
+    return mOuterWindow->MaybeActiveMediaComponents();
+  }
+
+  nsCOMPtr<nsPIDOMWindowInner> inner = GetCurrentInnerWindow();
+  if (!inner) {
+    return;
+  }
+
+  nsCOMPtr<nsIDocument> doc = inner->GetExtantDoc();
+  if (!doc) {
+    return;
+  }
+
+  if (!doc->Hidden() &&
+      mMediaSuspend == nsISuspendedTypes::SUSPENDED_BLOCK &&
+      AudioChannelService::IsServiceStarted()) {
+    SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED);
+  }
+}
+
 SuspendTypes
 nsPIDOMWindowOuter::GetMediaSuspend() const
 {
   if (IsInnerWindow()) {
     return mOuterWindow->GetMediaSuspend();
   }
 
   return mMediaSuspend;
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -958,16 +958,19 @@ public:
   void SetMediaSuspend(SuspendTypes aSuspend);
 
   bool GetAudioMuted() const;
   void SetAudioMuted(bool aMuted);
 
   float GetAudioVolume() const;
   nsresult SetAudioVolume(float aVolume);
 
+  void NotifyCreatedNewMediaComponent();
+  void MaybeActiveMediaComponents();
+
   void SetServiceWorkersTestingEnabled(bool aEnabled);
   bool GetServiceWorkersTestingEnabled();
 
   float GetDevicePixelRatio(mozilla::dom::CallerType aCallerType);
 
   void SetLargeAllocStatus(mozilla::dom::LargeAllocStatus aStatus);
 };