Bug 1315551 - part3 : check we have initialized agent when we want to call the agent's function.
MozReview-Commit-ID: 131tXUFnmXv
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2944,17 +2944,17 @@ HTMLMediaElement::HTMLMediaElement(alrea
MOZ_ASSERT(NS_IsMainThread());
mWatchManager.Watch(mDownloadSuspendedByCache, &HTMLMediaElement::UpdateReadyStateInternal);
// Paradoxically, there is a self-edge whereby UpdateReadyStateInternal refuses
// to run until mReadyState reaches at least HAVE_METADATA by some other means.
mWatchManager.Watch(mReadyState, &HTMLMediaElement::UpdateReadyStateInternal);
mShutdownObserver->Subscribe(this);
- CreateAudioChannelAgent();
+ MaybeCreateAudioChannelAgent();
}
HTMLMediaElement::~HTMLMediaElement()
{
NS_ASSERTION(!mHasSelfReference,
"How can we be destroyed if we're still holding a self reference?");
mShutdownObserver->Unsubscribe();
@@ -5757,27 +5757,36 @@ NS_IMETHODIMP HTMLMediaElement::SetMozPr
}
ImageContainer* HTMLMediaElement::GetImageContainer()
{
VideoFrameContainer* container = GetVideoFrameContainer();
return container ? container->GetImageContainer() : nullptr;
}
-void
-HTMLMediaElement::CreateAudioChannelAgent()
+bool
+HTMLMediaElement::MaybeCreateAudioChannelAgent()
{
if (mAudioChannelAgent) {
- return;
+ return true;
}
mAudioChannelAgent = new AudioChannelAgent();
- mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(),
+ nsresult rv = mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(),
static_cast<int32_t>(mAudioChannel),
this);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ mAudioChannelAgent = nullptr;
+ MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
+ ("HTMLMediaElement, Fail to initialize the audio channel agent,"
+ " this = %p\n", this));
+ return false;
+ }
+
+ return true;
}
bool
HTMLMediaElement::IsPlayingThroughTheAudioChannel() const
{
// If we have an error, we are not playing.
if (mError) {
return false;
@@ -5823,16 +5832,20 @@ HTMLMediaElement::IsPlayingThroughTheAud
void
HTMLMediaElement::UpdateAudioChannelPlayingState(bool aForcePlaying)
{
bool playingThroughTheAudioChannel =
aForcePlaying || IsPlayingThroughTheAudioChannel();
if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
+ if (!MaybeCreateAudioChannelAgent()) {
+ return;
+ }
+
mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel);
}
}
void
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
{
@@ -6033,29 +6046,30 @@ HTMLMediaElement::IsAllowedToPlay()
if (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK) {
return false;
}
// If the tab hasn't been activated yet, the media element in that tab can't
// be playback now until the tab goes to foreground first time or user clicks
// the unblocking tab icon.
- if (!IsTabActivated()) {
+ if (MaybeCreateAudioChannelAgent() && !IsTabActivated()) {
// Even we haven't start playing yet, we still need to notify the audio
// channe system because we need to receive the resume notification later.
UpdateAudioChannelPlayingState(true /* force to start */);
return false;
}
return true;
}
bool
HTMLMediaElement::IsTabActivated() const
{
+ MOZ_ASSERT(mAudioChannelAgent);
return !mAudioChannelAgent->ShouldBlockMedia();
}
static const char* VisibilityString(Visibility aVisibility) {
switch(aVisibility) {
case Visibility::UNTRACKED: {
return "UNTRACKED";
}
@@ -6457,19 +6471,18 @@ HTMLMediaElement::SetAudibleState(bool a
NotifyAudioPlaybackChanged(
AudioChannelService::AudibleChangedReasons::eDataAudibleChanged);
}
}
void
HTMLMediaElement::NotifyAudioPlaybackChanged(AudibleChangedReasons aReason)
{
- MOZ_ASSERT(mAudioChannelAgent);
-
- if (!mAudioChannelAgent->IsPlayingStarted()) {
+ if (MaybeCreateAudioChannelAgent() &&
+ !mAudioChannelAgent->IsPlayingStarted()) {
return;
}
if (mAudible == IsAudible()) {
return;
}
mAudible = IsAudible();
@@ -6502,16 +6515,17 @@ HTMLMediaElement::MaybeNotifyMediaResume
{
// In fennec, we should send the notification when media is resumed from the
// pause-disposable which was called by media control.
if (mAudioChannelSuspended != nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE &&
aSuspend != nsISuspendedTypes::NONE_SUSPENDED) {
return;
}
+ MOZ_ASSERT(mAudioChannelAgent);
uint64_t windowID = mAudioChannelAgent->WindowID();
NS_DispatchToMainThread(NS_NewRunnableFunction([windowID]() -> void {
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (NS_WARN_IF(!observerService)) {
return;
}
@@ -6578,24 +6592,23 @@ HTMLMediaElement::SetMediaInfo(const Med
{
mMediaInfo = aInfo;
AudioCaptureStreamChangeIfNeeded();
}
void
HTMLMediaElement::AudioCaptureStreamChangeIfNeeded()
{
- MOZ_ASSERT(mAudioChannelAgent);
-
// No need to capture a silence media element.
if (!HasAudio()) {
return;
}
- if (!mAudioChannelAgent->IsPlayingStarted()) {
+ if (MaybeCreateAudioChannelAgent() &&
+ !mAudioChannelAgent->IsPlayingStarted()) {
return;
}
if (mAudioCapturedByWindow && !mCaptureStreamPort) {
nsCOMPtr<nsPIDOMWindowInner> window = OwnerDoc()->GetInnerWindow();
if (!OwnerDoc()->GetInnerWindow()) {
return;
}
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1224,19 +1224,21 @@ protected:
TextTrackManager* GetOrCreateTextTrackManager();
// Recomputes ready state and fires events as necessary based on current state.
void UpdateReadyStateInternal();
// Notifies the audio channel agent when the element starts or stops playing.
void NotifyAudioChannelAgent(bool aPlaying);
- // Creates the audio channel agent in the beginning and this agent would be
- // used to communicate with the AudioChannelService.
- void CreateAudioChannelAgent();
+ // True if we create the audio channel agent successfully or we already have
+ // one. The agent is used to communicate with the AudioChannelService. eg.
+ // notify we are playing/audible and receive muted/unmuted/suspend/resume
+ // commands from AudioChannelService.
+ bool MaybeCreateAudioChannelAgent();
// Determine if the element should be paused because of suspend conditions.
bool ShouldElementBePaused();
// Create or destroy the captured stream depend on mAudioCapturedByWindow.
void AudioCaptureStreamChangeIfNeeded();
/**