Bug 1228564 - part 2 : check audio capturing when the agent is registered/unregistered. r=baku.

This commit is contained in:
Alastor Wu 2015-12-24 17:28:45 +08:00
parent d7a26cc3a6
commit 408dc1372e
12 changed files with 75 additions and 65 deletions

View File

@ -297,8 +297,15 @@ AudioChannelAgent::WindowID() const
return mWindow ? mWindow->WindowID() : 0;
}
uint64_t
AudioChannelAgent::InnerWindowID() const
{
return mInnerWindowID;
}
void
AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID)
AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID,
bool aCapture)
{
if (aInnerWindowID != mInnerWindowID) {
return;
@ -309,5 +316,9 @@ AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID)
return;
}
callback->WindowAudioCaptureChanged();
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, WindowAudioCaptureChanged, this = %p, "
"capture = %d\n", this, aCapture));
callback->WindowAudioCaptureChanged(aCapture);
}

View File

@ -34,7 +34,7 @@ public:
AudioChannelAgent();
void WindowVolumeChanged();
void WindowAudioCaptureChanged(uint64_t aInnerWindowID);
void WindowAudioCaptureChanged(uint64_t aInnerWindowID, bool aCapture);
nsPIDOMWindow* Window() const
{
@ -42,6 +42,7 @@ public:
}
uint64_t WindowID() const;
uint64_t InnerWindowID() const;
private:
virtual ~AudioChannelAgent();

View File

@ -294,6 +294,13 @@ AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
NS_DispatchToCurrentThread(runnable);
}
// If the window has already been captured, the agent of that window should
// also be captured.
if (winData->mIsAudioCaptured) {
aAgent->WindowAudioCaptureChanged(aAgent->InnerWindowID(),
winData->mIsAudioCaptured);
}
MaybeSendStatusUpdate();
}
@ -336,6 +343,11 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
NS_DispatchToCurrentThread(runnable);
}
// No need to capture non-audible object.
if (winData->mIsAudioCaptured) {
aAgent->WindowAudioCaptureChanged(aAgent->InnerWindowID(), false);
}
MaybeSendStatusUpdate();
}
@ -623,12 +635,18 @@ AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
}
void
AudioChannelService::RefreshAgentsCapture(nsPIDOMWindow* aWindow,
uint64_t aInnerWindowID)
AudioChannelService::SetWindowAudioCaptured(nsPIDOMWindow* aWindow,
uint64_t aInnerWindowID,
bool aCapture)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aWindow->IsOuterWindow());
MOZ_LOG(GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelService, SetWindowAudioCaptured, window = %p, "
"aCapture = %d\n", aWindow, aCapture));
nsCOMPtr<nsPIDOMWindow> topWindow = aWindow->GetScriptableTop();
if (!topWindow) {
return;
@ -645,10 +663,13 @@ AudioChannelService::RefreshAgentsCapture(nsPIDOMWindow* aWindow,
return;
}
nsTObserverArray<AudioChannelAgent*>::ForwardIterator
iter(winData->mAgents);
while (iter.HasMore()) {
iter.GetNext()->WindowAudioCaptureChanged(aInnerWindowID);
if (aCapture != winData->mIsAudioCaptured) {
winData->mIsAudioCaptured = aCapture;
nsTObserverArray<AudioChannelAgent*>::ForwardIterator
iter(winData->mAgents);
while (iter.HasMore()) {
iter.GetNext()->WindowAudioCaptureChanged(aInnerWindowID, aCapture);
}
}
}
@ -786,7 +807,7 @@ AudioChannelService::SetAudioChannelVolume(nsPIDOMWindow* aWindow,
MOZ_LOG(GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelService, SetAudioChannelVolume, window = %p, type = %d, "
"volume = %d\n", aWindow, aAudioChannel, aVolume));
"volume = %f\n", aWindow, aAudioChannel, aVolume));
AudioChannelWindow* winData = GetOrCreateWindowData(aWindow);
winData->mChannels[(uint32_t)aAudioChannel].mVolume = aVolume;

View File

@ -122,8 +122,9 @@ public:
// 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);
void SetWindowAudioCaptured(nsPIDOMWindow* aWindow,
uint64_t aInnerWindowID,
bool aCapture);
#ifdef MOZ_WIDGET_GONK
@ -187,13 +188,15 @@ private:
struct AudioChannelWindow final
{
explicit AudioChannelWindow(uint64_t aWindowID)
: mWindowID(aWindowID)
: mWindowID(aWindowID),
mIsAudioCaptured(false)
{
// Workaround for bug1183033, system channel type can always playback.
mChannels[(int16_t)AudioChannel::System].mMuted = false;
}
uint64_t mWindowID;
bool mIsAudioCaptured;
AudioChannelConfig mChannels[NUMBER_OF_AUDIO_CHANNELS];
// Raw pointer because the AudioChannelAgent must unregister itself.

View File

@ -6,7 +6,7 @@
interface nsIDOMWindow;
[uuid(5fe83b24-38b9-4901-a4a1-d1bd57d3fe18)]
[uuid(0a451ee0-972e-11e5-a837-0800200c9a66)]
interface nsIAudioChannelAgentCallback : nsISupports
{
/**
@ -17,7 +17,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
/**
* Notified when the capture state is changed.
*/
void windowAudioCaptureChanged();
void windowAudioCaptureChanged(in bool aCapture);
};
/**

View File

@ -3743,7 +3743,7 @@ nsPIDOMWindow::SetAudioCapture(bool aCapture)
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
if (service) {
service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture);
}
return NS_OK;

View File

@ -469,7 +469,7 @@ FMRadio::WindowVolumeChanged(float aVolume, bool aMuted)
}
NS_IMETHODIMP
FMRadio::WindowAudioCaptureChanged()
FMRadio::WindowAudioCaptureChanged(bool aCapture)
{
return NS_OK;
}

View File

@ -114,31 +114,18 @@ using mozilla::net::nsMediaFragmentURIParser;
class MOZ_STACK_CLASS AutoNotifyAudioChannelAgent
{
RefPtr<mozilla::dom::HTMLMediaElement> mElement;
bool mShouldNotify;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
public:
AutoNotifyAudioChannelAgent(mozilla::dom::HTMLMediaElement* aElement,
bool aNotify
AutoNotifyAudioChannelAgent(mozilla::dom::HTMLMediaElement* aElement
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mElement(aElement)
, mShouldNotify(aNotify)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (mShouldNotify) {
// The audio channel agent may not exist now.
if (mElement->MaybeCreateAudioChannelAgent()) {
mElement->NotifyAudioChannelAgent(false);
}
}
}
~AutoNotifyAudioChannelAgent()
{
if (mShouldNotify) {
// The audio channel agent is destroyed at this point.
if (mElement->MaybeCreateAudioChannelAgent()) {
mElement->NotifyAudioChannelAgent(true);
}
}
mElement->UpdateAudioChannelPlayingState();
}
};
@ -3399,10 +3386,7 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
// If the element is gaining or losing an audio track, we need to notify
// the audio channel agent so that the correct audio-playback events will
// get dispatched.
bool audioTrackChanging = mMediaInfo.HasAudio() != aInfo->HasAudio();
AutoNotifyAudioChannelAgent autoNotify(this,
audioTrackChanging &&
mPlayingThroughTheAudioChannel);
AutoNotifyAudioChannelAgent autoNotify(this);
mMediaInfo = *aInfo;
mIsEncrypted = aInfo->IsEncrypted()
@ -4761,6 +4745,11 @@ HTMLMediaElement::IsPlayingThroughTheAudioChannel() const
return false;
}
// If this element doesn't have any audio tracks.
if (!HasAudio()) {
return false;
}
// The volume should not be ~0
if (std::fabs(Volume()) <= 1e-7) {
return false;
@ -4816,15 +4805,6 @@ HTMLMediaElement::UpdateAudioChannelPlayingState()
void
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
{
// Don't do anything if this element doesn't have any audio tracks.
if (!HasAudio()) {
return;
}
// 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.
@ -4995,17 +4975,17 @@ HTMLMediaElement::GetTopLevelPrincipal()
}
#endif // MOZ_EME
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged(bool aCapture)
{
MOZ_ASSERT(mAudioChannelAgent);
MOZ_ASSERT(HasAudio());
if (!OwnerDoc()->GetInnerWindow()) {
return NS_OK;
}
bool captured = OwnerDoc()->GetInnerWindow()->GetAudioCaptured();
if (captured != mAudioCapturedByWindow) {
if (captured) {
if (aCapture != mAudioCapturedByWindow) {
if (aCapture) {
mAudioCapturedByWindow = true;
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(OwnerDoc()->GetParentObject());
@ -5041,7 +5021,7 @@ NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
}
}
return NS_OK;
return NS_OK;
}
AudioTrackList*

View File

@ -537,7 +537,7 @@ AudioDestinationNode::WindowVolumeChanged(float aVolume, bool aMuted)
}
NS_IMETHODIMP
AudioDestinationNode::WindowAudioCaptureChanged()
AudioDestinationNode::WindowAudioCaptureChanged(bool aCapture)
{
MOZ_ASSERT(mAudioChannelAgent);
@ -550,10 +550,8 @@ AudioDestinationNode::WindowAudioCaptureChanged()
return NS_OK;
}
bool captured = ownerWindow->GetAudioCaptured();
if (captured != mCaptured) {
if (captured) {
if (aCapture != mCaptured) {
if (aCapture) {
nsCOMPtr<nsPIDOMWindow> window = Context()->GetParentObject();
uint64_t id = window->WindowID();
mCaptureStreamPort =
@ -561,7 +559,7 @@ AudioDestinationNode::WindowAudioCaptureChanged()
} else {
mCaptureStreamPort->Destroy();
}
mCaptured = captured;
mCaptured = aCapture;
}
return NS_OK;
@ -653,10 +651,7 @@ AudioDestinationNode::CreateAudioChannelAgent()
return rv;
}
rv = WindowAudioCaptureChanged();
NS_WARN_IF(NS_FAILED(rv));
return rv;
return NS_OK;
}
void
@ -751,7 +746,6 @@ AudioDestinationNode::InputMuted(bool aMuted)
return;
}
WindowAudioCaptureChanged();
WindowVolumeChanged(volume, muted);
}

View File

@ -716,7 +716,7 @@ nsSpeechTask::WindowVolumeChanged(float aVolume, bool aMuted)
}
NS_IMETHODIMP
nsSpeechTask::WindowAudioCaptureChanged()
nsSpeechTask::WindowAudioCaptureChanged(bool aCapture)
{
// This is not supported yet.
return NS_OK;

View File

@ -1860,7 +1860,7 @@ nsNPAPIPluginInstance::WindowVolumeChanged(float aVolume, bool aMuted)
}
NS_IMETHODIMP
nsNPAPIPluginInstance::WindowAudioCaptureChanged()
nsNPAPIPluginInstance::WindowAudioCaptureChanged(bool aCapture)
{
return NS_OK;
}

View File

@ -711,7 +711,7 @@ Telephony::WindowVolumeChanged(float aVolume, bool aMuted)
}
NS_IMETHODIMP
Telephony::WindowAudioCaptureChanged()
Telephony::WindowAudioCaptureChanged(bool aCapture)
{
// Do nothing, it's useless for the telephony object.
return NS_OK;