Bug 1156472 - Part 1 - Allow to capture all HTMLMediaElements and AudioContexts for a document. r=baku,padenot
This is built on top of the AudioChannel infrastructure. This patch does not actually implement the capture, it just does the plumbing to be able to notify all HTMLMediaElement/AudioContext for a document.
This commit is contained in:
@@ -35,6 +35,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioChannelAgent)
|
|||||||
|
|
||||||
AudioChannelAgent::AudioChannelAgent()
|
AudioChannelAgent::AudioChannelAgent()
|
||||||
: mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
|
: mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
|
||||||
|
, mInnerWindowID(0)
|
||||||
, mIsRegToService(false)
|
, mIsRegToService(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -104,6 +105,10 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (aWindow) {
|
if (aWindow) {
|
||||||
|
nsCOMPtr<nsPIDOMWindow> pInnerWindow = do_QueryInterface(aWindow);
|
||||||
|
MOZ_ASSERT(pInnerWindow->IsInnerWindow());
|
||||||
|
mInnerWindowID = pInnerWindow->WindowID();
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMWindow> topWindow;
|
nsCOMPtr<nsIDOMWindow> topWindow;
|
||||||
aWindow->GetScriptableTop(getter_AddRefs(topWindow));
|
aWindow->GetScriptableTop(getter_AddRefs(topWindow));
|
||||||
mWindow = do_QueryInterface(topWindow);
|
mWindow = do_QueryInterface(topWindow);
|
||||||
@@ -191,3 +196,18 @@ AudioChannelAgent::WindowID() const
|
|||||||
{
|
{
|
||||||
return mWindow ? mWindow->WindowID() : 0;
|
return mWindow ? mWindow->WindowID() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID)
|
||||||
|
{
|
||||||
|
if (aInnerWindowID != mInnerWindowID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
|
||||||
|
if (!callback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback->WindowAudioCaptureChanged();
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public:
|
|||||||
AudioChannelAgent();
|
AudioChannelAgent();
|
||||||
|
|
||||||
void WindowVolumeChanged();
|
void WindowVolumeChanged();
|
||||||
|
void WindowAudioCaptureChanged(uint64_t aInnerWindowID);
|
||||||
|
|
||||||
nsPIDOMWindow* Window() const
|
nsPIDOMWindow* Window() const
|
||||||
{
|
{
|
||||||
@@ -61,6 +62,7 @@ private:
|
|||||||
nsWeakPtr mWeakCallback;
|
nsWeakPtr mWeakCallback;
|
||||||
|
|
||||||
int32_t mAudioChannelType;
|
int32_t mAudioChannelType;
|
||||||
|
uint64_t mInnerWindowID;
|
||||||
bool mIsRegToService;
|
bool mIsRegToService;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -546,6 +546,29 @@ AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioChannelService::RefreshAgentsCapture(nsPIDOMWindow* aWindow,
|
||||||
|
uint64_t aInnerWindowID)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWindow);
|
||||||
|
MOZ_ASSERT(aWindow->IsOuterWindow());
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMWindow> topWindow;
|
||||||
|
aWindow->GetScriptableTop(getter_AddRefs(topWindow));
|
||||||
|
nsCOMPtr<nsPIDOMWindow> pTopWindow = do_QueryInterface(topWindow);
|
||||||
|
if (!pTopWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioChannelWindow* winData = GetWindowData(pTopWindow->WindowID());
|
||||||
|
|
||||||
|
nsTObserverArray<AudioChannelAgent*>::ForwardIterator
|
||||||
|
iter(winData->mAgents);
|
||||||
|
while (iter.HasMore()) {
|
||||||
|
iter.GetNext()->WindowAudioCaptureChanged(aInnerWindowID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ const nsAttrValue::EnumTable*
|
/* static */ const nsAttrValue::EnumTable*
|
||||||
AudioChannelService::GetAudioChannelTable()
|
AudioChannelService::GetAudioChannelTable()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -102,6 +102,14 @@ public:
|
|||||||
|
|
||||||
void RefreshAgentsVolume(nsPIDOMWindow* aWindow);
|
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
|
#ifdef MOZ_WIDGET_GONK
|
||||||
void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
|
void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,13 +6,18 @@
|
|||||||
|
|
||||||
interface nsIDOMWindow;
|
interface nsIDOMWindow;
|
||||||
|
|
||||||
[uuid(4f537c88-3722-4946-9a09-ce559fa0591d)]
|
[uuid(5fe83b24-38b9-4901-a4a1-d1bd57d3fe18)]
|
||||||
interface nsIAudioChannelAgentCallback : nsISupports
|
interface nsIAudioChannelAgentCallback : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Notified when the window volume/mute is changed
|
* Notified when the window volume/mute is changed
|
||||||
*/
|
*/
|
||||||
void windowVolumeChanged(in float aVolume, in bool aMuted);
|
void windowVolumeChanged(in float aVolume, in bool aMuted);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notified when the capture state is changed.
|
||||||
|
*/
|
||||||
|
void windowAudioCaptureChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -564,7 +564,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
|
|||||||
mMayHavePointerEnterLeaveEventListener(false),
|
mMayHavePointerEnterLeaveEventListener(false),
|
||||||
mIsModalContentWindow(false),
|
mIsModalContentWindow(false),
|
||||||
mIsActive(false), mIsBackground(false),
|
mIsActive(false), mIsBackground(false),
|
||||||
mAudioMuted(false), mAudioVolume(1.0),
|
mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
|
||||||
mDesktopModeViewport(false), mInnerWindow(nullptr),
|
mDesktopModeViewport(false), mInnerWindow(nullptr),
|
||||||
mOuterWindow(aOuterWindow),
|
mOuterWindow(aOuterWindow),
|
||||||
// Make sure no actual window ends up with mWindowID == 0
|
// Make sure no actual window ends up with mWindowID == 0
|
||||||
@@ -3745,6 +3745,26 @@ nsPIDOMWindow::RefreshMediaElements()
|
|||||||
service->RefreshAgentsVolume(GetOuterWindow());
|
service->RefreshAgentsVolume(GetOuterWindow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsPIDOMWindow::GetAudioCaptured() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsInnerWindow());
|
||||||
|
return mAudioCaptured;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsPIDOMWindow::SetAudioCapture(bool aCapture)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsInnerWindow());
|
||||||
|
|
||||||
|
mAudioCaptured = aCapture;
|
||||||
|
|
||||||
|
nsRefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||||
|
service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// nsISpeechSynthesisGetter
|
// nsISpeechSynthesisGetter
|
||||||
|
|
||||||
#ifdef MOZ_WEBSPEECH
|
#ifdef MOZ_WEBSPEECH
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ public:
|
|||||||
float GetAudioVolume() const;
|
float GetAudioVolume() const;
|
||||||
nsresult SetAudioVolume(float aVolume);
|
nsresult SetAudioVolume(float aVolume);
|
||||||
|
|
||||||
|
bool GetAudioCaptured() const;
|
||||||
|
nsresult SetAudioCapture(bool aCapture);
|
||||||
|
|
||||||
virtual void SetServiceWorkersTestingEnabled(bool aEnabled)
|
virtual void SetServiceWorkersTestingEnabled(bool aEnabled)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsOuterWindow());
|
MOZ_ASSERT(IsOuterWindow());
|
||||||
@@ -822,6 +825,8 @@ protected:
|
|||||||
bool mAudioMuted;
|
bool mAudioMuted;
|
||||||
float mAudioVolume;
|
float mAudioVolume;
|
||||||
|
|
||||||
|
bool mAudioCaptured;
|
||||||
|
|
||||||
// current desktop mode flag.
|
// current desktop mode flag.
|
||||||
bool mDesktopModeViewport;
|
bool mDesktopModeViewport;
|
||||||
|
|
||||||
|
|||||||
@@ -471,6 +471,12 @@ FMRadio::WindowVolumeChanged(float aVolume, bool aMuted)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FMRadio::WindowAudioCaptureChanged()
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FMRadio)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FMRadio)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
|
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
|
||||||
|
|||||||
@@ -4492,7 +4492,7 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
|
|||||||
if (!mAudioChannelAgent) {
|
if (!mAudioChannelAgent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetWindow(),
|
mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(),
|
||||||
static_cast<int32_t>(mAudioChannel),
|
static_cast<int32_t>(mAudioChannel),
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
@@ -4504,6 +4504,10 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
|
|||||||
void
|
void
|
||||||
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
|
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().
|
// This is needed to pass nsContentUtils::IsCallerChrome().
|
||||||
// AudioChannel API should not called from content but it can happen that
|
// AudioChannel API should not called from content but it can happen that
|
||||||
// this method has some content JS in its stack.
|
// this method has some content JS in its stack.
|
||||||
@@ -4674,6 +4678,15 @@ HTMLMediaElement::GetTopLevelPrincipal()
|
|||||||
}
|
}
|
||||||
#endif // MOZ_EME
|
#endif // MOZ_EME
|
||||||
|
|
||||||
|
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mAudioChannelAgent);
|
||||||
|
DebugOnly<bool> captured = OwnerDoc()->GetInnerWindow()->GetAudioCaptured();
|
||||||
|
|
||||||
|
// Something is going to happen here!!
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
AudioTrackList*
|
AudioTrackList*
|
||||||
HTMLMediaElement::AudioTracks()
|
HTMLMediaElement::AudioTracks()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -505,6 +505,21 @@ AudioDestinationNode::WindowVolumeChanged(float aVolume, bool aMuted)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AudioDestinationNode::WindowAudioCaptureChanged()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mAudioChannelAgent);
|
||||||
|
|
||||||
|
if (!mStream) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugOnly<bool> captured = GetOwner()->GetAudioCaptured();
|
||||||
|
|
||||||
|
// XXXtodopadenot actually capture
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
AudioChannel
|
AudioChannel
|
||||||
AudioDestinationNode::MozAudioChannelType() const
|
AudioDestinationNode::MozAudioChannelType() const
|
||||||
{
|
{
|
||||||
@@ -591,6 +606,8 @@ AudioDestinationNode::CreateAudioChannelAgent()
|
|||||||
// The AudioChannelAgent must start playing immediately in order to avoid
|
// The AudioChannelAgent must start playing immediately in order to avoid
|
||||||
// race conditions with mozinterruptbegin/end events.
|
// race conditions with mozinterruptbegin/end events.
|
||||||
InputMuted(false);
|
InputMuted(false);
|
||||||
|
|
||||||
|
WindowAudioCaptureChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user