diff --git a/dom/html/HTMLAudioElement.cpp b/dom/html/HTMLAudioElement.cpp index 69a2a60d40fe..2572f4011849 100644 --- a/dom/html/HTMLAudioElement.cpp +++ b/dom/html/HTMLAudioElement.cpp @@ -20,12 +20,31 @@ #include "mozilla/dom/TimeRanges.h" #include "AudioStream.h" -NS_IMPL_NS_NEW_HTML_ELEMENT(Audio) +nsGenericHTMLElement* NS_NewHTMLAudioElement( + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser) { + mozilla::dom::HTMLAudioElement* element = + new mozilla::dom::HTMLAudioElement(std::move(aNodeInfo)); + element->Init(); + return element; +} namespace mozilla { namespace dom { -NS_IMPL_ELEMENT_CLONE(HTMLAudioElement) +nsresult HTMLAudioElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, + nsINode** aResult) const { + *aResult = nullptr; + RefPtr ni(aNodeInfo); + HTMLAudioElement* it = new HTMLAudioElement(ni.forget()); + it->Init(); + nsCOMPtr kungFuDeathGrip = it; + nsresult rv = const_cast(this)->CopyInnerTo(it); + if (NS_SUCCEEDED(rv)) { + kungFuDeathGrip.swap(*aResult); + } + return rv; +} HTMLAudioElement::HTMLAudioElement(already_AddRefed&& aNodeInfo) : HTMLMediaElement(std::move(aNodeInfo)) { @@ -54,7 +73,8 @@ already_AddRefed HTMLAudioElement::Audio( RefPtr nodeInfo = doc->NodeInfoManager()->GetNodeInfo( nsGkAtoms::audio, nullptr, kNameSpaceID_XHTML, ELEMENT_NODE); - RefPtr audio = new HTMLAudioElement(nodeInfo.forget()); + RefPtr audio = + static_cast(NS_NewHTMLAudioElement(nodeInfo.forget())); audio->SetHTMLAttr(nsGkAtoms::preload, NS_LITERAL_STRING("auto"), aRv); if (aRv.Failed()) { return nullptr; diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index f305cdcb867b..e1b432c773d4 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -3498,13 +3498,27 @@ HTMLMediaElement::HTMLMediaElement( mShutdownObserver(new ShutdownObserver), mPlayed(new TimeRanges(ToSupports(OwnerDoc()))), mPaused(true, "HTMLMediaElement::mPaused"), - mAudioTrackList(new AudioTrackList(OwnerDoc()->GetParentObject(), this)), - mVideoTrackList(new VideoTrackList(OwnerDoc()->GetParentObject(), this)), mErrorSink(new ErrorSink(this)), mAudioChannelWrapper(new AudioChannelAgentCallback(this)), mSink(MakePair(nsString(), RefPtr())) { MOZ_ASSERT(mMainThreadEventTarget); MOZ_ASSERT(mAbstractMainThread); + // Please don't add anything to this constructor or the initialization + // list that can cause AddRef to be called. This prevents subclasses + // from overriding AddRef in a way that works with our refcount + // logging mechanisms. Put these things inside of the ::Init method + // instead. +} + +void HTMLMediaElement::Init() { + MOZ_ASSERT(mRefCnt == 0 && !mRefCnt.IsPurple(), + "HTMLMediaElement::Init called when AddRef has been called " + "at least once already, probably in the constructor. Please " + "see the documentation in the HTMLMediaElement constructor."); + MOZ_ASSERT(!mRefCnt.IsPurple()); + + mAudioTrackList = new AudioTrackList(OwnerDoc()->GetParentObject(), this); + mVideoTrackList = new VideoTrackList(OwnerDoc()->GetParentObject(), this); DecoderDoctorLogger::LogConstruction(this); @@ -3525,9 +3539,12 @@ HTMLMediaElement::HTMLMediaElement( MediaShutdownManager::InitStatics(); mShutdownObserver->Subscribe(this); + mInitialized = true; } HTMLMediaElement::~HTMLMediaElement() { + MOZ_ASSERT(mInitialized, + "HTMLMediaElement must be initialized before it is destroyed."); NS_ASSERTION( !mHasSelfReference, "How can we be destroyed if we're still holding a self reference?"); diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index ac86a02b8c19..2aba76d77b13 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -117,6 +117,7 @@ class HTMLMediaElement : public nsGenericHTMLElement, explicit HTMLMediaElement( already_AddRefed&& aNodeInfo); + void Init(); void ReportCanPlayTelemetry(); @@ -1750,6 +1751,9 @@ class HTMLMediaElement : public nsGenericHTMLElement, // threshold. void ReportPlayedTimeAfterBlockedTelemetry(); + // True if Init() has been called after construction + bool mInitialized = false; + // True if user has called load(), seek() or element has started playing // before. It's *only* use for checking autoplay policy bool mIsBlessed = false; diff --git a/dom/html/HTMLVideoElement.cpp b/dom/html/HTMLVideoElement.cpp index 15b4fd89d307..9e60ce506a93 100644 --- a/dom/html/HTMLVideoElement.cpp +++ b/dom/html/HTMLVideoElement.cpp @@ -35,14 +35,33 @@ #include #include -NS_IMPL_NS_NEW_HTML_ELEMENT(Video) +nsGenericHTMLElement* NS_NewHTMLVideoElement( + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser) { + mozilla::dom::HTMLVideoElement* element = + new mozilla::dom::HTMLVideoElement(std::move(aNodeInfo)); + element->Init(); + return element; +} namespace mozilla { namespace dom { static bool sVideoStatsEnabled; -NS_IMPL_ELEMENT_CLONE(HTMLVideoElement) +nsresult HTMLVideoElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, + nsINode** aResult) const { + *aResult = nullptr; + RefPtr ni(aNodeInfo); + HTMLVideoElement* it = new HTMLVideoElement(ni.forget()); + it->Init(); + nsCOMPtr kungFuDeathGrip = it; + nsresult rv = const_cast(this)->CopyInnerTo(it); + if (NS_SUCCEEDED(rv)) { + kungFuDeathGrip.swap(*aResult); + } + return rv; +} HTMLVideoElement::HTMLVideoElement(already_AddRefed&& aNodeInfo) : HTMLMediaElement(std::move(aNodeInfo)), mIsOrientationLocked(false) { @@ -308,7 +327,8 @@ void HTMLVideoElement::ReleaseVideoWakeLockIfExists() { } } -void HTMLVideoElement::Init() { +/* static */ +void HTMLVideoElement::InitStatics() { Preferences::AddBoolVarCache(&sVideoStatsEnabled, "media.video_stats.enabled"); } diff --git a/dom/html/HTMLVideoElement.h b/dom/html/HTMLVideoElement.h index 4e18fe68f638..e2acce0b3528 100644 --- a/dom/html/HTMLVideoElement.h +++ b/dom/html/HTMLVideoElement.h @@ -38,7 +38,7 @@ class HTMLVideoElement final : public HTMLMediaElement { nsAttrValue& aResult) override; NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override; - static void Init(); + static void InitStatics(); virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index e4b343ef7466..13ee34c9735c 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -255,7 +255,7 @@ nsresult nsLayoutStatics::Initialize() { nsCookieService::AppClearDataObserverInit(); nsApplicationCacheService::AppClearDataObserverInit(); - HTMLVideoElement::Init(); + HTMLVideoElement::InitStatics(); nsGenericHTMLFrameElement::InitStatics(); #ifdef MOZ_XUL