Bug 744896 - Part 1: Implement AudioTrack, VideoTrack and other related interfaces. r=bz,roc
☠☠ backed out by 77cca699e70f ☠ ☠
authorShelly Lin <slin@mozilla.com>
Wed, 16 Apr 2014 11:06:45 +0800
changeset 192165 b191be106cae30ec2477531fc53531cb53c35a64
parent 192164 f1bacafe789c9d30ae8e5f49f31822ed942217cc
child 192166 d8350c75691040b4d021fce2c835bcfd8a54b0ce
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbz, roc
bugs744896
milestone33.0a1
Bug 744896 - Part 1: Implement AudioTrack, VideoTrack and other related interfaces. r=bz,roc
content/media/AudioTrack.cpp
content/media/AudioTrack.h
content/media/AudioTrackList.cpp
content/media/AudioTrackList.h
content/media/MediaTrack.cpp
content/media/MediaTrack.h
content/media/MediaTrackList.cpp
content/media/MediaTrackList.h
content/media/TextTrackList.cpp
content/media/VideoTrack.cpp
content/media/VideoTrack.h
content/media/VideoTrackList.cpp
content/media/VideoTrackList.h
content/media/moz.build
dom/webidl/AudioTrack.webidl
dom/webidl/AudioTrackList.webidl
dom/webidl/TrackEvent.webidl
dom/webidl/VideoTrack.webidl
dom/webidl/VideoTrackList.webidl
dom/webidl/moz.build
modules/libpref/src/init/all.js
new file mode 100644
--- /dev/null
+++ b/content/media/AudioTrack.cpp
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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/. */
+
+#include "mozilla/dom/AudioTrack.h"
+#include "mozilla/dom/AudioTrackBinding.h"
+#include "mozilla/dom/AudioTrackList.h"
+#include "mozilla/dom/HTMLMediaElement.h"
+
+namespace mozilla {
+namespace dom {
+
+AudioTrack::AudioTrack(const nsAString& aId,
+                       const nsAString& aKind,
+                       const nsAString& aLabel,
+                       const nsAString& aLanguage,
+                       bool aEnabled)
+  : MediaTrack(aId, aKind, aLabel, aLanguage)
+  , mEnabled(aEnabled)
+{
+}
+
+JSObject*
+AudioTrack::WrapObject(JSContext* aCx)
+{
+  return AudioTrackBinding::Wrap(aCx, this);
+}
+
+void
+AudioTrack::SetEnabled(bool aEnabled)
+{
+  SetEnabledInternal(aEnabled, MediaTrack::DEFAULT);
+}
+
+void
+AudioTrack::SetEnabledInternal(bool aEnabled, int aFlags)
+{
+  if (aEnabled == mEnabled) {
+    return;
+  }
+  mEnabled = aEnabled;
+
+  // If this AudioTrack is no longer in its original AudioTrackList, then
+  // whether it is enabled or not has no effect on its original list.
+  if (!mList) {
+    return;
+  }
+
+  if (!(aFlags & MediaTrack::FIRE_NO_EVENTS)) {
+    mList->CreateAndDispatchChangeEvent();
+  }
+}
+
+} // namespace dom
+} //namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/AudioTrack.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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 mozilla_dom_AudioTrack_h
+#define mozilla_dom_AudioTrack_h
+
+#include "MediaTrack.h"
+
+namespace mozilla {
+namespace dom {
+
+class AudioTrackList;
+
+class AudioTrack : public MediaTrack
+{
+public:
+  AudioTrack(const nsAString& aId,
+             const nsAString& aKind,
+             const nsAString& aLabel,
+             const nsAString& aLanguage,
+             bool aEnabled);
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  virtual AudioTrack* AsAudioTrack() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
+  virtual void SetEnabledInternal(bool aEnabled, int aFlags) MOZ_OVERRIDE;
+
+  // WebIDL
+  bool Enabled() const
+  {
+    return mEnabled;
+  }
+
+  void SetEnabled(bool aEnabled);
+
+private:
+  bool mEnabled;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_AudioTrack_h
new file mode 100644
--- /dev/null
+++ b/content/media/AudioTrackList.cpp
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "mozilla/dom/AudioTrack.h"
+#include "mozilla/dom/AudioTrackList.h"
+#include "mozilla/dom/AudioTrackListBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+JSObject*
+AudioTrackList::WrapObject(JSContext* aCx)
+{
+  return AudioTrackListBinding::Wrap(aCx, this);
+}
+
+AudioTrack*
+AudioTrackList::operator[](uint32_t aIndex)
+{
+  MediaTrack* track = MediaTrackList::operator[](aIndex);
+  return track->AsAudioTrack();
+}
+
+AudioTrack*
+AudioTrackList::IndexedGetter(uint32_t aIndex, bool& aFound)
+{
+  MediaTrack* track = MediaTrackList::IndexedGetter(aIndex, aFound);
+  return track ? track->AsAudioTrack() : nullptr;
+}
+
+AudioTrack*
+AudioTrackList::GetTrackById(const nsAString& aId)
+{
+  MediaTrack* track = MediaTrackList::GetTrackById(aId);
+  return track ? track->AsAudioTrack() : nullptr;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/AudioTrackList.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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 mozilla_dom_AudioTrackList_h
+#define mozilla_dom_AudioTrackList_h
+
+#include "MediaTrack.h"
+#include "MediaTrackList.h"
+
+namespace mozilla {
+namespace dom {
+
+class AudioTrack;
+
+class AudioTrackList : public MediaTrackList
+{
+public:
+  AudioTrackList(nsPIDOMWindow* aOwnerWindow, HTMLMediaElement* aMediaElement)
+    : MediaTrackList(aOwnerWindow, aMediaElement) {}
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  AudioTrack* operator[](uint32_t aIndex);
+
+  // WebIDL
+  AudioTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
+
+  AudioTrack* GetTrackById(const nsAString& aId);
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_AudioTrackList_h
new file mode 100644
--- /dev/null
+++ b/content/media/MediaTrack.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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/. */
+
+#include "MediaTrack.h"
+#include "MediaTrackList.h"
+
+namespace mozilla {
+namespace dom {
+
+MediaTrack::MediaTrack(const nsAString& aId,
+                       const nsAString& aKind,
+                       const nsAString& aLabel,
+                       const nsAString& aLanguage)
+  : DOMEventTargetHelper()
+  , mId(aId)
+  , mKind(aKind)
+  , mLabel(aLabel)
+  , mLanguage(aLanguage)
+{
+}
+
+MediaTrack::~MediaTrack()
+{
+}
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaTrack, DOMEventTargetHelper, mList)
+
+NS_IMPL_ADDREF_INHERITED(MediaTrack, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(MediaTrack, DOMEventTargetHelper)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaTrack)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+void
+MediaTrack::SetTrackList(MediaTrackList* aList)
+{
+  mList = aList;
+}
+
+void
+MediaTrack::Init(nsPIDOMWindow* aOwnerWindow)
+{
+  BindToOwner(aOwnerWindow);
+  SetIsDOMBinding();
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/MediaTrack.h
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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 mozilla_dom_MediaTrack_h
+#define mozilla_dom_MediaTrack_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+
+namespace mozilla {
+namespace dom {
+
+class MediaTrackList;
+class VideoTrack;
+class AudioTrack;
+
+/**
+ * Base class of AudioTrack and VideoTrack. The AudioTrack and VideoTrack
+ * objects represent specific tracks of a media resource. Each track has aspects
+ * of an identifier, category, label, and language, even if a track is removed
+ * from its corresponding track list, those aspects do not change.
+ *
+ * When fetching the media resource, an audio/video track is created if the
+ * media resource is found to have an audio/video track. When the UA has learned
+ * that an audio/video track has ended, this audio/video track will be removed
+ * from its corresponding track list.
+ *
+ * Although AudioTrack and VideoTrack are not EventTargets, TextTrack is, and
+ * TextTrack inherits from MediaTrack as well (or is going to).
+ */
+class MediaTrack : public DOMEventTargetHelper
+{
+public:
+  MediaTrack(const nsAString& aId,
+             const nsAString& aKind,
+             const nsAString& aLabel,
+             const nsAString& aLanguage);
+
+  virtual ~MediaTrack();
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaTrack, DOMEventTargetHelper)
+
+  enum {
+    DEFAULT = 0,
+    FIRE_NO_EVENTS = 1 << 0,
+  };
+  // The default behavior of enabling an audio track or selecting a video track
+  // fires a change event and notifies its media resource about the changes.
+  // It should not fire any events when fetching media resource.
+  virtual void SetEnabledInternal(bool aEnabled, int aFlags) = 0;
+
+  virtual AudioTrack* AsAudioTrack()
+  {
+    return nullptr;
+  }
+
+  virtual VideoTrack* AsVideoTrack()
+  {
+    return nullptr;
+  }
+
+  const nsString& GetId() const
+  {
+    return mId;
+  }
+
+  // WebIDL
+  void GetId(nsAString& aId) const
+  {
+    aId = mId;
+  }
+  void GetKind(nsAString& aKind) const
+  {
+    aKind = mKind;
+  }
+  void GetLabel(nsAString& aLabel) const
+  {
+    aLabel = mLabel;
+  }
+  void GetLanguage(nsAString& aLanguage) const
+  {
+    aLanguage = mLanguage;
+  }
+
+  friend class MediaTrackList;
+
+protected:
+  void SetTrackList(MediaTrackList* aList);
+  void Init(nsPIDOMWindow* aOwnerWindow);
+
+  nsRefPtr<MediaTrackList> mList;
+  nsString mId;
+  nsString mKind;
+  nsString mLabel;
+  nsString mLanguage;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_MediaTrack_h
new file mode 100644
--- /dev/null
+++ b/content/media/MediaTrackList.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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/. */
+
+#include "MediaTrack.h"
+#include "MediaTrackList.h"
+#include "mozilla/AsyncEventDispatcher.h"
+#include "mozilla/dom/AudioTrack.h"
+#include "mozilla/dom/VideoTrack.h"
+#include "mozilla/dom/TrackEvent.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+MediaTrackList::MediaTrackList(nsPIDOMWindow* aOwnerWindow,
+                               HTMLMediaElement* aMediaElement)
+  : DOMEventTargetHelper(aOwnerWindow)
+  , mMediaElement(aMediaElement)
+{
+}
+
+MediaTrackList::~MediaTrackList()
+{
+}
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaTrackList,
+                                   DOMEventTargetHelper,
+                                   mTracks,
+                                   mMediaElement)
+
+NS_IMPL_ADDREF_INHERITED(MediaTrackList, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(MediaTrackList, DOMEventTargetHelper)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaTrackList)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+MediaTrack*
+MediaTrackList::operator[](uint32_t aIndex)
+{
+  return mTracks.ElementAt(aIndex);
+}
+
+MediaTrack*
+MediaTrackList::IndexedGetter(uint32_t aIndex, bool& aFound)
+{
+  aFound = aIndex < mTracks.Length();
+  return aFound ? mTracks[aIndex] : nullptr;
+}
+
+MediaTrack*
+MediaTrackList::GetTrackById(const nsAString& aId)
+{
+  for (uint32_t i = 0; i < mTracks.Length(); ++i) {
+    if (aId.Equals(mTracks[i]->GetId())) {
+      return mTracks[i];
+    }
+  }
+  return nullptr;
+}
+
+void
+MediaTrackList::AddTrack(MediaTrack* aTrack)
+{
+  mTracks.AppendElement(aTrack);
+  aTrack->Init(GetOwner());
+  aTrack->SetTrackList(this);
+  CreateAndDispatchTrackEventRunner(aTrack, NS_LITERAL_STRING("addtrack"));
+}
+
+void
+MediaTrackList::RemoveTrack(const nsRefPtr<MediaTrack>& aTrack)
+{
+  mTracks.RemoveElement(aTrack);
+  aTrack->SetTrackList(nullptr);
+  CreateAndDispatchTrackEventRunner(aTrack, NS_LITERAL_STRING("removetrack"));
+}
+
+void
+MediaTrackList::EmptyTracks()
+{
+  for (uint32_t i = 0; i < mTracks.Length(); ++i) {
+    mTracks[i]->SetTrackList(nullptr);
+  }
+  mTracks.Clear();
+}
+
+void
+MediaTrackList::CreateAndDispatchChangeEvent()
+{
+  nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
+    new AsyncEventDispatcher(this, NS_LITERAL_STRING("change"), false);
+  asyncDispatcher->PostDOMEvent();
+}
+
+void
+MediaTrackList::CreateAndDispatchTrackEventRunner(MediaTrack* aTrack,
+                                                  const nsAString& aEventName)
+{
+  TrackEventInit eventInit;
+
+  if (aTrack->AsAudioTrack()) {
+    eventInit.mTrack.SetValue().SetAsAudioTrack() = aTrack->AsAudioTrack();
+  } else if (aTrack->AsVideoTrack()) {
+    eventInit.mTrack.SetValue().SetAsVideoTrack() = aTrack->AsVideoTrack();
+  }
+
+  nsRefPtr<TrackEvent> event =
+    TrackEvent::Constructor(this, aEventName, eventInit);
+
+  nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
+    new AsyncEventDispatcher(this, event);
+  asyncDispatcher->PostDOMEvent();
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/MediaTrackList.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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 mozilla_dom_MediaTrackList_h
+#define mozilla_dom_MediaTrackList_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+
+namespace mozilla {
+namespace dom {
+
+class HTMLMediaElement;
+class MediaTrack;
+class AudioTrackList;
+class VideoTrackList;
+
+/**
+ * Base class of AudioTrackList and VideoTrackList. The AudioTrackList and
+ * VideoTrackList objects represent a dynamic list of zero or more audio and
+ * video tracks respectively.
+ *
+ * When a media element is to forget its media-resource-specific tracks, its
+ * audio track list and video track list will be emptied.
+ */
+class MediaTrackList : public DOMEventTargetHelper
+{
+public:
+  MediaTrackList(nsPIDOMWindow* aOwnerWindow, HTMLMediaElement* aMediaElement);
+  virtual ~MediaTrackList();
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaTrackList, DOMEventTargetHelper)
+
+  using DOMEventTargetHelper::DispatchTrustedEvent;
+
+  // The return value is non-null, assert an error if aIndex is out of bound
+  // for array mTracks.
+  MediaTrack* operator[](uint32_t aIndex);
+
+  void AddTrack(MediaTrack* aTrack);
+
+  void RemoveTrack(const nsRefPtr<MediaTrack>& aTrack);
+
+  virtual void EmptyTracks();
+
+  void CreateAndDispatchChangeEvent();
+
+  // WebIDL
+  MediaTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
+
+  MediaTrack* GetTrackById(const nsAString& aId);
+
+  uint32_t Length() const
+  {
+    return mTracks.Length();
+  }
+
+  IMPL_EVENT_HANDLER(change)
+  IMPL_EVENT_HANDLER(addtrack)
+  IMPL_EVENT_HANDLER(removetrack)
+
+protected:
+  void CreateAndDispatchTrackEventRunner(MediaTrack* aTrack,
+                                         const nsAString& aEventName);
+
+  nsTArray<nsRefPtr<MediaTrack>> mTracks;
+  nsRefPtr<HTMLMediaElement> mMediaElement;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_MediaTrackList_h
--- a/content/media/TextTrackList.cpp
+++ b/content/media/TextTrackList.cpp
@@ -179,19 +179,17 @@ TextTrackList::CreateAndDispatchChangeEv
   NS_DispatchToMainThread(eventRunner);
 }
 
 void
 TextTrackList::CreateAndDispatchTrackEventRunner(TextTrack* aTrack,
                                                  const nsAString& aEventName)
 {
   TrackEventInit eventInit;
-  eventInit.mBubbles = false;
-  eventInit.mCancelable = false;
-  eventInit.mTrack = aTrack;
+  eventInit.mTrack.SetValue().SetAsTextTrack() = aTrack;
   nsRefPtr<TrackEvent> event =
     TrackEvent::Constructor(this, aEventName, eventInit);
 
   // Dispatch the TrackEvent asynchronously.
   nsCOMPtr<nsIRunnable> eventRunner = new TrackEventRunner(this, event);
   NS_DispatchToMainThread(eventRunner);
 }
 
new file mode 100644
--- /dev/null
+++ b/content/media/VideoTrack.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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/. */
+
+#include "mozilla/dom/HTMLMediaElement.h"
+#include "mozilla/dom/VideoTrack.h"
+#include "mozilla/dom/VideoTrackBinding.h"
+#include "mozilla/dom/VideoTrackList.h"
+
+namespace mozilla {
+namespace dom {
+
+VideoTrack::VideoTrack(const nsAString& aId,
+                       const nsAString& aKind,
+                       const nsAString& aLabel,
+                       const nsAString& aLanguage)
+  : MediaTrack(aId, aKind, aLabel, aLanguage)
+  , mSelected(false)
+{
+}
+
+JSObject*
+VideoTrack::WrapObject(JSContext* aCx)
+{
+  return VideoTrackBinding::Wrap(aCx, this);
+}
+
+void VideoTrack::SetSelected(bool aSelected)
+{
+  SetEnabledInternal(aSelected, MediaTrack::DEFAULT);
+}
+
+void
+VideoTrack::SetEnabledInternal(bool aEnabled, int aFlags)
+{
+  if (aEnabled == mSelected) {
+    return;
+  }
+
+  mSelected = aEnabled;
+
+  // If this VideoTrack is no longer in its original VideoTrackList, then
+  // whether it is selected or not has no effect on its original list.
+  if (!mList) {
+    return;
+  }
+
+  VideoTrackList& list = static_cast<VideoTrackList&>(*mList);
+  if (mSelected) {
+    uint32_t curIndex = 0;
+
+    // Unselect all video tracks except the current one.
+    for (uint32_t i = 0; i < list.Length(); ++i) {
+      if (list[i] == this) {
+        curIndex = i;
+        continue;
+      }
+
+      VideoTrack* track = list[i];
+      track->SetSelected(false);
+    }
+
+    // Set the index of selected video track to the current's index.
+    list.mSelectedIndex = curIndex;
+  } else {
+    list.mSelectedIndex = -1;
+  }
+
+  // Fire the change event at selection changes on this video track, shall
+  // propose a spec change later.
+  if (!(aFlags & MediaTrack::FIRE_NO_EVENTS)) {
+    list.CreateAndDispatchChangeEvent();
+  }
+}
+
+} // namespace dom
+} //namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/VideoTrack.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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 mozilla_dom_VideoTrack_h
+#define mozilla_dom_VideoTrack_h
+
+#include "MediaTrack.h"
+
+namespace mozilla {
+namespace dom {
+
+class VideoTrackList;
+
+class VideoTrack : public MediaTrack
+{
+public:
+  VideoTrack(const nsAString& aId,
+             const nsAString& aKind,
+             const nsAString& aLabel,
+             const nsAString& aLanguage);
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  virtual VideoTrack* AsVideoTrack() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
+  // When fetching media resource, if no video track is selected by the media
+  // resource, then the first VideoTrack object in the list is set selected as
+  // default. If multiple video tracks are selected by its media resource at
+  // fetching phase, then the first enabled video track is set selected.
+  // aFlags contains FIRE_NO_EVENTS because no events are fired in such cases.
+  virtual void SetEnabledInternal(bool aEnabled, int aFlags) MOZ_OVERRIDE;
+
+  // WebIDL
+  bool Selected() const
+  {
+    return mSelected;
+  }
+
+  // Either zero or one video track is selected in a list; If the selected track
+  // is in a VideoTrackList, then all the other VideoTrack objects in that list
+  // must be unselected.
+  void SetSelected(bool aSelected);
+
+private:
+  bool mSelected;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_VideoTrack_h
new file mode 100644
--- /dev/null
+++ b/content/media/VideoTrackList.cpp
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "mozilla/dom/VideoTrack.h"
+#include "mozilla/dom/VideoTrackList.h"
+#include "mozilla/dom/VideoTrackListBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+JSObject*
+VideoTrackList::WrapObject(JSContext* aCx)
+{
+  return VideoTrackListBinding::Wrap(aCx, this);
+}
+
+VideoTrack*
+VideoTrackList::operator[](uint32_t aIndex)
+{
+  MediaTrack* track = MediaTrackList::operator[](aIndex);
+  return track->AsVideoTrack();
+}
+
+void
+VideoTrackList::EmptyTracks()
+{
+  mSelectedIndex = -1;
+  MediaTrackList::EmptyTracks();
+}
+
+VideoTrack*
+VideoTrackList::IndexedGetter(uint32_t aIndex, bool& aFound)
+{
+  MediaTrack* track = MediaTrackList::IndexedGetter(aIndex, aFound);
+  return track ? track->AsVideoTrack() : nullptr;
+}
+
+VideoTrack*
+VideoTrackList::GetTrackById(const nsAString& aId)
+{
+  MediaTrack* track = MediaTrackList::GetTrackById(aId);
+  return track ? track->AsVideoTrack() : nullptr;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/VideoTrackList.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* 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 mozilla_dom_VideoTrackList_h
+#define mozilla_dom_VideoTrackList_h
+
+#include "MediaTrack.h"
+#include "MediaTrackList.h"
+
+namespace mozilla {
+namespace dom {
+
+class VideoTrack;
+
+class VideoTrackList : public MediaTrackList
+{
+public:
+  VideoTrackList(nsPIDOMWindow* aOwnerWindow, HTMLMediaElement* aMediaElement)
+    : MediaTrackList(aOwnerWindow, aMediaElement)
+    , mSelectedIndex(-1)
+  {}
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  VideoTrack* operator[](uint32_t aIndex);
+
+  virtual void EmptyTracks() MOZ_OVERRIDE;
+
+  // WebIDL
+  int32_t SelectedIndex() const
+  {
+    return mSelectedIndex;
+  }
+
+  VideoTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
+
+  VideoTrack* GetTrackById(const nsAString& aId);
+
+  friend class VideoTrack;
+
+private:
+  int32_t mSelectedIndex;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_VideoTrackList_h
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -86,80 +86,92 @@ EXPORTS += [
     'MediaInfo.h',
     'MediaMetadataManager.h',
     'MediaQueue.h',
     'MediaRecorder.h',
     'MediaResource.h',
     'MediaSegment.h',
     'MediaStreamGraph.h',
     'MediaTaskQueue.h',
+    'MediaTrack.h',
+    'MediaTrackList.h',
     'MP3FrameParser.h',
     'nsIDocumentActivity.h',
     'RtspMediaResource.h',
     'SharedBuffer.h',
     'SharedThreadPool.h',
     'StreamBuffer.h',
     'TimeVarying.h',
     'TrackUnionStream.h',
     'VideoFrameContainer.h',
     'VideoSegment.h',
     'VideoUtils.h',
     'VorbisUtils.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'AudioStreamTrack.h',
+    'AudioTrack.h',
+    'AudioTrackList.h',
     'MediaStreamTrack.h',
     'TextTrack.h',
     'TextTrackCue.h',
     'TextTrackCueList.h',
     'TextTrackList.h',
     'TextTrackRegion.h',
     'VideoPlaybackQuality.h',
     'VideoStreamTrack.h',
+    'VideoTrack.h',
+    'VideoTrackList.h',
 ]
 
 UNIFIED_SOURCES += [
     'AudioChannelFormat.cpp',
     'AudioCompactor.cpp',
     'AudioNodeEngine.cpp',
     'AudioNodeExternalInputStream.cpp',
     'AudioNodeStream.cpp',
     'AudioSegment.cpp',
     'AudioSink.cpp',
     'AudioStream.cpp',
     'AudioStreamTrack.cpp',
+    'AudioTrack.cpp',
+    'AudioTrackList.cpp',
     'BufferDecoder.cpp',
     'DOMMediaStream.cpp',
     'EncodedBufferCache.cpp',
     'FileBlockCache.cpp',
     'MediaCache.cpp',
     'MediaData.cpp',
     'MediaDecoder.cpp',
     'MediaDecoderReader.cpp',
     'MediaDecoderStateMachine.cpp',
     'MediaRecorder.cpp',
     'MediaResource.cpp',
     'MediaShutdownManager.cpp',
     'MediaStreamGraph.cpp',
     'MediaStreamTrack.cpp',
     'MediaTaskQueue.cpp',
+    'MediaTrack.cpp',
+    'MediaTrackList.cpp',
     'MP3FrameParser.cpp',
     'RtspMediaResource.cpp',
     'SharedThreadPool.cpp',
     'StreamBuffer.cpp',
     'TextTrack.cpp',
     'TextTrackCue.cpp',
     'TextTrackCueList.cpp',
     'TextTrackList.cpp',
     'TextTrackRegion.cpp',
     'VideoFrameContainer.cpp',
     'VideoPlaybackQuality.cpp',
     'VideoSegment.cpp',
     'VideoStreamTrack.cpp',
+    'VideoTrack.cpp',
+    'VideoTrackList.cpp',
     'VideoUtils.cpp',
     'WebVTTListener.cpp',
 ]
 
 # DecoderTraits.cpp needs to be built separately because of Mac OS X headers.
 # Latency.cpp needs to be built separately because it forces NSPR logging.
 SOURCES += [
     'DecoderTraits.cpp',
new file mode 100644
--- /dev/null
+++ b/dom/webidl/AudioTrack.webidl
@@ -0,0 +1,17 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#audiotrack
+ */
+
+[Pref="media.track.enabled"]
+interface AudioTrack {
+  readonly attribute DOMString id;
+  readonly attribute DOMString kind;
+  readonly attribute DOMString label;
+  readonly attribute DOMString language;
+           attribute boolean enabled;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/AudioTrackList.webidl
@@ -0,0 +1,19 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#audiotracklist
+ */
+
+[Pref="media.track.enabled"]
+interface AudioTrackList : EventTarget {
+  readonly attribute unsigned long length;
+  getter AudioTrack (unsigned long index);
+  AudioTrack? getTrackById(DOMString id);
+
+           attribute EventHandler onchange;
+           attribute EventHandler onaddtrack;
+           attribute EventHandler onremovetrack;
+};
--- a/dom/webidl/TrackEvent.webidl
+++ b/dom/webidl/TrackEvent.webidl
@@ -1,17 +1,19 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#trackevent
  */
 
-
 [Constructor(DOMString type, optional TrackEventInit eventInitDict)]
 interface TrackEvent : Event
 {
-  readonly attribute TextTrack? track;
+  readonly attribute (VideoTrack or AudioTrack or TextTrack)? track;
 };
 
 dictionary TrackEventInit : EventInit
 {
-  TextTrack? track = null;
+  (VideoTrack or AudioTrack or TextTrack)? track = null;
 };
new file mode 100644
--- /dev/null
+++ b/dom/webidl/VideoTrack.webidl
@@ -0,0 +1,17 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#videotrack
+ */
+
+[Pref="media.track.enabled"]
+interface VideoTrack {
+  readonly attribute DOMString id;
+  readonly attribute DOMString kind;
+  readonly attribute DOMString label;
+  readonly attribute DOMString language;
+           attribute boolean selected;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/VideoTrackList.webidl
@@ -0,0 +1,21 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#videotracklist
+ */
+
+[Pref="media.track.enabled"]
+interface VideoTrackList : EventTarget {
+  readonly attribute unsigned long length;
+  getter VideoTrack (unsigned long index);
+  VideoTrack? getTrackById(DOMString id);
+  readonly attribute long selectedIndex;
+
+           attribute EventHandler onchange;
+           attribute EventHandler onaddtrack;
+           attribute EventHandler onremovetrack;
+};
+
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -32,16 +32,18 @@ WEBIDL_FILES = [
     'AudioChannel.webidl',
     'AudioContext.webidl',
     'AudioDestinationNode.webidl',
     'AudioListener.webidl',
     'AudioNode.webidl',
     'AudioParam.webidl',
     'AudioProcessingEvent.webidl',
     'AudioStreamTrack.webidl',
+    'AudioTrack.webidl',
+    'AudioTrackList.webidl',
     'BarProp.webidl',
     'BatteryManager.webidl',
     'BeforeUnloadEvent.webidl',
     'BiquadFilterNode.webidl',
     'Blob.webidl',
     'BrowserElementDictionaries.webidl',
     'CallsList.webidl',
     'CameraCapabilities.webidl',
@@ -461,16 +463,18 @@ WEBIDL_FILES = [
     'UndoManager.webidl',
     'URL.webidl',
     'URLSearchParams.webidl',
     'URLUtils.webidl',
     'URLUtilsReadOnly.webidl',
     'ValidityState.webidl',
     'VideoPlaybackQuality.webidl',
     'VideoStreamTrack.webidl',
+    'VideoTrack.webidl',
+    'VideoTrackList.webidl',
     'VTTCue.webidl',
     'VTTRegion.webidl',
     'WaveShaperNode.webidl',
     'WebComponents.webidl',
     'WebSocket.webidl',
     'WheelEvent.webidl',
     'WifiOptions.webidl',
     'Worker.webidl',
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -340,16 +340,19 @@ pref("media.navigator.enabled", true);
 pref("media.tabstreaming.width", 320);
 pref("media.tabstreaming.height", 240);
 pref("media.tabstreaming.time_per_frame", 40);
 
 // TextTrack support
 pref("media.webvtt.enabled", true);
 pref("media.webvtt.regions.enabled", false);
 
+// AudioTrack and VideoTrack support
+pref("media.track.enabled", false);
+
 // Whether to enable MediaSource support
 pref("media.mediasource.enabled", false);
 
 #ifdef MOZ_WEBSPEECH
 pref("media.webspeech.recognition.enable", false);
 pref("media.webspeech.synth.enabled", false);
 #endif
 #ifdef MOZ_WEBM_ENCODER