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 id27077
push userryanvm@gmail.com
push dateThu, 03 Jul 2014 21:03:59 +0000
treeherdermozilla-central@06e9a27a6fcc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, roc
bugs744896
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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