Bug 752353: DOM bindings for getUserMedia; r=jst
authorAnant Narayanan <anant@kix.in>
Sun, 03 Jun 2012 00:35:15 -0700
changeset 99725 82f14cddfb38de9f5cc36d99d95c95a87fde8a1b
parent 99724 3d74c0a1e1725db9c5cb6d2819b9cb7a4176a1e6
child 99726 0f52f1ab3dc801f0309867161c52083fa961b996
push idunknown
push userunknown
push dateunknown
reviewersjst
bugs752353
milestone15.0a1
Bug 752353: DOM bindings for getUserMedia; r=jst
b2g/installer/package-manifest.in
browser/installer/package-manifest.in
configure.in
content/media/Makefile.in
content/media/MediaEngineDefault.cpp
content/media/nsIDOMMediaStream.idl
dom/Makefile.in
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/dom-config.mk
dom/media/Makefile.in
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/nsIDOMMediaStream.idl
dom/media/nsIDOMNavigatorUserMedia.idl
layout/build/Makefile.in
mobile/android/installer/package-manifest.in
mobile/xul/installer/package-manifest.in
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -137,17 +137,16 @@
 @BINPATH@/components/commandhandler.xpt
 @BINPATH@/components/commandlines.xpt
 @BINPATH@/components/composer.xpt
 @BINPATH@/components/content_base.xpt
 @BINPATH@/components/content_events.xpt
 @BINPATH@/components/content_canvas.xpt
 @BINPATH@/components/content_htmldoc.xpt
 @BINPATH@/components/content_html.xpt
-@BINPATH@/components/content_media.xpt
 @BINPATH@/components/content_xslt.xpt
 @BINPATH@/components/content_xtf.xpt
 @BINPATH@/components/cookie.xpt
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
@@ -162,16 +161,17 @@
 #endif
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_contacts.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_devicestorage.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
+@BINPATH@/components/dom_media.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -1,13 +1,13 @@
 ; 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/.
 
-; Package file for the Firefox build. 
+; Package file for the Firefox build.
 ;
 ; Packaging manifest is used to copy files from dist/bin
 ; to the staging directory.
 ; Some other files are built in the staging directory directly,
 ; so they will be implicitly packaged too.
 ;
 ; File format:
 ;
@@ -142,17 +142,16 @@
 @BINPATH@/components/commandhandler.xpt
 @BINPATH@/components/commandlines.xpt
 @BINPATH@/components/composer.xpt
 @BINPATH@/components/content_base.xpt
 @BINPATH@/components/content_events.xpt
 @BINPATH@/components/content_canvas.xpt
 @BINPATH@/components/content_htmldoc.xpt
 @BINPATH@/components/content_html.xpt
-@BINPATH@/components/content_media.xpt
 @BINPATH@/components/content_xslt.xpt
 @BINPATH@/components/content_xtf.xpt
 @BINPATH@/components/cookie.xpt
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
@@ -167,16 +166,17 @@
 #endif
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_contacts.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_devicestorage.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
+@BINPATH@/components/dom_media.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
--- a/configure.in
+++ b/configure.in
@@ -4543,16 +4543,17 @@ MOZ_SPEEX_RESAMPLER=1
 MOZ_CUBEB=
 MOZ_VORBIS=
 MOZ_TREMOR=
 MOZ_WAVE=1
 MOZ_MEDIA=
 MOZ_OPUS=1
 MOZ_WEBM=1
 MOZ_MEDIA_PLUGINS=
+MOZ_MEDIA_NAVIGATOR=
 MOZ_OMX_PLUGIN=
 MOZ_VP8_ERROR_CONCEALMENT=
 MOZ_VP8_ENCODER=
 VPX_AS=
 VPX_ASFLAGS=
 VPX_AS_DASH_C_FLAG=
 VPX_AS_CONVERSION=
 VPX_ASM_SUFFIX=
@@ -5634,16 +5635,28 @@ MOZ_ARG_ENABLE_BOOL(media-plugins,
     MOZ_MEDIA_PLUGINS=1,
     MOZ_MEDIA_PLUGINS=)
 
 if test -n "$MOZ_MEDIA_PLUGINS"; then
   AC_DEFINE(MOZ_MEDIA_PLUGINS)
 fi
 
 dnl ========================================================
+dnl = Enable getUserMedia support
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(media-navigator,
+[  --enable-media-navigator  Enable support for getUserMedia],
+    MOZ_MEDIA_NAVIGATOR=1,
+    MOZ_MEDIA_NAVIGATOR=)
+
+if test -n "$MOZ_MEDIA_NAVIGATOR"; then
+  AC_DEFINE(MOZ_MEDIA_NAVIGATOR)
+fi
+
+dnl ========================================================
 dnl = Enable building OMX media plugin (B2G)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(omx-plugin,
 [  --enable-omx-plugin      Enable building OMX plugin (B2G)],
     MOZ_OMX_PLUGIN=1,
     MOZ_OMX_PLUGIN=)
 
 if test -n "$MOZ_OMX_PLUGIN"; then
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -7,21 +7,16 @@ topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = content
 LIBRARY_NAME = gkconmedia_s
 LIBXUL_LIBRARY = 1
-XPIDL_MODULE = content_media
-
-XPIDLSRCS = \
-  nsIDOMMediaStream.idl \
-  $(NULL)
 
 EXPORTS = \
   AudioSegment.h \
   FileBlockCache.h \
   MediaEngine.h \
   MediaEngineDefault.h \
   MediaResource.h \
   MediaSegment.h \
--- a/content/media/MediaEngineDefault.cpp
+++ b/content/media/MediaEngineDefault.cpp
@@ -280,9 +280,9 @@ MediaEngineDefault::EnumerateVideoDevice
 }
 
 void
 MediaEngineDefault::EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >* aASources) {
   aASources->AppendElement(mASource);
   return;
 }
 
-}
+} // namespace mozilla
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -45,16 +45,17 @@ DIRS += \
 
 DIRS += \
   apps \
   base \
   bindings \
   battery \
   contacts \
   devicestorage \
+  media \
   power \
   settings \
   sms \
   src \
   locales \
   network \
   plugins/base \
   plugins/ipc \
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -33,16 +33,19 @@
 #include "SmsManager.h"
 #include "nsISmsService.h"
 #include "mozilla/Hal.h"
 #include "nsIWebNavigation.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "Connection.h"
 #include "MobileConnection.h"
 
+#ifdef MOZ_MEDIA_NAVIGATOR
+#include "MediaManager.h"
+#endif
 #ifdef MOZ_B2G_RIL
 #include "TelephonyFactory.h"
 #endif
 #ifdef MOZ_B2G_BT
 #include "nsIDOMBluetoothManager.h"
 #include "BluetoothManager.h"
 #endif
 
@@ -90,16 +93,19 @@ NS_INTERFACE_MAP_BEGIN(Navigator)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMClientInformation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorDeviceStorage)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorBattery)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorDesktopNotification)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorSms)
+#ifdef MOZ_MEDIA_NAVIGATOR
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorUserMedia)
+#endif
 #ifdef MOZ_B2G_RIL
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorTelephony)
 #endif
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorNetwork)
 #ifdef MOZ_B2G_BT
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorBluetooth)
 #endif
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator)
@@ -895,16 +901,41 @@ NS_IMETHODIMP Navigator::GetGeolocation(
     return NS_ERROR_FAILURE;
   }
 
   NS_ADDREF(*_retval = mGeolocation);
   return NS_OK;
 }
 
 //*****************************************************************************
+//    Navigator::nsIDOMNavigatorUserMedia (mozGetUserMedia)
+//*****************************************************************************
+#ifdef MOZ_MEDIA_NAVIGATOR
+NS_IMETHODIMP
+Navigator::MozGetUserMedia(nsIMediaStreamOptions* aParams,
+                           nsIDOMGetUserMediaSuccessCallback* onSuccess,
+                           nsIDOMGetUserMediaErrorCallback* onError)
+{
+  if (!Preferences::GetBool("media.navigator.enabled", false)) {
+    return NS_OK;
+  }
+
+  MediaManager *manager = MediaManager::Get();
+  nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
+
+  if (!win || !win->GetOuterWindow() ||
+      win->GetOuterWindow()->GetCurrentInnerWindow() != win) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  return manager->GetUserMedia(win->WindowID(), aParams, onSuccess, onError);
+}
+#endif
+
+//*****************************************************************************
 //    Navigator::nsIDOMNavigatorDesktopNotification
 //*****************************************************************************
 
 NS_IMETHODIMP Navigator::GetMozNotification(nsIDOMDesktopNotificationCenter** aRetVal)
 {
   NS_ENSURE_ARG_POINTER(aRetVal);
   *aRetVal = nsnull;
 
@@ -1196,16 +1227,27 @@ Navigator::SizeOfIncludingThis(nsMallocS
 void
 Navigator::SetWindow(nsPIDOMWindow *aInnerWindow)
 {
   NS_ASSERTION(aInnerWindow->IsInnerWindow(),
                "Navigator must get an inner window!");
   mWindow = do_GetWeakReference(aInnerWindow);
 }
 
+void
+Navigator::OnNavigation()
+{
+  // Inform MediaManager in case there are live streams or pending callbacks.
+#ifdef MOZ_MEDIA_NAVIGATOR
+  MediaManager *manager = MediaManager::Get();
+  nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
+  return manager->OnNavigation(win->WindowID());
+#endif
+}
+
 } // namespace dom
 } // namespace mozilla
 
 nsresult
 NS_GetNavigatorUserAgent(nsAString& aUserAgent)
 {
   nsresult rv;
 
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -20,16 +20,20 @@
 
 class nsPluginArray;
 class nsMimeTypeArray;
 class nsGeolocation;
 class nsDesktopNotificationCenter;
 class nsPIDOMWindow;
 class nsIDOMMozConnection;
 
+#ifdef MOZ_MEDIA_NAVIGATOR
+#include "nsIDOMNavigatorUserMedia.h"
+#endif
+
 #ifdef MOZ_B2G_RIL
 #include "nsIDOMNavigatorTelephony.h"
 class nsIDOMTelephony;
 #endif
 
 #ifdef MOZ_B2G_BT
 #include "nsIDOMNavigatorBluetooth.h"
 #endif
@@ -60,36 +64,43 @@ class PowerManager;
 
 class Navigator : public nsIDOMNavigator
                 , public nsIDOMClientInformation
                 , public nsIDOMNavigatorDeviceStorage
                 , public nsIDOMNavigatorGeolocation
                 , public nsIDOMNavigatorDesktopNotification
                 , public nsIDOMMozNavigatorBattery
                 , public nsIDOMMozNavigatorSms
+#ifdef MOZ_MEDIA_NAVIGATOR
+                , public nsIDOMNavigatorUserMedia
+#endif
 #ifdef MOZ_B2G_RIL
                 , public nsIDOMNavigatorTelephony
 #endif
                 , public nsIDOMMozNavigatorNetwork
 #ifdef MOZ_B2G_BT
                 , public nsIDOMNavigatorBluetooth
 #endif
+
 {
 public:
   Navigator(nsPIDOMWindow *aInnerWindow);
   virtual ~Navigator();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMNAVIGATOR
   NS_DECL_NSIDOMCLIENTINFORMATION
   NS_DECL_NSIDOMNAVIGATORDEVICESTORAGE
   NS_DECL_NSIDOMNAVIGATORGEOLOCATION
   NS_DECL_NSIDOMNAVIGATORDESKTOPNOTIFICATION
   NS_DECL_NSIDOMMOZNAVIGATORBATTERY
   NS_DECL_NSIDOMMOZNAVIGATORSMS
+#ifdef MOZ_MEDIA_NAVIGATOR
+  NS_DECL_NSIDOMNAVIGATORUSERMEDIA
+#endif
 #ifdef MOZ_B2G_RIL
   NS_DECL_NSIDOMNAVIGATORTELEPHONY
 #endif
   NS_DECL_NSIDOMMOZNAVIGATORNETWORK
 
 #ifdef MOZ_B2G_BT
   NS_DECL_NSIDOMNAVIGATORBLUETOOTH
 #endif
@@ -105,16 +116,21 @@ public:
 
   size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   /**
    * For use during document.write where our inner window changes.
    */
   void SetWindow(nsPIDOMWindow *aInnerWindow);
 
+  /**
+   * Called when the inner window navigates to a new page.
+   */
+  void OnNavigation();
+
 private:
   bool IsSmsAllowed() const;
   bool IsSmsSupported() const;
 
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -422,16 +422,21 @@
 #include "nsIDOMDataTransfer.h"
 
 // Geolocation
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsIDOMGeoPositionCoords.h"
 #include "nsIDOMGeoPositionError.h"
 
+// User media
+#ifdef MOZ_MEDIA_NAVIGATOR
+#include "nsIDOMNavigatorUserMedia.h"
+#endif
+
 // Workers
 #include "mozilla/dom/workers/Workers.h"
 
 #include "nsDOMFile.h"
 #include "nsDOMFileReader.h"
 #include "nsIDOMFormData.h"
 
 #include "nsIDOMDOMStringMap.h"
@@ -2450,16 +2455,19 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorDeviceStorage)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorGeolocation)
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMNavigatorDesktopNotification,
                                         Navigator::HasDesktopNotificationSupport())
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientInformation)
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMMozNavigatorBattery,
                                         battery::BatteryManager::HasSupport())
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozNavigatorSms)
+#ifdef MOZ_MEDIA_NAVIGATOR
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorUserMedia)
+#endif
 #ifdef MOZ_B2G_RIL
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorTelephony)
 #endif
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMMozNavigatorNetwork,
                                         network::IsAPIEnabled())
 #ifdef MOZ_B2G_BT
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorBluetooth)
 #endif
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1078,16 +1078,17 @@ nsGlobalWindow::FreeInnerObjects()
     mListenerManager->Disconnect();
     mListenerManager = nsnull;
   }
 
   mLocation = nsnull;
   mHistory = nsnull;
 
   if (mNavigator) {
+    mNavigator->OnNavigation();
     mNavigator->Invalidate();
     mNavigator = nsnull;
   }
 
   if (mScreen) {
     mScreen = nsnull;
   }
 
@@ -1743,16 +1744,20 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 #ifdef DEBUG
   mLastOpenedURI = aDocument->GetDocumentURI();
 #endif
 
   mContext->WillInitializeContext();
 
   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
 
+  if (currentInner && currentInner->mNavigator) {
+    currentInner->mNavigator->OnNavigation();
+  }
+
   nsRefPtr<nsGlobalWindow> newInnerWindow;
   bool createdInnerWindow = false;
 
   bool thisChrome = IsChromeWindow();
 
   bool isChrome = false;
 
   nsCxPusher cxPusher;
--- a/dom/dom-config.mk
+++ b/dom/dom-config.mk
@@ -1,16 +1,17 @@
 # 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/.
 
 DOM_SRCDIRS = \
   dom/base \
   dom/battery \
   dom/power \
+  dom/media \
   dom/network/src \
   dom/settings \
   dom/sms/src \
   dom/contacts \
   dom/src/events \
   dom/src/storage \
   dom/src/offline \
   dom/src/geolocation \
new file mode 100644
--- /dev/null
+++ b/dom/media/Makefile.in
@@ -0,0 +1,38 @@
+# 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/.
+
+DEPTH            = ../..
+topsrcdir        = @top_srcdir@
+srcdir           = @srcdir@
+VPATH            = @srcdir@
+
+relativesrcdir   = dom/media
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE           = dom
+XPIDL_MODULE     = dom_media
+LIBRARY_NAME     = dom_media_s
+LIBXUL_LIBRARY   = 1
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/dom/dom-config.mk
+
+XPIDLSRCS = \
+  nsIDOMMediaStream.idl \
+  nsIDOMNavigatorUserMedia.idl \
+  $(NULL)
+
+EXPORTS_NAMESPACE = mozilla
+
+EXPORTS_mozilla = \
+  MediaManager.h \
+  $(NULL)
+
+CPPSRCS = \
+  MediaManager.cpp \
+  $(NULL)
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/media/MediaManager.cpp
@@ -0,0 +1,458 @@
+/* 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 "MediaManager.h"
+
+#include "MediaStreamGraph.h"
+#include "MediaEngineDefault.h"
+
+#include "nsIDOMFile.h"
+#include "nsIEventTarget.h"
+#include "nsIScriptGlobalObject.h"
+
+#include "nsJSUtils.h"
+#include "nsDOMFile.h"
+
+namespace mozilla {
+
+/**
+ * Send an error back to content. The error is the form a string.
+ * Do this only on the main thread.
+ */
+class ErrorCallbackRunnable : public nsRunnable
+{
+public:
+  ErrorCallbackRunnable(nsIDOMGetUserMediaErrorCallback* aError,
+    const nsString& aErrorMsg, PRUint64 aWindowID)
+    : mError(aError)
+    , mErrorMsg(aErrorMsg)
+    , mWindowID(aWindowID) {}
+
+  NS_IMETHOD
+  Run()
+  {
+    // Only run if the window is still active.
+    WindowTable* activeWindows = MediaManager::Get()->GetActiveWindows();
+    if (activeWindows->Get(mWindowID)) {
+      mError->OnError(mErrorMsg);
+    }
+    return NS_OK;
+  }
+
+private:
+  nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
+  const nsString mErrorMsg;
+  PRUint64 mWindowID;
+};
+
+/**
+ * Invoke the "onSuccess" callback in content. The callback will take a
+ * DOMBlob in the case of {picture:true}, and a MediaStream in the case of
+ * {audio:true} or {video:true}. There is a constructor available for each
+ * form. Do this only on the main thread.
+ */
+class SuccessCallbackRunnable : public nsRunnable
+{
+public:
+  SuccessCallbackRunnable(nsIDOMGetUserMediaSuccessCallback* aSuccess,
+    nsIDOMFile* aFile, PRUint64 aWindowID)
+    : mSuccess(aSuccess)
+    , mFile(aFile)
+    , mWindowID(aWindowID) {}
+
+  SuccessCallbackRunnable(nsIDOMGetUserMediaSuccessCallback* aSuccess,
+    nsIDOMMediaStream* aStream, PRUint64 aWindowID)
+    : mSuccess(aSuccess)
+    , mStream(aStream)
+    , mWindowID(aWindowID) {}
+
+  NS_IMETHOD
+  Run()
+  {
+    // Only run if the window is still active.
+    WindowTable* activeWindows = MediaManager::Get()->GetActiveWindows();
+    if (activeWindows->Get(mWindowID)) {
+      // XPConnect is a magical unicorn.
+      if (mFile) {
+        mSuccess->OnSuccess(mFile);
+      } else if (mStream) {
+        mSuccess->OnSuccess(mStream);
+      }
+    }
+    return NS_OK;
+  }
+
+private:
+  nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+  nsCOMPtr<nsIDOMFile> mFile;
+  nsCOMPtr<nsIDOMMediaStream> mStream;
+  PRUint64 mWindowID;
+};
+
+/**
+ * This runnable creates a nsDOMMediaStream from a given MediaEngineSource
+ * and returns it via a success callback. Both must be done on the main thread.
+ */
+class GetUserMediaCallbackRunnable : public nsRunnable
+{
+public:
+  GetUserMediaCallbackRunnable(MediaEngineSource* aSource, TrackID aId,
+    nsIDOMGetUserMediaSuccessCallback* aSuccess,
+    nsIDOMGetUserMediaErrorCallback* aError,
+    PRUint64 aWindowID,
+    StreamListeners* aListeners)
+    : mSource(aSource)
+    , mId(aId)
+    , mSuccess(aSuccess)
+    , mError(aError)
+    , mWindowID(aWindowID)
+    , mListeners(aListeners) {}
+
+  NS_IMETHOD
+  Run()
+  {
+    /**
+     * Normally we would now get the name & UUID for the device and ask the
+     * user permission. We will do that when we have some UI. Currently,
+     * only the Android {picture:true} backend is functional, which does not
+     * need a permission prompt, as permission is implicit by user action.
+     *
+     * See bug 748835 for progress on the desktop UI.
+     */
+    nsCOMPtr<nsDOMMediaStream> comStream = mSource->Allocate();
+    if (!comStream) {
+      NS_DispatchToMainThread(new ErrorCallbackRunnable(
+        mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
+      ));
+      return NS_OK;
+    }
+
+    // Add our listener. We'll call Start() on the source when get a callback
+    // that the MediaStream has started consuming. The listener is freed
+    // when the page is invalidated (on navigation or close).
+    GetUserMediaCallbackMediaStreamListener* listener =
+      new GetUserMediaCallbackMediaStreamListener(mSource, comStream, mId);
+    comStream->GetStream()->AddListener(listener);
+
+    {
+      MutexAutoLock lock(*(MediaManager::Get()->GetLock()));
+      mListeners->AppendElement(listener);
+    }
+
+    // Add the listener to CallbackRunnables so it can be invalidated.
+    NS_DispatchToMainThread(new SuccessCallbackRunnable(
+      mSuccess, comStream.get(), mWindowID
+    ));
+    return NS_OK;
+  }
+
+private:
+  nsCOMPtr<MediaEngineSource> mSource;
+  TrackID mId;
+  nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+  nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
+  PRUint64 mWindowID;
+  StreamListeners* mListeners;
+};
+
+/**
+ * This runnable creates a nsIDOMFile from a MediaEngineVideoSource and
+ * passes the result back via a SuccessRunnable. Both must be done on the
+ * main thread.
+ */
+class GetUserMediaSnapshotCallbackRunable : public nsRunnable
+{
+public:
+  GetUserMediaSnapshotCallbackRunable(MediaEngineSource* aSource,
+    PRUint32 aDuration,
+    nsIDOMGetUserMediaSuccessCallback* aSuccessCallback,
+    nsIDOMGetUserMediaErrorCallback* aErrorCallback,
+    PRUint64 aWindowID)
+    : mSource(aSource)
+    , mDuration(aDuration)
+    , mSuccessCallback(aSuccessCallback)
+    , mErrorCallback(aErrorCallback)
+    , mWindowID(aWindowID) {}
+
+  NS_IMETHOD
+  Run()
+  {
+    nsCOMPtr<nsDOMMediaStream> comStream = mSource->Allocate();
+    if (!comStream) {
+      NS_DispatchToMainThread(new ErrorCallbackRunnable(
+        mErrorCallback, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
+      ));
+      return NS_OK;
+    }
+
+    nsCOMPtr<nsIDOMFile> file;
+    mSource->Snapshot(mDuration, getter_AddRefs(file));
+    mSource->Deallocate();
+
+    NS_DispatchToMainThread(new SuccessCallbackRunnable(
+      mSuccessCallback, file, mWindowID
+    ));
+    return NS_OK;
+  }
+
+private:
+  nsCOMPtr<MediaEngineSource> mSource;
+  PRUint32 mDuration;
+  nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccessCallback;
+  nsCOMPtr<nsIDOMGetUserMediaErrorCallback>  mErrorCallback;
+  PRUint64 mWindowID;
+};
+
+/**
+ * Runs on a seperate thread and is responsible for enumerating devices.
+ * Depending on whether a picture or stream was asked for, either
+ * GetUserMediaCallbackRunnable or GetUserMediaSnapshotCallbackRunnable
+ * will be dispatched to the main thread to return the result to DOM.
+ *
+ * Do not run this on the main thread.
+ */
+class GetUserMediaRunnable : public nsRunnable
+{
+public:
+  GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
+    nsIDOMGetUserMediaSuccessCallback* aSuccess,
+    nsIDOMGetUserMediaErrorCallback* aError,
+    PRUint64 aWindowID, StreamListeners* aListeners)
+    : mAudio(aAudio)
+    , mVideo(aVideo)
+    , mPicture(aPicture)
+    , mSuccess(aSuccess)
+    , mError(aError)
+    , mWindowID(aWindowID)
+    , mListeners(aListeners) {}
+
+  ~GetUserMediaRunnable() {}
+
+  // We only support 1 audio and 1 video track for now.
+  enum {
+    kVideoTrack = 1,
+    kAudioTrack = 2
+  };
+
+  NS_IMETHOD
+  Run()
+  {
+    mManager = MediaManager::Get();
+
+    if (mPicture) {
+      SendPicture();
+      return NS_OK;
+    }
+
+    // XXX: Implement merging two streams (See bug 758391).
+    if (mAudio && mVideo) {
+      NS_DispatchToMainThread(new ErrorCallbackRunnable(
+        mError, NS_LITERAL_STRING("NOT_IMPLEMENTED"), mWindowID
+      ));
+      return NS_OK;
+    }
+
+    if (mVideo) {
+      SendVideo();
+      return NS_OK;
+    }
+
+    if (mAudio) {
+      SendAudio();
+      return NS_OK;
+    }
+
+    return NS_OK;
+  }
+
+  // {picture:true}
+  void
+  SendPicture()
+  {
+    nsTArray<nsRefPtr<MediaEngineVideoSource> > videoSources;
+    mManager->GetBackend()->EnumerateVideoDevices(&videoSources);
+
+    PRUint32 count = videoSources.Length();
+    if (!count) {
+      NS_DispatchToMainThread(new ErrorCallbackRunnable(
+        mError, NS_LITERAL_STRING("NO_DEVICES_FOUND"), mWindowID
+      ));
+      return;
+    }
+    MediaEngineVideoSource* videoSource = videoSources[count - 1];
+    NS_DispatchToMainThread(new GetUserMediaSnapshotCallbackRunable(
+      videoSource, 0 /* duration */, mSuccess, mError, mWindowID
+    ));
+  }
+
+  // {video:true}
+  void
+  SendVideo()
+  {
+    nsTArray<nsRefPtr<MediaEngineVideoSource> > videoSources;
+    mManager->GetBackend()->EnumerateVideoDevices(&videoSources);
+
+    PRUint32 count = videoSources.Length();
+    if (!count) {
+      NS_DispatchToMainThread(new ErrorCallbackRunnable(
+        mError, NS_LITERAL_STRING("NO_DEVICES_FOUND"), mWindowID
+      ));
+      return;
+    }
+
+    MediaEngineVideoSource* videoSource = videoSources[count - 1];
+    NS_DispatchToMainThread(new GetUserMediaCallbackRunnable(
+      videoSource, kVideoTrack, mSuccess, mError, mWindowID, mListeners
+    ));
+  }
+
+  // {audio:true}
+  void
+  SendAudio()
+  {
+    nsTArray<nsRefPtr<MediaEngineAudioSource> > audioSources;
+    mManager->GetBackend()->EnumerateAudioDevices(&audioSources);
+
+    PRUint32 count = audioSources.Length();
+    if (!count) {
+      NS_DispatchToMainThread(new ErrorCallbackRunnable(
+        mError, NS_LITERAL_STRING("NO_DEVICES_FOUND"), mWindowID
+      ));
+      return;
+    }
+
+    MediaEngineAudioSource* audioSource = audioSources[count - 1];
+    NS_DispatchToMainThread(new GetUserMediaCallbackRunnable(
+      audioSource, kAudioTrack, mSuccess, mError, mWindowID, mListeners
+    ));
+  }
+
+private:
+  bool mAudio;
+  bool mVideo;
+  bool mPicture;
+
+  nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+  nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
+  PRUint64 mWindowID;
+  StreamListeners* mListeners;
+
+  MediaManager* mManager;
+};
+
+
+nsRefPtr<MediaManager> MediaManager::sSingleton;
+
+NS_IMPL_ISUPPORTS1(MediaManager, nsIObserver)
+
+/**
+ * The entry point for this file. A call from Navigator::mozGetUserMedia
+ * will end up here. MediaManager is a singleton that is responsible
+ * for handling all incoming getUserMedia calls from every window.
+ */
+nsresult
+MediaManager::GetUserMedia(PRUint64 aWindowID, nsIMediaStreamOptions* aParams,
+  nsIDOMGetUserMediaSuccessCallback* onSuccess,
+  nsIDOMGetUserMediaErrorCallback* onError)
+{
+  NS_ENSURE_TRUE(aParams, NS_ERROR_NULL_POINTER);
+
+  bool audio, video, picture;
+  nsresult rv = aParams->GetPicture(&picture);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aParams->GetAudio(&audio);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aParams->GetVideo(&video);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // We only support "front" or "back". TBD: Send to GetUserMediaRunnable.
+  nsString cameraType;
+  rv = aParams->GetCamera(cameraType);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Store the WindowID in a hash table and mark as active. The entry is removed
+  // when this window is closed or navigated away from.
+  StreamListeners* listeners = mActiveWindows.Get(aWindowID);
+  if (!listeners) {
+    listeners = new StreamListeners;
+    mActiveWindows.Put(aWindowID, listeners);
+  }
+
+  // Pass runanbles along to GetUserMediaRunnable so it can add the
+  // MediaStreamListener to the runnable list.
+  nsCOMPtr<nsIRunnable> gUMRunnable = new GetUserMediaRunnable(
+    audio, video, picture, onSuccess, onError, aWindowID, listeners
+  );
+
+  // Reuse the same thread to save memory.
+  if (!mMediaThread) {
+    rv = NS_NewThread(getter_AddRefs(mMediaThread));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  mMediaThread->Dispatch(gUMRunnable, NS_DISPATCH_NORMAL);
+  return NS_OK;
+}
+
+MediaEngine*
+MediaManager::GetBackend()
+{
+  // Plugin backends as appropriate. Only default is available for now, which
+  // also includes picture support for Android.
+  if (!mBackend) {
+    mBackend = new MediaEngineDefault();
+  }
+  return mBackend;
+}
+
+WindowTable*
+MediaManager::GetActiveWindows()
+{
+  return &mActiveWindows;
+}
+
+void
+MediaManager::OnNavigation(PRUint64 aWindowID)
+{
+  // Invalidate this window. The runnables check this value before making
+  // a call to content.
+  StreamListeners* listeners = mActiveWindows.Get(aWindowID);
+  if (!listeners) {
+    return;
+  }
+
+  MutexAutoLock lock(*mLock);
+  PRUint32 length = listeners->Length();
+  for (PRUint32 i = 0; i < length; i++) {
+    nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
+      listeners->ElementAt(i);
+    listener->Invalidate();
+    listener = nsnull;
+  }
+  listeners->Clear();
+
+  mActiveWindows.Remove(aWindowID);
+}
+
+nsresult
+MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
+  const PRUnichar* aData)
+{
+  if (strcmp(aTopic, "xpcom-shutdown")) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  obs->RemoveObserver(this, "xpcom-shutdown");
+
+  // Close off any remaining active windows.
+  mActiveWindows.Clear();
+  sSingleton = nsnull;
+
+  return NS_OK;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/MediaManager.h
@@ -0,0 +1,128 @@
+/* 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 "MediaEngine.h"
+#include "mozilla/Services.h"
+
+#include "nsHashKeys.h"
+#include "nsClassHashtable.h"
+#include "nsObserverService.h"
+
+#include "nsIDOMNavigatorUserMedia.h"
+
+#include "stdio.h"
+
+namespace mozilla {
+
+/**
+ * This class is an implementation of MediaStreamListener. This is used
+ * to Start() and Stop() the underlying MediaEngineSource when MediaStreams
+ * are assigned and deassigned in content.
+ */
+class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
+{
+public:
+  GetUserMediaCallbackMediaStreamListener(MediaEngineSource* aSource,
+    nsDOMMediaStream* aStream, TrackID aListenId)
+    : mSource(aSource)
+    , mStream(aStream)
+    , mId(aListenId)
+    , mValid(true) {}
+
+  void
+  Invalidate()
+  {
+    if (!mValid) {
+      return;
+    }
+
+    mValid = false;
+    mSource->Stop();
+    mSource->Deallocate();
+  }
+
+  void
+  NotifyConsumptionChanged(MediaStreamGraph* aGraph, Consumption aConsuming)
+  {
+    if (aConsuming == CONSUMED) {
+      nsRefPtr<SourceMediaStream> stream = mStream->GetStream()->AsSourceStream();
+      mSource->Start(stream, mId);
+      return;
+    }
+
+    // NOT_CONSUMED
+    Invalidate();
+    return;
+  }
+
+  void NotifyBlockingChanged(MediaStreamGraph* aGraph, Blocking aBlocked) {}
+  void NotifyOutput(MediaStreamGraph* aGraph) {}
+  void NotifyFinished(MediaStreamGraph* aGraph) {}
+  void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
+    TrackRate aTrackRate, TrackTicks aTrackOffset,
+    PRUint32 aTrackEvents, const MediaSegment& aQueuedMedia) {}
+  nsresult Run() { return NS_OK; }
+
+private:
+  nsCOMPtr<MediaEngineSource> mSource;
+  nsCOMPtr<nsDOMMediaStream> mStream;
+  TrackID mId;
+  bool mValid;
+};
+
+typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
+typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
+
+class MediaManager : public nsIObserver {
+public:
+  static MediaManager* Get() {
+    if (!sSingleton) {
+      sSingleton = new MediaManager();
+
+      nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+      obs->AddObserver(sSingleton, "xpcom-shutdown", false);
+    }
+    return sSingleton;
+  }
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  Mutex* GetLock() {
+    return mLock;
+  }
+
+  MediaEngine* GetBackend();
+  WindowTable* GetActiveWindows();
+
+  nsresult GetUserMedia(PRUint64 aWindowID, nsIMediaStreamOptions* aParams,
+    nsIDOMGetUserMediaSuccessCallback* onSuccess,
+    nsIDOMGetUserMediaErrorCallback* onError);
+  void OnNavigation(PRUint64 aWindowID);
+
+private:
+  // Make private because we want only one instance of this class
+  MediaManager()
+  : mBackend(nsnull)
+  , mMediaThread(nsnull) {
+    mLock = new mozilla::Mutex("MediaManager::StreamListenersLock");
+    mActiveWindows.Init();
+  };
+  MediaManager(MediaManager const&) {};
+
+  ~MediaManager() {
+    delete mLock;
+    delete mBackend;
+  };
+
+  MediaEngine* mBackend;
+  nsCOMPtr<nsIThread> mMediaThread;
+
+  Mutex* mLock;
+  WindowTable mActiveWindows;
+
+  static nsRefPtr<MediaManager> sSingleton;
+};
+
+} // namespace mozilla
rename from content/media/nsIDOMMediaStream.idl
rename to dom/media/nsIDOMMediaStream.idl
new file mode 100644
--- /dev/null
+++ b/dom/media/nsIDOMNavigatorUserMedia.idl
@@ -0,0 +1,39 @@
+/* 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 "nsISupports.idl"
+#include "nsIDOMMediaStream.idl"
+
+[scriptable, function, uuid(f2a144fc-3534-4761-8c5d-989ae720f89a)]
+interface nsIDOMGetUserMediaSuccessCallback : nsISupports
+{
+  /*
+   * value must be a nsIDOMBlob if picture is true and a
+   * nsIDOMMediaStream if either audio or video are true.
+   */
+  void onSuccess(in nsISupports value);
+};
+
+[scriptable, function, uuid(2614bbcf-85cc-43e5-8740-964f52bdc7ca)]
+interface nsIDOMGetUserMediaErrorCallback : nsISupports
+{
+  void onError(in DOMString error);
+};
+
+[scriptable, uuid(8a26205e-e8f7-4372-bd15-97ff982b4c1c)]
+interface nsIMediaStreamOptions : nsISupports
+{
+  readonly attribute boolean audio;
+  readonly attribute boolean video;
+  readonly attribute boolean picture;
+  readonly attribute DOMString camera;
+};
+
+[scriptable, uuid(381e0071-0be5-4f6b-ae21-8e3407a37faa)]
+interface nsIDOMNavigatorUserMedia : nsISupports
+{
+  void mozGetUserMedia(in nsIMediaStreamOptions params,
+    in nsIDOMGetUserMediaSuccessCallback onsuccess,
+    in nsIDOMGetUserMediaErrorCallback onerror);
+};
--- a/layout/build/Makefile.in
+++ b/layout/build/Makefile.in
@@ -61,16 +61,17 @@ SHARED_LIBRARY_LIBS = \
 	$(DEPTH)/view/src/$(LIB_PREFIX)gkview_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/base/$(LIB_PREFIX)jsdombase_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/battery/$(LIB_PREFIX)dom_battery_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/contacts/$(LIB_PREFIX)jsdomcontacts_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/devicestorage/$(LIB_PREFIX)domdevicestorage_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/power/$(LIB_PREFIX)dom_power_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/settings/$(LIB_PREFIX)jsdomsettings_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/network/src/$(LIB_PREFIX)dom_network_s.$(LIB_SUFFIX) \
+	$(DEPTH)/dom/media/$(LIB_PREFIX)dom_media_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/sms/src/$(LIB_PREFIX)dom_sms_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/src/events/$(LIB_PREFIX)jsdomevents_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/src/json/$(LIB_PREFIX)json_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/src/jsurl/$(LIB_PREFIX)jsurl_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/src/storage/$(LIB_PREFIX)jsdomstorage_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/src/offline/$(LIB_PREFIX)jsdomoffline_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/src/geolocation/$(LIB_PREFIX)jsdomgeolocation_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/src/notification/$(LIB_PREFIX)jsdomnotification_s.$(LIB_SUFFIX) \
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -143,31 +143,31 @@
 @BINPATH@/components/commandhandler.xpt
 @BINPATH@/components/commandlines.xpt
 @BINPATH@/components/composer.xpt
 @BINPATH@/components/content_base.xpt
 @BINPATH@/components/content_events.xpt
 @BINPATH@/components/content_canvas.xpt
 @BINPATH@/components/content_htmldoc.xpt
 @BINPATH@/components/content_html.xpt
-@BINPATH@/components/content_media.xpt
 @BINPATH@/components/content_xslt.xpt
 @BINPATH@/components/content_xtf.xpt
 @BINPATH@/components/cookie.xpt
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
 @BINPATH@/components/dom_battery.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
+@BINPATH@/components/dom_media.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_sidebar.xpt
--- a/mobile/xul/installer/package-manifest.in
+++ b/mobile/xul/installer/package-manifest.in
@@ -1,13 +1,13 @@
 ; 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/.
 
-; Package file for the Fennec build. 
+; Package file for the Fennec build.
 ;
 ; File format:
 ;
 ; [] designates a toplevel component. Example: [xpcom]
 ; - in front of a file specifies it to be removed from the destination
 ; * wildcard support to recursively copy the entire directory
 ; ; file comment
 ;
@@ -143,17 +143,16 @@
 @BINPATH@/components/commandhandler.xpt
 @BINPATH@/components/commandlines.xpt
 @BINPATH@/components/composer.xpt
 @BINPATH@/components/content_base.xpt
 @BINPATH@/components/content_events.xpt
 @BINPATH@/components/content_canvas.xpt
 @BINPATH@/components/content_htmldoc.xpt
 @BINPATH@/components/content_html.xpt
-@BINPATH@/components/content_media.xpt
 @BINPATH@/components/content_xslt.xpt
 @BINPATH@/components/content_xtf.xpt
 @BINPATH@/components/cookie.xpt
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_base.xpt
 #ifdef MOZ_B2G_RIL