Bug 1281418 - Release and reload the vtt resource when the src attribute of TrackElement changed. r=rillian draft
authorbechen <bechen@mozilla.com>
Thu, 21 Jul 2016 16:49:24 +0800
changeset 390523 85f35210d368c874534e1209b51291db54197414
parent 389838 fe12b9988437e2bf9eb87dbd54e37ef0901e2569
child 526013 a8239b3c45c2984a8255aa27ddc43978822f7e82
push id23685
push userbechen@mozilla.com
push dateThu, 21 Jul 2016 09:22:13 +0000
reviewersrillian
bugs1281418
milestone50.0a1
Bug 1281418 - Release and reload the vtt resource when the src attribute of TrackElement changed. r=rillian MozReview-Commit-ID: B8wdOxP3HId
dom/html/HTMLTrackElement.cpp
dom/html/HTMLTrackElement.h
--- a/dom/html/HTMLTrackElement.cpp
+++ b/dom/html/HTMLTrackElement.cpp
@@ -71,16 +71,17 @@ static constexpr nsAttrValue::EnumTable 
 
 // Invalid values are treated as "metadata" in ParseAttribute, but if no value
 // at all is specified, it's treated as "subtitles" in GetKind
 static constexpr const nsAttrValue::EnumTable* kKindTableInvalidValueDefault = &kKindTable[4];
 
 /** HTMLTrackElement */
 HTMLTrackElement::HTMLTrackElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
+  , mLoadResourceDispatched(false)
 {
 }
 
 HTMLTrackElement::~HTMLTrackElement()
 {
 }
 
 NS_IMPL_ELEMENT_CLONE(HTMLTrackElement)
@@ -178,18 +179,55 @@ HTMLTrackElement::ParseAttribute(int32_t
   // Otherwise call the generic implementation.
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID,
                                               aAttribute,
                                               aValue,
                                               aResult);
 }
 
 void
+HTMLTrackElement::SetSrc(const nsAString& aSrc, ErrorResult& aError)
+{
+  SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
+  uint16_t oldReadyState = ReadyState();
+  SetReadyState(TextTrackReadyState::NotLoaded);
+  if (!mMediaParent) {
+    return;
+  }
+  if (mTrack && (oldReadyState != TextTrackReadyState::NotLoaded)) {
+    // Remove all the cues in MediaElement.
+    mMediaParent->RemoveTextTrack(mTrack);
+    // Recreate mTrack.
+    CreateTextTrack();
+  }
+  // Stop WebVTTListener.
+  mListener = nullptr;
+  if (mChannel) {
+    mChannel->Cancel(NS_BINDING_ABORTED);
+    mChannel = nullptr;
+  }
+
+  DispatchLoadResource();
+}
+
+void
+HTMLTrackElement::DispatchLoadResource()
+{
+  if (!mLoadResourceDispatched) {
+    RefPtr<Runnable> r = NewRunnableMethod(this, &HTMLTrackElement::LoadResource);
+    nsContentUtils::RunInStableState(r.forget());
+    mLoadResourceDispatched = true;
+  }
+}
+
+void
 HTMLTrackElement::LoadResource()
 {
+  mLoadResourceDispatched = false;
+
   // Find our 'src' url
   nsAutoString src;
   if (!GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
     return;
   }
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NewURIFromString(src, getter_AddRefs(uri));
@@ -253,18 +291,17 @@ HTMLTrackElement::BindToTree(nsIDocument
     LOG(LogLevel::Debug, ("Track element sent notification to parent."));
 
     // We may already have a TextTrack at this point if GetTrack() has already
     // been called. This happens, for instance, if script tries to get the
     // TextTrack before its mTrackElement has been bound to the DOM tree.
     if (!mTrack) {
       CreateTextTrack();
     }
-    RefPtr<Runnable> r = NewRunnableMethod(this, &HTMLTrackElement::LoadResource);
-    nsContentUtils::RunInStableState(r.forget());
+    DispatchLoadResource();
   }
 
   return NS_OK;
 }
 
 void
 HTMLTrackElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
--- a/dom/html/HTMLTrackElement.h
+++ b/dom/html/HTMLTrackElement.h
@@ -41,20 +41,18 @@ public:
   {
     SetHTMLAttr(nsGkAtoms::kind, aKind, aError);
   }
 
   void GetSrc(DOMString& aSrc) const
   {
     GetHTMLURIAttr(nsGkAtoms::src, aSrc);
   }
-  void SetSrc(const nsAString& aSrc, ErrorResult& aError)
-  {
-    SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
-  }
+
+  void SetSrc(const nsAString& aSrc, ErrorResult& aError);
 
   void GetSrclang(DOMString& aSrclang) const
   {
     GetHTMLAttr(nsGkAtoms::srclang, aSrclang);
   }
   void GetSrclang(nsAString& aSrclang) const
   {
     GetHTMLAttr(nsGkAtoms::srclang, aSrclang);
@@ -129,14 +127,18 @@ protected:
   friend class WebVTTListener;
 
   RefPtr<TextTrack> mTrack;
   nsCOMPtr<nsIChannel> mChannel;
   RefPtr<HTMLMediaElement> mMediaParent;
   RefPtr<WebVTTListener> mListener;
 
   void CreateTextTrack();
+
+private:
+  void DispatchLoadResource();
+  bool mLoadResourceDispatched;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLTrackElement_h