Bug 1338137 - part1 : ref media content when the media element bind to tree. r=baku
authorAlastor Wu <alwu@mozilla.com>
Sat, 04 Mar 2017 01:14:24 +0800
changeset 374913 193319b673f2e8d43a18ee6d0d18c1114396b4e1
parent 374912 7b8d033f771784cdf6f1048a92b5fd00ed48c43c
child 374914 422571b302dab5db408a3fcc89571788646b8d68
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1338137, 1319771
milestone54.0a1
Bug 1338137 - part1 : ref media content when the media element bind to tree. r=baku 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
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsIDocument.h
dom/html/HTMLMediaElement.cpp
--- 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);
   }