Bug 1338137 - part1 : ref media content when the media element bind to tree.
In bug1319771, we found that the tab would become visible unexpectly in short
period in some situations. We don't want to resume the tab in this kind of
situation, so we check whether there is any alive media component in the tab
using IsServiceStarted(). However, since we have lots different ways to create
the service, this function is not accurate at all.
Therefore, we can add media element directly to the document when it binds to
tree so that we can really know whether there is any alive media component.
MozReview-Commit-ID: FvZFg91IqgE
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -10270,16 +10270,32 @@ nsDocument::AddResponsiveContent(nsICont
void
nsDocument::RemoveResponsiveContent(nsIContent* aContent)
{
MOZ_ASSERT(aContent);
mResponsiveContent.RemoveEntry(aContent);
}
void
+nsDocument::AddMediaContent(nsIContent* aContent)
+{
+ MOZ_ASSERT(aContent);
+ MOZ_ASSERT(aContent->IsHTMLElement(nsGkAtoms::video) ||
+ aContent->IsHTMLElement(nsGkAtoms::audio));
+ mMediaContent.PutEntry(aContent);
+}
+
+void
+nsDocument::RemoveMediaContent(nsIContent* aContent)
+{
+ MOZ_ASSERT(aContent);
+ mMediaContent.RemoveEntry(aContent);
+}
+
+void
nsDocument::NotifyMediaFeatureValuesChanged()
{
for (auto iter = mResponsiveContent.ConstIter(); !iter.Done();
iter.Next()) {
nsCOMPtr<nsIContent> content = iter.Get()->GetKey();
if (content->IsHTMLElement(nsGkAtoms::img)) {
auto* imageElement = static_cast<HTMLImageElement*>(content.get());
imageElement->MediaFeatureValuesChanged();
@@ -12070,16 +12086,20 @@ nsDocument::MaybeActiveMediaComponents()
if (mEverInForeground) {
return;
}
if (!mWindow) {
return;
}
+ if (mMediaContent.IsEmpty()) {
+ return;
+ }
+
mEverInForeground = true;
GetWindow()->MaybeActiveMediaComponents();
}
NS_IMETHODIMP
nsDocument::GetHidden(bool* aHidden)
{
*aHidden = Hidden();
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1006,16 +1006,23 @@ public:
virtual nsresult AddResponsiveContent(nsIContent* aContent) override;
// Removes an element from mResponsiveContent when the element is
// removed from the tree.
virtual void RemoveResponsiveContent(nsIContent* aContent) override;
// Notifies any responsive content added by AddResponsiveContent upon media
// features values changing.
virtual void NotifyMediaFeatureValuesChanged() override;
+ // Adds an element to mMediaContent when the element is added to the tree.
+ virtual void AddMediaContent(nsIContent* aContent) override;
+
+ // Removes an element from mMediaContent when the element is removed from
+ // the tree.
+ virtual void RemoveMediaContent(nsIContent* aContent) override;
+
virtual nsresult GetStateObject(nsIVariant** aResult) override;
virtual nsDOMNavigationTiming* GetNavigationTiming() const override;
virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) override;
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) override;
virtual nsTArray<Element*> GetFullscreenStack() const override;
@@ -1553,16 +1560,19 @@ private:
// state so we can provide useful assertions to consumers of ForgetLink and
// AddStyleRelevantLink.
bool mStyledLinksCleared;
#endif
// A set of responsive images keyed by address pointer.
nsTHashtable< nsPtrHashKey<nsIContent> > mResponsiveContent;
+ // A set of media elements keyed by address pointer.
+ nsTHashtable<nsPtrHashKey<nsIContent>> mMediaContent;
+
// Member to store out last-selected stylesheet set.
nsString mLastStyleSheetSet;
nsTArray<RefPtr<nsFrameLoader> > mInitializableFrameLoaders;
nsTArray<nsCOMPtr<nsIRunnable> > mFrameLoaderFinalizers;
RefPtr<nsRunnableMethod<nsDocument> > mFrameLoaderRunner;
nsCOMPtr<nsIRunnable> mMaybeEndOutermostXBLUpdateRunner;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2428,16 +2428,19 @@ public:
virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) = 0;
virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin) = 0;
virtual void GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins) = 0;
virtual nsresult AddResponsiveContent(nsIContent* aContent) = 0;
virtual void RemoveResponsiveContent(nsIContent* aContent) = 0;
virtual void NotifyMediaFeatureValuesChanged() = 0;
+ virtual void AddMediaContent(nsIContent* aContent) = 0;
+ virtual void RemoveMediaContent(nsIContent* aContent) = 0;
+
virtual nsresult GetStateObject(nsIVariant** aResult) = 0;
virtual nsDOMNavigationTiming* GetNavigationTiming() const = 0;
virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) = 0;
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4274,16 +4274,17 @@ nsresult HTMLMediaElement::BindToTree(ns
if (aDocument) {
mAutoplayEnabled =
IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument()) &&
!IsEditable();
// The preload action depends on the value of the autoplay attribute.
// It's value may have changed, so update it.
UpdatePreloadAction();
+ aDocument->AddMediaContent(this);
}
if (mDecoder) {
// When the MediaElement is binding to tree, the dormant status is
// aligned to document's hidden status.
mDecoder->NotifyOwnerActivityChanged(!IsHidden());
}
@@ -4509,16 +4510,19 @@ HTMLMediaElement::ReportTelemetry()
}
}
}
void HTMLMediaElement::UnbindFromTree(bool aDeep,
bool aNullParent)
{
mUnboundFromTree = true;
+ if (OwnerDoc()) {
+ OwnerDoc()->RemoveMediaContent(this);
+ }
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
if (mDecoder) {
MOZ_ASSERT(IsHidden());
mDecoder->NotifyOwnerActivityChanged(false);
}