Bug 1374930. P4 - move ResourceCallback to ChannelMediaDecoder.
We also move some methods to protected so they are callable from ChannelMediaDecoder.
MozReview-Commit-ID: 6s9LKNkbJhX
--- a/dom/media/ChannelMediaDecoder.cpp
+++ b/dom/media/ChannelMediaDecoder.cpp
@@ -4,14 +4,162 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ChannelMediaDecoder.h"
#include "MediaResource.h"
namespace mozilla {
+ChannelMediaDecoder::ResourceCallback::ResourceCallback(
+ AbstractThread* aMainThread)
+ : mAbstractMainThread(aMainThread)
+{
+ MOZ_ASSERT(aMainThread);
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::Connect(ChannelMediaDecoder* aDecoder)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ mDecoder = aDecoder;
+ mTimer = do_CreateInstance("@mozilla.org/timer;1");
+ mTimer->SetTarget(mAbstractMainThread->AsEventTarget());
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::Disconnect()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mDecoder) {
+ mDecoder = nullptr;
+ mTimer->Cancel();
+ mTimer = nullptr;
+ }
+}
+
+MediaDecoderOwner*
+ChannelMediaDecoder::ResourceCallback::GetMediaOwner() const
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ return mDecoder ? mDecoder->GetOwner() : nullptr;
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::SetInfinite(bool aInfinite)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mDecoder) {
+ mDecoder->SetInfinite(aInfinite);
+ }
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::NotifyNetworkError()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mDecoder) {
+ mDecoder->NetworkError();
+ }
+}
+
+/* static */ void
+ChannelMediaDecoder::ResourceCallback::TimerCallback(nsITimer* aTimer,
+ void* aClosure)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ ResourceCallback* thiz = static_cast<ResourceCallback*>(aClosure);
+ MOZ_ASSERT(thiz->mDecoder);
+ thiz->mDecoder->NotifyDataArrivedInternal();
+ thiz->mTimerArmed = false;
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::NotifyDataArrived()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!mDecoder) {
+ return;
+ }
+
+ mDecoder->DownloadProgressed();
+
+ if (mTimerArmed) {
+ return;
+ }
+ // In situations where these notifications come from stochastic network
+ // activity, we can save significant computation by throttling the
+ // calls to MediaDecoder::NotifyDataArrived() which will update the buffer
+ // ranges of the reader.
+ mTimerArmed = true;
+ mTimer->InitWithFuncCallback(
+ TimerCallback, this, sDelay, nsITimer::TYPE_ONE_SHOT);
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::NotifyDataEnded(nsresult aStatus)
+{
+ RefPtr<ResourceCallback> self = this;
+ nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=]() {
+ if (!self->mDecoder) {
+ return;
+ }
+ self->mDecoder->NotifyDownloadEnded(aStatus);
+ if (NS_SUCCEEDED(aStatus)) {
+ MediaDecoderOwner* owner = self->GetMediaOwner();
+ MOZ_ASSERT(owner);
+ owner->DownloadSuspended();
+
+ // NotifySuspendedStatusChanged will tell the element that download
+ // has been suspended "by the cache", which is true since we never
+ // download anything. The element can then transition to HAVE_ENOUGH_DATA.
+ self->mDecoder->NotifySuspendedStatusChanged();
+ }
+ });
+ mAbstractMainThread->Dispatch(r.forget());
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::NotifyPrincipalChanged()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mDecoder) {
+ mDecoder->NotifyPrincipalChanged();
+ }
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::NotifySuspendedStatusChanged()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mDecoder) {
+ mDecoder->NotifySuspendedStatusChanged();
+ }
+}
+
+void
+ChannelMediaDecoder::ResourceCallback::NotifyBytesConsumed(int64_t aBytes,
+ int64_t aOffset)
+{
+ RefPtr<ResourceCallback> self = this;
+ nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=]() {
+ if (self->mDecoder) {
+ self->mDecoder->NotifyBytesConsumed(aBytes, aOffset);
+ }
+ });
+ mAbstractMainThread->Dispatch(r.forget());
+}
+
ChannelMediaDecoder::ChannelMediaDecoder(MediaDecoderInit& aInit)
: MediaDecoder(aInit)
+ , mResourceCallback(new ResourceCallback(aInit.mOwner->AbstractMainThread()))
{
+ mResourceCallback->Connect(this);
+}
+
+void
+ChannelMediaDecoder::Shutdown()
+{
+ mResourceCallback->Disconnect();
+ MediaDecoder::Shutdown();
}
} // namespace mozilla
--- a/dom/media/ChannelMediaDecoder.h
+++ b/dom/media/ChannelMediaDecoder.h
@@ -3,24 +3,71 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef ChannelMediaDecoder_h_
#define ChannelMediaDecoder_h_
#include "MediaDecoder.h"
+#include "MediaResourceCallback.h"
namespace mozilla {
class ChannelMediaDecoder : public MediaDecoder
{
+ // Used to register with MediaResource to receive notifications which will
+ // be forwarded to MediaDecoder.
+ class ResourceCallback : public MediaResourceCallback
+ {
+ // Throttle calls to MediaDecoder::NotifyDataArrived()
+ // to be at most once per 500ms.
+ static const uint32_t sDelay = 500;
+
+ public:
+ explicit ResourceCallback(AbstractThread* aMainThread);
+ // Start to receive notifications from ResourceCallback.
+ void Connect(ChannelMediaDecoder* aDecoder);
+ // Called upon shutdown to stop receiving notifications.
+ void Disconnect();
+
+ private:
+ /* MediaResourceCallback functions */
+ MediaDecoderOwner* GetMediaOwner() const override;
+ void SetInfinite(bool aInfinite) override;
+ void NotifyNetworkError() override;
+ void NotifyDataArrived() override;
+ void NotifyDataEnded(nsresult aStatus) override;
+ void NotifyPrincipalChanged() override;
+ void NotifySuspendedStatusChanged() override;
+ void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) override;
+
+ static void TimerCallback(nsITimer* aTimer, void* aClosure);
+
+ // The decoder to send notifications. Main-thread only.
+ ChannelMediaDecoder* mDecoder = nullptr;
+ nsCOMPtr<nsITimer> mTimer;
+ bool mTimerArmed = false;
+ const RefPtr<AbstractThread> mAbstractMainThread;
+ };
+
+ RefPtr<ResourceCallback> mResourceCallback;
+
public:
explicit ChannelMediaDecoder(MediaDecoderInit& aInit);
+ // Return a callback object used to register with MediaResource to receive
+ // notifications.
+ MediaResourceCallback* GetResourceCallback() const
+ {
+ return mResourceCallback;
+ }
+
+ void Shutdown() override;
+
// Create a new decoder of the same type as this one.
// Subclasses must implement this.
virtual ChannelMediaDecoder* Clone(MediaDecoderInit& aInit) = 0;
};
} // namespace mozilla
#endif // ChannelMediaDecoder_h_
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -130,152 +130,17 @@ MediaDecoder::InitStatics()
{
MOZ_ASSERT(NS_IsMainThread());
}
NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
NS_IMPL_ISUPPORTS0(MediaDecoder)
-MediaDecoder::ResourceCallback::ResourceCallback(AbstractThread* aMainThread)
- : mAbstractMainThread(aMainThread)
-{
- MOZ_ASSERT(aMainThread);
-}
-void
-MediaDecoder::ResourceCallback::Connect(MediaDecoder* aDecoder)
-{
- MOZ_ASSERT(NS_IsMainThread());
- mDecoder = aDecoder;
- mTimer = do_CreateInstance("@mozilla.org/timer;1");
- mTimer->SetTarget(mAbstractMainThread->AsEventTarget());
-}
-
-void
-MediaDecoder::ResourceCallback::Disconnect()
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (mDecoder) {
- mDecoder = nullptr;
- mTimer->Cancel();
- mTimer = nullptr;
- }
-}
-
-MediaDecoderOwner*
-MediaDecoder::ResourceCallback::GetMediaOwner() const
-{
- MOZ_ASSERT(NS_IsMainThread());
- return mDecoder ? mDecoder->GetOwner() : nullptr;
-}
-
-void
-MediaDecoder::ResourceCallback::SetInfinite(bool aInfinite)
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (mDecoder) {
- mDecoder->SetInfinite(aInfinite);
- }
-}
-
-void
-MediaDecoder::ResourceCallback::NotifyNetworkError()
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (mDecoder) {
- mDecoder->NetworkError();
- }
-}
-
-/* static */ void
-MediaDecoder::ResourceCallback::TimerCallback(nsITimer* aTimer, void* aClosure)
-{
- MOZ_ASSERT(NS_IsMainThread());
- ResourceCallback* thiz = static_cast<ResourceCallback*>(aClosure);
- MOZ_ASSERT(thiz->mDecoder);
- thiz->mDecoder->NotifyDataArrivedInternal();
- thiz->mTimerArmed = false;
-}
-
-void
-MediaDecoder::ResourceCallback::NotifyDataArrived()
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (!mDecoder) {
- return;
- }
-
- mDecoder->DownloadProgressed();
-
- if (mTimerArmed) {
- return;
- }
- // In situations where these notifications come from stochastic network
- // activity, we can save significant computation by throttling the
- // calls to MediaDecoder::NotifyDataArrived() which will update the buffer
- // ranges of the reader.
- mTimerArmed = true;
- mTimer->InitWithFuncCallback(
- TimerCallback, this, sDelay, nsITimer::TYPE_ONE_SHOT);
-}
-
-void
-MediaDecoder::ResourceCallback::NotifyDataEnded(nsresult aStatus)
-{
- RefPtr<ResourceCallback> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
- if (!self->mDecoder) {
- return;
- }
- self->mDecoder->NotifyDownloadEnded(aStatus);
- if (NS_SUCCEEDED(aStatus)) {
- MediaDecoderOwner* owner = self->GetMediaOwner();
- MOZ_ASSERT(owner);
- owner->DownloadSuspended();
-
- // NotifySuspendedStatusChanged will tell the element that download
- // has been suspended "by the cache", which is true since we never
- // download anything. The element can then transition to HAVE_ENOUGH_DATA.
- self->mDecoder->NotifySuspendedStatusChanged();
- }
- });
- mAbstractMainThread->Dispatch(r.forget());
-}
-
-void
-MediaDecoder::ResourceCallback::NotifyPrincipalChanged()
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (mDecoder) {
- mDecoder->NotifyPrincipalChanged();
- }
-}
-
-void
-MediaDecoder::ResourceCallback::NotifySuspendedStatusChanged()
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (mDecoder) {
- mDecoder->NotifySuspendedStatusChanged();
- }
-}
-
-void
-MediaDecoder::ResourceCallback::NotifyBytesConsumed(int64_t aBytes,
- int64_t aOffset)
-{
- RefPtr<ResourceCallback> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
- if (self->mDecoder) {
- self->mDecoder->NotifyBytesConsumed(aBytes, aOffset);
- }
- });
- mAbstractMainThread->Dispatch(r.forget());
-}
void
MediaDecoder::NotifyOwnerActivityChanged(bool aIsDocumentVisible,
Visibility aElementVisibility,
bool aIsElementInTree)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
@@ -354,17 +219,16 @@ MediaDecoder::IsInfinite() const
name(mOwner->AbstractMainThread(), val, "MediaDecoder::" #name " (Mirror)")
#define INIT_CANONICAL(name, val) \
name(mOwner->AbstractMainThread(), val, "MediaDecoder::" #name " (Canonical)")
MediaDecoder::MediaDecoder(MediaDecoderInit& aInit)
: mWatchManager(this, aInit.mOwner->AbstractMainThread())
, mLogicalPosition(0.0)
, mDuration(std::numeric_limits<double>::quiet_NaN())
- , mResourceCallback(new ResourceCallback(aInit.mOwner->AbstractMainThread()))
, mCDMProxyPromise(mCDMProxyPromiseHolder.Ensure(__func__))
, mIgnoreProgressData(false)
, mInfiniteStream(false)
, mOwner(aInit.mOwner)
, mAbstractMainThread(aInit.mOwner->AbstractMainThread())
, mFrameStats(new FrameStatistics())
, mVideoFrameContainer(aInit.mOwner->GetVideoFrameContainer())
, mPinnedForSeek(false)
@@ -398,18 +262,16 @@ MediaDecoder::MediaDecoder(MediaDecoderI
, mTelemetryReported(false)
, mIsMediaElement(!!mOwner->GetMediaElement())
, mElement(mOwner->GetMediaElement())
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mAbstractMainThread);
MediaMemoryTracker::AddMediaDecoder(this);
- mResourceCallback->Connect(this);
-
//
// Initialize watchers.
//
// mDuration
mWatchManager.Watch(mStateMachineDuration, &MediaDecoder::DurationChanged);
// readyState
@@ -440,18 +302,16 @@ void
MediaDecoder::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
// Unwatch all watch targets to prevent further notifications.
mWatchManager.Shutdown();
- mResourceCallback->Disconnect();
-
mCDMProxyPromiseHolder.RejectIfExists(true, __func__);
DiscardOngoingSeekIfExists();
// This changes the decoder state to SHUTDOWN and does other things
// necessary to unblock the state machine thread if it's blocked, so
// the asynchronous shutdown in nsDestroyStateMachine won't deadlock.
if (mDecoderStateMachine) {
@@ -506,17 +366,16 @@ MediaDecoder::NotifyXPCOMShutdown()
Shutdown();
}
}
MediaDecoder::~MediaDecoder()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(IsShutdown());
- mResourceCallback->Disconnect();
MediaMemoryTracker::RemoveMediaDecoder(this);
UnpinForSeek();
}
void
MediaDecoder::OnPlaybackEvent(MediaEventType aEvent)
{
switch (aEvent) {
@@ -581,22 +440,16 @@ MediaDecoder::FinishShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
mDecoderStateMachine->BreakCycles();
SetStateMachine(nullptr);
mVideoFrameContainer = nullptr;
MediaShutdownManager::Instance().Unregister(this);
}
-MediaResourceCallback*
-MediaDecoder::GetResourceCallback() const
-{
- return mResourceCallback;
-}
-
nsresult
MediaDecoder::OpenResource(nsIStreamListener** aStreamListener)
{
MOZ_ASSERT(NS_IsMainThread());
if (aStreamListener) {
*aStreamListener = nullptr;
}
return mResource->Open(aStreamListener);
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -24,17 +24,16 @@
#include "nsITimer.h"
#include "AbstractMediaDecoder.h"
#include "DecoderDoctorDiagnostics.h"
#include "MediaDecoderOwner.h"
#include "MediaEventSource.h"
#include "MediaMetadataManager.h"
#include "MediaResource.h"
-#include "MediaResourceCallback.h"
#include "MediaStatistics.h"
#include "MediaStreamGraph.h"
#include "TimeUnits.h"
#include "SeekTarget.h"
class nsIStreamListener;
class nsIPrincipal;
@@ -86,51 +85,16 @@ struct MediaDecoderInit
, mLooping(aLooping)
{
}
};
class MediaDecoder : public AbstractMediaDecoder
{
public:
- // Used to register with MediaResource to receive notifications which will
- // be forwarded to MediaDecoder.
- class ResourceCallback : public MediaResourceCallback
- {
- // Throttle calls to MediaDecoder::NotifyDataArrived()
- // to be at most once per 500ms.
- static const uint32_t sDelay = 500;
-
- public:
- explicit ResourceCallback(AbstractThread* aMainThread);
- // Start to receive notifications from ResourceCallback.
- void Connect(MediaDecoder* aDecoder);
- // Called upon shutdown to stop receiving notifications.
- void Disconnect();
-
- private:
- /* MediaResourceCallback functions */
- MediaDecoderOwner* GetMediaOwner() const override;
- void SetInfinite(bool aInfinite) override;
- void NotifyNetworkError() override;
- void NotifyDataArrived() override;
- void NotifyDataEnded(nsresult aStatus) override;
- void NotifyPrincipalChanged() override;
- void NotifySuspendedStatusChanged() override;
- void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) override;
-
- static void TimerCallback(nsITimer* aTimer, void* aClosure);
-
- // The decoder to send notifications. Main-thread only.
- MediaDecoder* mDecoder = nullptr;
- nsCOMPtr<nsITimer> mTimer;
- bool mTimerArmed = false;
- const RefPtr<AbstractThread> mAbstractMainThread;
- };
-
typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */,
/* IsExclusive = */ true>
SeekPromise;
NS_DECL_THREADSAFE_ISUPPORTS
// Enumeration for the valid play states (see mPlayState)
enum PlayState
@@ -143,19 +107,16 @@ public:
PLAY_STATE_SHUTDOWN
};
// Must be called exactly once, on the main thread, during startup.
static void InitStatics();
explicit MediaDecoder(MediaDecoderInit& aInit);
- // Return a callback object used to register with MediaResource to receive
- // notifications.
- MediaResourceCallback* GetResourceCallback() const;
// Create a new state machine to run this decoder.
// Subclasses must implement this.
virtual MediaDecoderStateMachine* CreateStateMachine() = 0;
// Cleanup internal data structures. Must be called on the main
// thread by the owning object before that object disposes of this object.
virtual void Shutdown();
@@ -576,22 +537,16 @@ protected:
// Amount of buffered data ahead of current time required to consider that
// the next frame is available.
// An arbitrary value of 250ms is used.
static constexpr auto DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED =
media::TimeUnit::FromMicroseconds(250000);
private:
- void NotifyDataArrivedInternal();
-
- // Called to recompute playback rate and notify 'progress' event.
- // Call on the main thread only.
- void DownloadProgressed();
-
nsCString GetDebugInfo();
// Called when the metadata from the media file has been loaded by the
// state machine. Call on the main thread only.
void MetadataLoaded(UniquePtr<MediaInfo> aInfo,
UniquePtr<MetadataTags> aTags,
MediaDecoderEventVisibility aEventVisibility);
@@ -626,25 +581,58 @@ private:
// call methods of this object from other threads. Its internal data
// is synchronised on a monitor. The lifetime of this object is
// after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
// is safe to access it during this period.
//
// Explicitly prievate to force access via accessors.
RefPtr<MediaDecoderStateMachine> mDecoderStateMachine;
- RefPtr<ResourceCallback> mResourceCallback;
-
MozPromiseHolder<CDMProxyPromise> mCDMProxyPromiseHolder;
RefPtr<CDMProxyPromise> mCDMProxyPromise;
protected:
+ void NotifyDataArrivedInternal();
void DiscardOngoingSeekIfExists();
virtual void CallSeek(const SeekTarget& aTarget);
+ // Called to recompute playback rate and notify 'progress' event.
+ // Call on the main thread only.
+ void DownloadProgressed();
+
+ // A media stream is assumed to be infinite if the metadata doesn't
+ // contain the duration, and range requests are not supported, and
+ // no headers give a hint of a possible duration (Content-Length,
+ // Content-Duration, and variants), and we cannot seek in the media
+ // stream to determine the duration.
+ //
+ // When the media stream ends, we can know the duration, thus the stream is
+ // no longer considered to be infinite.
+ void SetInfinite(bool aInfinite);
+
+ // Called by MediaResource when the "cache suspended" status changes.
+ // If MediaResource::IsSuspendedByCache returns true, then the decoder
+ // should stop buffering or otherwise waiting for download progress and
+ // start consuming data, if possible, because the cache is full.
+ void NotifySuspendedStatusChanged();
+
+ // Called by MediaResource when the principal of the resource has
+ // changed. Called on main thread only.
+ void NotifyPrincipalChanged();
+
+ // Called by the MediaResource to keep track of the number of bytes read
+ // from the resource. Called on the main by an event runner dispatched
+ // by the MediaResource read functions.
+ void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset);
+
+ // Called by nsChannelToPipeListener or MediaResource when the
+ // download has ended. Called on the main thread only. aStatus is
+ // the result from OnStopRequest.
+ void NotifyDownloadEnded(nsresult aStatus);
+
MozPromiseRequestHolder<SeekPromise> mSeekRequest;
// True when seeking or otherwise moving the play position around in
// such a manner that progress event data is inaccurate. This is set
// during seek and duration operations to prevent the progress indicator
// from jumping around. Read/Write on the main thread only.
bool mIgnoreProgressData;
@@ -847,48 +835,16 @@ public:
{
return &mDecoderPosition;
}
private:
// Notify owner when the audible state changed
void NotifyAudibleStateChanged();
- /* Functions called by ResourceCallback */
-
- // A media stream is assumed to be infinite if the metadata doesn't
- // contain the duration, and range requests are not supported, and
- // no headers give a hint of a possible duration (Content-Length,
- // Content-Duration, and variants), and we cannot seek in the media
- // stream to determine the duration.
- //
- // When the media stream ends, we can know the duration, thus the stream is
- // no longer considered to be infinite.
- void SetInfinite(bool aInfinite);
-
- // Called by MediaResource when the principal of the resource has
- // changed. Called on main thread only.
- void NotifyPrincipalChanged();
-
- // Called by MediaResource when the "cache suspended" status changes.
- // If MediaResource::IsSuspendedByCache returns true, then the decoder
- // should stop buffering or otherwise waiting for download progress and
- // start consuming data, if possible, because the cache is full.
- void NotifySuspendedStatusChanged();
-
- // Called by the MediaResource to keep track of the number of bytes read
- // from the resource. Called on the main by an event runner dispatched
- // by the MediaResource read functions.
- void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset);
-
- // Called by nsChannelToPipeListener or MediaResource when the
- // download has ended. Called on the main thread only. aStatus is
- // the result from OnStopRequest.
- void NotifyDownloadEnded(nsresult aStatus);
-
bool mTelemetryReported;
// Used to debug how mOwner becomes a dangling pointer in bug 1326294.
bool mIsMediaElement;
WeakPtr<dom::HTMLMediaElement> mElement;
};
} // namespace mozilla