diff --git a/dom/audiochannel/AudioChannelAgent.cpp b/dom/audiochannel/AudioChannelAgent.cpp index c02602db25de..3a68bdd371ac 100644 --- a/dom/audiochannel/AudioChannelAgent.cpp +++ b/dom/audiochannel/AudioChannelAgent.cpp @@ -35,6 +35,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioChannelAgent) AudioChannelAgent::AudioChannelAgent() : mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR) + , mInnerWindowID(0) , mIsRegToService(false) { } @@ -104,6 +105,10 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType, } if (aWindow) { + nsCOMPtr pInnerWindow = do_QueryInterface(aWindow); + MOZ_ASSERT(pInnerWindow->IsInnerWindow()); + mInnerWindowID = pInnerWindow->WindowID(); + nsCOMPtr topWindow; aWindow->GetScriptableTop(getter_AddRefs(topWindow)); mWindow = do_QueryInterface(topWindow); @@ -191,3 +196,18 @@ AudioChannelAgent::WindowID() const { return mWindow ? mWindow->WindowID() : 0; } + +void +AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID) +{ + if (aInnerWindowID != mInnerWindowID) { + return; + } + + nsCOMPtr callback = GetCallback(); + if (!callback) { + return; + } + + callback->WindowAudioCaptureChanged(); +} diff --git a/dom/audiochannel/AudioChannelAgent.h b/dom/audiochannel/AudioChannelAgent.h index 75b2fd335edc..809d34f2a1e7 100644 --- a/dom/audiochannel/AudioChannelAgent.h +++ b/dom/audiochannel/AudioChannelAgent.h @@ -34,6 +34,7 @@ public: AudioChannelAgent(); void WindowVolumeChanged(); + void WindowAudioCaptureChanged(uint64_t aInnerWindowID); nsPIDOMWindow* Window() const { @@ -61,6 +62,7 @@ private: nsWeakPtr mWeakCallback; int32_t mAudioChannelType; + uint64_t mInnerWindowID; bool mIsRegToService; }; diff --git a/dom/audiochannel/AudioChannelService.cpp b/dom/audiochannel/AudioChannelService.cpp index c3b858ab7761..b71b491c5078 100644 --- a/dom/audiochannel/AudioChannelService.cpp +++ b/dom/audiochannel/AudioChannelService.cpp @@ -546,6 +546,29 @@ AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow) } } +void +AudioChannelService::RefreshAgentsCapture(nsPIDOMWindow* aWindow, + uint64_t aInnerWindowID) +{ + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsOuterWindow()); + + nsCOMPtr topWindow; + aWindow->GetScriptableTop(getter_AddRefs(topWindow)); + nsCOMPtr pTopWindow = do_QueryInterface(topWindow); + if (!pTopWindow) { + return; + } + + AudioChannelWindow* winData = GetWindowData(pTopWindow->WindowID()); + + nsTObserverArray::ForwardIterator + iter(winData->mAgents); + while (iter.HasMore()) { + iter.GetNext()->WindowAudioCaptureChanged(aInnerWindowID); + } +} + /* static */ const nsAttrValue::EnumTable* AudioChannelService::GetAudioChannelTable() { diff --git a/dom/audiochannel/AudioChannelService.h b/dom/audiochannel/AudioChannelService.h index a0a65d8c737a..4dc0bedb7475 100644 --- a/dom/audiochannel/AudioChannelService.h +++ b/dom/audiochannel/AudioChannelService.h @@ -102,6 +102,14 @@ public: void RefreshAgentsVolume(nsPIDOMWindow* aWindow); + // This method needs to know the inner window that wants to capture audio. We + // group agents per top outer window, but we can have multiple innerWindow per + // top outerWindow (subiframes, etc.) and we have to identify all the agents + // just for a particular innerWindow. + void RefreshAgentsCapture(nsPIDOMWindow* aWindow, + uint64_t aInnerWindowID); + + #ifdef MOZ_WIDGET_GONK void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager) { diff --git a/dom/audiochannel/nsIAudioChannelAgent.idl b/dom/audiochannel/nsIAudioChannelAgent.idl index a35f54c09530..87934d4bacc0 100644 --- a/dom/audiochannel/nsIAudioChannelAgent.idl +++ b/dom/audiochannel/nsIAudioChannelAgent.idl @@ -6,13 +6,18 @@ interface nsIDOMWindow; -[uuid(4f537c88-3722-4946-9a09-ce559fa0591d)] +[uuid(5fe83b24-38b9-4901-a4a1-d1bd57d3fe18)] interface nsIAudioChannelAgentCallback : nsISupports { /** * Notified when the window volume/mute is changed */ void windowVolumeChanged(in float aVolume, in bool aMuted); + + /** + * Notified when the capture state is changed. + */ + void windowAudioCaptureChanged(); }; /** diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 3827f6b57a01..59483a458bd1 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -564,7 +564,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow) mMayHavePointerEnterLeaveEventListener(false), mIsModalContentWindow(false), mIsActive(false), mIsBackground(false), - mAudioMuted(false), mAudioVolume(1.0), + mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false), mDesktopModeViewport(false), mInnerWindow(nullptr), mOuterWindow(aOuterWindow), // Make sure no actual window ends up with mWindowID == 0 @@ -3745,6 +3745,26 @@ nsPIDOMWindow::RefreshMediaElements() service->RefreshAgentsVolume(GetOuterWindow()); } +bool +nsPIDOMWindow::GetAudioCaptured() const +{ + MOZ_ASSERT(IsInnerWindow()); + return mAudioCaptured; +} + +nsresult +nsPIDOMWindow::SetAudioCapture(bool aCapture) +{ + MOZ_ASSERT(IsInnerWindow()); + + mAudioCaptured = aCapture; + + nsRefPtr service = AudioChannelService::GetOrCreate(); + service->RefreshAgentsCapture(GetOuterWindow(), mWindowID); + + return NS_OK; +} + // nsISpeechSynthesisGetter #ifdef MOZ_WEBSPEECH diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index b9f17bb801a4..3e6404e9950c 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -185,6 +185,9 @@ public: float GetAudioVolume() const; nsresult SetAudioVolume(float aVolume); + bool GetAudioCaptured() const; + nsresult SetAudioCapture(bool aCapture); + virtual void SetServiceWorkersTestingEnabled(bool aEnabled) { MOZ_ASSERT(IsOuterWindow()); @@ -822,6 +825,8 @@ protected: bool mAudioMuted; float mAudioVolume; + bool mAudioCaptured; + // current desktop mode flag. bool mDesktopModeViewport; diff --git a/dom/fmradio/FMRadio.cpp b/dom/fmradio/FMRadio.cpp index 1f5d8de3f0e1..150ee703a1f7 100644 --- a/dom/fmradio/FMRadio.cpp +++ b/dom/fmradio/FMRadio.cpp @@ -471,6 +471,12 @@ FMRadio::WindowVolumeChanged(float aVolume, bool aMuted) return NS_OK; } +NS_IMETHODIMP +FMRadio::WindowAudioCaptureChanged() +{ + return NS_OK; +} + NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FMRadio) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 493bbd26678a..42c5f63f7774 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -4492,7 +4492,7 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState() if (!mAudioChannelAgent) { return; } - mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetWindow(), + mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(), static_cast(mAudioChannel), this); } @@ -4504,6 +4504,10 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState() void HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying) { + // Immediately check if this should go to the MSG instead of the normal + // media playback route. + WindowAudioCaptureChanged(); + // This is needed to pass nsContentUtils::IsCallerChrome(). // AudioChannel API should not called from content but it can happen that // this method has some content JS in its stack. @@ -4674,6 +4678,15 @@ HTMLMediaElement::GetTopLevelPrincipal() } #endif // MOZ_EME +NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged() +{ + MOZ_ASSERT(mAudioChannelAgent); + DebugOnly captured = OwnerDoc()->GetInnerWindow()->GetAudioCaptured(); + + // Something is going to happen here!! + return NS_OK; +} + AudioTrackList* HTMLMediaElement::AudioTracks() { diff --git a/dom/media/webaudio/AudioDestinationNode.cpp b/dom/media/webaudio/AudioDestinationNode.cpp index 95ab1b413459..3f5a3650a0df 100644 --- a/dom/media/webaudio/AudioDestinationNode.cpp +++ b/dom/media/webaudio/AudioDestinationNode.cpp @@ -505,6 +505,21 @@ AudioDestinationNode::WindowVolumeChanged(float aVolume, bool aMuted) return NS_OK; } +NS_IMETHODIMP +AudioDestinationNode::WindowAudioCaptureChanged() +{ + MOZ_ASSERT(mAudioChannelAgent); + + if (!mStream) { + return NS_OK; + } + + DebugOnly captured = GetOwner()->GetAudioCaptured(); + + // XXXtodopadenot actually capture + return NS_OK; +} + AudioChannel AudioDestinationNode::MozAudioChannelType() const { @@ -591,6 +606,8 @@ AudioDestinationNode::CreateAudioChannelAgent() // The AudioChannelAgent must start playing immediately in order to avoid // race conditions with mozinterruptbegin/end events. InputMuted(false); + + WindowAudioCaptureChanged(); } void