Bug 1553328 - use browsing context to notify tab mute/unmute media. r=baku,farre
authorAlastor Wu <alwu@mozilla.com>
Wed, 22 May 2019 12:19:49 +0000
changeset 475002 7fc705ad4f94b72b04eaaaa93e5147c3d791f712
parent 475001 227b93441c8360a43e05c58402ccd27d3dd30e63
child 475003 6f891c10e2da60e2d5d33e1baa9d9fc7d2444350
push id113187
push userbtara@mozilla.com
push dateThu, 23 May 2019 04:45:24 +0000
treeherdermozilla-inbound@490fd8b22dea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku, farre
bugs1553328
milestone69.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 1553328 - use browsing context to notify tab mute/unmute media. r=baku,farre This bug will use the browsing context to notify content tab to mute/unmute media, instead of using MessageManager. We would use the top level canonical browsing context to set the media mute property for the top level window and propagate it to other top level windows in other processes. If we don't do so, we're not able to mute/unmute media in the different process when we we enable Fission, because the current way we use can only notify one process and would cause the media on other process can't be muted/unmuted. Differential Revision: https://phabricator.services.mozilla.com/D32077
docshell/base/CanonicalBrowsingContext.cpp
docshell/base/CanonicalBrowsingContext.h
dom/base/nsGlobalWindowOuter.cpp
dom/chrome-webidl/BrowsingContext.webidl
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/PContent.ipdl
toolkit/content/widgets/browser-custom-element.js
--- a/docshell/base/CanonicalBrowsingContext.cpp
+++ b/docshell/base/CanonicalBrowsingContext.cpp
@@ -173,16 +173,26 @@ void CanonicalBrowsingContext::NotifySta
   // Notfiy all content browsing contexts which are related with the canonical
   // browsing content tree to start delayed autoplay media.
 
   Group()->EachParent([&](ContentParent* aParent) {
     Unused << aParent->SendStartDelayedAutoplayMediaComponents(this);
   });
 }
 
+void CanonicalBrowsingContext::NotifyMediaMutedChanged(bool aMuted) {
+  nsPIDOMWindowOuter* window = GetDOMWindow();
+  if (window) {
+    window->SetAudioMuted(aMuted);
+  }
+  Group()->EachParent([&](ContentParent* aParent) {
+    Unused << aParent->SendSetMediaMuted(this, aMuted);
+  });
+}
+
 void CanonicalBrowsingContext::SetFieldEpochsForChild(
     ContentParent* aChild, const BrowsingContext::FieldEpochs& aEpochs) {
   mChildFieldEpochs.Put(aChild->ChildID(), aEpochs);
 }
 
 const BrowsingContext::FieldEpochs&
 CanonicalBrowsingContext::GetFieldEpochsForChild(ContentParent* aChild) {
   static const BrowsingContext::FieldEpochs sDefaultFieldEpochs;
--- a/docshell/base/CanonicalBrowsingContext.h
+++ b/docshell/base/CanonicalBrowsingContext.h
@@ -68,16 +68,21 @@ class CanonicalBrowsingContext final : p
   void NotifySetUserGestureActivationFromIPC(bool aIsUserGestureActivation);
 
   // This function is used to start the autoplay media which are delayed to
   // start. If needed, it would also notify the content browsing context which
   // are related with the canonical browsing content tree to start delayed
   // autoplay media.
   void NotifyStartDelayedAutoplayMedia();
 
+  // This function is used to mute or unmute all media within a tab. It would
+  // set the media mute property for the top level window and propagate it to
+  // other top level windows in other processes.
+  void NotifyMediaMutedChanged(bool aMuted);
+
   // Validate that the given process is allowed to perform the given
   // transaction. aSource is |nullptr| if set in the parent process.
   bool ValidateTransaction(const Transaction& aTransaction,
                            ContentParent* aSource);
 
   void SetFieldEpochsForChild(ContentParent* aChild,
                               const FieldEpochs& aEpochs);
   const FieldEpochs& GetFieldEpochsForChild(ContentParent* aChild);
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -2881,16 +2881,19 @@ void nsPIDOMWindowOuter::MaybeNotifyMedi
 
 bool nsPIDOMWindowOuter::GetAudioMuted() const { return mAudioMuted; }
 
 void nsPIDOMWindowOuter::SetAudioMuted(bool aMuted) {
   if (mAudioMuted == aMuted) {
     return;
   }
 
+  MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
+          ("nsPIDOMWindowOuter %p, SetAudioMuted=%s", this,
+           aMuted ? "muted" : "unmuted"));
   mAudioMuted = aMuted;
   RefreshMediaElementsVolume();
 }
 
 float nsPIDOMWindowOuter::GetAudioVolume() const { return mAudioVolume; }
 
 nsresult nsPIDOMWindowOuter::SetAudioVolume(float aVolume) {
   if (aVolume < 0.0) {
--- a/dom/chrome-webidl/BrowsingContext.webidl
+++ b/dom/chrome-webidl/BrowsingContext.webidl
@@ -41,14 +41,15 @@ interface CanonicalBrowsingContext : Bro
   // synchronously create WindowGlobalParent. It can throw if somehow the
   // content process has died.
   [Throws]
   readonly attribute DOMString? currentRemoteType;
 
   readonly attribute WindowGlobalParent? embedderWindowGlobal;
 
   void notifyStartDelayedAutoplayMedia();
+  void notifyMediaMutedChanged(boolean muted);
 };
 
 [Exposed=Window, ChromeOnly]
 interface BrowsingContextGroup {
   sequence<BrowsingContext> getToplevels();
 };
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -3622,16 +3622,26 @@ mozilla::ipc::IPCResult ContentChild::Re
 
 mozilla::ipc::IPCResult ContentChild::RecvStartDelayedAutoplayMediaComponents(
     BrowsingContext* aContext) {
   MOZ_ASSERT(aContext);
   aContext->StartDelayedAutoplayMediaComponents();
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult ContentChild::RecvSetMediaMuted(
+    BrowsingContext* aContext, bool aMuted) {
+  MOZ_ASSERT(aContext);
+  nsCOMPtr<nsPIDOMWindowOuter> window = aContext->GetDOMWindow();
+  if (window) {
+    window->SetAudioMuted(aMuted);
+  }
+  return IPC_OK();
+}
+
 already_AddRefed<nsIEventTarget> ContentChild::GetSpecificMessageEventTarget(
     const Message& aMsg) {
   switch (aMsg.type()) {
     // Javascript
     case PJavaScript::Msg_DropTemporaryStrongReferences__ID:
     case PJavaScript::Msg_DropObject__ID:
 
     // Navigation
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -669,16 +669,19 @@ class ContentChild final : public PConte
       const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
       const Maybe<LoadInfoArgs>& aLoadInfoForwarder, const uint64_t& aChannelId,
       nsIURI* aOriginalURI, const uint64_t& aIdentifier,
       const uint32_t& aRedirectMode);
 
   mozilla::ipc::IPCResult RecvStartDelayedAutoplayMediaComponents(
       BrowsingContext* aContext);
 
+  mozilla::ipc::IPCResult RecvSetMediaMuted(BrowsingContext* aContext,
+                                            bool aMuted);
+
   void HoldBrowsingContextGroup(BrowsingContextGroup* aBCG);
 
 #ifdef NIGHTLY_BUILD
   // Fetch the current number of pending input events.
   //
   // NOTE: This method performs an atomic read, and is safe to call from all
   // threads.
   uint32_t GetPendingInputEvents() { return mPendingInputEvents; }
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -795,16 +795,21 @@ child:
                                uint32_t aRedirectMode);
 
     /**
     * This method is used to notifty content process to start delayed autoplay
     * media via browsing context.
     */
     async StartDelayedAutoplayMediaComponents(BrowsingContext aContext);
 
+    /**
+    * This method is used to notifty content process to mute or unmute media.
+    */
+    async SetMediaMuted(BrowsingContext aContext, bool aMuted);
+
     // Begin subscribing to a new BrowsingContextGroup, sending down the current
     // value for every individual BrowsingContext.
     async RegisterBrowsingContextGroup(BrowsingContextInitializer[] aInits);
 
 parent:
     async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
 
     sync OpenRecordReplayChannel(uint32_t channelId)
--- a/toolkit/content/widgets/browser-custom-element.js
+++ b/toolkit/content/widgets/browser-custom-element.js
@@ -974,22 +974,22 @@ class MozBrowser extends MozElements.Moz
     event.initEvent("DOMAudioPlaybackBlockStopped", true, false);
     this.dispatchEvent(event);
   }
 
   mute(transientState) {
     if (!transientState) {
       this._audioMuted = true;
     }
-    this.messageManager.sendAsyncMessage("AudioPlayback", { type: "mute" });
+    this.frameLoader.browsingContext.notifyMediaMutedChanged(true);
   }
 
   unmute() {
     this._audioMuted = false;
-    this.messageManager.sendAsyncMessage("AudioPlayback", { type: "unmute" });
+    this.frameLoader.browsingContext.notifyMediaMutedChanged(false);
   }
 
   pauseMedia(disposable) {
     let suspendedReason;
     if (disposable) {
       suspendedReason = "mediaControlPaused";
     } else {
       suspendedReason = "lostAudioFocusTransiently";