Merge inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 31 Aug 2015 15:21:02 -0400
changeset 260158 cafb1c90f794a73100a8f0afb9fe3301df0f2bde
parent 260157 ca7ff0423165f27224cef4f332a2038937568594 (current diff)
parent 260090 6782a855c2430eb2b16b1099e402196fb2abb12c (diff)
child 260159 6dd4151f383cb4141df75ef3a598ce1e379b9a9c
child 260257 c9750b48ac731f84bba0da0bda814e2dba659e50
child 260281 0ad328359d9719dd6558de26c242ba457174320b
push id64418
push userryanvm@gmail.com
push dateMon, 31 Aug 2015 19:25:16 +0000
treeherdermozilla-inbound@6dd4151f383c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone43.0a1
first release with
nightly linux32
cafb1c90f794 / 43.0a1 / 20150901030226 / files
nightly linux64
cafb1c90f794 / 43.0a1 / 20150901030226 / files
nightly mac
cafb1c90f794 / 43.0a1 / 20150901030226 / files
nightly win32
cafb1c90f794 / 43.0a1 / 20150901030226 / files
nightly win64
cafb1c90f794 / 43.0a1 / 20150901030226 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c. a=merge
docshell/base/timeline/moz.build
dom/bluetooth/moz.build
dom/media/webrtc/MediaEngineWebRTCVideo.cpp
layout/base/nsPresShell.cpp
mobile/android/app/mobile.js
testing/docker/desktop32-build/bin/build.sh
--- a/accessible/atk/moz.build
+++ b/accessible/atk/moz.build
@@ -50,10 +50,8 @@ if CONFIG['MOZ_ENABLE_GTK']:
 if CONFIG['MOZ_ENABLE_DBUS']:
     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 if CONFIG['CLANG_CXX']:
     # Suppress clang warning about unused function from gobject's RTTI macros.
     CXXFLAGS += ['-Wno-unused-function']
-
-FAIL_ON_WARNINGS = True
--- a/accessible/base/moz.build
+++ b/accessible/base/moz.build
@@ -92,10 +92,8 @@ else:
     ]
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_ENABLE_GTK']:
     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')
-
-FAIL_ON_WARNINGS = True
--- a/accessible/generic/moz.build
+++ b/accessible/generic/moz.build
@@ -52,10 +52,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
-
-FAIL_ON_WARNINGS = True
--- a/accessible/html/moz.build
+++ b/accessible/html/moz.build
@@ -38,10 +38,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/accessible/ipc/moz.build
+++ b/accessible/ipc/moz.build
@@ -42,10 +42,8 @@ if CONFIG['ACCESSIBILITY']:
     else:
         LOCAL_INCLUDES += [
             '/accessible/other',
         ]
 
     FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
-
-FAIL_ON_WARNINGS = True
--- a/accessible/mac/moz.build
+++ b/accessible/mac/moz.build
@@ -36,10 +36,8 @@ LOCAL_INCLUDES += [
     '/layout/xul',
     '/widget',
     '/widget/cocoa',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
-
-FAIL_ON_WARNINGS = True
--- a/accessible/other/moz.build
+++ b/accessible/other/moz.build
@@ -17,10 +17,8 @@ SOURCES += [
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/accessible/windows/ia2/moz.build
+++ b/accessible/windows/ia2/moz.build
@@ -45,11 +45,9 @@ LOCAL_INCLUDES += [
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -59,10 +59,8 @@ LOCAL_INCLUDES += [
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
-
-FAIL_ON_WARNINGS = True
--- a/accessible/windows/sdn/moz.build
+++ b/accessible/windows/sdn/moz.build
@@ -18,10 +18,8 @@ LOCAL_INCLUDES += [
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
-
-FAIL_ON_WARNINGS = True
--- a/accessible/windows/uia/moz.build
+++ b/accessible/windows/uia/moz.build
@@ -13,10 +13,8 @@ LOCAL_INCLUDES += [
     '/accessible/generic',
     '/accessible/html',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -43,10 +43,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
--- a/accessible/xul/moz.build
+++ b/accessible/xul/moz.build
@@ -43,10 +43,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/b2g/app/moz.build
+++ b/b2g/app/moz.build
@@ -73,17 +73,15 @@ DISABLE_STL_WRAPPING = True
 if CONFIG['OS_ARCH'] == 'WINNT':
     OS_LIBS += [
         'version',
     ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 JS_PREFERENCE_FILES += [
     'b2g.js',
 ]
 
 DIST_FILES += [
   'ua-update.json.in',
 ]
--- a/b2g/config/mozconfigs/linux32_gecko/debug
+++ b/b2g/config/mozconfigs/linux32_gecko/debug
@@ -14,17 +14,17 @@ ac_add_options --enable-debug
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 
 #B2G options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
--- a/b2g/config/mozconfigs/linux32_gecko/nightly
+++ b/b2g/config/mozconfigs/linux32_gecko/nightly
@@ -14,17 +14,17 @@ ac_add_options --enable-signmar
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 
 #B2G options
 ac_add_options --enable-application=b2g
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
--- a/b2g/config/mozconfigs/linux64_gecko/debug
+++ b/b2g/config/mozconfigs/linux64_gecko/debug
@@ -14,17 +14,17 @@ ac_add_options --enable-debug
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 
 #B2G options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
--- a/b2g/config/mozconfigs/linux64_gecko/nightly
+++ b/b2g/config/mozconfigs/linux64_gecko/nightly
@@ -14,17 +14,17 @@ ac_add_options --enable-signmar
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 
 #B2G options
 ac_add_options --enable-application=b2g
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
--- a/b2g/config/mozconfigs/macosx64_gecko/debug
+++ b/b2g/config/mozconfigs/macosx64_gecko/debug
@@ -13,17 +13,17 @@ ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 #ac_add_options --with-macbundlename-prefix=Firefox
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # B2G Stuff
 ac_add_options --enable-application=b2g
 ac_add_options --enable-debug-symbols
 ac_add_options --enable-debug
 ENABLE_MARIONETTE=1
 
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly
+++ b/b2g/config/mozconfigs/macosx64_gecko/nightly
@@ -14,17 +14,17 @@ ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 #ac_add_options --with-macbundlename-prefix=Firefox
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # B2G Stuff
 ac_add_options --enable-application=b2g
 ac_add_options --enable-debug-symbols
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
 
 GAIADIR=$topsrcdir/gaia
--- a/b2g/dev/config/mozconfigs/macosx64/mulet
+++ b/b2g/dev/config/mozconfigs/macosx64/mulet
@@ -12,17 +12,17 @@ ac_add_options --enable-profiling
 ac_add_options --enable-instruments
 ac_add_options --enable-dtrace
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 # Include Firefox OS fonts.
 MOZTTDIR=$topsrcdir/moz-tt
 
--- a/b2g/gaia/moz.build
+++ b/b2g/gaia/moz.build
@@ -15,10 +15,8 @@ if not CONFIG['MOZ_B2GDROID']:
         DEFINES['B2G_NAME'] = 'L"%s-bin%s"' % (PROGRAM, CONFIG['BIN_SUFFIX'])
         DEFINES['GAIA_PATH'] = 'L"gaia\\\\profile"'
     else:
         SOURCES += [
             'run-b2g.c',
         ]
         DEFINES['B2G_NAME'] = '"%s-bin%s"' % (PROGRAM, CONFIG['BIN_SUFFIX'])
         DEFINES['GAIA_PATH'] = '"gaia/profile"'
-
-FAIL_ON_WARNINGS = True
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -81,10 +81,8 @@ if CONFIG['MOZ_LINKER']:
 
 if CONFIG['HAVE_CLOCK_MONOTONIC']:
     OS_LIBS += CONFIG['REALTIME_LIBS']
 
 JAR_MANIFESTS += ['jar.mn']
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
-
-FAIL_ON_WARNINGS = True
--- a/browser/components/about/moz.build
+++ b/browser/components/about/moz.build
@@ -12,10 +12,8 @@ SOURCES += [
     'AboutRedirector.cpp',
 ]
 
 FINAL_LIBRARY = 'browsercomps'
 
 LOCAL_INCLUDES += [
     '../build',
 ]
-
-FAIL_ON_WARNINGS = True
--- a/browser/components/build/moz.build
+++ b/browser/components/build/moz.build
@@ -33,10 +33,8 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     DELAYLOAD_DLLS += [
         'esent.dll',
     ]
 
 # Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
 # GTK2: Need to link with glib for GNOME shell service
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'):
     OS_LIBS += CONFIG['TK_LIBS']
-
-FAIL_ON_WARNINGS = True
--- a/browser/components/dirprovider/moz.build
+++ b/browser/components/dirprovider/moz.build
@@ -16,10 +16,8 @@ XPCSHELL_TESTS_MANIFESTS += [
     'tests/unit/xpcshell.ini',
 ]
 
 FINAL_LIBRARY = 'browsercomps'
 
 LOCAL_INCLUDES += [
     '../build'
 ]
-
-FAIL_ON_WARNINGS = True
--- a/browser/components/feeds/moz.build
+++ b/browser/components/feeds/moz.build
@@ -35,12 +35,10 @@ FINAL_LIBRARY = 'browsercomps'
 
 for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
     DEFINES[var] = CONFIG[var]
 
 LOCAL_INCLUDES += [
     '../build',
 ]
 
-FAIL_ON_WARNINGS = True
-
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'RSS Discovery and Preview')
--- a/browser/components/migration/moz.build
+++ b/browser/components/migration/moz.build
@@ -59,12 +59,10 @@ EXTRA_PP_JS_MODULES += [
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     EXTRA_JS_MODULES += [
         'MSMigrationUtils.jsm',
     ]
 
 FINAL_LIBRARY = 'browsercomps'
 
-FAIL_ON_WARNINGS = True
-
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'Migration')
--- a/browser/components/shell/moz.build
+++ b/browser/components/shell/moz.build
@@ -45,12 +45,10 @@ EXTRA_COMPONENTS += [
     'nsSetDefaultBrowser.manifest',
 ]
 
 for var in ('MOZ_APP_NAME', 'MOZ_APP_VERSION'):
     DEFINES[var] = '"%s"' % CONFIG[var]
 
 CXXFLAGS += CONFIG['TK_CFLAGS']
 
-FAIL_ON_WARNINGS = True
-
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'Shell Integration')
--- a/browser/config/mozconfigs/linux32/common-opt
+++ b/browser/config/mozconfigs/linux32/common-opt
@@ -8,13 +8,13 @@ ac_add_options --with-mozilla-api-keyfil
 
 . $topsrcdir/build/unix/mozconfig.linux32
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux32/debug
+++ b/browser/config/mozconfigs/linux32/debug
@@ -7,17 +7,17 @@ MOZ_AUTOMATION_L10N_CHECK=0
 
 . $topsrcdir/build/unix/mozconfig.linux32
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 #Use ccache
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/common-opt
+++ b/browser/config/mozconfigs/linux64/common-opt
@@ -8,13 +8,13 @@ ac_add_options --with-mozilla-api-keyfil
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -5,17 +5,17 @@ ac_add_options --with-google-oauth-api-k
 
 MOZ_AUTOMATION_L10N_CHECK=0
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx-universal/common-opt
+++ b/browser/config/mozconfigs/macosx-universal/common-opt
@@ -11,13 +11,13 @@ ac_add_options --with-google-api-keyfile
 ac_add_options --with-google-oauth-api-keyfile=/builds/google-oauth-api.key
 ac_add_options --with-mozilla-api-keyfile=/builds/mozilla-desktop-geoloc-api.key
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64/debug
@@ -7,17 +7,17 @@ ac_add_options --with-google-oauth-api-k
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then
 ac_add_options --with-macbundlename-prefix=Firefox
 fi
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . "$topsrcdir/build/macosx/mozconfig.rust"
--- a/browser/config/mozconfigs/macosx64/debug-static-analysis
+++ b/browser/config/mozconfigs/macosx64/debug-static-analysis
@@ -2,15 +2,15 @@ MOZ_AUTOMATION_BUILD_SYMBOLS=0
 MOZ_AUTOMATION_PACKAGE_TESTS=0
 MOZ_AUTOMATION_L10N_CHECK=0
 
 . $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-debug
 ac_add_options --enable-dmd
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 ac_add_options --enable-clang-plugin
 
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.cache"
--- a/browser/config/mozconfigs/macosx64/nightly
+++ b/browser/config/mozconfigs/macosx64/nightly
@@ -5,17 +5,17 @@ ac_add_options --with-google-oauth-api-k
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then
 ac_add_options --with-macbundlename-prefix=Firefox
 fi
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . "$topsrcdir/build/macosx/mozconfig.rust"
--- a/browser/config/mozconfigs/win32/common-opt
+++ b/browser/config/mozconfigs/win32/common-opt
@@ -24,17 +24,17 @@ ac_add_options --with-mozilla-api-keyfil
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 . $topsrcdir/build/win32/mozconfig.vs2013-win64
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Enable Adobe Primetime CDM on 32-bit Windows in Mozilla builds.
 # Enabled here on the assumption that downstream vendors will not be using
 # these build configs.
 ac_add_options --enable-eme=adobe
 
 # Package js shell.
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -15,17 +15,17 @@ else
 fi
 ac_add_options --with-google-oauth-api-keyfile=${_google_oauth_api_keyfile}
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 . $topsrcdir/build/win32/mozconfig.vs2013-win64
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/common-opt
+++ b/browser/config/mozconfigs/win64/common-opt
@@ -20,15 +20,15 @@ fi
 ac_add_options --with-google-oauth-api-keyfile=${_google_oauth_api_keyfile}
 ac_add_options --with-mozilla-api-keyfile=/c/builds/mozilla-desktop-geoloc-api.key
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 . $topsrcdir/build/win64/mozconfig.vs2013
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -15,17 +15,17 @@ if [ -f /c/builds/google-oauth-api.key ]
 else
   _google_oauth_api_keyfile=/e/builds/google-oauth-api.key
 fi
 ac_add_options --with-google-oauth-api-keyfile=${_google_oauth_api_keyfile}
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . $topsrcdir/build/win64/mozconfig.vs2013
--- a/build/mobile/sutagent/android/fencp/DirCursor.java
+++ b/build/mobile/sutagent/android/fencp/DirCursor.java
@@ -43,19 +43,16 @@ public class DirCursor extends MatrixCur
     private void doLoadCursor(String sDir) {
         File dir = new File(sDir);
         int    nFiles = 0;
         int nCols = theColumns.length;
         int    lcvFiles = 0;
         int    nCIndex = 0;
         Object [] vals = new Object[nCols];
         
-        if (vals == null)
-            return;
-        
         if (dir.isDirectory()) {
             try {
                 nCIndex = getColumnIndex(_ID);
                 if (nCIndex > -1)
                     vals[nCIndex] = -1;
 
                 nCIndex = getColumnIndex(ISDIR);
                 if (nCIndex > -1)
--- a/build/mobile/sutagent/android/ffxcp/DirCursor.java
+++ b/build/mobile/sutagent/android/ffxcp/DirCursor.java
@@ -43,19 +43,16 @@ public class DirCursor extends MatrixCur
     private void doLoadCursor(String sDir) {
         File dir = new File(sDir);
         int    nFiles = 0;
         int nCols = theColumns.length;
         int    lcvFiles = 0;
         int    nCIndex = 0;
         Object [] vals = new Object[nCols];
 
-        if (vals == null)
-            return;
-
         if (dir.isDirectory()) {
             try {
                 nCIndex = getColumnIndex(_ID);
                 if (nCIndex > -1)
                     vals[nCIndex] = -1;
 
                 nCIndex = getColumnIndex(ISDIR);
                 if (nCIndex > -1)
--- a/build/stlport/moz.build
+++ b/build/stlport/moz.build
@@ -64,8 +64,10 @@ if CONFIG['GNU_CXX']:
         '-Wno-empty-body',
         '-Wno-type-limits',
         '-Wno-unused-local-typedefs',
     ]
 
 # Force to build a static library, instead of a fake library, without
 # installing it in dist/lib.
 NO_EXPAND_LIBS = True
+
+ALLOW_COMPILER_WARNINGS = True
--- a/caps/moz.build
+++ b/caps/moz.build
@@ -46,10 +46,8 @@ UNIFIED_SOURCES += [
 LOCAL_INCLUDES += [
     '/dom/base',
     '/js/xpconnect/src',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/chrome/moz.build
+++ b/chrome/moz.build
@@ -35,10 +35,8 @@ GENERATED_INCLUDES += [
 LOCAL_INCLUDES += [
     '/netwerk/base',
     '/netwerk/protocol/res',
     '/xpcom/components'
 ]
 
 if CONFIG['MOZ_ENABLE_GTK']:
     CXXFLAGS += CONFIG['TK_CFLAGS']
-
-FAIL_ON_WARNINGS = True
--- a/config/config.mk
+++ b/config/config.mk
@@ -354,35 +354,37 @@ else
 HOST_CFLAGS	+= $(MOZ_OPTIMIZE_FLAGS)
 endif # MOZ_OPTIMIZE == 1
 endif # MOZ_OPTIMIZE
 endif # CROSS_COMPILE
 
 CFLAGS += $(MOZ_FRAMEPTR_FLAGS)
 CXXFLAGS += $(MOZ_FRAMEPTR_FLAGS)
 
-# Check for FAIL_ON_WARNINGS (Shorthand for Makefiles to request that we use
-# the 'warnings as errors' compile flags)
+# Check for ALLOW_COMPILER_WARNINGS (shorthand for Makefiles to request that we
+# *don't* use the warnings-as-errors compile flags)
 
-# NOTE: First, we clear FAIL_ON_WARNINGS[_DEBUG] if we're doing a Windows PGO
-# build, since WARNINGS_AS_ERRORS has been suspected of causing isuses in that
-# situation. (See bug 437002.)
+# Don't use warnings-as-errors in Windows PGO builds because it is suspected of
+# causing problems in that situation. (See bug 437002.)
 ifeq (WINNT_1,$(OS_ARCH)_$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
-FAIL_ON_WARNINGS=
+ALLOW_COMPILER_WARNINGS=1
 endif # WINNT && (MOS_PROFILE_GENERATE ^ MOZ_PROFILE_USE)
 
-# Check for normal version of flag, and add WARNINGS_AS_ERRORS if it's set to 1.
-ifdef FAIL_ON_WARNINGS
-# Never treat warnings as errors in clang-cl, because it warns about many more
+# Don't use warnings-as-errors in clang-cl because it warns about many more
 # things than MSVC does.
-ifndef CLANG_CL
+ifdef CLANG_CL
+ALLOW_COMPILER_WARNINGS=1
+endif # CLANG_CL
+
+# Use warnings-as-errors if ALLOW_COMPILER_WARNINGS is not set to 1 (which
+# includes the case where it's undefined).
+ifneq (1,$(ALLOW_COMPILER_WARNINGS))
 CXXFLAGS += $(WARNINGS_AS_ERRORS)
 CFLAGS   += $(WARNINGS_AS_ERRORS)
-endif # CLANG_CL
-endif # FAIL_ON_WARNINGS
+endif # ALLOW_COMPILER_WARNINGS
 
 ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
 #// Currently, unless USE_STATIC_LIBS is defined, the multithreaded
 #// DLL version of the RTL is used...
 #//
 #//------------------------------------------------------------------------
 ifdef USE_STATIC_LIBS
 RTL_FLAGS=-MT          # Statically linked multithreaded RTL
--- a/config/external/nss/moz.build
+++ b/config/external/nss/moz.build
@@ -40,8 +40,11 @@ else:
     Library('nss')
     USE_LIBS += [
         '/security/nss/lib/nss/nss3',
         '/security/nss/lib/smime/smime3',
         '/security/nss/lib/ssl/ssl3',
         '/security/nss/lib/util/nssutil3',
         'sqlite',
     ]
+
+# XXX: We should fix these warnings.
+ALLOW_COMPILER_WARNINGS = True
--- a/config/moz.build
+++ b/config/moz.build
@@ -37,8 +37,11 @@ PYTHON_UNIT_TESTS += [
     'tests/unit-expandlibs.py',
     'tests/unit-mozunit.py',
     'tests/unit-nsinstall.py',
     'tests/unit-printprereleasesuffix.py',
 ]
 
 if CONFIG['GNU_CC'] and CONFIG['MOZ_OPTIMIZE']:
     CFLAGS += ['-O3']
+
+# XXX: We should fix these warnings.
+ALLOW_COMPILER_WARNINGS = True
--- a/db/sqlite3/src/moz.build
+++ b/db/sqlite3/src/moz.build
@@ -4,16 +4,18 @@
 # 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/.
 NO_VISIBILITY_FLAGS = True
 
 EXPORTS += [
     'sqlite3.h',
 ]
 
+ALLOW_COMPILER_WARNINGS = True
+
 if CONFIG['MOZ_FOLD_LIBS']:
     # When folding libraries, sqlite is actually in the nss library.
     FINAL_LIBRARY = 'nss'
 else:
     # The final library is in config/external/sqlite
     FINAL_LIBRARY = 'sqlite'
 
 SOURCES += [
--- a/docshell/base/moz.build
+++ b/docshell/base/moz.build
@@ -60,18 +60,16 @@ UNIFIED_SOURCES += [
     'nsDocShellLoadInfo.cpp',
     'nsDocShellTransferableHooks.cpp',
     'nsDownloadHistory.cpp',
     'nsDSURIContentListener.cpp',
     'nsWebNavigationInfo.cpp',
     'SerializedLoadContext.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/docshell/shistory',
     '/dom/base',
     '/layout/base',
     '/layout/generic',
--- a/docshell/base/timeline/moz.build
+++ b/docshell/base/timeline/moz.build
@@ -22,15 +22,13 @@ EXPORTS.mozilla += [
 UNIFIED_SOURCES += [
     'AutoGlobalTimelineMarker.cpp',
     'AutoTimelineMarker.cpp',
     'ObservedDocShell.cpp',
     'TimelineConsumers.cpp',
     'TimelineMarker.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/docshell/base'
 ]
--- a/docshell/build/moz.build
+++ b/docshell/build/moz.build
@@ -22,10 +22,8 @@ LOCAL_INCLUDES += [
 
 if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
     LOCAL_INCLUDES += ['/uriloader/exthandler/mac']
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
-
-FAIL_ON_WARNINGS = True
--- a/docshell/shistory/moz.build
+++ b/docshell/shistory/moz.build
@@ -22,15 +22,13 @@ EXPORTS += [
 
 UNIFIED_SOURCES += [
     'nsSHEntry.cpp',
     'nsSHEntryShared.cpp',
     'nsSHistory.cpp',
     'nsSHTransaction.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/docshell/base',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/activities/moz.build
+++ b/dom/activities/moz.build
@@ -26,17 +26,15 @@ EXTRA_COMPONENTS += [
     'ActivityWrapper.js',
 ]
 
 EXTRA_JS_MODULES += [
     'ActivitiesService.jsm',
     'ActivitiesServiceFilter.jsm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/alarm/moz.build
+++ b/dom/alarm/moz.build
@@ -23,17 +23,15 @@ EXTRA_COMPONENTS += [
     'AlarmsManager.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'AlarmDB.jsm',
     'AlarmService.jsm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -569,17 +569,18 @@ Animation::ComposeStyle(nsRefPtr<AnimVal
                         bool& aNeedsRefreshes)
 {
   if (!mEffect) {
     return;
   }
 
   AnimationPlayState playState = PlayState();
   if (playState == AnimationPlayState::Running ||
-      playState == AnimationPlayState::Pending) {
+      playState == AnimationPlayState::Pending ||
+      HasEndEventToQueue()) {
     aNeedsRefreshes = true;
   }
 
   if (!IsInEffect()) {
     return;
   }
 
   // In order to prevent flicker, there are a few cases where we want to use
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -293,16 +293,29 @@ public:
    * |aNeedsRefreshes| will be set to true if this animation expects to update
    * the style rule on the next refresh driver tick as well (because it
    * is running and has an effect to sample).
    */
   void ComposeStyle(nsRefPtr<AnimValuesStyleRule>& aStyleRule,
                     nsCSSPropertySet& aSetProperties,
                     bool& aNeedsRefreshes);
 
+
+  // FIXME: Because we currently determine if we need refresh driver ticks
+  // during restyling (specifically ComposeStyle above) and not necessarily
+  // during a refresh driver tick, we can arrive at a situation where we
+  // have finished running an animation but are waiting until the next tick
+  // to queue the final end event. This method tells us when we are in that
+  // situation so we can avoid unregistering from the refresh driver until
+  // we've finished dispatching events.
+  //
+  // This is a temporary measure until bug 1195180 is done and we can do all
+  // our registering and unregistering within a tick callback.
+  virtual bool HasEndEventToQueue() const { return false; }
+
   void NotifyEffectTimingUpdated();
 
 protected:
   void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime);
   void SilentlySetPlaybackRate(double aPlaybackRate);
   void DoCancel();
   void DoPlay(ErrorResult& aRv, LimitBehavior aLimitBehavior);
   void DoPause(ErrorResult& aRv);
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -25,11 +25,9 @@ UNIFIED_SOURCES += [
     'Animation.cpp',
     'AnimationEffectReadOnly.cpp',
     'AnimationTimeline.cpp',
     'DocumentTimeline.cpp',
     'KeyframeEffect.cpp',
     'PendingAnimationTracker.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/apps/moz.build
+++ b/dom/apps/moz.build
@@ -49,15 +49,13 @@ EXTRA_PP_JS_MODULES += [
     'OperatorApps.jsm',
     'ScriptPreloader.jsm',
     'Webapps.jsm',
 ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/js/xpconnect/wrappers',
 ]
--- a/dom/archivereader/moz.build
+++ b/dom/archivereader/moz.build
@@ -19,17 +19,15 @@ UNIFIED_SOURCES += [
     'ArchiveRequest.cpp',
     'ArchiveZipEvent.cpp',
     'ArchiveZipFile.cpp',
 ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
--- a/dom/asmjscache/moz.build
+++ b/dom/asmjscache/moz.build
@@ -11,15 +11,13 @@ EXPORTS.mozilla.dom.asmjscache += [
 SOURCES += [
     'AsmJSCache.cpp'
 ]
 
 IPDL_SOURCES += [
     'PAsmJSCacheEntry.ipdl'
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -156,25 +156,30 @@ static const nsAttrValue::EnumTable kMoz
   { "notification",       (int16_t)AudioChannel::Notification },
   { "alarm",              (int16_t)AudioChannel::Alarm },
   { "telephony",          (int16_t)AudioChannel::Telephony },
   { "ringer",             (int16_t)AudioChannel::Ringer },
   { "publicnotification", (int16_t)AudioChannel::Publicnotification },
   { nullptr }
 };
 
-/* static */ already_AddRefed<AudioChannelService>
-AudioChannelService::GetOrCreate()
+/* static */ void
+AudioChannelService::CreateServiceIfNeeded()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!gAudioChannelService) {
     gAudioChannelService = new AudioChannelService();
   }
+}
 
+/* static */ already_AddRefed<AudioChannelService>
+AudioChannelService::GetOrCreate()
+{
+  CreateServiceIfNeeded();
   nsRefPtr<AudioChannelService> service = gAudioChannelService.get();
   return service.forget();
 }
 
 void
 AudioChannelService::Shutdown()
 {
   if (gAudioChannelService) {
@@ -914,10 +919,11 @@ AudioChannelService::ChildStatusReceived
 
   data->mActiveTelephonyChannel = aTelephonyChannel;
   data->mActiveContentOrNormalChannel = aContentOrNormalChannel;
 }
 
 /* static */ bool
 AudioChannelService::IsAudioChannelMutedByDefault()
 {
+  CreateServiceIfNeeded();
   return sAudioChannelMutedByDefault;
 }
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -137,16 +137,18 @@ public:
 
   void ChildStatusReceived(uint64_t aChildID, bool aTelephonyChannel,
                            bool aContentOrNormalChannel, bool aAnyChannel);
 
 private:
   AudioChannelService();
   ~AudioChannelService();
 
+  static void CreateServiceIfNeeded();
+
   /**
    * Shutdown the singleton.
    */
   static void Shutdown();
 
   void MaybeSendStatusUpdate();
 
   bool ContentOrNormalChannelIsActive();
--- a/dom/audiochannel/moz.build
+++ b/dom/audiochannel/moz.build
@@ -16,13 +16,11 @@ EXPORTS += [
     'AudioChannelService.h',
 ]
 
 UNIFIED_SOURCES += [
     'AudioChannelAgent.cpp',
     'AudioChannelService.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -404,18 +404,16 @@ if CONFIG['MOZ_BUILD_APP'] != 'mobile/an
         'SiteSpecificUserAgent.manifest',
     ]
 
 EXTRA_JS_MODULES += [
     'DOMRequestHelper.jsm',
     'IndexedDBHelper.jsm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../battery',
     '../bluetooth/common',
     '../bluetooth/common/webapi',
     '../events',
     '../media',
     '../network',
     '../time',
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -361,29 +361,28 @@ nsAnimationReceiver::RecordAnimationMuta
   }
 
   if (!Animations() || !(Subtree() || animationTarget == Target()) ||
       animationTarget->ChromeOnlyAccess()) {
     return;
   }
 
   if (nsAutoAnimationMutationBatch::IsBatching()) {
-    if (nsAutoAnimationMutationBatch::GetBatchTarget() != animationTarget) {
-      return;
-    }
-
     switch (aMutationType) {
       case eAnimationMutation_Added:
-        nsAutoAnimationMutationBatch::AnimationAdded(aAnimation);
+        nsAutoAnimationMutationBatch::AnimationAdded(aAnimation,
+                                                     animationTarget);
         break;
       case eAnimationMutation_Changed:
-        nsAutoAnimationMutationBatch::AnimationChanged(aAnimation);
+        nsAutoAnimationMutationBatch::AnimationChanged(aAnimation,
+                                                       animationTarget);
         break;
       case eAnimationMutation_Removed:
-        nsAutoAnimationMutationBatch::AnimationRemoved(aAnimation);
+        nsAutoAnimationMutationBatch::AnimationRemoved(aAnimation,
+                                                       animationTarget);
         break;
     }
 
     nsAutoAnimationMutationBatch::AddObserver(Observer());
     return;
   }
 
   nsDOMMutationRecord* m =
@@ -1054,39 +1053,53 @@ nsAutoAnimationMutationBatch::sCurrentBa
 
 void
 nsAutoAnimationMutationBatch::Done()
 {
   if (sCurrentBatch != this) {
     return;
   }
 
-  sCurrentBatch = mPreviousBatch;
+  sCurrentBatch = nullptr;
   if (mObservers.IsEmpty()) {
     nsDOMMutationObserver::LeaveMutationHandling();
     // Nothing to do.
     return;
   }
 
+  mBatchTargets.Sort(TreeOrderComparator());
+
   for (nsDOMMutationObserver* ob : mObservers) {
-    nsRefPtr<nsDOMMutationRecord> m =
-      new nsDOMMutationRecord(nsGkAtoms::animations, ob->GetParentObject());
-    m->mTarget = mBatchTarget;
+    bool didAddRecords = false;
+
+    for (nsINode* target : mBatchTargets) {
+      EntryArray* entries = mEntryTable.Get(target);
+      MOZ_ASSERT(entries,
+        "Targets in entry table and targets list should match");
+
+      nsRefPtr<nsDOMMutationRecord> m =
+        new nsDOMMutationRecord(nsGkAtoms::animations, ob->GetParentObject());
+      m->mTarget = target;
 
-    for (const Entry& e : mEntries) {
-      if (e.mState == eState_Added) {
-        m->mAddedAnimations.AppendElement(e.mAnimation);
-      } else if (e.mState == eState_Removed) {
-        m->mRemovedAnimations.AppendElement(e.mAnimation);
-      } else if (e.mState == eState_RemainedPresent && e.mChanged) {
-        m->mChangedAnimations.AppendElement(e.mAnimation);
+      for (const Entry& e : *entries) {
+        if (e.mState == eState_Added) {
+          m->mAddedAnimations.AppendElement(e.mAnimation);
+        } else if (e.mState == eState_Removed) {
+          m->mRemovedAnimations.AppendElement(e.mAnimation);
+        } else if (e.mState == eState_RemainedPresent && e.mChanged) {
+          m->mChangedAnimations.AppendElement(e.mAnimation);
+        }
+      }
+
+      if (!m->mAddedAnimations.IsEmpty() ||
+          !m->mChangedAnimations.IsEmpty() ||
+          !m->mRemovedAnimations.IsEmpty()) {
+        ob->AppendMutationRecord(m.forget());
+        didAddRecords = true;
       }
     }
 
-    if (!m->mAddedAnimations.IsEmpty() ||
-        !m->mChangedAnimations.IsEmpty() ||
-        !m->mRemovedAnimations.IsEmpty()) {
-      ob->AppendMutationRecord(m.forget());
+    if (didAddRecords) {
       ob->ScheduleForRun();
     }
   }
   nsDOMMutationObserver::LeaveMutationHandling();
 }
--- a/dom/base/nsDOMMutationObserver.h
+++ b/dom/base/nsDOMMutationObserver.h
@@ -737,30 +737,31 @@ private:
   nsCOMPtr<nsINode> mNextSibling;
 };
 
 class nsAutoAnimationMutationBatch
 {
   struct Entry;
 
 public:
-  explicit nsAutoAnimationMutationBatch(nsINode* aTarget)
-    : mBatchTarget(nullptr)
+  explicit nsAutoAnimationMutationBatch(nsIDocument* aDocument)
   {
-    Init(aTarget);
+    Init(aDocument);
   }
 
-  void Init(nsINode* aTarget)
+  void Init(nsIDocument* aDocument)
   {
-    if (aTarget && aTarget->OwnerDoc()->MayHaveDOMMutationObservers()) {
-      mBatchTarget = aTarget;
-      mPreviousBatch = sCurrentBatch;
-      sCurrentBatch = this;
-      nsDOMMutationObserver::EnterMutationHandling();
+    if (!aDocument ||
+        !aDocument->MayHaveDOMMutationObservers() ||
+        sCurrentBatch) {
+      return;
     }
+
+    sCurrentBatch = this;
+    nsDOMMutationObserver::EnterMutationHandling();
   }
 
   ~nsAutoAnimationMutationBatch()
   {
     Done();
   }
 
   void Done();
@@ -778,118 +779,130 @@ public:
   static void AddObserver(nsDOMMutationObserver* aObserver)
   {
     if (sCurrentBatch->mObservers.Contains(aObserver)) {
       return;
     }
     sCurrentBatch->mObservers.AppendElement(aObserver);
   }
 
-  static nsINode* GetBatchTarget()
-  {
-    return sCurrentBatch->mBatchTarget;
-  }
-
-  static void AnimationAdded(mozilla::dom::Animation* aAnimation)
+  static void AnimationAdded(mozilla::dom::Animation* aAnimation,
+                             nsINode* aTarget)
   {
     if (!IsBatching()) {
       return;
     }
 
-    Entry* entry = sCurrentBatch->FindEntry(aAnimation);
+    Entry* entry = sCurrentBatch->FindEntry(aAnimation, aTarget);
     if (entry) {
       switch (entry->mState) {
         case eState_RemainedAbsent:
           entry->mState = eState_Added;
           break;
         case eState_Removed:
           entry->mState = eState_RemainedPresent;
           break;
         default:
           NS_NOTREACHED("shouldn't have observed an animation being added "
                         "twice");
       }
     } else {
-      entry = sCurrentBatch->mEntries.AppendElement();
-      entry->mAnimation = aAnimation;
+      entry = sCurrentBatch->AddEntry(aAnimation, aTarget);
       entry->mState = eState_Added;
       entry->mChanged = false;
     }
   }
 
-  static void AnimationChanged(mozilla::dom::Animation* aAnimation)
+  static void AnimationChanged(mozilla::dom::Animation* aAnimation,
+                               nsINode* aTarget)
   {
-    Entry* entry = sCurrentBatch->FindEntry(aAnimation);
+    Entry* entry = sCurrentBatch->FindEntry(aAnimation, aTarget);
     if (entry) {
       NS_ASSERTION(entry->mState == eState_RemainedPresent ||
                    entry->mState == eState_Added,
                    "shouldn't have observed an animation being changed after "
                    "being removed");
       entry->mChanged = true;
     } else {
-      entry = sCurrentBatch->mEntries.AppendElement();
-      entry->mAnimation = aAnimation;
+      entry = sCurrentBatch->AddEntry(aAnimation, aTarget);
       entry->mState = eState_RemainedPresent;
       entry->mChanged = true;
     }
   }
 
-  static void AnimationRemoved(mozilla::dom::Animation* aAnimation)
+  static void AnimationRemoved(mozilla::dom::Animation* aAnimation,
+                               nsINode* aTarget)
   {
-    Entry* entry = sCurrentBatch->FindEntry(aAnimation);
+    Entry* entry = sCurrentBatch->FindEntry(aAnimation, aTarget);
     if (entry) {
       switch (entry->mState) {
         case eState_RemainedPresent:
           entry->mState = eState_Removed;
           break;
         case eState_Added:
           entry->mState = eState_RemainedAbsent;
           break;
         default:
           NS_NOTREACHED("shouldn't have observed an animation being removed "
                         "twice");
       }
     } else {
-      entry = sCurrentBatch->mEntries.AppendElement();
-      entry->mAnimation = aAnimation;
+      entry = sCurrentBatch->AddEntry(aAnimation, aTarget);
       entry->mState = eState_Removed;
       entry->mChanged = false;
     }
   }
 
 private:
-  Entry* FindEntry(mozilla::dom::Animation* aAnimation)
+  Entry* FindEntry(mozilla::dom::Animation* aAnimation, nsINode* aTarget)
   {
-    for (Entry& e : mEntries) {
+    EntryArray* entries = mEntryTable.Get(aTarget);
+    if (!entries) {
+      return nullptr;
+    }
+
+    for (Entry& e : *entries) {
       if (e.mAnimation == aAnimation) {
         return &e;
       }
     }
     return nullptr;
   }
 
+  Entry* AddEntry(mozilla::dom::Animation* aAnimation, nsINode* aTarget)
+  {
+    EntryArray* entries = sCurrentBatch->mEntryTable.LookupOrAdd(aTarget);
+    if (entries->IsEmpty()) {
+      sCurrentBatch->mBatchTargets.AppendElement(aTarget);
+    }
+    Entry* entry = entries->AppendElement();
+    entry->mAnimation = aAnimation;
+    return entry;
+  }
+
   enum State {
     eState_RemainedPresent,
     eState_RemainedAbsent,
     eState_Added,
     eState_Removed
   };
 
   struct Entry
   {
     nsRefPtr<mozilla::dom::Animation> mAnimation;
     State mState;
     bool mChanged;
   };
 
   static nsAutoAnimationMutationBatch* sCurrentBatch;
-  nsAutoAnimationMutationBatch* mPreviousBatch;
   nsAutoTArray<nsDOMMutationObserver*, 2> mObservers;
-  nsTArray<Entry> mEntries;
-  nsINode* mBatchTarget;
+  typedef nsTArray<Entry> EntryArray;
+  nsClassHashtable<nsPtrHashKey<nsINode>, EntryArray> mEntryTable;
+  // List of nodes referred to by mEntryTable so we can sort them
+  nsTArray<nsINode*> mBatchTargets;
 };
 
 inline
 nsDOMMutationObserver*
 nsMutationReceiverBase::Observer()
 {
   return mParent ?
     mParent->Observer() : static_cast<nsDOMMutationObserver*>(mObserver);
--- a/dom/battery/moz.build
+++ b/dom/battery/moz.build
@@ -8,15 +8,13 @@ EXPORTS.mozilla.dom.battery += [
     'Constants.h',
     'Types.h',
 ]
 
 SOURCES += [
     'BatteryManager.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -34,18 +34,16 @@ EXPORTS.mozilla.dom += [
     'PrimitiveConversions.h',
     'RootedDictionary.h',
     'StructuredClone.h',
     'ToJSValue.h',
     'TypedArray.h',
     'UnionMember.h',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/battery',
     '/dom/bluetooth/common/webapi',
     '/dom/camera',
     '/dom/canvas',
     '/dom/geolocation',
     '/dom/html',
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -149,17 +149,15 @@ EXPORTS.mozilla.dom.bluetooth += [
     'common/webapi/BluetoothPbapRequestHandle.h'
 ]
 IPDL_SOURCES += [
     'ipc/BluetoothTypes.ipdlh',
     'ipc/PBluetooth.ipdl',
     'ipc/PBluetoothRequest.ipdl'
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
     '../network',
     '../system/gonk'
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/broadcastchannel/moz.build
+++ b/dom/broadcastchannel/moz.build
@@ -24,9 +24,8 @@ LOCAL_INCLUDES += [
 ]
 
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-FAIL_ON_WARNINGS = True
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -564,43 +564,52 @@ BrowserElementChild.prototype = {
     let win = e.target.ownerDocument.defaultView;
     // Ignore metas which don't come from the top-level
     // <iframe mozbrowser> window.
     if (win != content) {
       debug('Not top level!');
       return;
     }
 
-    if (!e.target.name) {
+    var name = e.target.name;
+    var property = e.target.getAttributeNS(null, "property");
+
+    if (!name && !property) {
       return;
     }
 
-    debug('Got metaChanged: (' + e.target.name + ') ' + e.target.content);
+    debug('Got metaChanged: (' + (name || property) + ') ' +
+          e.target.content);
 
     let handlers = {
-      'viewmode': this._genericMetaHandler.bind(null, 'viewmode'),
-      'theme-color': this._genericMetaHandler.bind(null, 'theme-color'),
-      'theme-group': this._genericMetaHandler.bind(null, 'theme-group'),
+      'viewmode': this._genericMetaHandler,
+      'theme-color': this._genericMetaHandler,
+      'theme-group': this._genericMetaHandler,
       'application-name': this._applicationNameChangedHandler
     };
+    let handler = handlers[name];
 
-    let handler = handlers[e.target.name];
+    if ((property || name).match(/^og:/)) {
+      name = property || name;
+      handler = this._genericMetaHandler;
+    }
+
     if (handler) {
-      handler(e.type, e.target);
+      handler(name, e.type, e.target);
     }
   },
 
-  _applicationNameChangedHandler: function(eventType, target) {
+  _applicationNameChangedHandler: function(name, eventType, target) {
     if (eventType !== 'DOMMetaAdded') {
       // Bug 1037448 - Decide what to do when <meta name="application-name">
       // changes
       return;
     }
 
-    let meta = { name: 'application-name',
+    let meta = { name: name,
                  content: target.content };
 
     let lang;
     let elm;
 
     for (elm = target;
          !lang && elm && elm.nodeType == target.ELEMENT_NODE;
          elm = elm.parentNode) {
--- a/dom/browser-element/mochitest/browserElement_Metachange.js
+++ b/dom/browser-element/mochitest/browserElement_Metachange.js
@@ -19,16 +19,20 @@ function createHtmlWithLang(meta, lang) 
 function createMeta(name, content) {
   return '<meta name="' + name + '" content="' + content + '">';
 }
 
 function createMetaWithLang(name, content, lang) {
   return '<meta name="' + name + '" content="' + content + '" lang="' + lang + '">';
 }
 
+function createMetaWithProperty(property, content) {
+  return '<meta property="' + property + '" content="' + content + '">';
+}
+
 function runTest() {
   var iframe1 = document.createElement('iframe');
   iframe1.setAttribute('mozbrowser', 'true');
   document.body.appendChild(iframe1);
 
   // iframe2 is a red herring; we modify its meta elements but don't listen for
   // metachanges; we want to make sure that its metachange events aren't
   // picked up by the listener on iframe1.
@@ -126,16 +130,36 @@ function runTest() {
       // Test the content-language
       iframe1.src = "http://test/tests/dom/browser-element/mochitest/file_browserElement_Metachange.sjs?ru|dk";
     }
     else if (numMetaChanges == 10) {
       is(e.detail.name, 'application-name', 'name matches');
       is(e.detail.content, 'sjs', 'content matches');
       is(e.detail.lang, 'dk', 'language matches');
 
+      // Test Open Graph property
+      iframe1.src = createHtml(createMetaWithProperty('og:description', 'Fascinating article'));
+
+      // We should not get event if property doesn't start with 'og:'
+      iframe3.src = createHtml(createMetaWithProperty('go:description', 'Fascinating article'));
+    }
+    else if (numMetaChanges == 11) {
+      is(e.detail.name, 'og:description', 'property name matches');
+      is(e.detail.content, 'Fascinating article', 'content matches');
+
+      // Sometimes 'name' is used instead of 'property'. Verify that works.
+      iframe1.src = createHtml(createMeta('og:title', 'One weird trick!'));
+
+      // We should not get event if property doesn't start with 'og:'
+      iframe3.src = createHtml(createMeta('go:title', 'One weird trick!'));
+    }
+    else if (numMetaChanges == 12) {
+      is(e.detail.name, 'og:title', 'property name matches');
+      is(e.detail.content, 'One weird trick!', 'content matches');
+
       // Test the language
       SimpleTest.finish();
     } else {
       ok(false, 'Too many metachange events.');
     }
   });
 
   iframe3.addEventListener('mozbrowsermetachange', function(e) {
--- a/dom/browser-element/moz.build
+++ b/dom/browser-element/moz.build
@@ -27,18 +27,16 @@ EXTRA_COMPONENTS += [
     'BrowserElementParent.js',
     'BrowserElementParent.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'BrowserElementPromptService.jsm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../bluetooth',
     '/dom/html',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/cache/moz.build
+++ b/dom/cache/moz.build
@@ -82,18 +82,16 @@ IPDL_SOURCES += [
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '../workers',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += [
     'test/mochitest/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += [
     'test/mochitest/chrome.ini',
--- a/dom/camera/CameraPreviewMediaStream.cpp
+++ b/dom/camera/CameraPreviewMediaStream.cpp
@@ -31,17 +31,19 @@ FakeMediaStreamGraph::DispatchToMainThre
 CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
   : MediaStream(aWrapper)
   , mMutex("mozilla::camera::CameraPreviewMediaStream")
   , mInvalidatePending(0)
   , mDiscardedFrames(0)
   , mRateLimit(false)
   , mTrackCreated(false)
 {
-  SetGraphImpl(MediaStreamGraph::GetInstance());
+  SetGraphImpl(
+      MediaStreamGraph::GetInstance(
+        MediaStreamGraph::SYSTEM_THREAD_DRIVER, AudioChannel::Normal));
   mFakeMediaStreamGraph = new FakeMediaStreamGraph();
   mIsConsumed = false;
 }
 
 void
 CameraPreviewMediaStream::AddAudioOutput(void* aKey)
 {
 }
--- a/dom/camera/moz.build
+++ b/dom/camera/moz.build
@@ -56,18 +56,16 @@ if CONFIG['MOZ_B2G_CAMERA']:
         'CameraTestHardware.manifest',
     ]
 else:
     UNIFIED_SOURCES += [
         'FallbackCameraControl.cpp',
         'FallbackCameraManager.cpp',
     ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
     '/media/libyuv/include',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 # Suppress some GCC warnings being treated as errors:
--- a/dom/canvas/compiledtest/moz.build
+++ b/dom/canvas/compiledtest/moz.build
@@ -6,13 +6,11 @@
 
 GeckoCppUnitTests([
     'TestWebGLElementArrayCache',
 ])
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../',
 ]
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -138,18 +138,16 @@ UNIFIED_SOURCES += [
     'WebGLVertexArrayObject.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '../..', # Support `#include "mfbt/RefPtr.h"`
     '/js/xpconnect/wrappers',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../workers',
     '/dom/base',
     '/dom/html',
     '/dom/svg',
--- a/dom/cellbroadcast/moz.build
+++ b/dom/cellbroadcast/moz.build
@@ -30,11 +30,9 @@ EXPORTS.mozilla.dom.cellbroadcast += [
 ]
 
 IPDL_SOURCES += [
     'ipc/PCellBroadcast.ipdl',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/crypto/moz.build
+++ b/dom/crypto/moz.build
@@ -14,18 +14,16 @@ EXPORTS.mozilla.dom += [
 
 UNIFIED_SOURCES += [
     'CryptoBuffer.cpp',
     'CryptoKey.cpp',
     'KeyAlgorithmProxy.cpp',
     'WebCryptoTask.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/security/manager/ssl',
 ]
 
--- a/dom/datastore/moz.build
+++ b/dom/datastore/moz.build
@@ -40,9 +40,8 @@ EXTRA_JS_MODULES += [
     'DataStoreDB.jsm',
 ]
 
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-FAIL_ON_WARNINGS = True
--- a/dom/devicestorage/moz.build
+++ b/dom/devicestorage/moz.build
@@ -27,18 +27,16 @@ UNIFIED_SOURCES += [
     'DeviceStorageStatics.cpp',
     'nsDeviceStorage.cpp',
 ]
 
 IPDL_SOURCES += [
     'PDeviceStorageRequest.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/ipc',
 ]
 
--- a/dom/encoding/moz.build
+++ b/dom/encoding/moz.build
@@ -13,18 +13,16 @@ EXPORTS.mozilla.dom += [
 
 UNIFIED_SOURCES += [
     'EncodingUtils.cpp',
     'FallbackEncoding.cpp',
     'TextDecoder.cpp',
     'TextEncoder.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/intl/locale',
 ]
 
 props2arrays = '/intl/locale/props2arrays.py'
 prefixes = (
     'domainsfallbacks',
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -119,18 +119,16 @@ UNIFIED_SOURCES += [
 SOURCES += [
     'CustomEvent.cpp',
     'EventStateManager.cpp',
 ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     UNIFIED_SOURCES += ['SpeechRecognitionError.cpp']
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/html',
     '/dom/settings',
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -39,12 +39,11 @@ LOCAL_INCLUDES += [
     # For HttpBaseChannel.h dependencies
     '/netwerk/base',
     # For nsDataHandler.h
     '/netwerk/protocol/data',
     # For HttpBaseChannel.h
     '/netwerk/protocol/http',
 ]
 
-FAIL_ON_WARNINGS = True
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/filehandle/moz.build
+++ b/dom/filehandle/moz.build
@@ -21,18 +21,16 @@ UNIFIED_SOURCES += [
     'FileRequest.cpp',
     'FileService.cpp',
     'FileStreamWrappers.cpp',
     'MemoryStreams.cpp',
     'MetadataHelper.cpp',
     'MutableFile.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '../base',
 ]
 
 FINAL_LIBRARY = 'xul'
 
--- a/dom/filesystem/moz.build
+++ b/dom/filesystem/moz.build
@@ -37,10 +37,10 @@ IPDL_SOURCES += [
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
-if not CONFIG['CLANG_CXX']:
-    FAIL_ON_WARNINGS = True
+if CONFIG['CLANG_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
--- a/dom/fmradio/ipc/moz.build
+++ b/dom/fmradio/ipc/moz.build
@@ -13,18 +13,16 @@ EXPORTS.mozilla.dom += [
 
 UNIFIED_SOURCES += [
     'FMRadioChild.cpp',
     'FMRadioParent.cpp',
     'FMRadioRequestChild.cpp',
     'FMRadioRequestParent.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
--- a/dom/fmradio/moz.build
+++ b/dom/fmradio/moz.build
@@ -22,15 +22,13 @@ if CONFIG['MOZ_B2G_FM']:
 
     FINAL_LIBRARY = 'xul'
 
 IPDL_SOURCES += [
     'ipc/PFMRadio.ipdl',
     'ipc/PFMRadioRequest.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
     '../system/gonk',
 ]
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/gamepad/moz.build
+++ b/dom/gamepad/moz.build
@@ -38,18 +38,16 @@ elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'l
     UNIFIED_SOURCES += [
         'linux/LinuxGamepad.cpp'
     ]
 elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'android':
     UNIFIED_SOURCES += [
         'android/AndroidGamepad.cpp'
     ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 CFLAGS += CONFIG['GLIB_CFLAGS']
--- a/dom/geolocation/moz.build
+++ b/dom/geolocation/moz.build
@@ -16,18 +16,16 @@ SOURCES += [
 
 UNIFIED_SOURCES += [
     'MLSFallback.cpp',
     'nsGeoGridFuzzer.cpp',
     'nsGeolocationSettings.cpp',
     'nsGeoPosition.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/ipc',
 ]
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1825,16 +1825,24 @@ HTMLMediaElement::CaptureStreamInternal(
   if (!window) {
     return nullptr;
   }
 #ifdef MOZ_EME
   if (ContainsRestrictedContent()) {
     return nullptr;
   }
 #endif
+
+  if (!aGraph) {
+    MediaStreamGraph::GraphDriverType graphDriverType =
+      HasAudio() ? MediaStreamGraph::AUDIO_THREAD_DRIVER
+                 : MediaStreamGraph::SYSTEM_THREAD_DRIVER;
+    aGraph = MediaStreamGraph::GetInstance(graphDriverType, mAudioChannel);
+  }
+
   OutputMediaStream* out = mOutputStreams.AppendElement();
   out->mStream = DOMMediaStream::CreateTrackUnionStream(window, aGraph);
   nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
   out->mStream->CombineWithPrincipal(principal);
   out->mStream->SetCORSMode(mCORSMode);
   out->mFinishWhenEnded = aFinishWhenEnded;
 
   mAudioCaptured = true;
@@ -3046,17 +3054,18 @@ void HTMLMediaElement::SetupSrcMediaStre
   }
 
   // XXX Remove this if with CameraPreviewMediaStream per bug 1124630.
   if (!mSrcStream->GetStream()->AsCameraPreviewStream()) {
     // Now that we have access to |mSrcStream| we can pipe it to our shadow
     // version |mPlaybackStream|. If two media elements are playing the
     // same realtime DOMMediaStream, this allows them to pause playback
     // independently of each other.
-    mPlaybackStream = DOMMediaStream::CreateTrackUnionStream(window);
+    MediaStreamGraph* graph = mSrcStream->GetStream()->Graph();
+    mPlaybackStream = DOMMediaStream::CreateTrackUnionStream(window, graph);
     mPlaybackStreamInputPort = mPlaybackStream->GetStream()->AsProcessedStream()->
       AllocateInputPort(mSrcStream->GetStream(), MediaInputPort::FLAG_BLOCK_OUTPUT);
 
     nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
     mPlaybackStream->CombineWithPrincipal(principal);
 
     // Let |mSrcStream| decide when the stream has finished.
     GetSrcMediaStream()->AsProcessedStream()->SetAutofinish(true);
@@ -4704,17 +4713,19 @@ NS_IMETHODIMP HTMLMediaElement::WindowAu
   bool captured = OwnerDoc()->GetInnerWindow()->GetAudioCaptured();
 
   if (captured != mAudioCapturedByWindow) {
     if (captured) {
       mAudioCapturedByWindow = true;
       nsCOMPtr<nsPIDOMWindow> window =
         do_QueryInterface(OwnerDoc()->GetParentObject());
       uint64_t id = window->WindowID();
-      MediaStreamGraph* msg = MediaStreamGraph::GetInstance();
+      MediaStreamGraph* msg =
+        MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
+                                      AudioChannel::Normal);
 
       if (!mPlaybackStream) {
         nsRefPtr<DOMMediaStream> stream = CaptureStreamInternal(false, msg);
         mCaptureStreamPort = msg->ConnectToCaptureStream(id, stream->GetStream());
       } else {
         mCaptureStreamPort = msg->ConnectToCaptureStream(id, mPlaybackStream->GetStream());
       }
     } else {
--- a/dom/html/moz.build
+++ b/dom/html/moz.build
@@ -217,18 +217,16 @@ SOURCES += [
     'PluginDocument.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'htmlMenuBuilder.js',
     'htmlMenuBuilder.manifest'
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/caps',
     '/docshell/base',
     '/dom/base',
     '/dom/canvas',
     '/dom/media/',
--- a/dom/icc/moz.build
+++ b/dom/icc/moz.build
@@ -43,17 +43,15 @@ IPDL_SOURCES += [
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
     EXTRA_COMPONENTS += [
         'gonk/IccService.js',
         'gonk/IccService.manifest',
         'gonk/StkCmdFactory.js',
         'gonk/StkCmdFactory.manifest'
     ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/system/gonk',
 ]
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -82,18 +82,16 @@ IPDL_SOURCES += [
     'PBackgroundIDBVersionChangeTransaction.ipdl',
     'PIndexedDBPermissionRequest.ipdl',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/db/sqlite3/src',
     '/dom/base',
     '/dom/storage',
     '/dom/workers',
     '/ipc/glue',
     '/xpcom/build',
     '/xpcom/threads',
--- a/dom/inputport/InputPort.cpp
+++ b/dom/inputport/InputPort.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "MediaStreamGraph.h"
 #include "DOMMediaStream.h"
 #include "InputPortData.h"
 #include "InputPortListeners.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/dom/InputPort.h"
 
 namespace mozilla {
 namespace dom {
@@ -55,17 +56,20 @@ InputPort::Init(nsIInputPortData* aData,
     return;
   }
 
   aData->GetConnected(&mIsConnected);
 
   mInputPortListener = static_cast<InputPortListener*>(aListener);
   mInputPortListener->RegisterInputPort(this);
 
-  mStream = DOMMediaStream::CreateSourceStream(GetOwner());
+  MediaStreamGraph* graph =
+    MediaStreamGraph::GetInstance(MediaStreamGraph::SYSTEM_THREAD_DRIVER,
+                                  AudioChannel::Normal);
+  mStream = DOMMediaStream::CreateSourceStream(GetOwner(), graph);
 }
 
 void
 InputPort::Shutdown()
 {
   MOZ_ASSERT(mInputPortListener);
   if (mInputPortListener) {
     mInputPortListener->UnregisterInputPort(this);
--- a/dom/inputport/moz.build
+++ b/dom/inputport/moz.build
@@ -39,10 +39,8 @@ XPIDL_MODULE = 'dom_inputport'
 
 MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
\ No newline at end of file
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -107,18 +107,16 @@ IPDL_SOURCES += [
     'PMemoryReportRequest.ipdl',
     'PNuwa.ipdl',
     'PPluginWidget.ipdl',
     'PProcessHangMonitor.ipdl',
     'PScreenManager.ipdl',
     'PTabContext.ipdlh',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
     USE_LIBS += [
         'mozsandbox',
     ]
--- a/dom/json/moz.build
+++ b/dom/json/moz.build
@@ -7,18 +7,16 @@
 EXPORTS += [
     'nsJSON.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsJSON.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
--- a/dom/jsurl/moz.build
+++ b/dom/jsurl/moz.build
@@ -7,18 +7,16 @@
 EXPORTS += [
     'nsJSProtocolHandler.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsJSProtocolHandler.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     "/dom/base",
     "/netwerk/base",
 ]
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/mathml/moz.build
+++ b/dom/mathml/moz.build
@@ -4,17 +4,15 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'nsMathMLElement.cpp',
     'nsMathMLElementFactory.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
--- a/dom/media/CanvasCaptureMediaStream.cpp
+++ b/dom/media/CanvasCaptureMediaStream.cpp
@@ -351,15 +351,18 @@ CanvasCaptureMediaStream::Init(const dom
   return mOutputStreamDriver->Start();
 }
 
 already_AddRefed<CanvasCaptureMediaStream>
 CanvasCaptureMediaStream::CreateSourceStream(nsIDOMWindow* aWindow,
                                              HTMLCanvasElement* aCanvas)
 {
   nsRefPtr<CanvasCaptureMediaStream> stream = new CanvasCaptureMediaStream(aCanvas);
-  stream->InitSourceStream(aWindow);
+  MediaStreamGraph* graph =
+    MediaStreamGraph::GetInstance(MediaStreamGraph::SYSTEM_THREAD_DRIVER,
+                                  AudioChannel::Normal);
+  stream->InitSourceStream(aWindow, graph);
   return stream.forget();
 }
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -5,16 +5,17 @@
 
 #include "DOMMediaStream.h"
 #include "nsContentUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIUUIDGenerator.h"
 #include "mozilla/dom/MediaStreamBinding.h"
 #include "mozilla/dom/LocalMediaStreamBinding.h"
 #include "mozilla/dom/AudioNode.h"
+#include "AudioChannelAgent.h"
 #include "mozilla/dom/AudioTrack.h"
 #include "mozilla/dom/AudioTrackList.h"
 #include "mozilla/dom/VideoTrack.h"
 #include "mozilla/dom/VideoTrackList.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "MediaStreamGraph.h"
 #include "AudioStreamTrack.h"
 #include "VideoStreamTrack.h"
@@ -278,43 +279,34 @@ DOMMediaStream::IsFinished()
   return !mStream || mStream->IsFinished();
 }
 
 void
 DOMMediaStream::InitSourceStream(nsIDOMWindow* aWindow,
                                  MediaStreamGraph* aGraph)
 {
   mWindow = aWindow;
-  if (!aGraph) {
-    aGraph = MediaStreamGraph::GetInstance();
-  }
   InitStreamCommon(aGraph->CreateSourceStream(this));
 }
 
 void
 DOMMediaStream::InitTrackUnionStream(nsIDOMWindow* aWindow,
                                      MediaStreamGraph* aGraph)
 {
   mWindow = aWindow;
 
-  if (!aGraph) {
-    aGraph = MediaStreamGraph::GetInstance();
-  }
   InitStreamCommon(aGraph->CreateTrackUnionStream(this));
 }
 
 void
 DOMMediaStream::InitAudioCaptureStream(nsIDOMWindow* aWindow,
                                        MediaStreamGraph* aGraph)
 {
   mWindow = aWindow;
 
-  if (!aGraph) {
-    aGraph = MediaStreamGraph::GetInstance();
-  }
   InitStreamCommon(aGraph->CreateAudioCaptureStream(this));
 }
 
 void
 DOMMediaStream::InitStreamCommon(MediaStream* aStream)
 {
   mStream = aStream;
 
@@ -717,17 +709,21 @@ DOMHwMediaStream::DOMHwMediaStream()
 DOMHwMediaStream::~DOMHwMediaStream()
 {
 }
 
 already_AddRefed<DOMHwMediaStream>
 DOMHwMediaStream::CreateHwStream(nsIDOMWindow* aWindow)
 {
   nsRefPtr<DOMHwMediaStream> stream = new DOMHwMediaStream();
-  stream->InitSourceStream(aWindow);
+
+  MediaStreamGraph* graph =
+    MediaStreamGraph::GetInstance(MediaStreamGraph::SYSTEM_THREAD_DRIVER,
+                                  AudioChannel::Normal);
+  stream->InitSourceStream(aWindow, graph);
   stream->Init(stream->GetStream());
 
   return stream.forget();
 }
 
 void
 DOMHwMediaStream::Init(MediaStream* stream)
 {
--- a/dom/media/DOMMediaStream.h
+++ b/dom/media/DOMMediaStream.h
@@ -185,30 +185,30 @@ public:
   // Webrtc allows the remote side to name a stream whatever it wants, and we
   // need to surface this to content.
   void AssignId(const nsAString& aID) { mID = aID; }
 
   /**
    * Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream.
    */
   static already_AddRefed<DOMMediaStream> CreateSourceStream(nsIDOMWindow* aWindow,
-                                                             MediaStreamGraph* aGraph = nullptr);
+                                                             MediaStreamGraph* aGraph);
 
   /**
    * Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream.
    */
   static already_AddRefed<DOMMediaStream> CreateTrackUnionStream(nsIDOMWindow* aWindow,
-                                                                 MediaStreamGraph* aGraph = nullptr);
+                                                                 MediaStreamGraph* aGraph);
 
   /**
    * Create an nsDOMMediaStream whose underlying stream is an
    * AudioCaptureStream
    */
   static already_AddRefed<DOMMediaStream> CreateAudioCaptureStream(
-    nsIDOMWindow* aWindow, MediaStreamGraph* aGraph = nullptr);
+    nsIDOMWindow* aWindow, MediaStreamGraph* aGraph);
 
   void SetLogicalStreamStartTime(StreamTime aTime)
   {
     mLogicalStreamStartTime = aTime;
   }
 
   // Notifications from StreamListener.
   // BindDOMTrack should only be called when it's safe to run script.
@@ -260,21 +260,21 @@ public:
 
   virtual void NotifyMediaStreamTrackEnded(MediaStreamTrack* aTrack);
 
 protected:
   virtual ~DOMMediaStream();
 
   void Destroy();
   void InitSourceStream(nsIDOMWindow* aWindow,
-                        MediaStreamGraph* aGraph = nullptr);
+                        MediaStreamGraph* aGraph);
   void InitTrackUnionStream(nsIDOMWindow* aWindow,
-                            MediaStreamGraph* aGraph = nullptr);
+                            MediaStreamGraph* aGraph);
   void InitAudioCaptureStream(nsIDOMWindow* aWindow,
-                              MediaStreamGraph* aGraph = nullptr);
+                              MediaStreamGraph* aGraph);
   void InitStreamCommon(MediaStream* aStream);
   already_AddRefed<AudioTrack> CreateAudioTrack(AudioStreamTrack* aStreamTrack);
   already_AddRefed<VideoTrack> CreateVideoTrack(VideoStreamTrack* aStreamTrack);
 
   // Called when MediaStreamGraph has finished an iteration where tracks were
   // created.
   void TracksCreated();
 
@@ -346,30 +346,30 @@ public:
 
   virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID) { return nullptr; }
 
   /**
    * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
    */
   static already_AddRefed<DOMLocalMediaStream>
   CreateSourceStream(nsIDOMWindow* aWindow,
-                     MediaStreamGraph* aGraph = nullptr);
+                     MediaStreamGraph* aGraph);
 
   /**
    * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
    */
   static already_AddRefed<DOMLocalMediaStream>
   CreateTrackUnionStream(nsIDOMWindow* aWindow,
-                         MediaStreamGraph* aGraph = nullptr);
+                         MediaStreamGraph* aGraph);
 
   /**
    * Create an nsDOMLocalMediaStream whose underlying stream is an
    * AudioCaptureStream. */
   static already_AddRefed<DOMLocalMediaStream> CreateAudioCaptureStream(
-    nsIDOMWindow* aWindow, MediaStreamGraph* aGraph = nullptr);
+    nsIDOMWindow* aWindow, MediaStreamGraph* aGraph);
 
 protected:
   virtual ~DOMLocalMediaStream();
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(DOMLocalMediaStream,
                               NS_DOMLOCALMEDIASTREAM_IID)
 
@@ -383,17 +383,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
 
   /**
    * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream.
    */
   static already_AddRefed<DOMAudioNodeMediaStream>
   CreateTrackUnionStream(nsIDOMWindow* aWindow,
                          AudioNode* aNode,
-                         MediaStreamGraph* aGraph = nullptr);
+                         MediaStreamGraph* aGraph);
 
 protected:
   ~DOMAudioNodeMediaStream();
 
 private:
   // If this object wraps a stream owned by an AudioNode, we need to ensure that
   // the node isn't cycle-collected too early.
   nsRefPtr<AudioNode> mStreamNode;
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -477,22 +477,23 @@ nsresult AudioDevice::Allocate(const dom
  */
 class nsDOMUserMediaStream : public DOMLocalMediaStream
 {
 public:
   static already_AddRefed<nsDOMUserMediaStream>
   CreateTrackUnionStream(nsIDOMWindow* aWindow,
                          GetUserMediaCallbackMediaStreamListener* aListener,
                          MediaEngineSource* aAudioSource,
-                         MediaEngineSource* aVideoSource)
+                         MediaEngineSource* aVideoSource,
+                         MediaStreamGraph* aMSG)
   {
     nsRefPtr<nsDOMUserMediaStream> stream = new nsDOMUserMediaStream(aListener,
                                                                      aAudioSource,
                                                                      aVideoSource);
-    stream->InitTrackUnionStream(aWindow);
+    stream->InitTrackUnionStream(aWindow, aMSG);
     return stream.forget();
   }
 
   nsDOMUserMediaStream(GetUserMediaCallbackMediaStreamListener* aListener,
                        MediaEngineSource *aAudioSource,
                        MediaEngineSource *aVideoSource) :
     mListener(aListener),
     mAudioSource(aAudioSource),
@@ -781,39 +782,46 @@ public:
         branch->GetIntPref("media.getusermedia.agc", &agc);
         branch->GetBoolPref("media.getusermedia.noise_enabled", &noise_on);
         branch->GetIntPref("media.getusermedia.noise", &noise);
         branch->GetIntPref("media.getusermedia.playout_delay", &playout_delay);
       }
     }
 #endif
 
-    MediaStreamGraph* msg = MediaStreamGraph::GetInstance();
+    MediaStreamGraph::GraphDriverType graphDriverType =
+      mAudioSource ? MediaStreamGraph::AUDIO_THREAD_DRIVER
+                   : MediaStreamGraph::SYSTEM_THREAD_DRIVER;
+    MediaStreamGraph* msg =
+      MediaStreamGraph::GetInstance(graphDriverType,
+                                    dom::AudioChannel::Normal);
+
     nsRefPtr<SourceMediaStream> stream = msg->CreateSourceStream(nullptr);
 
     nsRefPtr<DOMLocalMediaStream> domStream;
     // AudioCapture is a special case, here, in the sense that we're not really
     // using the audio source and the SourceMediaStream, which acts as
     // placeholders. We re-route a number of stream internaly in the MSG and mix
     // them down instead.
     if (mAudioSource &&
         mAudioSource->GetMediaSource() == dom::MediaSourceEnum::AudioCapture) {
-      domStream = DOMLocalMediaStream::CreateAudioCaptureStream(window);
+      domStream = DOMLocalMediaStream::CreateAudioCaptureStream(window, msg);
       // It should be possible to pipe the capture stream to anything. CORS is
       // not a problem here, we got explicit user content.
       domStream->SetPrincipal(window->GetExtantDoc()->NodePrincipal());
       msg->RegisterCaptureStreamForWindow(
             mWindowID, domStream->GetStream()->AsProcessedStream());
       window->SetAudioCapture(true);
     } else {
       // Normal case, connect the source stream to the track union stream to
       // avoid us blocking
       nsRefPtr<nsDOMUserMediaStream> trackunion =
         nsDOMUserMediaStream::CreateTrackUnionStream(window, mListener,
-                                                     mAudioSource, mVideoSource);
+                                                     mAudioSource, mVideoSource,
+                                                     msg);
       trackunion->GetStream()->AsProcessedStream()->SetAutofinish(true);
       nsRefPtr<MediaInputPort> port = trackunion->GetStream()->AsProcessedStream()->
         AllocateInputPort(stream, MediaInputPort::FLAG_BLOCK_OUTPUT);
       trackunion->mSourceStream = stream;
       trackunion->mPort = port.forget();
       // Log the relationship between SourceMediaStream and TrackUnion stream
       // Make sure logger starts before capture
       AsyncLatencyLogger::Get(true);
@@ -2826,17 +2834,20 @@ GetUserMediaCallbackMediaStreamListener:
                              this, nullptr, nullptr,
                              nullptr, mVideoSource,
                              mFinished, mWindowID, nullptr));
   } else if (mAudioSource &&
              mAudioSource->GetMediaSource() == dom::MediaSourceEnum::AudioCapture) {
     nsCOMPtr<nsPIDOMWindow> window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
     MOZ_ASSERT(window);
     window->SetAudioCapture(false);
-    MediaStreamGraph::GetInstance()->UnregisterCaptureStreamForWindow(mWindowID);
+    MediaStreamGraph* graph =
+      MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
+                                    dom::AudioChannel::Normal);
+    graph->UnregisterCaptureStreamForWindow(mWindowID);
     mStream->Destroy();
   }
 }
 
 // Stop backend for track
 
 void
 GetUserMediaCallbackMediaStreamListener::StopTrack(TrackID aID, bool aIsAudio)
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -53,17 +53,17 @@ PRLogModuleInfo* gMediaStreamGraphLog;
 #  else
 #    define LIFECYCLE_LOG(...) printf(__VA_ARGS__);printf("\n");
 #  endif
 #else
 #  define LIFECYCLE_LOG(...)
 #endif
 
 /**
- * The singleton graph instance.
+ * A hash table containing the graph instances, one per AudioChannel.
  */
 static nsDataHashtable<nsUint32HashKey, MediaStreamGraphImpl*> gGraphs;
 
 MediaStreamGraphImpl::~MediaStreamGraphImpl()
 {
   NS_ASSERTION(IsEmpty(),
                "All streams should have been destroyed by messages from the main thread");
   STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p destroyed", this));
@@ -2860,34 +2860,33 @@ ProcessedMediaStream::DestroyImpl()
   }
   MediaStream::DestroyImpl();
   // The stream order is only important if there are connections, in which
   // case MediaInputPort::Disconnect() called SetStreamOrderDirty().
   // MediaStreamGraphImpl::RemoveStreamGraphThread() will also call
   // SetStreamOrderDirty(), for other reasons.
 }
 
-MediaStreamGraphImpl::MediaStreamGraphImpl(bool aRealtime,
+MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
                                            TrackRate aSampleRate,
-                                           bool aStartWithAudioDriver,
                                            dom::AudioChannel aChannel)
   : MediaStreamGraph(aSampleRate)
   , mPortCount(0)
   , mNeedAnotherIteration(false)
   , mGraphDriverAsleep(false)
   , mMonitor("MediaStreamGraphImpl")
   , mLifecycleState(LIFECYCLE_THREAD_NOT_STARTED)
   , mEndTime(GRAPH_TIME_MAX)
   , mForceShutDown(false)
   , mPostedRunInStableStateEvent(false)
   , mFlushSourcesNow(false)
   , mFlushSourcesOnNextIteration(false)
   , mDetectedNotRunning(false)
   , mPostedRunInStableState(false)
-  , mRealtime(aRealtime)
+  , mRealtime(aDriverRequested != OFFLINE_THREAD_DRIVER)
   , mNonRealtimeProcessing(false)
   , mStreamOrderDirty(false)
   , mLatencyLog(AsyncLatencyLogger::Get())
 #ifdef MOZ_WEBRTC
   , mFarendObserverRef(nullptr)
 #endif
   , mMemoryReportMonitor("MSGIMemory")
   , mSelfRef(this)
@@ -2898,17 +2897,17 @@ MediaStreamGraphImpl::MediaStreamGraphIm
 #endif
   , mAudioChannel(static_cast<uint32_t>(aChannel))
 {
   if (!gMediaStreamGraphLog) {
     gMediaStreamGraphLog = PR_NewLogModule("MediaStreamGraph");
   }
 
   if (mRealtime) {
-    if (aStartWithAudioDriver) {
+    if (aDriverRequested == AUDIO_THREAD_DRIVER) {
       AudioCallbackDriver* driver = new AudioCallbackDriver(this, aChannel);
       mDriver = driver;
       mMixer.AddCallback(driver);
     } else {
       mDriver = new SystemClockDriver(this);
     }
   } else {
     mDriver = new OfflineClockDriver(this, MEDIA_GRAPH_TARGET_PERIOD_MS);
@@ -2955,47 +2954,55 @@ MediaStreamGraphShutdownObserver::Observ
     gGraphs.EnumerateRead(ForceShutdownEnumerator, nullptr);
     nsContentUtils::UnregisterShutdownObserver(this);
     gShutdownObserverRegistered = false;
   }
   return NS_OK;
 }
 
 MediaStreamGraph*
-MediaStreamGraph::GetInstance(bool aStartWithAudioDriver,
+MediaStreamGraph::GetInstance(MediaStreamGraph::GraphDriverType aGraphDriverRequested,
                               dom::AudioChannel aChannel)
 {
   NS_ASSERTION(NS_IsMainThread(), "Main thread only");
 
   uint32_t channel = static_cast<uint32_t>(aChannel);
   MediaStreamGraphImpl* graph = nullptr;
 
   if (!gGraphs.Get(channel, &graph)) {
     if (!gShutdownObserverRegistered) {
       gShutdownObserverRegistered = true;
       nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver());
     }
 
     CubebUtils::InitPreferredSampleRate();
 
-    graph = new MediaStreamGraphImpl(true, CubebUtils::PreferredSampleRate(), aStartWithAudioDriver, aChannel);
+    graph = new MediaStreamGraphImpl(aGraphDriverRequested,
+                                     CubebUtils::PreferredSampleRate(),
+                                     aChannel);
+
     gGraphs.Put(channel, graph);
 
-    STREAM_LOG(LogLevel::Debug, ("Starting up MediaStreamGraph %p", graph));
+    STREAM_LOG(LogLevel::Debug,
+        ("Starting up MediaStreamGraph %p for channel %s",
+         graph, AudioChannelValues::strings[channel]));
   }
 
   return graph;
 }
 
 MediaStreamGraph*
 MediaStreamGraph::CreateNonRealtimeInstance(TrackRate aSampleRate)
 {
   NS_ASSERTION(NS_IsMainThread(), "Main thread only");
 
-  MediaStreamGraphImpl* graph = new MediaStreamGraphImpl(false, aSampleRate);
+  MediaStreamGraphImpl* graph =
+    new MediaStreamGraphImpl(OFFLINE_THREAD_DRIVER,
+                             aSampleRate,
+                             AudioChannel::Normal);
 
   STREAM_LOG(LogLevel::Debug, ("Starting up Offline MediaStreamGraph %p", graph));
 
   return graph;
 }
 
 void
 MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -1190,32 +1190,43 @@ protected:
   bool mAutofinish;
   // After UpdateStreamOrder(), mCycleMarker is either 0 or 1 to indicate
   // whether this stream is in a muted cycle.  During ordering it can contain
   // other marker values - see MediaStreamGraphImpl::UpdateStreamOrder().
   uint32_t mCycleMarker;
 };
 
 /**
- * Initially, at least, we will have a singleton MediaStreamGraph per
- * process.  Each OfflineAudioContext object creates its own MediaStreamGraph
- * object too.
+ * There can be multiple MediaStreamGraph per process: one per AudioChannel.
+ * Additionaly, each OfflineAudioContext object creates its own MediaStreamGraph
+ * object too..
  */
 class MediaStreamGraph
 {
 public:
+
   // We ensure that the graph current time advances in multiples of
   // IdealAudioBlockSize()/AudioStream::PreferredSampleRate(). A stream that
   // never blocks and has a track with the ideal audio rate will produce audio
   // in multiples of the block size.
   //
 
+  // Initializing an graph that outputs audio can be quite long on some
+  // platforms. Code that want to output audio at some point can express the
+  // fact that they will need an audio stream at some point by passing
+  // AUDIO_THREAD_DRIVER when getting an instance of MediaStreamGraph, so that
+  // the graph starts with the right driver.
+  enum GraphDriverType {
+    AUDIO_THREAD_DRIVER,
+    SYSTEM_THREAD_DRIVER,
+    OFFLINE_THREAD_DRIVER
+  };
   // Main thread only
-  static MediaStreamGraph* GetInstance(bool aStartWithAudioDriver = false,
-                                       dom::AudioChannel aChannel = dom::AudioChannel::Normal);
+  static MediaStreamGraph* GetInstance(GraphDriverType aGraphDriverRequested,
+                                       dom::AudioChannel aChannel);
   static MediaStreamGraph* CreateNonRealtimeInstance(TrackRate aSampleRate);
   // Idempotent
   static void DestroyNonRealtimeInstance(MediaStreamGraph* aGraph);
 
   // Control API.
   /**
    * Create a stream that a media decoder (or some other source of
    * media data, such as a camera) can write to.
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -88,26 +88,26 @@ public:
 class MediaStreamGraphImpl : public MediaStreamGraph,
                              public nsIMemoryReporter
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIMEMORYREPORTER
 
   /**
-   * Set aRealtime to true in order to create a MediaStreamGraph which provides
-   * support for real-time audio and video.  Set it to false in order to create
-   * a non-realtime instance which just churns through its inputs and produces
-   * output.  Those objects currently only support audio, and are used to
-   * implement OfflineAudioContext.  They do not support MediaStream inputs.
+   * Use aGraphDriverRequested with SYSTEM_THREAD_DRIVER or AUDIO_THREAD_DRIVER
+   * to create a MediaStreamGraph which provides support for real-time audio
+   * and/or video.  Set it to false in order to create a non-realtime instance
+   * which just churns through its inputs and produces output.  Those objects
+   * currently only support audio, and are used to implement
+   * OfflineAudioContext.  They do not support MediaStream inputs.
    */
-  explicit MediaStreamGraphImpl(bool aRealtime,
+  explicit MediaStreamGraphImpl(GraphDriverType aGraphDriverRequested,
                                 TrackRate aSampleRate,
-                                bool aStartWithAudioDriver = false,
-                                dom::AudioChannel aChannel = dom::AudioChannel::Normal);
+                                dom::AudioChannel aChannel);
 
   /**
    * Unregisters memory reporting and deletes this instance. This should be
    * called instead of calling the destructor directly.
    */
   void Destroy();
 
   // Main thread only.
--- a/dom/media/android/moz.build
+++ b/dom/media/android/moz.build
@@ -20,10 +20,8 @@ UNIFIED_SOURCES += [
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/apple/moz.build
+++ b/dom/media/apple/moz.build
@@ -9,13 +9,11 @@ EXPORTS += [
     'AppleMP3Reader.h',
 ]
 
 UNIFIED_SOURCES += [
     'AppleDecoder.cpp',
     'AppleMP3Reader.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 OS_LIBS += ['-framework AudioToolbox']
--- a/dom/media/bridge/moz.build
+++ b/dom/media/bridge/moz.build
@@ -21,10 +21,8 @@ LOCAL_INCLUDES += [
     '/media/webrtc/',
     '/media/webrtc/signaling/src/common/time_profiling',
     '/media/webrtc/signaling/src/media-conduit',
     '/media/webrtc/signaling/src/mediapipeline',
     '/media/webrtc/signaling/src/peerconnection',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/compiledtest/moz.build
+++ b/dom/media/compiledtest/moz.build
@@ -4,17 +4,15 @@
 # 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/.
 
 GeckoCppUnitTests([
     'TestAudioBuffers',
     'TestAudioMixer'
 ])
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '..',
 ]
 
 USE_LIBS += [
     'lgpllibs',
 ]
--- a/dom/media/directshow/moz.build
+++ b/dom/media/directshow/moz.build
@@ -30,14 +30,12 @@ SOURCES += [
 if not CONFIG['MOZ_WEBRTC']:
     SOURCES += [
         '/media/webrtc/trunk/webrtc/modules/video_capture/windows/BaseFilter.cpp',
         '/media/webrtc/trunk/webrtc/modules/video_capture/windows/BaseInputPin.cpp',
         '/media/webrtc/trunk/webrtc/modules/video_capture/windows/BasePin.cpp',
         '/media/webrtc/trunk/webrtc/modules/video_capture/windows/MediaType.cpp',
     ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/media/webrtc/trunk/webrtc/modules/video_capture/windows',
 ]
--- a/dom/media/eme/EMEUtils.cpp
+++ b/dom/media/eme/EMEUtils.cpp
@@ -84,17 +84,16 @@ ParseKeySystem(const nsAString& aExpecte
   }
   aOutCDMVersion = version;
 
   return true;
 }
 
 static const char16_t* sKeySystems[] = {
   MOZ_UTF16("org.w3.clearkey"),
-  MOZ_UTF16("com.adobe.access"),
   MOZ_UTF16("com.adobe.primetime"),
 };
 
 bool
 ParseKeySystem(const nsAString& aInputKeySystem,
                nsAString& aOutKeySystem,
                int32_t& aOutCDMVersion)
 {
@@ -119,9 +118,19 @@ LogToBrowserConsole(const nsAString& aMs
   if (!console) {
     NS_WARNING("Failed to log message to console.");
     return;
   }
   nsAutoString msg(aMsg);
   console->LogStringMessage(msg.get());
 }
 
+void
+ConstructKeySystem(const nsAString& aKeySystem,
+                   const nsAString& aCDMVersion,
+                   nsAString& aOutKeySystem)
+{
+  aOutKeySystem.Append(aKeySystem);
+  aOutKeySystem.AppendLiteral(".");
+  aOutKeySystem.Append(aCDMVersion);
+}
+
 } // namespace mozilla
--- a/dom/media/eme/EMEUtils.h
+++ b/dom/media/eme/EMEUtils.h
@@ -49,11 +49,16 @@ namespace mozilla {
 // if present. If it was not present, aOutMinCDMVersion is NO_CDM_VERSION.
 bool ParseKeySystem(const nsAString& aKeySystem,
                     nsAString& aOutKeySystem,
                     int32_t& aOutMinCDMVersion);
 
 void
 LogToBrowserConsole(const nsAString& aMsg);
 
+void
+ConstructKeySystem(const nsAString& aKeySystem,
+                   const nsAString& aCDMVersion,
+                   nsAString& aOutKeySystem);
+
 } // namespace mozilla
 
 #endif // EME_LOG_H_
--- a/dom/media/eme/GMPVideoDecoderTrialCreator.h
+++ b/dom/media/eme/GMPVideoDecoderTrialCreator.h
@@ -85,17 +85,17 @@ private:
     Pending = 0,
     Succeeded = 1,
     Failed = 2,
   };
 
   static TrialCreateState GetCreateTrialState(const nsAString& aKeySystem);
 
   struct TrialCreateData {
-    TrialCreateData(const nsAString& aKeySystem)
+    explicit TrialCreateData(const nsAString& aKeySystem)
       : mKeySystem(aKeySystem)
       , mStatus(GetCreateTrialState(aKeySystem))
     {}
     ~TrialCreateData() {}
     const nsString mKeySystem;
     nsRefPtr<TestGMPVideoDecoder> mTest;
     nsTArray<nsRefPtr<AbstractPromiseLike>> mPending;
     TrialCreateState mStatus;
@@ -136,17 +136,17 @@ public:
   virtual void Error(GMPErr aErr) override;
   virtual void Terminated() override;
 
   void ActorCreated(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost); // Main thread.
 
   class Callback : public GetGMPVideoDecoderCallback
   {
   public:
-    Callback(TestGMPVideoDecoder* aInstance)
+    explicit Callback(TestGMPVideoDecoder* aInstance)
       : mInstance(aInstance)
     {}
     ~Callback() {}
     void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost) override;
   private:
     nsRefPtr<TestGMPVideoDecoder> mInstance;
   };
 
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -38,21 +38,23 @@ NS_IMPL_RELEASE_INHERITED(MediaKeySessio
 // Count of number of instances. Used to give each instance a
 // unique token.
 static uint32_t sMediaKeySessionNum = 0;
 
 MediaKeySession::MediaKeySession(JSContext* aCx,
                                  nsPIDOMWindow* aParent,
                                  MediaKeys* aKeys,
                                  const nsAString& aKeySystem,
+                                 const nsAString& aCDMVersion,
                                  SessionType aSessionType,
                                  ErrorResult& aRv)
   : DOMEventTargetHelper(aParent)
   , mKeys(aKeys)
   , mKeySystem(aKeySystem)
+  , mCDMVersion(aCDMVersion)
   , mSessionType(aSessionType)
   , mToken(sMediaKeySessionNum++)
   , mIsClosed(false)
   , mUninitialized(true)
   , mKeyStatusMap(new MediaKeyStatusMap(aCx, aParent, aRv))
 {
   EME_LOG("MediaKeySession[%p,''] session Id set", this);
 
@@ -81,19 +83,19 @@ MediaKeySession::~MediaKeySession()
 
 MediaKeyError*
 MediaKeySession::GetError() const
 {
   return mMediaKeyError;
 }
 
 void
-MediaKeySession::GetKeySystem(nsString& aKeySystem) const
+MediaKeySession::GetKeySystem(nsString& aOutKeySystem) const
 {
-  aKeySystem = mKeySystem;
+  ConstructKeySystem(mKeySystem, mCDMVersion, aOutKeySystem);
 }
 
 void
 MediaKeySession::GetSessionId(nsString& aSessionId) const
 {
   aSessionId = GetSessionId();
 }
 
--- a/dom/media/eme/MediaKeySession.h
+++ b/dom/media/eme/MediaKeySession.h
@@ -36,16 +36,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaKeySession,
                                            DOMEventTargetHelper)
 public:
   MediaKeySession(JSContext* aCx,
                   nsPIDOMWindow* aParent,
                   MediaKeys* aKeys,
                   const nsAString& aKeySystem,
+                  const nsAString& aCDMVersion,
                   SessionType aSessionType,
                   ErrorResult& aRv);
 
   void SetSessionId(const nsAString& aSessionId);
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // Mark this as resultNotAddRefed to return raw pointers
@@ -101,16 +102,17 @@ private:
   already_AddRefed<DetailedPromise> MakePromise(ErrorResult& aRv,
                                                 const nsACString& aName);
 
   nsRefPtr<DetailedPromise> mClosed;
 
   nsRefPtr<MediaKeyError> mMediaKeyError;
   nsRefPtr<MediaKeys> mKeys;
   const nsString mKeySystem;
+  const nsString mCDMVersion;
   nsString mSessionId;
   const SessionType mSessionType;
   const uint32_t mToken;
   bool mIsClosed;
   bool mUninitialized;
   nsRefPtr<MediaKeyStatusMap> mKeyStatusMap;
 };
 
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -10,45 +10,54 @@
 #include "nsContentTypeParser.h"
 #ifdef MOZ_FMP4
 #include "MP4Decoder.h"
 #endif
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
 #include "WMFDecoderModule.h"
 #endif
+#ifdef XP_MACOSX
+#include "nsCocoaFeatures.h"
+#endif
 #include "nsContentCID.h"
 #include "nsServiceManagerUtils.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "VideoUtils.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 #include "mozilla/EMEUtils.h"
 #include "GMPUtils.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsXULAppAPI.h"
 
+#if defined(XP_WIN) || defined(XP_MACOSX)
+#define PRIMETIME_EME_SUPPORTED 1
+#endif
+
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeySystemAccess,
                                       mParent)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeySystemAccess)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeySystemAccess)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccess)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 MediaKeySystemAccess::MediaKeySystemAccess(nsPIDOMWindow* aParent,
-                                           const nsAString& aKeySystem)
+                                           const nsAString& aKeySystem,
+                                           const nsAString& aCDMVersion)
   : mParent(aParent)
   , mKeySystem(aKeySystem)
+  , mCDMVersion(aCDMVersion)
 {
 }
 
 MediaKeySystemAccess::~MediaKeySystemAccess()
 {
 }
 
 JSObject*
@@ -59,25 +68,25 @@ MediaKeySystemAccess::WrapObject(JSConte
 
 nsPIDOMWindow*
 MediaKeySystemAccess::GetParentObject() const
 {
   return mParent;
 }
 
 void
-MediaKeySystemAccess::GetKeySystem(nsString& aRetVal) const
+MediaKeySystemAccess::GetKeySystem(nsString& aOutKeySystem) const
 {
-  aRetVal = mKeySystem;
+  ConstructKeySystem(mKeySystem, mCDMVersion, aOutKeySystem);
 }
 
 already_AddRefed<Promise>
 MediaKeySystemAccess::CreateMediaKeys(ErrorResult& aRv)
 {
-  nsRefPtr<MediaKeys> keys(new MediaKeys(mParent, mKeySystem));
+  nsRefPtr<MediaKeys> keys(new MediaKeys(mParent, mKeySystem, mCDMVersion));
   return keys->Init(aRv);
 }
 
 static bool
 HaveGMPFor(mozIGeckoMediaPluginService* aGMPService,
            const nsCString& aKeySystem,
            const nsCString& aAPI,
            const nsCString& aTag = EmptyCString())
@@ -143,38 +152,40 @@ AdobePluginVoucherExists(const nsACStrin
   return AdobePluginFileExists(aVersionStr, NS_LITERAL_STRING("eme-adobe.voucher"));
 }
 #endif
 
 static MediaKeySystemStatus
 EnsureMinCDMVersion(mozIGeckoMediaPluginService* aGMPService,
                     const nsAString& aKeySystem,
                     int32_t aMinCdmVersion,
-                    nsACString& aOutMessage)
+                    nsACString& aOutMessage,
+                    nsACString& aOutCdmVersion)
 {
   nsTArray<nsCString> tags;
   tags.AppendElement(NS_ConvertUTF16toUTF8(aKeySystem));
   bool hasPlugin;
   nsAutoCString versionStr;
   if (NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR),
                                                     &tags,
                                                     &hasPlugin,
                                                     versionStr))) {
     aOutMessage = NS_LITERAL_CSTRING("GetPluginVersionForAPI failed");
     return MediaKeySystemStatus::Error;
   }
 
+  aOutCdmVersion = versionStr;
+
   if (!hasPlugin) {
     aOutMessage = NS_LITERAL_CSTRING("CDM is not installed");
     return MediaKeySystemStatus::Cdm_not_installed;
   }
 
 #ifdef XP_WIN
-  if (aKeySystem.EqualsLiteral("com.adobe.access") ||
-      aKeySystem.EqualsLiteral("com.adobe.primetime")) {
+  if (aKeySystem.EqualsLiteral("com.adobe.primetime")) {
     // Verify that anti-virus hasn't "helpfully" deleted the Adobe GMP DLL,
     // as we suspect may happen (Bug 1160382).
     bool somethingMissing = false;
     if (!AdobePluginDLLExists(versionStr)) {
       aOutMessage = NS_LITERAL_CSTRING("Adobe DLL was expected to be on disk but was not");
       somethingMissing = true;
     }
     if (!AdobePluginVoucherExists(versionStr)) {
@@ -202,54 +213,61 @@ EnsureMinCDMVersion(mozIGeckoMediaPlugin
 
   return MediaKeySystemStatus::Available;
 }
 
 /* static */
 MediaKeySystemStatus
 MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
                                          int32_t aMinCdmVersion,
-                                         nsACString& aOutMessage)
+                                         nsACString& aOutMessage,
+                                         nsACString& aOutCdmVersion)
 {
   MOZ_ASSERT(Preferences::GetBool("media.eme.enabled", false));
   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   if (NS_WARN_IF(!mps)) {
     aOutMessage = NS_LITERAL_CSTRING("Failed to get GMP service");
     return MediaKeySystemStatus::Error;
   }
 
   if (aKeySystem.EqualsLiteral("org.w3.clearkey")) {
     if (!Preferences::GetBool("media.eme.clearkey.enabled", true)) {
       aOutMessage = NS_LITERAL_CSTRING("ClearKey was disabled");
       return MediaKeySystemStatus::Cdm_disabled;
     }
-    return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage);
+    return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion);
   }
 
+#ifdef PRIMETIME_EME_SUPPORTED
+  if (aKeySystem.EqualsLiteral("com.adobe.primetime")) {
+    if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
+      aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled");
+      return MediaKeySystemStatus::Cdm_disabled;
+    }
 #ifdef XP_WIN
-  if ((aKeySystem.EqualsLiteral("com.adobe.access") ||
-       aKeySystem.EqualsLiteral("com.adobe.primetime"))) {
     // Win Vista and later only.
     if (!IsVistaOrLater()) {
       aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version not met for Adobe EME");
       return MediaKeySystemStatus::Cdm_not_supported;
     }
-    if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
-      aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled");
-      return MediaKeySystemStatus::Cdm_disabled;
+#endif
+#ifdef XP_MACOSX
+    if (!nsCocoaFeatures::OnLionOrLater()) {
+      aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version not met for Adobe EME");
+      return MediaKeySystemStatus::Cdm_not_supported;
     }
+#endif
     if (!EMEVoucherFileExists()) {
-      // The system doesn't have the codecs that Adobe EME relies
-      // on installed, or doesn't have a voucher for the plugin-container.
+      // Gecko doesn't have a voucher file for the plugin-container.
       // Adobe EME isn't going to work, so don't advertise that it will.
       aOutMessage = NS_LITERAL_CSTRING("Plugin-container voucher not present");
       return MediaKeySystemStatus::Cdm_not_supported;
     }
-    return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage);
+    return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion);
   }
 #endif
 
   return MediaKeySystemStatus::Cdm_not_supported;
 }
 
 static bool
 IsPlayableWithGMP(mozIGeckoMediaPluginService* aGMPS,
--- a/dom/media/eme/MediaKeySystemAccess.h
+++ b/dom/media/eme/MediaKeySystemAccess.h
@@ -25,17 +25,18 @@ class MediaKeySystemAccess final : publi
                                    public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeySystemAccess)
 
 public:
   explicit MediaKeySystemAccess(nsPIDOMWindow* aParent,
-                                const nsAString& aKeySystem);
+                                const nsAString& aKeySystem,
+                                const nsAString& aCDMVersion);
 
 protected:
   ~MediaKeySystemAccess();
 
 public:
   nsPIDOMWindow* GetParentObject() const;
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
@@ -43,26 +44,28 @@ public:
   void GetKeySystem(nsString& aRetVal) const;
 
   already_AddRefed<Promise> CreateMediaKeys(ErrorResult& aRv);
 
 
 
   static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem,
                                                  int32_t aMinCdmVersion,
-                                                 nsACString& aOutExceptionMessage);
+                                                 nsACString& aOutExceptionMessage,
+                                                 nsACString& aOutCdmVersion);
 
   static bool IsSupported(const nsAString& aKeySystem,
                           const Sequence<MediaKeySystemOptions>& aOptions);
 
   static void NotifyObservers(nsIDOMWindow* aWindow,
                               const nsAString& aKeySystem,
                               MediaKeySystemStatus aStatus);
 
 private:
   nsCOMPtr<nsPIDOMWindow> mParent;
   const nsString mKeySystem;
+  const nsString mCDMVersion;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_MediaKeySystemAccess_h
--- a/dom/media/eme/MediaKeySystemAccessManager.cpp
+++ b/dom/media/eme/MediaKeySystemAccessManager.cpp
@@ -8,16 +8,19 @@
 #include "nsServiceManagerUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/DetailedPromise.h"
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
 #endif
+#ifdef XP_MACOSX
+#include "nsCocoaFeatures.h"
+#endif
 #include "nsPrintfCString.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccessManager)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
@@ -69,16 +72,33 @@ MediaKeySystemAccessManager::Request(Det
                           NS_LITERAL_CSTRING("Invalid keysystem type or invalid options sequence"));
     return;
   }
   Sequence<MediaKeySystemOptions> optionsNotPassed;
   const auto& options = aOptions.WasPassed() ? aOptions.Value() : optionsNotPassed;
   Request(aPromise, aKeySystem, options, RequestType::Initial);
 }
 
+static bool
+ShouldTrialCreateGMP(const nsAString& aKeySystem)
+{
+  // Trial create where the CDM has a decoder;
+  // * ClearKey and Primetime on Windows Vista and later.
+  // * Primetime on MacOSX Lion and later.
+  return
+#ifdef XP_WIN
+    IsVistaOrLater();
+#elif defined(XP_MACOSX)
+    aKeySystem.EqualsLiteral("com.adobe.primetime") &&
+    nsCocoaFeatures::OnLionOrLater();
+#else
+    false;
+#endif
+}
+
 void
 MediaKeySystemAccessManager::Request(DetailedPromise* aPromise,
                                      const nsAString& aKeySystem,
                                      const Sequence<MediaKeySystemOptions>& aOptions,
                                      RequestType aType)
 {
   EME_LOG("MediaKeySystemAccessManager::Request %s", NS_ConvertUTF16toUTF8(aKeySystem).get());
   if (!Preferences::GetBool("media.eme.enabled", false)) {
@@ -102,24 +122,26 @@ MediaKeySystemAccessManager::Request(Det
     // to chrome to show a failure notice.
     MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, MediaKeySystemStatus::Cdm_not_supported);
     aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
                           NS_LITERAL_CSTRING("Key system string is invalid, or key system is unsupported"));
     return;
   }
 
   nsAutoCString message;
+  nsAutoCString cdmVersion;
   MediaKeySystemStatus status =
-    MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion, message);
+    MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion, message, cdmVersion);
 
   nsPrintfCString msg("MediaKeySystemAccess::GetKeySystemStatus(%s, minVer=%d) "
-                      "result=%s msg='%s'",
+                      "result=%s version='%s' msg='%s'",
                       NS_ConvertUTF16toUTF8(keySystem).get(),
                       minCdmVersion,
                       MediaKeySystemStatusValues::strings[(size_t)status].value,
+                      cdmVersion.get(),
                       message.get());
   LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg));
 
   if ((status == MediaKeySystemStatus::Cdm_not_installed ||
        status == MediaKeySystemStatus::Cdm_insufficient_version) &&
       keySystem.EqualsLiteral("com.adobe.primetime")) {
     // These are cases which could be resolved by downloading a new(er) CDM.
     // When we send the status to chrome, chrome's GMPProvider will attempt to
@@ -155,27 +177,25 @@ MediaKeySystemAccessManager::Request(Det
     }
     aPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                           NS_LITERAL_CSTRING("GetKeySystemAccess failed"));
     return;
   }
 
   if (aOptions.IsEmpty() ||
       MediaKeySystemAccess::IsSupported(keySystem, aOptions)) {
-    nsRefPtr<MediaKeySystemAccess> access(new MediaKeySystemAccess(mWindow, keySystem));
-#ifdef XP_WIN
-    if (IsVistaOrLater()) {
-      // On Windows, ensure we have tried creating a GMPVideoDecoder for this
+    nsRefPtr<MediaKeySystemAccess> access(
+      new MediaKeySystemAccess(mWindow, keySystem, NS_ConvertUTF8toUTF16(cdmVersion)));
+   if (ShouldTrialCreateGMP(keySystem)) {
+      // Ensure we have tried creating a GMPVideoDecoder for this
       // keySystem, and that we can use it to decode. This ensures that we only
-      // report that we support this keySystem when the CDM us usable (i.e.
-      // all system libraries required are installed).
+      // report that we support this keySystem when the CDM us usable.
       mTrialCreator->MaybeAwaitTrialCreate(keySystem, access, aPromise, mWindow);
       return;
     }
-#endif
     aPromise->MaybeResolve(access);
     return;
   }
 
   aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
                         NS_LITERAL_CSTRING("Key system is not supported"));
 }
 
--- a/dom/media/eme/MediaKeySystemAccessManager.h
+++ b/dom/media/eme/MediaKeySystemAccessManager.h
@@ -1,19 +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/. */
 
 #ifndef mozilla_dom_MediaKeySystemAccessManager_h
 #define mozilla_dom_MediaKeySystemAccessManager_h
 
 #include "mozilla/dom/MediaKeySystemAccess.h"
-#ifdef XP_WIN
 #include "mozilla/dom/GMPVideoDecoderTrialCreator.h"
-#endif
 #include "nsIObserver.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupportsImpl.h"
 #include "nsITimer.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -74,17 +72,15 @@ private:
 
   void RetryRequest(PendingRequest& aRequest);
 
   nsTArray<PendingRequest> mRequests;
 
   nsCOMPtr<nsPIDOMWindow> mWindow;
   bool mAddedObservers;
 
-#ifdef XP_WIN
   nsRefPtr<GMPVideoDecoderTrialCreator> mTrialCreator;
-#endif
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -42,19 +42,22 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Me
                                       mPendingSessions);
 NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeys)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeys)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeys)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-MediaKeys::MediaKeys(nsPIDOMWindow* aParent, const nsAString& aKeySystem)
+MediaKeys::MediaKeys(nsPIDOMWindow* aParent,
+                     const nsAString& aKeySystem,
+                     const nsAString& aCDMVersion)
   : mParent(aParent)
   , mKeySystem(aKeySystem)
+  , mCDMVersion(aCDMVersion)
   , mCreatePromiseId(0)
 {
   EME_LOG("MediaKeys[%p] constructed keySystem=%s",
           this, NS_ConvertUTF16toUTF8(mKeySystem).get());
 }
 
 static PLDHashOperator
 RejectPromises(const uint32_t& aKey,
@@ -134,19 +137,19 @@ MediaKeys::GetParentObject() const
 
 JSObject*
 MediaKeys::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return MediaKeysBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
-MediaKeys::GetKeySystem(nsString& retval) const
+MediaKeys::GetKeySystem(nsString& aOutKeySystem) const
 {
-  retval = mKeySystem;
+  ConstructKeySystem(mKeySystem, mCDMVersion, aOutKeySystem);
 }
 
 already_AddRefed<DetailedPromise>
 MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv)
 {
   nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
     NS_LITERAL_CSTRING("MediaKeys.setServerCertificate")));
   if (aRv.Failed()) {
@@ -428,16 +431,17 @@ MediaKeys::CreateSession(JSContext* aCx,
   }
 
   EME_LOG("MediaKeys[%p] Creating session", this);
 
   nsRefPtr<MediaKeySession> session = new MediaKeySession(aCx,
                                                           GetParentObject(),
                                                           this,
                                                           mKeySystem,
+                                                          mCDMVersion,
                                                           aSessionType,
                                                           aRv);
 
   if (aRv.Failed()) {
     return nullptr;
   }
 
   // Add session to the set of sessions awaiting their sessionId being ready.
--- a/dom/media/eme/MediaKeys.h
+++ b/dom/media/eme/MediaKeys.h
@@ -47,17 +47,17 @@ class MediaKeys final : public nsISuppor
                         public nsWrapperCache
 {
   ~MediaKeys();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeys)
 
-  MediaKeys(nsPIDOMWindow* aParentWindow, const nsAString& aKeySystem);
+  MediaKeys(nsPIDOMWindow* aParentWindow, const nsAString& aKeySystem, const nsAString& aCDMVersion);
 
   already_AddRefed<DetailedPromise> Init(ErrorResult& aRv);
 
   nsPIDOMWindow* GetParentObject() const;
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   nsresult Bind(HTMLMediaElement* aElement);
@@ -132,17 +132,18 @@ private:
 
   // Owning ref to proxy. The proxy has a weak reference back to the MediaKeys,
   // and the MediaKeys destructor clears the proxy's reference to the MediaKeys.
   nsRefPtr<CDMProxy> mProxy;
 
   nsRefPtr<HTMLMediaElement> mElement;
 
   nsCOMPtr<nsPIDOMWindow> mParent;
-  nsString mKeySystem;
+  const nsString mKeySystem;
+  const nsString mCDMVersion;
   nsCString mNodeId;
   KeySessionHashMap mKeySessions;
   PromiseHashMap mPromises;
   PendingKeySessionsHashMap mPendingSessions;
   PromiseId mCreatePromiseId;
 
   nsRefPtr<nsIPrincipal> mPrincipal;
   nsRefPtr<nsIPrincipal> mTopLevelPrincipal;
--- a/dom/media/eme/moz.build
+++ b/dom/media/eme/moz.build
@@ -1,15 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS.mozilla.dom += [
+    'GMPVideoDecoderTrialCreator.h',
     'MediaEncryptedEvent.h',
     'MediaKeyError.h',
     'MediaKeyMessageEvent.h',
     'MediaKeys.h',
     'MediaKeySession.h',
     'MediaKeyStatusMap.h',
     'MediaKeySystemAccess.h',
     'MediaKeySystemAccessManager.h',
@@ -24,29 +25,20 @@ EXPORTS.mozilla += [
 ]
 
 UNIFIED_SOURCES += [
     'CDMCallbackProxy.cpp',
     'CDMCaps.cpp',
     'CDMProxy.cpp',
     'DetailedPromise.cpp',
     'EMEUtils.cpp',
+    'GMPVideoDecoderTrialCreator.cpp',
     'MediaEncryptedEvent.cpp',
     'MediaKeyError.cpp',
     'MediaKeyMessageEvent.cpp',
     'MediaKeys.cpp',
     'MediaKeySession.cpp',
     'MediaKeyStatusMap.cpp',
     'MediaKeySystemAccess.cpp',
     'MediaKeySystemAccessManager.cpp',
 ]
 
-if CONFIG['OS_ARCH'] == 'WINNT':
-    UNIFIED_SOURCES += [
-        'GMPVideoDecoderTrialCreator.cpp',
-    ]
-    EXPORTS.mozilla.dom += [
-        'GMPVideoDecoderTrialCreator.h',
-    ]
-
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/encoder/fmp4_muxer/moz.build
+++ b/dom/media/encoder/fmp4_muxer/moz.build
@@ -13,11 +13,9 @@ UNIFIED_SOURCES += [
     'AMRBox.cpp',
     'AVCBox.cpp',
     'ISOControl.cpp',
     'ISOMediaBoxes.cpp',
     'ISOMediaWriter.cpp',
     'MP4ESDS.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/media/encoder/moz.build
+++ b/dom/media/encoder/moz.build
@@ -33,18 +33,16 @@ if CONFIG['MOZ_WEBM_ENCODER']:
     EXPORTS += ['VorbisTrackEncoder.h',
                 'VP8TrackEncoder.h',
     ]
     UNIFIED_SOURCES += ['VorbisTrackEncoder.cpp',
                         'VP8TrackEncoder.cpp',
     ]
     LOCAL_INCLUDES += ['/media/libyuv/include']
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 # These includes are from Android JB, for use of MediaCodec.
 LOCAL_INCLUDES += ['/ipc/chromium/src']
 CXXFLAGS += [
     '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
         'frameworks/native/opengl/include',
         'frameworks/native/include',
--- a/dom/media/fmp4/moz.build
+++ b/dom/media/fmp4/moz.build
@@ -16,12 +16,10 @@ UNIFIED_SOURCES += [
 ]
 
 SOURCES += [
     'MP4Demuxer.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 if CONFIG['MOZ_GONK_MEDIACODEC']:
     DEFINES['MOZ_GONK_MEDIACODEC'] = True
--- a/dom/media/gmp-plugin-openh264/moz.build
+++ b/dom/media/gmp-plugin-openh264/moz.build
@@ -17,10 +17,8 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     OS_LIBS += [
         'ole32',
     ]
 
 USE_STATIC_LIBS = True
 NO_VISIBILITY_FLAGS = True
 # Don't use STL wrappers; this isn't Gecko code
 DISABLE_STL_WRAPPING = True
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/gmp-plugin/moz.build
+++ b/dom/media/gmp-plugin/moz.build
@@ -19,10 +19,8 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     OS_LIBS += [
         'ole32',
     ]
 
 USE_STATIC_LIBS = True
 NO_VISIBILITY_FLAGS = True
 # Don't use STL wrappers; this isn't Gecko code
 DISABLE_STL_WRAPPING = True
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -128,18 +128,16 @@ IPDL_SOURCES += [
 ]
 
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 # comment this out to use Unsafe Shmem for more performance
 DEFINES['GMP_SAFE_SHMEM'] = True
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 # media/mtransport so we work with --disable-webrtc
 LOCAL_INCLUDES += [
     '/media/mtransport',
     '/xpcom/base',
     '/xpcom/build',
--- a/dom/media/gmp/rlz/moz.build
+++ b/dom/media/gmp/rlz/moz.build
@@ -15,10 +15,10 @@ UNIFIED_SOURCES += [
     'lib/string_utils.cc',
     'win/lib/machine_id_win.cc',
 ]
 
 LOCAL_INCLUDES += [
     '..',
 ]
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
--- a/dom/media/gstreamer/moz.build
+++ b/dom/media/gstreamer/moz.build
@@ -23,18 +23,16 @@ if CONFIG['GST_API_VERSION'] == '1.0':
         'GStreamerAllocator.cpp',
     ]
 else:
     SOURCES += [
         'GStreamerMozVideoBuffer.cpp',
         'GStreamerReader-0.10.cpp',
     ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
 ]
 
 CFLAGS += CONFIG['GSTREAMER_CFLAGS']
 CXXFLAGS += CONFIG['GSTREAMER_CFLAGS']
--- a/dom/media/gtest/moz.build
+++ b/dom/media/gtest/moz.build
@@ -57,10 +57,8 @@ LOCAL_INCLUDES += [
     '/dom/media/encoder',
     '/dom/media/fmp4',
     '/dom/media/gmp',
     '/security/certverifier',
     '/security/pkix/include',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/imagecapture/moz.build
+++ b/dom/media/imagecapture/moz.build
@@ -9,10 +9,8 @@ EXPORTS.mozilla.dom += [
 ]
 
 UNIFIED_SOURCES += [
     'CaptureTask.cpp',
     'ImageCapture.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/mediasink/moz.build
+++ b/dom/media/mediasink/moz.build
@@ -4,10 +4,8 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'DecodedAudioDataSink.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/mediasource/gtest/moz.build
+++ b/dom/media/mediasource/gtest/moz.build
@@ -9,10 +9,8 @@ UNIFIED_SOURCES += [
 ]
 
 LOCAL_INCLUDES += [
     '/dom/media',
     '/dom/media/mediasource',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/mediasource/moz.build
+++ b/dom/media/mediasource/moz.build
@@ -38,11 +38,9 @@ UNIFIED_SOURCES += [
 
 TEST_DIRS += [
     'gtest',
 ]
 
 if CONFIG['MOZ_GONK_MEDIACODEC']:
     DEFINES['MOZ_GONK_MEDIACODEC'] = True
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -273,18 +273,16 @@ EXTRA_COMPONENTS += [
 ]
 
 EXTRA_JS_MODULES.media += [
     'IdpSandbox.jsm',
     'PeerConnectionIdp.jsm',
     'RTCStatsReport.jsm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/base',
     '/dom/camera',
     '/layout/generic',
     '/layout/xul',
     '/netwerk/base',
 ]
--- a/dom/media/ogg/moz.build
+++ b/dom/media/ogg/moz.build
@@ -15,11 +15,9 @@ EXPORTS += [
 UNIFIED_SOURCES += [
     'OggCodecState.cpp',
     'OggDecoder.cpp',
     'OggReader.cpp',
     'OggWriter.cpp',
     'OpusParser.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/media/omx/moz.build
+++ b/dom/media/omx/moz.build
@@ -109,10 +109,8 @@ CXXFLAGS += [
         'frameworks/native/opengl/include',
         'frameworks/native/include',
         'hardware/libhardware/include/',
     ]
 ]
 
 if CONFIG['ANDROID_VERSION'] > '15':
     DEFINES['MOZ_OMX_WEBM_DECODER'] = True
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/platforms/PlatformDecoderModule.cpp
+++ b/dom/media/platforms/PlatformDecoderModule.cpp
@@ -142,16 +142,20 @@ PlatformDecoderModule::Create()
   }
   return CreateAgnosticDecoderModule();
 }
 
 /* static */
 already_AddRefed<PlatformDecoderModule>
 PlatformDecoderModule::CreatePDM()
 {
+  if (sGMPDecoderEnabled) {
+    nsRefPtr<PlatformDecoderModule> m(new GMPDecoderModule());
+    return m.forget();
+  }
 #ifdef MOZ_WIDGET_ANDROID
   if(sAndroidMCDecoderPreferred && sAndroidMCDecoderEnabled){
     nsRefPtr<PlatformDecoderModule> m(new AndroidDecoderModule());
     return m.forget();
   }
 #endif
   if (sUseBlankDecoder) {
     return CreateBlankDecoderModule();
@@ -179,20 +183,16 @@ PlatformDecoderModule::CreatePDM()
   }
 #endif
 #ifdef MOZ_WIDGET_ANDROID
   if(sAndroidMCDecoderEnabled){
     nsRefPtr<PlatformDecoderModule> m(new AndroidDecoderModule());
     return m.forget();
   }
 #endif
-  if (sGMPDecoderEnabled) {
-    nsRefPtr<PlatformDecoderModule> m(new GMPDecoderModule());
-    return m.forget();
-  }
   return nullptr;
 }
 
 already_AddRefed<MediaDataDecoder>
 PlatformDecoderModule::CreateDecoder(const TrackInfo& aConfig,
                                      FlushableTaskQueue* aTaskQueue,
                                      MediaDataDecoderCallback* aCallback,
                                      layers::LayersBackend aLayersBackend,
--- a/dom/media/platforms/agnostic/eme/moz.build
+++ b/dom/media/platforms/agnostic/eme/moz.build
@@ -16,10 +16,8 @@ UNIFIED_SOURCES += [
     'EMEDecoderModule.cpp',
     'EMEVideoDecoder.cpp',
     'SamplesWaitingForKey.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp
@@ -46,17 +46,16 @@ AudioCallbackAdapter::Decoded(const nsTA
     mAudioFrameSum = 0;
     auto timestamp = UsecsToFrames(aTimeStamp, aRate);
     if (!timestamp.isValid()) {
       NS_WARNING("Invalid timestamp");
       mCallback->Error();
       return;
     }
     mAudioFrameOffset = timestamp.value();
-    MOZ_ASSERT(mAudioFrameOffset >= 0);
     mMustRecaptureAudioPosition = false;
   }
 
   auto timestamp = FramesToUsecs(mAudioFrameOffset + mAudioFrameSum, aRate);
   if (!timestamp.isValid()) {
     NS_WARNING("Invalid timestamp on audio samples");
     mCallback->Error();
     return;
--- a/dom/media/platforms/agnostic/gmp/moz.build
+++ b/dom/media/platforms/agnostic/gmp/moz.build
@@ -17,10 +17,8 @@ UNIFIED_SOURCES += [
     'GMPVideoDecoder.cpp',
     'MediaDataDecoderProxy.cpp',
 ]
 
 # GMPVideoEncodedFrameImpl.h needs IPC
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/platforms/ffmpeg/libav53/moz.build
+++ b/dom/media/platforms/ffmpeg/libav53/moz.build
@@ -12,14 +12,12 @@ UNIFIED_SOURCES += [
 ]
 LOCAL_INCLUDES += [
     '..',
     'include',
 ]
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 if CONFIG['CLANG_CXX']:
   CXXFLAGS += [
     '-Wno-unknown-attributes',
   ]
--- a/dom/media/platforms/ffmpeg/libav54/moz.build
+++ b/dom/media/platforms/ffmpeg/libav54/moz.build
@@ -12,14 +12,12 @@ UNIFIED_SOURCES += [
 ]
 LOCAL_INCLUDES += [
     '..',
     'include',
 ]
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 if CONFIG['CLANG_CXX']:
   CXXFLAGS += [
     '-Wno-unknown-attributes',
   ]
--- a/dom/media/platforms/ffmpeg/libav55/moz.build
+++ b/dom/media/platforms/ffmpeg/libav55/moz.build
@@ -13,14 +13,12 @@ UNIFIED_SOURCES += [
 LOCAL_INCLUDES += [
     '..',
     'include',
 ]
 CXXFLAGS += [ '-Wno-deprecated-declarations' ]
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 if CONFIG['CLANG_CXX']:
   CXXFLAGS += [
     '-Wno-unknown-attributes',
   ]
--- a/dom/media/platforms/gonk/moz.build
+++ b/dom/media/platforms/gonk/moz.build
@@ -28,14 +28,12 @@ include('/ipc/chromium/chromium-config.m
 if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
   CXXFLAGS += [
     '-Wno-error=attributes',
     '-Wno-error=multichar'
   ]
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 CXXFLAGS += [
     '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
         'frameworks/native/opengl/include',]
 ]
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -77,10 +77,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'andr
     EXPORTS += [
         'android/AndroidDecoderModule.h',
     ]
     UNIFIED_SOURCES += [
         'android/AndroidDecoderModule.cpp',
     ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/platforms/wmf/moz.build
+++ b/dom/media/platforms/wmf/moz.build
@@ -26,11 +26,9 @@ UNIFIED_SOURCES += [
 SOURCES += [
     'WMFUtils.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
--- a/dom/media/raw/moz.build
+++ b/dom/media/raw/moz.build
@@ -10,16 +10,14 @@ EXPORTS += [
     'RawStructs.h',
 ]
 
 UNIFIED_SOURCES += [
     'RawDecoder.cpp',
     'RawReader.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
 ]
 
 FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -0,0 +1,741 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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 "CamerasChild.h"
+#include "CamerasUtils.h"
+
+#include "webrtc/video_engine/include/vie_capture.h"
+#undef FF
+
+#include "mozilla/Assertions.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+#include "mozilla/Logging.h"
+#include "mozilla/SyncRunnable.h"
+#include "mozilla/WeakPtr.h"
+#include "mozilla/unused.h"
+#include "MediaUtils.h"
+#include "nsThreadUtils.h"
+
+#undef LOG
+#undef LOG_ENABLED
+PRLogModuleInfo *gCamerasChildLog;
+#define LOG(args) MOZ_LOG(gCamerasChildLog, mozilla::LogLevel::Debug, args)
+#define LOG_ENABLED() MOZ_LOG_TEST(gCamerasChildLog, mozilla::LogLevel::Debug)
+
+namespace mozilla {
+namespace camera {
+
+// We emulate the sync webrtc.org API with the help of singleton
+// CamerasSingleton, which manages a pointer to an IPC object, a thread
+// where IPC operations should run on, and a mutex.
+// The static function Cameras() will use that Singleton to set up,
+// if needed, both the thread and the associated IPC objects and return
+// a pointer to the IPC object. Users can then do IPC calls on that object
+// after dispatching them to aforementioned thread.
+
+// 2 Threads are involved in this code:
+// - the MediaManager thread, which will call the (static, sync API) functions
+//   through MediaEngineRemoteVideoSource
+// - the Cameras IPC thread, which will be doing our IPC to the parent process
+//   via PBackground
+
+// Our main complication is that we emulate a sync API while (having to do)
+// async messaging. We dispatch the messages to another thread to send them
+// async and hold a Monitor to wait for the result to be asynchronously received
+// again. The requirement for async messaging originates on the parent side:
+// it's not reasonable to block all PBackground IPC there while waiting for
+// something like device enumeration to complete.
+
+class CamerasSingleton {
+public:
+  CamerasSingleton()
+    : mCamerasMutex("CamerasSingleton::mCamerasMutex"),
+      mCameras(nullptr),
+      mCamerasChildThread(nullptr) {
+    if (!gCamerasChildLog) {
+      gCamerasChildLog = PR_NewLogModule("CamerasChild");
+    }
+    LOG(("CamerasSingleton: %p", this));
+  }
+
+  ~CamerasSingleton() {
+    LOG(("~CamerasSingleton: %p", this));
+  }
+
+  static CamerasSingleton& GetInstance() {
+    static CamerasSingleton instance;
+    return instance;
+  }
+
+  static OffTheBooksMutex& Mutex() {
+    return GetInstance().mCamerasMutex;
+  }
+
+  static CamerasChild*& Child() {
+    GetInstance().Mutex().AssertCurrentThreadOwns();
+    return GetInstance().mCameras;
+  }
+
+  static nsCOMPtr<nsIThread>& Thread() {
+    GetInstance().Mutex().AssertCurrentThreadOwns();
+    return GetInstance().mCamerasChildThread;
+  }
+
+private:
+  // Reinitializing CamerasChild will change the pointers below.
+  // We don't want this to happen in the middle of preparing IPC.
+  // We will be alive on destruction, so this needs to be off the books.
+  mozilla::OffTheBooksMutex mCamerasMutex;
+
+  // This is owned by the IPC code, and the same code controls the lifetime.
+  // It will set and clear this pointer as appropriate in setup/teardown.
+  // We'd normally make this a WeakPtr but unfortunately the IPC code already
+  // uses the WeakPtr mixin in a protected base class of CamerasChild, and in
+  // any case the object becomes unusable as soon as IPC is tearing down, which
+  // will be before actual destruction.
+  CamerasChild* mCameras;
+  nsCOMPtr<nsIThread> mCamerasChildThread;
+};
+
+class InitializeIPCThread : public nsRunnable
+{
+public:
+  InitializeIPCThread()
+    : mCamerasChild(nullptr) {}
+
+  NS_IMETHOD Run() override {
+    // Try to get the PBackground handle
+    ipc::PBackgroundChild* existingBackgroundChild =
+      ipc::BackgroundChild::GetForCurrentThread();
+    // If it's not spun up yet, block until it is, and retry
+    if (!existingBackgroundChild) {
+      LOG(("No existingBackgroundChild"));
+      SynchronouslyCreatePBackground();
+      existingBackgroundChild =
+        ipc::BackgroundChild::GetForCurrentThread();
+      LOG(("BackgroundChild: %p", existingBackgroundChild));
+    }
+    // By now PBackground is guaranteed to be up
+    MOZ_RELEASE_ASSERT(existingBackgroundChild);
+
+    // Create CamerasChild
+    // We will be returning the resulting pointer (synchronously) to our caller.
+    mCamerasChild =
+      static_cast<mozilla::camera::CamerasChild*>(existingBackgroundChild->SendPCamerasConstructor());
+
+    return NS_OK;
+  }
+
+  CamerasChild* GetCamerasChild() {
+    MOZ_ASSERT(mCamerasChild);
+    return mCamerasChild;
+  }
+
+private:
+  CamerasChild* mCamerasChild;
+};
+
+static CamerasChild*
+Cameras() {
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  if (!CamerasSingleton::Child()) {
+    MOZ_ASSERT(!NS_IsMainThread(), "Should not be on the main Thread");
+    if (!gCamerasChildLog) {
+      gCamerasChildLog = PR_NewLogModule("CamerasChild");
+    }
+
+    MOZ_ASSERT(!CamerasSingleton::Thread());
+    LOG(("No sCameras, setting up IPC Thread"));
+    nsresult rv = NS_NewNamedThread("Cameras IPC",
+                                    getter_AddRefs(CamerasSingleton::Thread()));
+    if (NS_FAILED(rv)) {
+      LOG(("Error launching IPC Thread"));
+      return nullptr;
+    }
+
+    // At this point we are in the MediaManager thread, and the thread we are
+    // dispatching to is the specific Cameras IPC thread that was just made
+    // above, so now we will fire off a runnable to run
+    // SynchronouslyCreatePBackground there, while we block in this thread.
+    // We block until the following happens in the Cameras IPC thread:
+    // 1) Creation of PBackground finishes
+    // 2) Creation of PCameras finishes by sending a message to the parent
+    nsRefPtr<InitializeIPCThread> runnable = new InitializeIPCThread();
+    nsRefPtr<SyncRunnable> sr = new SyncRunnable(runnable);
+    sr->DispatchToThread(CamerasSingleton::Thread());
+    CamerasSingleton::Child() = runnable->GetCamerasChild();
+  }
+  MOZ_ASSERT(CamerasSingleton::Child());
+  return CamerasSingleton::Child();
+}
+
+bool
+CamerasChild::RecvReplyFailure(void)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MonitorAutoLock monitor(mReplyMonitor);
+  mReceivedReply = true;
+  mReplySuccess = false;
+  monitor.Notify();
+  return true;
+}
+
+bool
+CamerasChild::RecvReplySuccess(void)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MonitorAutoLock monitor(mReplyMonitor);
+  mReceivedReply = true;
+  mReplySuccess = true;
+  monitor.Notify();
+  return true;
+}
+
+int NumberOfCapabilities(CaptureEngine aCapEngine, const char* deviceUniqueIdUTF8)
+{
+  return Cameras()->NumberOfCapabilities(aCapEngine, deviceUniqueIdUTF8);
+}
+
+bool
+CamerasChild::RecvReplyNumberOfCapabilities(const int& numdev)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MonitorAutoLock monitor(mReplyMonitor);
+  mReceivedReply = true;
+  mReplySuccess = true;
+  mReplyInteger = numdev;
+  monitor.Notify();
+  return true;
+}
+
+bool
+CamerasChild::DispatchToParent(nsIRunnable* aRunnable,
+                               MonitorAutoLock& aMonitor)
+{
+  {
+    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+    CamerasSingleton::Thread()->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
+  }
+  // We can't see if the send worked, so we need to be able to bail
+  // out on shutdown (when it failed and we won't get a reply).
+  if (!mIPCIsAlive) {
+    return false;
+  }
+  // Guard against spurious wakeups.
+  mReceivedReply = false;
+  // Wait for a reply
+  do {
+    aMonitor.Wait();
+  } while (!mReceivedReply && mIPCIsAlive);
+  if (!mReplySuccess) {
+    return false;
+  }
+  return true;
+}
+
+int
+CamerasChild::NumberOfCapabilities(CaptureEngine aCapEngine,
+                                   const char* deviceUniqueIdUTF8)
+{
+  // Prevents multiple outstanding requests from happening.
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG((__PRETTY_FUNCTION__));
+  LOG(("NumberOfCapabilities for %s", deviceUniqueIdUTF8));
+  nsCString unique_id(deviceUniqueIdUTF8);
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine, unique_id]() -> nsresult {
+      if (this->SendNumberOfCapabilities(aCapEngine, unique_id)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  // Prevent concurrent use of the reply variables. Note
+  // that this is unlocked while waiting for the reply to be
+  // filled in, necessitating the first Mutex above.
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    LOG(("Get capture capability count failed"));
+    return 0;
+  }
+  LOG(("Capture capability count: %d", mReplyInteger));
+  return mReplyInteger;
+}
+
+int NumberOfCaptureDevices(CaptureEngine aCapEngine)
+{
+  return Cameras()->NumberOfCaptureDevices(aCapEngine);
+}
+
+int
+CamerasChild::NumberOfCaptureDevices(CaptureEngine aCapEngine)
+{
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG((__PRETTY_FUNCTION__));
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine]() -> nsresult {
+      if (this->SendNumberOfCaptureDevices(aCapEngine)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    LOG(("Get NumberOfCaptureDevices failed"));
+    return 0;
+  }
+  LOG(("Capture Devices: %d", mReplyInteger));
+  return mReplyInteger;
+}
+
+bool
+CamerasChild::RecvReplyNumberOfCaptureDevices(const int& numdev)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MonitorAutoLock monitor(mReplyMonitor);
+  mReceivedReply = true;
+  mReplySuccess = true;
+  mReplyInteger = numdev;
+  monitor.Notify();
+  return true;
+}
+
+int GetCaptureCapability(CaptureEngine aCapEngine, const char* unique_idUTF8,
+                         const unsigned int capability_number,
+                         webrtc::CaptureCapability& capability)
+{
+  return Cameras()->GetCaptureCapability(aCapEngine,
+                                         unique_idUTF8,
+                                         capability_number,
+                                         capability);
+}
+
+int
+CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
+                                   const char* unique_idUTF8,
+                                   const unsigned int capability_number,
+                                   webrtc::CaptureCapability& capability)
+{
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number));
+  nsCString unique_id(unique_idUTF8);
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine, unique_id, capability_number]() -> nsresult {
+      if (this->SendGetCaptureCapability(aCapEngine, unique_id, capability_number)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    return -1;
+  }
+  capability = mReplyCapability;
+  return 0;
+}
+
+bool
+CamerasChild::RecvReplyGetCaptureCapability(const CaptureCapability& ipcCapability)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MonitorAutoLock monitor(mReplyMonitor);
+  mReceivedReply = true;
+  mReplySuccess = true;
+  mReplyCapability.width = ipcCapability.width();
+  mReplyCapability.height = ipcCapability.height();
+  mReplyCapability.maxFPS = ipcCapability.maxFPS();
+  mReplyCapability.expectedCaptureDelay = ipcCapability.expectedCaptureDelay();
+  mReplyCapability.rawType = static_cast<webrtc::RawVideoType>(ipcCapability.rawType());
+  mReplyCapability.codecType = static_cast<webrtc::VideoCodecType>(ipcCapability.codecType());
+  mReplyCapability.interlaced = ipcCapability.interlaced();
+  monitor.Notify();
+  return true;
+}
+
+
+int GetCaptureDevice(CaptureEngine aCapEngine,
+                     unsigned int list_number, char* device_nameUTF8,
+                     const unsigned int device_nameUTF8Length,
+                     char* unique_idUTF8,
+                     const unsigned int unique_idUTF8Length)
+{
+  return Cameras()->GetCaptureDevice(aCapEngine,
+                                     list_number,
+                                     device_nameUTF8,
+                                     device_nameUTF8Length,
+                                     unique_idUTF8,
+                                     unique_idUTF8Length);
+}
+
+int
+CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
+                               unsigned int list_number, char* device_nameUTF8,
+                               const unsigned int device_nameUTF8Length,
+                               char* unique_idUTF8,
+                               const unsigned int unique_idUTF8Length)
+{
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG((__PRETTY_FUNCTION__));
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine, list_number]() -> nsresult {
+      if (this->SendGetCaptureDevice(aCapEngine, list_number)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    LOG(("GetCaptureDevice failed"));
+    return -1;
+  }
+  base::strlcpy(device_nameUTF8, mReplyDeviceName.get(), device_nameUTF8Length);
+  base::strlcpy(unique_idUTF8, mReplyDeviceID.get(), unique_idUTF8Length);
+  LOG(("Got %s name %s id", device_nameUTF8, unique_idUTF8));
+  return 0;
+}
+
+bool
+CamerasChild::RecvReplyGetCaptureDevice(const nsCString& device_name,
+                                        const nsCString& device_id)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MonitorAutoLock monitor(mReplyMonitor);
+  mReceivedReply = true;
+  mReplySuccess = true;
+  mReplyDeviceName = device_name;
+  mReplyDeviceID = device_id;
+  monitor.Notify();
+  return true;
+}
+
+int AllocateCaptureDevice(CaptureEngine aCapEngine,
+                          const char* unique_idUTF8,
+                          const unsigned int unique_idUTF8Length,
+                          int& capture_id)
+{
+  return Cameras()->AllocateCaptureDevice(aCapEngine,
+                                          unique_idUTF8,
+                                          unique_idUTF8Length,
+                                          capture_id);
+}
+
+int
+CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
+                                    const char* unique_idUTF8,
+                                    const unsigned int unique_idUTF8Length,
+                                    int& capture_id)
+{
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG((__PRETTY_FUNCTION__));
+  nsCString unique_id(unique_idUTF8);
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine, unique_id]() -> nsresult {
+      if (this->SendAllocateCaptureDevice(aCapEngine, unique_id)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    LOG(("AllocateCaptureDevice failed"));
+    return -1;
+  }
+  LOG(("Capture Device allocated: %d", mReplyInteger));
+  capture_id = mReplyInteger;
+  return 0;
+}
+
+
+bool
+CamerasChild::RecvReplyAllocateCaptureDevice(const int& numdev)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MonitorAutoLock monitor(mReplyMonitor);
+  mReceivedReply = true;
+  mReplySuccess = true;
+  mReplyInteger = numdev;
+  monitor.Notify();
+  return true;
+}
+
+int ReleaseCaptureDevice(CaptureEngine aCapEngine, const int capture_id)
+{
+  return Cameras()->ReleaseCaptureDevice(aCapEngine, capture_id);
+}
+
+int
+CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine,
+                                   const int capture_id)
+{
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG((__PRETTY_FUNCTION__));
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine, capture_id]() -> nsresult {
+      if (this->SendReleaseCaptureDevice(aCapEngine, capture_id)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    return -1;
+  }
+  return 0;
+}
+
+void
+CamerasChild::AddCallback(const CaptureEngine aCapEngine, const int capture_id,
+                          webrtc::ExternalRenderer* render)
+{
+  MutexAutoLock lock(mCallbackMutex);
+  CapturerElement ce;
+  ce.engine = aCapEngine;
+  ce.id = capture_id;
+  ce.callback = render;
+  mCallbacks.AppendElement(ce);
+}
+
+void
+CamerasChild::RemoveCallback(const CaptureEngine aCapEngine, const int capture_id)
+{
+  MutexAutoLock lock(mCallbackMutex);
+  for (unsigned int i = 0; i < mCallbacks.Length(); i++) {
+    CapturerElement ce = mCallbacks[i];
+    if (ce.engine == aCapEngine && ce.id == capture_id) {
+      mCallbacks.RemoveElementAt(i);
+      break;
+    }
+  }
+}
+
+int StartCapture(CaptureEngine aCapEngine,
+                 const int capture_id,
+                 webrtc::CaptureCapability& webrtcCaps,
+                 webrtc::ExternalRenderer* cb)
+{
+  return Cameras()->StartCapture(aCapEngine,
+                                 capture_id,
+                                 webrtcCaps,
+                                 cb);
+}
+
+int
+CamerasChild::StartCapture(CaptureEngine aCapEngine,
+                           const int capture_id,
+                           webrtc::CaptureCapability& webrtcCaps,
+                           webrtc::ExternalRenderer* cb)
+{
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG((__PRETTY_FUNCTION__));
+  AddCallback(aCapEngine, capture_id, cb);
+  CaptureCapability capCap(webrtcCaps.width,
+                           webrtcCaps.height,
+                           webrtcCaps.maxFPS,
+                           webrtcCaps.expectedCaptureDelay,
+                           webrtcCaps.rawType,
+                           webrtcCaps.codecType,
+                           webrtcCaps.interlaced);
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine, capture_id, capCap]() -> nsresult {
+      if (this->SendStartCapture(aCapEngine, capture_id, capCap)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    return -1;
+  }
+  return 0;
+}
+
+int StopCapture(CaptureEngine aCapEngine, const int capture_id)
+{
+  return Cameras()->StopCapture(aCapEngine, capture_id);
+}
+
+int
+CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id)
+{
+  MutexAutoLock requestLock(mRequestMutex);
+  LOG((__PRETTY_FUNCTION__));
+  nsCOMPtr<nsIRunnable> runnable =
+    media::NewRunnableFrom([this, aCapEngine, capture_id]() -> nsresult {
+      if (this->SendStopCapture(aCapEngine, capture_id)) {
+        return NS_OK;
+      }
+      return NS_ERROR_FAILURE;
+    });
+  MonitorAutoLock monitor(mReplyMonitor);
+  if (!DispatchToParent(runnable, monitor)) {
+    return -1;
+  }
+  RemoveCallback(aCapEngine, capture_id);
+  return 0;
+}
+
+void
+Shutdown(void)
+{
+  {
+    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+    if (!CamerasSingleton::Child()) {
+      // We don't want to cause everything to get fired up if we're
+      // really already shut down.
+      LOG(("Shutdown when already shut down"));
+      return;
+    }
+  }
+  Cameras()->Shutdown();
+}
+
+class ShutdownRunnable : public nsRunnable {
+public:
+  ShutdownRunnable(nsRefPtr<nsRunnable> aReplyEvent,
+                   nsIThread* aReplyThread)
+    : mReplyEvent(aReplyEvent), mReplyThread(aReplyThread) {};
+
+  NS_IMETHOD Run() override {
+    LOG(("Closing BackgroundChild"));
+    ipc::BackgroundChild::CloseForCurrentThread();
+
+    LOG(("PBackground thread exists, shutting down thread"));
+    mReplyThread->Dispatch(mReplyEvent, NS_DISPATCH_NORMAL);
+
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<nsRunnable> mReplyEvent;
+  nsIThread* mReplyThread;
+};
+
+void
+CamerasChild::Shutdown()
+{
+  {
+    MonitorAutoLock monitor(mReplyMonitor);
+    mIPCIsAlive = false;
+    monitor.NotifyAll();
+  }
+
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  if (CamerasSingleton::Thread()) {
+    LOG(("Dispatching actor deletion"));
+    // Delete the parent actor.
+    nsRefPtr<nsRunnable> deleteRunnable =
+      // CamerasChild (this) will remain alive and is only deleted by the
+      // IPC layer when SendAllDone returns.
+      media::NewRunnableFrom([this]() -> nsresult {
+        unused << this->SendAllDone();
+        return NS_OK;
+      });
+    CamerasSingleton::Thread()->Dispatch(deleteRunnable, NS_DISPATCH_NORMAL);
+    LOG(("PBackground thread exists, dispatching close"));
+    // Dispatch closing the IPC thread back to us when the
+    // BackgroundChild is closed.
+    nsRefPtr<nsRunnable> event =
+      new ThreadDestructor(CamerasSingleton::Thread());
+    nsRefPtr<ShutdownRunnable> runnable =
+      new ShutdownRunnable(event, NS_GetCurrentThread());
+    CamerasSingleton::Thread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  } else {
+    LOG(("Shutdown called without PBackground thread"));
+  }
+  LOG(("Erasing sCameras & thread refs (original thread)"));
+  CamerasSingleton::Child() = nullptr;
+  CamerasSingleton::Thread() = nullptr;
+}
+
+bool
+CamerasChild::RecvDeliverFrame(const int& capEngine,
+                               const int& capId,
+                               mozilla::ipc::Shmem&& shmem,
+                               const int& size,
+                               const uint32_t& time_stamp,
+                               const int64_t& ntp_time,
+                               const int64_t& render_time)
+{
+  MutexAutoLock lock(mCallbackMutex);
+  CaptureEngine capEng = static_cast<CaptureEngine>(capEngine);
+  if (Callback(capEng, capId)) {
+    unsigned char* image = shmem.get<unsigned char>();
+    Callback(capEng, capId)->DeliverFrame(image, size,
+                                          time_stamp,
+                                          ntp_time, render_time,
+                                          nullptr);
+  } else {
+    LOG(("DeliverFrame called with dead callback"));
+  }
+  SendReleaseFrame(shmem);
+  return true;
+}
+
+bool
+CamerasChild::RecvFrameSizeChange(const int& capEngine,
+                                  const int& capId,
+                                  const int& w, const int& h)
+{
+  LOG((__PRETTY_FUNCTION__));
+  MutexAutoLock lock(mCallbackMutex);
+  CaptureEngine capEng = static_cast<CaptureEngine>(capEngine);
+  if (Callback(capEng, capId)) {
+    Callback(capEng, capId)->FrameSizeChange(w, h, 0);
+  } else {
+    LOG(("Frame size change with dead callback"));
+  }
+  return true;
+}
+
+void
+CamerasChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+  MonitorAutoLock monitor(mReplyMonitor);
+  mIPCIsAlive = false;
+  // Hopefully prevent us from getting stuck
+  // on replies that'll never come.
+  monitor.NotifyAll();
+}
+
+CamerasChild::CamerasChild()
+  : mCallbackMutex("mozilla::cameras::CamerasChild::mCallbackMutex"),
+    mIPCIsAlive(true),
+    mRequestMutex("mozilla::cameras::CamerasChild::mRequestMutex"),
+    mReplyMonitor("mozilla::cameras::CamerasChild::mReplyMonitor")
+{
+  if (!gCamerasChildLog) {
+    gCamerasChildLog = PR_NewLogModule("CamerasChild");
+  }
+
+  LOG(("CamerasChild: %p", this));
+
+  MOZ_COUNT_CTOR(CamerasChild);
+}
+
+CamerasChild::~CamerasChild()
+{
+  LOG(("~CamerasChild: %p", this));
+
+  Shutdown();
+
+  MOZ_COUNT_DTOR(CamerasChild);
+}
+
+webrtc::ExternalRenderer* CamerasChild::Callback(CaptureEngine aCapEngine,
+                                                 int capture_id)
+{
+  for (unsigned int i = 0; i < mCallbacks.Length(); i++) {
+    CapturerElement ce = mCallbacks[i];
+    if (ce.engine == aCapEngine && ce.id == capture_id) {
+      return ce.callback;
+    }
+  }
+
+  return nullptr;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/CamerasChild.h
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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_CamerasChild_h
+#define mozilla_CamerasChild_h
+
+#include "mozilla/Pair.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/camera/PCamerasChild.h"
+#include "mozilla/camera/PCamerasParent.h"
+#include "mozilla/Mutex.h"
+#include "nsCOMPtr.h"
+
+// conflicts with #include of scoped_ptr.h
+#undef FF
+#include "webrtc/common.h"
+// Video Engine
+#include "webrtc/video_engine/include/vie_base.h"
+#include "webrtc/video_engine/include/vie_capture.h"
+#include "webrtc/video_engine/include/vie_render.h"
+
+namespace mozilla {
+
+namespace ipc {
+class BackgroundChildImpl;
+}
+
+namespace camera {
+
+enum CaptureEngine : int {
+  InvalidEngine = 0,
+  ScreenEngine,
+  BrowserEngine,
+  WinEngine,
+  AppEngine,
+  CameraEngine,
+  MaxEngine
+};
+
+struct CapturerElement {
+  CaptureEngine engine;
+  int id;
+  webrtc::ExternalRenderer* callback;
+};
+
+// statically mirror webrtc.org ViECapture API
+// these are called via MediaManager->MediaEngineRemoteVideoSource
+// on the MediaManager thread
+int NumberOfCapabilities(CaptureEngine aCapEngine,
+                         const char* deviceUniqueIdUTF8);
+int GetCaptureCapability(CaptureEngine aCapEngine,
+                         const char* unique_idUTF8,
+                         const unsigned int capability_number,
+                         webrtc::CaptureCapability& capability);
+int NumberOfCaptureDevices(CaptureEngine aCapEngine);
+int GetCaptureDevice(CaptureEngine aCapEngine,
+                     unsigned int list_number, char* device_nameUTF8,
+                     const unsigned int device_nameUTF8Length,
+                     char* unique_idUTF8,
+                     const unsigned int unique_idUTF8Length);
+int AllocateCaptureDevice(CaptureEngine aCapEngine,
+                          const char* unique_idUTF8,
+                          const unsigned int unique_idUTF8Length,
+                          int& capture_id);
+int ReleaseCaptureDevice(CaptureEngine aCapEngine,
+                         const int capture_id);
+int StartCapture(CaptureEngine aCapEngine,
+                 const int capture_id, webrtc::CaptureCapability& capability,
+                 webrtc::ExternalRenderer* func);
+int StopCapture(CaptureEngine aCapEngine, const int capture_id);
+void Shutdown(void);
+
+class CamerasChild final : public PCamerasChild
+{
+  friend class mozilla::ipc::BackgroundChildImpl;
+
+public:
+  // We are owned by the PBackground thread only. CamerasSingleton
+  // takes a non-owning reference.
+  NS_INLINE_DECL_REFCOUNTING(CamerasChild)
+
+  // IPC messages recevied, received on the PBackground thread
+  // these are the actual callbacks with data
+  virtual bool RecvDeliverFrame(const int&, const int&, mozilla::ipc::Shmem&&,
+                                const int&, const uint32_t&, const int64_t&,
+                                const int64_t&) override;
+  virtual bool RecvFrameSizeChange(const int&, const int&,
+                                   const int& w, const int& h) override;
+
+  // these are response messages to our outgoing requests
+  virtual bool RecvReplyNumberOfCaptureDevices(const int&) override;
+  virtual bool RecvReplyNumberOfCapabilities(const int&) override;
+  virtual bool RecvReplyAllocateCaptureDevice(const int&) override;
+  virtual bool RecvReplyGetCaptureCapability(const CaptureCapability& capability) override;
+  virtual bool RecvReplyGetCaptureDevice(const nsCString& device_name,
+                                         const nsCString& device_id) override;
+  virtual bool RecvReplyFailure(void) override;
+  virtual bool RecvReplySuccess(void) override;
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+  // the webrtc.org ViECapture calls are mirrored here, but with access
+  // to a specific PCameras instance to communicate over. These also
+  // run on the MediaManager thread
+  int NumberOfCaptureDevices(CaptureEngine aCapEngine);
+  int NumberOfCapabilities(CaptureEngine aCapEngine,
+                           const char* deviceUniqueIdUTF8);
+  int ReleaseCaptureDevice(CaptureEngine aCapEngine,
+                           const int capture_id);
+  int StartCapture(CaptureEngine aCapEngine,
+                   const int capture_id, webrtc::CaptureCapability& capability,
+                   webrtc::ExternalRenderer* func);
+  int StopCapture(CaptureEngine aCapEngine, const int capture_id);
+  int AllocateCaptureDevice(CaptureEngine aCapEngine,
+                            const char* unique_idUTF8,
+                            const unsigned int unique_idUTF8Length,
+                            int& capture_id);
+  int GetCaptureCapability(CaptureEngine aCapEngine,
+                           const char* unique_idUTF8,
+                           const unsigned int capability_number,
+                           webrtc::CaptureCapability& capability);
+  int GetCaptureDevice(CaptureEngine aCapEngine,
+                       unsigned int list_number, char* device_nameUTF8,
+                       const unsigned int device_nameUTF8Length,
+                       char* unique_idUTF8,
+                       const unsigned int unique_idUTF8Length);
+  void Shutdown();
+
+  webrtc::ExternalRenderer* Callback(CaptureEngine aCapEngine, int capture_id);
+  void AddCallback(const CaptureEngine aCapEngine, const int capture_id,
+                   webrtc::ExternalRenderer* render);
+  void RemoveCallback(const CaptureEngine aCapEngine, const int capture_id);
+
+
+private:
+  CamerasChild();
+  ~CamerasChild();
+  // Dispatch a Runnable to the PCamerasParent, by executing it on the
+  // decidecated Cameras IPC/PBackground thread.
+  bool DispatchToParent(nsIRunnable* aRunnable,
+                        MonitorAutoLock& aMonitor);
+
+  nsTArray<CapturerElement> mCallbacks;
+  // Protects the callback arrays
+  Mutex mCallbackMutex;
+
+  bool mIPCIsAlive;
+
+  // Hold to prevent multiple outstanding requests. We don't use
+  // request IDs so we only support one at a time. Don't want try
+  // to use the webrtc.org API from multiple threads simultanously.
+  // The monitor below isn't sufficient for this, as it will drop
+  // the lock when Wait-ing for a response, allowing us to send a new
+  // request. The Notify on receiving the response will then unblock
+  // both waiters and one will be guaranteed to get the wrong result.
+  // Take this one before taking mReplyMonitor.
+  Mutex mRequestMutex;
+  // Hold to wait for an async response to our calls
+  Monitor mReplyMonitor;
+  // Async resposne valid?
+  bool mReceivedReply;
+  // Aynsc reponses data contents;
+  bool mReplySuccess;
+  int mReplyInteger;
+  webrtc::CaptureCapability mReplyCapability;
+  nsCString mReplyDeviceName;
+  nsCString mReplyDeviceID;
+};
+
+} // namespace camera
+} // namespace mozilla
+
+#endif  // mozilla_CamerasChild_h
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -0,0 +1,821 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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 "CamerasParent.h"
+#include "CamerasUtils.h"
+#include "MediaEngine.h"
+#include "MediaUtils.h"
+
+#include "mozilla/Assertions.h"
+#include "mozilla/unused.h"
+#include "mozilla/Logging.h"
+#include "mozilla/ipc/BackgroundParent.h"
+#include "nsThreadUtils.h"
+
+#undef LOG
+#undef LOG_ENABLED
+PRLogModuleInfo *gCamerasParentLog;
+#define LOG(args) MOZ_LOG(gCamerasParentLog, mozilla::LogLevel::Debug, args)
+#define LOG_ENABLED() MOZ_LOG_TEST(gCamerasParentLog, mozilla::LogLevel::Debug)
+
+namespace mozilla {
+namespace camera {
+
+// 3 threads are involved in this code:
+// - the main thread for some setups, and occassionally for video capture setup
+//   calls that don't work correctly elsewhere.
+// - the IPC thread on which PBackground is running and which receives and
+//   sends messages
+// - a thread which will execute the actual (possibly slow) camera access
+//   called "VideoCapture". On Windows this is a thread with an event loop
+//   suitable for UI access.
+
+class FrameSizeChangeRunnable : public nsRunnable {
+public:
+  FrameSizeChangeRunnable(CamerasParent *aParent, CaptureEngine capEngine,
+                          int cap_id, unsigned int aWidth, unsigned int aHeight)
+    : mParent(aParent), mCapEngine(capEngine), mCapId(cap_id),
+      mWidth(aWidth), mHeight(aHeight) {}
+
+  NS_IMETHOD Run() {
+    if (mParent->IsShuttingDown()) {
+      // Communication channel is being torn down
+      LOG(("FrameSizeChangeRunnable is active without active Child"));
+      mResult = 0;
+      return NS_OK;
+    }
+    if (!mParent->SendFrameSizeChange(mCapEngine, mCapId, mWidth, mHeight)) {
+      mResult = -1;
+    } else {
+      mResult = 0;
+    }
+    return NS_OK;
+  }
+
+  int GetResult() {
+    return mResult;
+  }
+
+private:
+  nsRefPtr<CamerasParent> mParent;
+  CaptureEngine mCapEngine;
+  int mCapId;
+  unsigned int mWidth;
+  unsigned int mHeight;
+  int mResult;
+};
+
+int
+CallbackHelper::FrameSizeChange(unsigned int w, unsigned int h,
+                                unsigned int streams)
+{
+  LOG(("CallbackHelper Video FrameSizeChange: %ux%u", w, h));
+  nsRefPtr<FrameSizeChangeRunnable> runnable =
+    new FrameSizeChangeRunnable(mParent, mCapEngine, mCapturerId, w, h);
+  MOZ_ASSERT(mParent);
+  nsIThread * thread = mParent->GetBackgroundThread();
+  MOZ_ASSERT(thread != nullptr);
+  thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  return 0;
+}
+
+class DeliverFrameRunnable : public nsRunnable {
+public:
+  DeliverFrameRunnable(CamerasParent *aParent,
+                       CaptureEngine engine,
+                       int cap_id,
+                       ShmemBuffer buffer,
+                       unsigned char* altbuffer,
+                       int size,
+                       uint32_t time_stamp,
+                       int64_t ntp_time,
+                       int64_t render_time)
+    : mParent(aParent), mCapEngine(engine), mCapId(cap_id), mBuffer(Move(buffer)),
+      mSize(size), mTimeStamp(time_stamp), mNtpTime(ntp_time),
+      mRenderTime(render_time) {
+    // No ShmemBuffer (of the right size) was available, so make an
+    // extra buffer here.  We have no idea when we are going to run and
+    // it will be potentially long after the webrtc frame callback has
+    // returned, so the copy needs to be no later than here.
+    // We will need to copy this back into a Shmem later on so we prefer
+    // using ShmemBuffers to avoid the extra copy.
+    if (altbuffer != nullptr) {
+      mAlternateBuffer.reset(new unsigned char[size]);
+      memcpy(mAlternateBuffer.get(), altbuffer, size);
+    }
+  };
+
+  NS_IMETHOD Run() {
+    if (mParent->IsShuttingDown()) {
+      // Communication channel is being torn down
+      mResult = 0;
+      return NS_OK;
+    }
+    if (!mParent->DeliverFrameOverIPC(mCapEngine, mCapId,
+                                      Move(mBuffer), mAlternateBuffer.get(),
+                                      mSize, mTimeStamp,
+                                      mNtpTime, mRenderTime)) {
+      mResult = -1;
+    } else {
+      mResult = 0;
+    }
+    return NS_OK;
+  }
+
+  int GetResult() {
+    return mResult;
+  }
+
+private:
+  nsRefPtr<CamerasParent> mParent;
+  CaptureEngine mCapEngine;
+  int mCapId;
+  ShmemBuffer mBuffer;
+  mozilla::UniquePtr<unsigned char[]> mAlternateBuffer;
+  int mSize;
+  uint32_t mTimeStamp;
+  int64_t mNtpTime;
+  int64_t mRenderTime;
+  int mResult;
+};
+
+int
+CamerasParent::DeliverFrameOverIPC(CaptureEngine cap_engine,
+                                   int cap_id,
+                                   ShmemBuffer buffer,
+                                   unsigned char* altbuffer,
+                                   int size,
+                                   uint32_t time_stamp,
+                                   int64_t ntp_time,
+                                   int64_t render_time)
+{
+  // No ShmemBuffers were available, so construct one now of the right size
+  // and copy into it. That is an extra copy, but we expect this to be
+  // the exceptional case, because we just assured the next call *will* have a
+  // buffer of the right size.
+  if (altbuffer != nullptr) {
+    // Get a shared memory buffer from the pool, at least size big
+    ShmemBuffer shMemBuff = mShmemPool.Get(this, size);
+
+    if (!shMemBuff.Valid()) {
+      LOG(("Video shmem is not writeable in DeliverFrame"));
+      // We can skip this frame if we run out of buffers, it's not a real error.
+      return 0;
+    }
+
+    // get() and Size() check for proper alignment of the segment
+    memcpy(shMemBuff.GetBytes(), altbuffer, size);
+
+    if (!SendDeliverFrame(cap_engine, cap_id,
+                          shMemBuff.Get(), size,
+                          time_stamp, ntp_time, render_time)) {
+      return -1;
+    }
+  } else {
+    // ShmemBuffer was available, we're all good. A single copy happened
+    // in the original webrtc callback.
+    if (!SendDeliverFrame(cap_engine, cap_id,
+                          buffer.Get(), size,
+                          time_stamp, ntp_time, render_time)) {
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+ShmemBuffer
+CamerasParent::GetBuffer(size_t aSize)
+{
+  return mShmemPool.GetIfAvailable(aSize);
+}
+
+int
+CallbackHelper::DeliverFrame(unsigned char* buffer,
+                             int size,
+                             uint32_t time_stamp,
+                             int64_t ntp_time,
+                             int64_t render_time,
+                             void *handle)
+{
+  // Get a shared memory buffer to copy the frame data into
+  ShmemBuffer shMemBuffer = mParent->GetBuffer(size);
+  if (!shMemBuffer.Valid()) {
+    // Either we ran out of buffers or they're not the right size yet
+    LOG(("Video shmem is not available in DeliverFrame"));
+    // We will do the copy into a(n extra) temporary buffer inside
+    // the DeliverFrameRunnable constructor.
+  } else {
+    // Shared memory buffers of the right size are available, do the copy here.
+    memcpy(shMemBuffer.GetBytes(), buffer, size);
+    // Mark the original buffer as cleared.
+    buffer = nullptr;
+  }
+  nsRefPtr<DeliverFrameRunnable> runnable =
+    new DeliverFrameRunnable(mParent, mCapEngine, mCapturerId,
+                             Move(shMemBuffer), buffer, size, time_stamp,
+                             ntp_time, render_time);
+  MOZ_ASSERT(mParent);
+  nsIThread* thread = mParent->GetBackgroundThread();
+  MOZ_ASSERT(thread != nullptr);
+  thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  return 0;
+}
+
+bool
+CamerasParent::RecvReleaseFrame(mozilla::ipc::Shmem&& s) {
+  mShmemPool.Put(ShmemBuffer(s));
+  return true;
+}
+
+bool
+CamerasParent::SetupEngine(CaptureEngine aCapEngine)
+{
+  EngineHelper *helper = &mEngines[aCapEngine];
+
+  // Already initialized
+  if (helper->mEngine) {
+    return true;
+  }
+
+  webrtc::CaptureDeviceInfo *captureDeviceInfo = nullptr;
+
+  switch (aCapEngine) {
+  case ScreenEngine:
+    captureDeviceInfo =
+      new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Screen);
+    break;
+  case BrowserEngine:
+    captureDeviceInfo =
+      new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Browser);
+    break;
+  case WinEngine:
+    captureDeviceInfo =
+      new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Window);
+    break;
+  case AppEngine:
+    captureDeviceInfo =
+      new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Application);
+    break;
+  case CameraEngine:
+    captureDeviceInfo =
+      new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Camera);
+    break;
+  default:
+    LOG(("Invalid webrtc Video engine"));
+    MOZ_CRASH();
+    break;
+  }
+
+  helper->mConfig.Set<webrtc::CaptureDeviceInfo>(captureDeviceInfo);
+  helper->mEngine = webrtc::VideoEngine::Create(helper->mConfig);
+
+  if (!helper->mEngine) {
+    LOG(("VideoEngine::Create failed"));
+    return false;
+  }
+
+  helper->mPtrViEBase = webrtc::ViEBase::GetInterface(helper->mEngine);
+  if (!helper->mPtrViEBase) {
+    LOG(("ViEBase::GetInterface failed"));
+    return false;
+  }
+
+  if (helper->mPtrViEBase->Init() < 0) {
+    LOG(("ViEBase::Init failed"));
+    return false;
+  }
+
+  helper->mPtrViECapture = webrtc::ViECapture::GetInterface(helper->mEngine);
+  if (!helper->mPtrViECapture) {
+    LOG(("ViECapture::GetInterface failed"));
+    return false;
+  }
+
+  helper->mPtrViERender = webrtc::ViERender::GetInterface(helper->mEngine);
+  if (!helper->mPtrViERender) {
+    LOG(("ViERender::GetInterface failed"));
+    return false;
+  }
+
+  return true;
+}
+
+void
+CamerasParent::CloseEngines()
+{
+  {
+    MutexAutoLock lock(mCallbackMutex);
+    // Stop the callers
+    while (mCallbacks.Length()) {
+      auto capEngine = mCallbacks[0]->mCapEngine;
+      auto capNum = mCallbacks[0]->mCapturerId;
+      LOG(("Forcing shutdown of engine %d, capturer %d", capEngine, capNum));
+      {
+        MutexAutoUnlock unlock(mCallbackMutex);
+        RecvStopCapture(capEngine, capNum);
+        RecvReleaseCaptureDevice(capEngine, capNum);
+      }
+      // The callbacks list might have changed while we released the lock,
+      // but note that due to the loop construct this will not break us.
+    }
+  }
+
+  for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
+    if (mEngines[i].mEngineIsRunning) {
+      LOG(("Being closed down while engine %d is running!", i));
+    }
+    if (mEngines[i].mPtrViERender) {
+      mEngines[i].mPtrViERender->Release();
+      mEngines[i].mPtrViERender = nullptr;
+    }
+    if (mEngines[i].mPtrViECapture) {
+      mEngines[i].mPtrViECapture->Release();
+      mEngines[i].mPtrViECapture = nullptr;
+    }
+    if(mEngines[i].mPtrViEBase) {
+      mEngines[i].mPtrViEBase->Release();
+      mEngines[i].mPtrViEBase = nullptr;
+    }
+  }
+}
+
+bool
+CamerasParent::EnsureInitialized(int aEngine)
+{
+  LOG((__PRETTY_FUNCTION__));
+  CaptureEngine capEngine = static_cast<CaptureEngine>(aEngine);
+  if (!SetupEngine(capEngine)) {
+    return false;
+  }
+
+  return true;
+}
+
+// Dispatch the runnable to do the camera operation on the
+// specific Cameras thread, preventing us from blocking, and
+// chain a runnable to send back the result on the IPC thread.
+// It would be nice to get rid of the code duplication here,
+// perhaps via Promises.
+bool
+CamerasParent::RecvNumberOfCaptureDevices(const int& aCapEngine)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("RecvNumberOfCaptureDevices fails to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
+      int num = self->mEngines[aCapEngine].mPtrViECapture->NumberOfCaptureDevices();
+      nsRefPtr<nsIRunnable> ipc_runnable =
+        media::NewRunnableFrom([self, num]() -> nsresult {
+          if (self->IsShuttingDown()) {
+            return NS_ERROR_FAILURE;
+          }
+          if (num < 0) {
+            LOG(("RecvNumberOfCaptureDevices couldn't find devices"));
+            unused << self->SendReplyFailure();
+            return NS_ERROR_FAILURE;
+          } else {
+            LOG(("RecvNumberOfCaptureDevices: %d", num));
+            unused << self->SendReplyNumberOfCaptureDevices(num);
+            return NS_OK;
+          }
+        });
+        self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    });
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+
+  return true;
+}
+
+bool
+CamerasParent::RecvNumberOfCapabilities(const int& aCapEngine,
+                                        const nsCString& unique_id)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("RecvNumberOfCapabilities fails to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  LOG(("Getting caps for %s", unique_id.get()));
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, unique_id, aCapEngine]() -> nsresult {
+      int num =
+        self->mEngines[aCapEngine].mPtrViECapture->NumberOfCapabilities(
+         unique_id.get(),
+          MediaEngineSource::kMaxUniqueIdLength);
+      nsRefPtr<nsIRunnable> ipc_runnable =
+        media::NewRunnableFrom([self, num]() -> nsresult {
+          if (self->IsShuttingDown()) {
+            return NS_ERROR_FAILURE;
+          }
+          if (num < 0) {
+            LOG(("RecvNumberOfCapabilities couldn't find capabilities"));
+            unused << self->SendReplyFailure();
+            return NS_ERROR_FAILURE;
+          } else {
+            LOG(("RecvNumberOfCapabilities: %d", num));
+          }
+          unused << self->SendReplyNumberOfCapabilities(num);
+          return NS_OK;
+        });
+      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    });
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+  return true;
+}
+
+bool
+CamerasParent::RecvGetCaptureCapability(const int &aCapEngine,
+                                        const nsCString& unique_id,
+                                        const int& num)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("Fails to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  LOG(("RecvGetCaptureCapability: %s %d", unique_id.get(), num));
+
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, unique_id, aCapEngine, num]() -> nsresult {
+      webrtc::CaptureCapability webrtcCaps;
+      int error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureCapability(
+        unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, num, webrtcCaps);
+      nsRefPtr<nsIRunnable> ipc_runnable =
+        media::NewRunnableFrom([self, webrtcCaps, error]() -> nsresult {
+          if (self->IsShuttingDown()) {
+            return NS_ERROR_FAILURE;
+          }
+          CaptureCapability capCap(webrtcCaps.width,
+                                   webrtcCaps.height,
+                                   webrtcCaps.maxFPS,
+                                   webrtcCaps.expectedCaptureDelay,
+                                   webrtcCaps.rawType,
+                                   webrtcCaps.codecType,
+                                   webrtcCaps.interlaced);
+          LOG(("Capability: %u %u %u %u %d %d",
+               webrtcCaps.width,
+               webrtcCaps.height,
+               webrtcCaps.maxFPS,
+               webrtcCaps.expectedCaptureDelay,
+               webrtcCaps.rawType,
+               webrtcCaps.codecType));
+          if (error) {
+            unused << self->SendReplyFailure();
+            return NS_ERROR_FAILURE;
+          }
+          unused << self->SendReplyGetCaptureCapability(capCap);
+          return NS_OK;
+        });
+      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    });
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+  return true;
+}
+
+bool
+CamerasParent::RecvGetCaptureDevice(const int& aCapEngine,
+                                    const int& aListNumber)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("Fails to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  LOG(("RecvGetCaptureDevice"));
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, aCapEngine, aListNumber]() -> nsresult {
+      char deviceName[MediaEngineSource::kMaxDeviceNameLength];
+      char deviceUniqueId[MediaEngineSource::kMaxUniqueIdLength];
+      nsCString name;
+      nsCString uniqueId;
+
+      int error =
+        self->mEngines[aCapEngine].mPtrViECapture->GetCaptureDevice(aListNumber,
+                                                                    deviceName,
+                                                                    sizeof(deviceName),
+                                                                    deviceUniqueId,
+                                                                    sizeof(deviceUniqueId));
+      if (!error) {
+        name.Assign(deviceName);
+        uniqueId.Assign(deviceUniqueId);
+      }
+
+      nsRefPtr<nsIRunnable> ipc_runnable =
+        media::NewRunnableFrom([self, error, name, uniqueId]() -> nsresult {
+          if (self->IsShuttingDown()) {
+            return NS_ERROR_FAILURE;
+          }
+          if (error) {
+            LOG(("GetCaptureDevice failed: %d", error));
+            unused << self->SendReplyFailure();
+            return NS_ERROR_FAILURE;
+          }
+
+          LOG(("Returning %s name %s id", name.get(), uniqueId.get()));
+          unused << self->SendReplyGetCaptureDevice(name, uniqueId);
+          return NS_OK;
+        });
+      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    });
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+  return true;
+}
+
+bool
+CamerasParent::RecvAllocateCaptureDevice(const int& aCapEngine,
+                                         const nsCString& unique_id)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("Fails to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, aCapEngine, unique_id]() -> nsresult {
+      int numdev;
+      int error = self->mEngines[aCapEngine].mPtrViECapture->AllocateCaptureDevice(
+        unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, numdev);
+      nsRefPtr<nsIRunnable> ipc_runnable =
+        media::NewRunnableFrom([self, numdev, error]() -> nsresult {
+          if (self->IsShuttingDown()) {
+            return NS_ERROR_FAILURE;
+          }
+          if (error) {
+            unused << self->SendReplyFailure();
+            return NS_ERROR_FAILURE;
+          } else {
+            LOG(("Allocated device nr %d", numdev));
+            unused << self->SendReplyAllocateCaptureDevice(numdev);
+            return NS_OK;
+          }
+        });
+      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    });
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+  return true;
+}
+
+bool
+CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
+                                        const int& numdev)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("Fails to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, aCapEngine, numdev]() -> nsresult {
+      LOG(("RecvReleaseCamera device nr %d", numdev));
+      int error = self->mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(numdev);
+      nsRefPtr<nsIRunnable> ipc_runnable =
+        media::NewRunnableFrom([self, error, numdev]() -> nsresult {
+          if (self->IsShuttingDown()) {
+            return NS_ERROR_FAILURE;
+          }
+          if (error) {
+            unused << self->SendReplyFailure();
+            return NS_ERROR_FAILURE;
+          } else {
+            unused << self->SendReplySuccess();
+            LOG(("Freed device nr %d", numdev));
+            return NS_OK;
+          }
+        });
+      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    });
+#ifndef XP_MACOSX
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+#else
+  // Mac OS X hangs on shutdown if we don't do this on the main thread.
+  NS_DispatchToMainThread(webrtc_runnable);
+#endif
+  return true;
+}
+
+bool
+CamerasParent::RecvStartCapture(const int& aCapEngine,
+                                const int& capnum,
+                                const CaptureCapability& ipcCaps)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("Failure to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, aCapEngine, capnum, ipcCaps]() -> nsresult {
+      MutexAutoLock lock(self->mCallbackMutex);
+      auto cbh = self->mCallbacks.AppendElement(
+        new CallbackHelper(static_cast<CaptureEngine>(aCapEngine), capnum, self));
+      auto render = static_cast<webrtc::ExternalRenderer*>(*cbh);
+
+      EngineHelper* helper = &self->mEngines[aCapEngine];
+
+      int error =
+        helper->mPtrViERender->AddRenderer(capnum, webrtc::kVideoI420, render);
+
+      if (!error) {
+        error = helper->mPtrViERender->StartRender(capnum);
+      }
+
+      webrtc::CaptureCapability capability;
+      capability.width = ipcCaps.width();
+      capability.height = ipcCaps.height();
+      capability.maxFPS = ipcCaps.maxFPS();
+      capability.expectedCaptureDelay = ipcCaps.expectedCaptureDelay();
+      capability.rawType = static_cast<webrtc::RawVideoType>(ipcCaps.rawType());
+      capability.codecType = static_cast<webrtc::VideoCodecType>(ipcCaps.codecType());
+      capability.interlaced = ipcCaps.interlaced();
+
+      if (!error) {
+        error = helper->mPtrViECapture->StartCapture(capnum, capability);
+      }
+
+      if (!error) {
+        helper->mEngineIsRunning = true;
+      }
+
+      nsRefPtr<nsIRunnable> ipc_runnable =
+        media::NewRunnableFrom([self, error]() -> nsresult {
+          if (self->IsShuttingDown()) {
+            return NS_ERROR_FAILURE;
+          }
+          if (!error) {
+            unused << self->SendReplySuccess();
+            return NS_OK;
+          } else {
+            unused << self->SendReplyFailure();
+            return NS_ERROR_FAILURE;
+          }
+        });
+      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    });
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+  return true;
+}
+
+bool
+CamerasParent::RecvStopCapture(const int& aCapEngine,
+                               const int& capnum)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!EnsureInitialized(aCapEngine)) {
+    LOG(("Failure to initialize"));
+    unused << SendReplyFailure();
+    return false;
+  }
+
+  nsRefPtr<CamerasParent> self(this);
+  nsRefPtr<nsRunnable> webrtc_runnable =
+    media::NewRunnableFrom([self, aCapEngine, capnum]() -> nsresult {
+      self->mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
+      self->mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
+      self->mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
+      self->mEngines[aCapEngine].mEngineIsRunning = false;
+
+      MutexAutoLock lock(self->mCallbackMutex);
+      for (unsigned int i = 0; i < self->mCallbacks.Length(); i++) {
+        if (self->mCallbacks[i]->mCapEngine == aCapEngine
+            && self->mCallbacks[i]->mCapturerId == capnum) {
+          delete self->mCallbacks[i];
+          self->mCallbacks.RemoveElementAt(i);
+          break;
+        }
+      }
+      return NS_OK;
+    });
+
+  mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
+  return SendReplySuccess();
+}
+
+bool
+CamerasParent::RecvAllDone()
+{
+  LOG((__PRETTY_FUNCTION__));
+  // Don't try to send anything to the child now
+  mChildIsAlive = false;
+  return Send__delete__(this);
+}
+
+void CamerasParent::DoShutdown()
+{
+  LOG((__PRETTY_FUNCTION__));
+  CloseEngines();
+
+  for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
+    if (mEngines[i].mEngine) {
+      mEngines[i].mEngine->SetTraceCallback(nullptr);
+      webrtc::VideoEngine::Delete(mEngines[i].mEngine);
+      mEngines[i].mEngine = nullptr;
+    }
+  }
+
+  mShmemPool.Cleanup(this);
+
+  mPBackgroundThread = nullptr;
+
+  if (mVideoCaptureThread) {
+    if (mVideoCaptureThread->IsRunning()) {
+      mVideoCaptureThread->Stop();
+    }
+    delete mVideoCaptureThread;
+    mVideoCaptureThread = nullptr;
+  }
+}
+
+void
+CamerasParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  // No more IPC from here
+  LOG((__PRETTY_FUNCTION__));
+  // We don't want to receive callbacks or anything if we can't
+  // forward them anymore anyway.
+  mChildIsAlive = false;
+  mDestroyed = true;
+  CloseEngines();
+}
+
+CamerasParent::CamerasParent()
+  : mCallbackMutex("CamerasParent.mCallbackMutex"),
+    mShmemPool(CaptureEngine::MaxEngine),
+    mVideoCaptureThread(nullptr),
+    mChildIsAlive(true),
+    mDestroyed(false)
+{
+  if (!gCamerasParentLog) {
+    gCamerasParentLog = PR_NewLogModule("CamerasParent");
+  }
+  LOG(("CamerasParent: %p", this));
+
+  mPBackgroundThread = NS_GetCurrentThread();
+  MOZ_ASSERT(mPBackgroundThread != nullptr, "GetCurrentThread failed");
+
+  LOG(("Spinning up WebRTC Cameras Thread"));
+  mVideoCaptureThread = new base::Thread("VideoCapture");
+  base::Thread::Options options;
+#if defined(_WIN32)
+  options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD;
+#else
+  options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD;
+#endif
+  if (!mVideoCaptureThread->StartWithOptions(options)) {
+    MOZ_CRASH();
+  }
+
+  MOZ_COUNT_CTOR(CamerasParent);
+}
+
+CamerasParent::~CamerasParent()
+{
+  LOG(("~CamerasParent: %p", this));
+
+  MOZ_COUNT_DTOR(CamerasParent);
+  DoShutdown();
+}
+
+already_AddRefed<CamerasParent>
+CamerasParent::Create() {
+  mozilla::ipc::AssertIsOnBackgroundThread();
+  nsRefPtr<CamerasParent> camerasParent = new CamerasParent();
+  return camerasParent.forget();
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/CamerasParent.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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_CamerasParent_h
+#define mozilla_CamerasParent_h
+
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/camera/PCamerasParent.h"
+#include "mozilla/ipc/Shmem.h"
+#include "mozilla/ShmemPool.h"
+
+// conflicts with #include of scoped_ptr.h
+#undef FF
+#include "webrtc/common.h"
+// Video Engine
+#include "webrtc/video_engine/include/vie_base.h"
+#include "webrtc/video_engine/include/vie_capture.h"
+#include "webrtc/video_engine/include/vie_render.h"
+#include "CamerasChild.h"
+
+#include "base/thread.h"
+
+namespace mozilla {
+namespace camera {
+
+class CamerasParent;
+
+class CallbackHelper : public webrtc::ExternalRenderer
+{
+public:
+  CallbackHelper(CaptureEngine aCapEng, int aCapId, CamerasParent *aParent)
+    : mCapEngine(aCapEng), mCapturerId(aCapId), mParent(aParent) {};
+
+  // ViEExternalRenderer implementation. These callbacks end up
+  // running on the VideoCapture thread.
+  virtual int FrameSizeChange(unsigned int w, unsigned int h,
+                              unsigned int streams) override;
+  virtual int DeliverFrame(unsigned char* buffer,
+                           int size,
+                           uint32_t time_stamp,
+                           int64_t ntp_time,
+                           int64_t render_time,
+                           void *handle) override;
+  virtual bool IsTextureSupported() override { return false; };
+
+  friend CamerasParent;
+
+private:
+  CaptureEngine mCapEngine;
+  int mCapturerId;
+  CamerasParent *mParent;
+};
+
+class EngineHelper
+{
+public:
+  EngineHelper() :
+    mEngine(nullptr), mPtrViEBase(nullptr), mPtrViECapture(nullptr),
+    mPtrViERender(nullptr), mEngineIsRunning(false) {};
+
+  webrtc::VideoEngine *mEngine;
+  webrtc::ViEBase *mPtrViEBase;
+  webrtc::ViECapture *mPtrViECapture;
+  webrtc::ViERender *mPtrViERender;
+
+  // The webrtc code keeps a reference to this one.
+  webrtc::Config mConfig;
+
+  // Engine alive
+  bool mEngineIsRunning;
+};
+
+class CamerasParent :  public PCamerasParent
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CamerasParent);
+
+public:
+  static already_AddRefed<CamerasParent> Create();
+
+  // Messages received form the child. These run on the IPC/PBackground thread.
+  virtual bool RecvAllocateCaptureDevice(const int&, const nsCString&) override;
+  virtual bool RecvReleaseCaptureDevice(const int&, const int &) override;
+  virtual bool RecvNumberOfCaptureDevices(const int&) override;
+  virtual bool RecvNumberOfCapabilities(const int&, const nsCString&) override;
+  virtual bool RecvGetCaptureCapability(const int&, const nsCString&, const int&) override;
+  virtual bool RecvGetCaptureDevice(const int&, const int&) override;
+  virtual bool RecvStartCapture(const int&, const int&, const CaptureCapability&) override;
+  virtual bool RecvStopCapture(const int&, const int&) override;
+  virtual bool RecvReleaseFrame(mozilla::ipc::Shmem&&) override;
+  virtual bool RecvAllDone() override;
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+  nsIThread* GetBackgroundThread() { return mPBackgroundThread; };
+  bool IsShuttingDown() { return !mChildIsAlive || mDestroyed; };
+  ShmemBuffer GetBuffer(size_t aSize);
+
+  // helper to forward to the PBackground thread
+  int DeliverFrameOverIPC(CaptureEngine capEng,
+                          int cap_id,
+                          ShmemBuffer buffer,
+                          unsigned char* altbuffer,
+                          int size,
+                          uint32_t time_stamp,
+                          int64_t ntp_time,
+                          int64_t render_time);
+
+
+  CamerasParent();
+
+protected:
+  virtual ~CamerasParent();
+
+  bool SetupEngine(CaptureEngine aCapEngine);
+  void CloseEngines();
+  bool EnsureInitialized(int aEngine);
+  void DoShutdown();
+
+  EngineHelper mEngines[CaptureEngine::MaxEngine];
+  nsTArray<CallbackHelper*> mCallbacks;
+  // Protects the callback arrays
+  Mutex mCallbackMutex;
+
+  // image buffers
+  mozilla::ShmemPool mShmemPool;
+
+  // PBackground parent thread
+  nsCOMPtr<nsIThread> mPBackgroundThread;
+
+  // video processing thread - where webrtc.org capturer code runs
+  base::Thread* mVideoCaptureThread;
+
+  // Shutdown handling
+  bool mChildIsAlive;
+  bool mDestroyed;
+};
+
+PCamerasParent* CreateCamerasParent();
+
+} // namespace camera
+} // namespace mozilla
+
+#endif  // mozilla_CameraParent_h
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/CamerasUtils.cpp
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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/unused.h"
+#include "nsThreadUtils.h"
+#include "nsCOMPtr.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+#include "nsIIPCBackgroundChildCreateCallback.h"
+
+namespace mozilla {
+namespace camera {
+
+class WorkerBackgroundChildCallback final :
+  public nsIIPCBackgroundChildCreateCallback
+{
+  bool* mDone;
+
+public:
+  explicit WorkerBackgroundChildCallback(bool* aDone)
+  : mDone(aDone)
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(mDone);
+  }
+
+  NS_DECL_ISUPPORTS
+
+private:
+  ~WorkerBackgroundChildCallback() { }
+
+  virtual void
+  ActorCreated(PBackgroundChild* aActor) override
+  {
+    *mDone = true;
+  }
+
+  virtual void
+  ActorFailed() override
+  {
+    *mDone = true;
+  }
+};
+NS_IMPL_ISUPPORTS(WorkerBackgroundChildCallback, nsIIPCBackgroundChildCreateCallback)
+
+nsresult
+SynchronouslyCreatePBackground()
+{
+  using mozilla::ipc::BackgroundChild;
+
+  MOZ_ASSERT(!BackgroundChild::GetForCurrentThread());
+
+  bool done = false;
+  nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
+    new WorkerBackgroundChildCallback(&done);
+
+  if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(callback))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIThread *thread = NS_GetCurrentThread();
+
+  while (!done) {
+    if (NS_WARN_IF(!NS_ProcessNextEvent(thread, true /* aMayWait */))) {
+      return NS_ERROR_FAILURE;
+    }
+  }
+
+  if (NS_WARN_IF(!BackgroundChild::GetForCurrentThread())) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/CamerasUtils.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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_CameraUtils_h
+#define mozilla_CameraUtils_h
+
+#include "nsThreadUtils.h"
+#include "nsCOMPtr.h"
+#include "mozilla/UniquePtr.h"
+
+#include "base/thread.h"
+
+namespace mozilla {
+namespace camera {
+
+nsresult SynchronouslyCreatePBackground();
+
+class ThreadDestructor : public nsRunnable
+{
+  DISALLOW_COPY_AND_ASSIGN(ThreadDestructor);
+
+public:
+  explicit ThreadDestructor(nsIThread* aThread)
+    : mThread(aThread) {}
+
+  NS_IMETHOD Run() override
+  {
+    if (mThread) {
+      mThread->Shutdown();
+    }
+    return NS_OK;
+  }
+
+private:
+  ~ThreadDestructor() {}
+  nsCOMPtr<nsIThread> mThread;
+};
+
+class RunnableTask : public Task
+{
+public:
+  explicit RunnableTask(nsRunnable* aRunnable)
+    : mRunnable(aRunnable) {}
+
+  void Run() override {
+    mRunnable->Run();
+  }
+
+private:
+  ~RunnableTask() {}
+  nsRefPtr<nsRunnable> mRunnable;
+};
+
+}
+}
+
+#endif // mozilla_CameraUtils_h
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/PCameras.ipdl
@@ -0,0 +1,60 @@
+/* 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 protocol PContent;
+include protocol PBackground;
+
+namespace mozilla {
+namespace camera {
+
+struct CaptureCapability
+{
+  int width;
+  int height;
+  int maxFPS;
+  int expectedCaptureDelay;
+  int rawType;
+  int codecType;
+  bool interlaced;
+};
+
+async protocol PCameras
+{
+  manager PBackground;
+
+child:
+  async FrameSizeChange(int capEngine, int cap_id, int w, int h);
+  // transfers ownership of |buffer| from parent to child
+  async DeliverFrame(int capEngine, int cap_id,
+                     Shmem buffer, int size, uint32_t time_stamp,
+                     int64_t ntp_time, int64_t render_time);
+  async ReplyNumberOfCaptureDevices(int numdev);
+  async ReplyNumberOfCapabilities(int numdev);
+  async ReplyAllocateCaptureDevice(int numdev);
+  async ReplyGetCaptureCapability(CaptureCapability cap);
+  async ReplyGetCaptureDevice(nsCString device_name, nsCString device_id);
+  async ReplyFailure();
+  async ReplySuccess();
+  async __delete__();
+
+parent:
+  async NumberOfCaptureDevices(int engine);
+  async NumberOfCapabilities(int engine, nsCString deviceUniqueIdUTF8);
+
+  async GetCaptureCapability(int engine, nsCString unique_idUTF8, int capability_number);
+  async GetCaptureDevice(int engine, int num);
+
+  async AllocateCaptureDevice(int engine, nsCString unique_idUTF8);
+  async ReleaseCaptureDevice(int engine, int numdev);
+  async StartCapture(int engine, int numdev, CaptureCapability capability);
+  async StopCapture(int engine, int numdev);
+  // transfers frame back
+  async ReleaseFrame(Shmem s);
+
+  // Ask parent to delete us
+  async AllDone();
+};
+
+} // namespace camera
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/ShmemPool.cpp
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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/Assertions.h"
+#include "mozilla/Logging.h"
+#include "mozilla/ShmemPool.h"
+#include "mozilla/Move.h"
+
+#undef LOG
+#undef LOG_ENABLED
+#define LOG(args) MOZ_LOG(gCamerasParentLog, mozilla::LogLevel::Debug, args)
+#define LOG_ENABLED() MOZ_LOG_TEST(gCamerasParentLog, mozilla::LogLevel::Debug)
+
+namespace mozilla {
+
+ShmemPool::ShmemPool(size_t aPoolSize)
+  : mMutex("mozilla::ShmemPool"),
+    mPoolFree(aPoolSize)
+#ifdef DEBUG
+    ,mMaxPoolUse(0)
+#endif
+{
+  mShmemPool.SetLength(aPoolSize);
+}
+
+mozilla::ShmemBuffer ShmemPool::GetIfAvailable(size_t aSize)
+{
+  MutexAutoLock lock(mMutex);
+
+  // Pool is empty, don't block caller.
+  if (mPoolFree == 0) {
+    // This isn't initialized, so will be understood as an error.
+    return ShmemBuffer();
+  }
+
+  ShmemBuffer& res = mShmemPool[mPoolFree - 1];
+
+  if (!res.mInitialized) {
+    return ShmemBuffer();
+  }
+
+  MOZ_ASSERT(res.mShmem.IsWritable(), "Pool in Shmem is not writable?");
+
+  if (res.mShmem.Size<char>() < aSize) {
+    return ShmemBuffer();
+  }
+
+  mPoolFree--;
+#ifdef DEBUG
+  size_t poolUse = mShmemPool.Length() - mPoolFree;
+  if (poolUse > mMaxPoolUse) {
+    mMaxPoolUse = poolUse;
+    LOG(("Maximum ShmemPool use increased: %d buffers", mMaxPoolUse));
+  }
+#endif
+  return Move(res);
+}
+
+template <class T>
+mozilla::ShmemBuffer ShmemPool::Get(T* aInstance, size_t aSize)
+{
+  MutexAutoLock lock(mMutex);
+
+  // Pool is empty, don't block caller.
+  if (mPoolFree == 0) {
+    // This isn't initialized, so will be understood as an error.
+    return ShmemBuffer();
+  }
+
+  ShmemBuffer res = Move(mShmemPool[mPoolFree - 1]);
+
+  if (!res.mInitialized) {
+    LOG(("Initiaizing new Shmem in pool"));
+    aInstance->AllocShmem(aSize, SharedMemory::TYPE_BASIC, &res.mShmem);
+    res.mInitialized = true;
+  }
+
+  MOZ_ASSERT(res.mShmem.IsWritable(), "Pool in Shmem is not writable?");
+
+  // Prepare buffer, increase size if needed (we never shrink as we don't
+  // maintain seperate sized pools and we don't want to keep reallocating)
+  if (res.mShmem.Size<char>() < aSize) {
+    LOG(("Size change/increase in Shmem Pool"));
+    aInstance->DeallocShmem(res.mShmem);
+    // this may fail; always check return value
+    if (!aInstance->AllocShmem(aSize, SharedMemory::TYPE_BASIC, &res.mShmem)) {
+      LOG(("Failure allocating new size Shmem buffer"));
+      return ShmemBuffer();
+    }
+  }
+
+  mPoolFree--;
+  return res;
+}
+
+void ShmemPool::Put(ShmemBuffer&& aShmem)
+{
+  MutexAutoLock lock(mMutex);
+  MOZ_ASSERT(mPoolFree < mShmemPool.Length());
+  mShmemPool[mPoolFree] = Move(aShmem);
+  mPoolFree++;
+}
+
+template <class T>
+void ShmemPool::Cleanup(T* aInstance)
+{
+  MutexAutoLock lock(mMutex);
+  for (size_t i = 0; i < mShmemPool.Length(); i++) {
+    if (mShmemPool[i].mInitialized) {
+      aInstance->DeallocShmem(mShmemPool[i].Get());
+      mShmemPool[i].mInitialized = false;
+    }
+  }
+}
+
+ShmemPool::~ShmemPool()
+{
+#ifdef DEBUG
+  for (size_t i = 0; i < mShmemPool.Length(); i++) {
+    MOZ_ASSERT(!mShmemPool[i].Valid());
+  }
+#endif
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/systemservices/ShmemPool.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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_ShmemPool_h
+#define mozilla_ShmemPool_h
+
+#include "mozilla/ipc/Shmem.h"
+#include "mozilla/Mutex.h"
+
+namespace mozilla {
+
+class ShmemPool;
+
+class ShmemBuffer {
+public:
+  ShmemBuffer() : mInitialized(false) {}
+  explicit ShmemBuffer(mozilla::ipc::Shmem aShmem) {
+    mInitialized = true;
+    mShmem = aShmem;
+  }
+
+  ShmemBuffer(ShmemBuffer&& rhs) {
+    mInitialized = rhs.mInitialized;
+    mShmem = Move(rhs.mShmem);
+  }
+
+  ShmemBuffer& operator=(ShmemBuffer&& rhs) {
+    MOZ_ASSERT(&rhs != this, "self-moves are prohibited");
+    mInitialized = rhs.mInitialized;
+    mShmem = Move(rhs.mShmem);
+    return *this;
+  }
+
+  // No copies allowed
+  ShmemBuffer(const ShmemBuffer&) = delete;
+  ShmemBuffer& operator=(const ShmemBuffer&) = delete;
+
+  bool Valid() {
+    return mInitialized;
+  }
+
+  char* GetBytes() {
+    return mShmem.get<char>();
+  }
+
+  mozilla::ipc::Shmem& Get() {
+    return mShmem;
+  }
+
+private:
+  friend class ShmemPool;
+
+  bool mInitialized;
+  mozilla::ipc::Shmem mShmem;
+};
+
+class ShmemPool {
+public:
+  explicit ShmemPool(size_t aPoolSize);
+  ~ShmemPool();
+  // We need to use the allocation/deallocation functions
+  // of a specific IPC child/parent instance.
+  template <class T> void Cleanup(T* aInstance);
+  // These 2 differ in what thread they can run on. GetIfAvailable
+  // can run anywhere but won't allocate if the right size isn't available.
+  ShmemBuffer GetIfAvailable(size_t aSize);
+  template <class T> ShmemBuffer Get(T* aInstance, size_t aSize);
+  void Put(ShmemBuffer&& aShmem);
+
+private:
+  Mutex mMutex;
+  size_t mPoolFree;
+#ifdef DEBUG
+  size_t mMaxPoolUse;
+#endif
+  nsTArray<ShmemBuffer> mShmemPool;
+};
+
+
+} // namespace mozilla
+
+#endif  // mozilla_ShmemPool_h
--- a/dom/media/systemservices/moz.build
+++ b/dom/media/systemservices/moz.build
@@ -1,24 +1,34 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 if CONFIG['MOZ_WEBRTC']:
-    EXPORTS += ['LoadManager.h',
+    EXPORTS += ['CamerasChild.h',
+                'CamerasParent.h',
+                'CamerasUtils.h',
+                'LoadManager.h',
                 'LoadManagerFactory.h',
                 'LoadMonitor.h',
     ]
-    UNIFIED_SOURCES += ['LoadManager.cpp',
+    UNIFIED_SOURCES += ['CamerasChild.cpp',
+                        'CamerasParent.cpp',
+                        'CamerasUtils.cpp',
+                        'LoadManager.cpp',
                         'LoadManagerFactory.cpp',
                         'LoadMonitor.cpp',
     ]
+    IPDL_SOURCES = [
+        'PCameras.ipdl',
+    ]
     LOCAL_INCLUDES += [
+        '/media/webrtc/signaling',
         '/media/webrtc/trunk',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
     EXPORTS += [
         'OpenSLESProvider.h'
     ]
     UNIFIED_SOURCES += [
@@ -32,42 +42,46 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     CXXFLAGS += [
         '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
             'frameworks/wilhelm/include',
             'system/media/wilhelm/include',
         ]
     ]
 
+if CONFIG['_MSC_VER']:
+    DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__'
+
+EXPORTS.mozilla += ['ShmemPool.h',]
+
 EXPORTS.mozilla.media += ['MediaChild.h',
                           'MediaParent.h',
                           'MediaSystemResourceClient.h',
                           'MediaSystemResourceManager.h',
                           'MediaSystemResourceManagerChild.h',
                           'MediaSystemResourceManagerParent.h',
                           'MediaSystemResourceMessageUtils.h',
                           'MediaSystemResourceService.h',
                           'MediaSystemResourceTypes.h',
-                          'MediaUtils.h'
+                          'MediaUtils.h',
 ]
 UNIFIED_SOURCES += ['MediaChild.cpp',
                     'MediaParent.cpp',
                     'MediaSystemResourceClient.cpp',
                     'MediaSystemResourceManager.cpp',
                     'MediaSystemResourceManagerChild.cpp',
                     'MediaSystemResourceManagerParent.cpp',
                     'MediaSystemResourceService.cpp',
                     'MediaUtils.cpp',
+                    'ShmemPool.cpp',
 ]
 IPDL_SOURCES += [
     'PMedia.ipdl',
     'PMediaSystemResourceManager.ipdl',
 ]
 # /dom/base needed for nsGlobalWindow.h in MediaChild.cpp
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/test/test_eme_requestKeySystemAccess.html
+++ b/dom/media/test/test_eme_requestKeySystemAccess.html
@@ -6,42 +6,44 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
   <script type="text/javascript" src="eme.js"></script>
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+const CLEARKEY_ID = 'org.w3.clearkey';
+const CLEARKEY_VERSION = '1';
+
 function Test(test) {
   var name = "'" + test.name + "'";
   return new Promise(function(resolve, reject) {
     var p;
     if (test.options) {
       p = navigator.requestMediaKeySystemAccess(test.keySystem, test.options);
     } else {
       p = navigator.requestMediaKeySystemAccess(test.keySystem);
     }
     p.then(
       function(keySystemAccess) {
         ok(test.shouldPass, name + " passed and was expected to " + (test.shouldPass ? "pass" : "fail"));
+        is(keySystemAccess.keySystem, CLEARKEY_ID + "." + CLEARKEY_VERSION, "CDM version should be in MediaKeySystemAccess.keySystem");
         resolve();
       },
       function(ex) {
         if (test.shouldPass) {
           info(name + " failed: " + ex);
         }
         ok(!test.shouldPass, name + " failed and was expected to " + (test.shouldPass ? "pass" : "fail"));
         resolve();
       });
   });
 }
 
-const CLEARKEY_ID = 'org.w3.clearkey';
-
 var tests = [
   {
     name: 'Empty keySystem string',
     keySystem: '',
     options: [ ],
     shouldPass: false,
   },
   {
--- a/dom/media/wave/moz.build
+++ b/dom/media/wave/moz.build
@@ -9,11 +9,9 @@ EXPORTS += [
     'WaveReader.h',
 ]
 
 UNIFIED_SOURCES += [
     'WaveDecoder.cpp',
     'WaveReader.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -315,20 +315,19 @@ AudioDestinationNode::AudioDestinationNo
   , mAudioChannel(AudioChannel::Normal)
   , mIsOffline(aIsOffline)
   , mAudioChannelAgentPlaying(false)
   , mExtraCurrentTime(0)
   , mExtraCurrentTimeSinceLastStartedBlocking(0)
   , mExtraCurrentTimeUpdatedSinceLastStableState(false)
   , mCaptured(false)
 {
-  bool startWithAudioDriver = true;
   MediaStreamGraph* graph = aIsOffline ?
                             MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate) :
-                            MediaStreamGraph::GetInstance(startWithAudioDriver, aChannel);
+                            MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER, aChannel);
   AudioNodeEngine* engine = aIsOffline ?
                             new OfflineDestinationNodeEngine(this, aNumberOfChannels,
                                                              aLength, aSampleRate) :
                             static_cast<AudioNodeEngine*>(new DestinationNodeEngine(this));
 
   AudioNodeStream::Flags flags =
     AudioNodeStream::NEED_MAIN_THREAD_CURRENT_TIME |
     AudioNodeStream::NEED_MAIN_THREAD_FINISHED |
--- a/dom/media/webaudio/blink/moz.build
+++ b/dom/media/webaudio/blink/moz.build
@@ -26,10 +26,10 @@ UNIFIED_SOURCES += [
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/media/webaudio',
 ]
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
--- a/dom/media/webaudio/compiledtest/moz.build
+++ b/dom/media/webaudio/compiledtest/moz.build
@@ -3,13 +3,11 @@
 # 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/.
 
 GeckoCppUnitTests([
     'TestAudioEventTimeline',
 ])
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '..',
 ]
--- a/dom/media/webaudio/moz.build
+++ b/dom/media/webaudio/moz.build
@@ -105,17 +105,15 @@ UNIFIED_SOURCES += [
 
 if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
     SOURCES += ['AudioNodeEngineNEON.cpp']
     SOURCES['AudioNodeEngineNEON.cpp'].flags += ['-mfpu=neon']
     LOCAL_INCLUDES += [
         '/media/openmax_dl/dl/api/'
     ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '..'
 ]
 
--- a/dom/media/webm/moz.build
+++ b/dom/media/webm/moz.build
@@ -30,11 +30,9 @@ if CONFIG['MOZ_FMP4'] and CONFIG['MOZ_WM
 if CONFIG['MOZ_WEBM_ENCODER']:
     EXPORTS += ['WebMWriter.h']
     UNIFIED_SOURCES += ['EbmlComposer.cpp',
                         'WebMWriter.cpp',
     ]
 
 CXXFLAGS += CONFIG['MOZ_LIBVPX_CFLAGS']
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.h
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.h
@@ -25,17 +25,16 @@ public:
     : MediaEngineVideoSource(kReleased)
     , mMonitor(aMonitorName)
     , mWidth(0)
     , mHeight(0)
     , mInitDone(false)
     , mHasDirectListeners(false)
     , mCaptureIndex(aIndex)
     , mTrackID(0)
-    , mFps(-1)
   {}
 
 
   virtual void GetName(nsAString& aName) override;
   virtual void GetUUID(nsACString& aUUID) override;
   virtual void SetDirectListeners(bool aHasListeners) override;
   virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
                           bool aAgcOn, uint32_t aAGC,
@@ -45,20 +44,16 @@ public:
     return NS_OK;
   };
 
   virtual bool IsFake() override
   {
     return false;
   }
 
-  virtual const dom::MediaSourceEnum GetMediaSource() override {
-      return dom::MediaSourceEnum::Camera;
-  }
-
   virtual nsresult TakePhoto(PhotoCallback* aCallback) override
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   uint32_t GetBestFitnessDistance(
       const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets,
       const nsString& aDeviceId) override;
@@ -114,17 +109,16 @@ protected:
   int mWidth, mHeight; // protected with mMonitor on Gonk due to different threading
   // end of data protected by mMonitor
 
 
   bool mInitDone;
   bool mHasDirectListeners;
   int mCaptureIndex;
   TrackID mTrackID;
-  int mFps; // Track rate (30 fps by default)
 
   webrtc::CaptureCapability mCapability; // Doesn't work on OS X.
 
   nsTArray<webrtc::CaptureCapability> mHardcodedCapabilities; // For OSX & B2G
 private:
   nsString mDeviceName;
   nsCString mUniqueId;
   nsString mFacingMode;
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.h
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.h
@@ -65,16 +65,19 @@ public:
                             const nsString& aDeviceId) override;
   virtual nsresult Deallocate() override;
   virtual nsresult Start(SourceMediaStream* aStream, TrackID aID) override;
   virtual nsresult Stop(SourceMediaStream* aSource, TrackID aID) override;
   virtual void NotifyPull(MediaStreamGraph* aGraph,
                           SourceMediaStream* aSource,
                           TrackID aId,
                           StreamTime aDesiredTime) override;
+  virtual const dom::MediaSourceEnum GetMediaSource() override {
+    return dom::MediaSourceEnum::Camera;
+  }
 
   void OnHardwareStateChange(HardwareState aState, nsresult aReason) override;
   void GetRotation();
   bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) override;
   void OnUserError(UserContext aContext, nsresult aError) override;
   void OnTakePictureComplete(const uint8_t* aData, uint32_t aLength, const nsAString& aMimeType) override;
 
   void AllocImpl();
new file mode 100644
--- /dev/null
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -0,0 +1,398 @@
+/* -*- 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 "MediaEngineRemoteVideoSource.h"
+
+#include "mozilla/RefPtr.h"
+#include "VideoUtils.h"
+#include "nsIPrefService.h"
+#include "MediaTrackConstraints.h"
+#include "CamerasChild.h"
+
+extern PRLogModuleInfo* GetMediaManagerLog();
+#define LOG(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Debug, msg)
+#define LOGFRAME(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Verbose, msg)
+
+namespace mozilla {
+
+using dom::ConstrainLongRange;
+
+NS_IMPL_ISUPPORTS0(MediaEngineRemoteVideoSource)
+
+MediaEngineRemoteVideoSource::MediaEngineRemoteVideoSource(
+  int aIndex, mozilla::camera::CaptureEngine aCapEngine,
+  dom::MediaSourceEnum aMediaSource, const char* aMonitorName)
+  : MediaEngineCameraVideoSource(aIndex, aMonitorName),
+    mMediaSource(aMediaSource),
+    mCapEngine(aCapEngine)
+{
+  MOZ_ASSERT(aMediaSource != dom::MediaSourceEnum::Other);
+  Init();
+}
+
+void
+MediaEngineRemoteVideoSource::Init()
+{
+  LOG((__PRETTY_FUNCTION__));
+  char deviceName[kMaxDeviceNameLength];
+  char uniqueId[kMaxUniqueIdLength];
+  if (mozilla::camera::GetCaptureDevice(mCapEngine,
+                                        mCaptureIndex,
+                                        deviceName, kMaxDeviceNameLength,
+                                        uniqueId, kMaxUniqueIdLength)) {
+    LOG(("Error initializing RemoteVideoSource (GetCaptureDevice)"));
+    return;
+  }
+
+  SetName(NS_ConvertUTF8toUTF16(deviceName));
+  SetUUID(uniqueId);
+
+  mInitDone = true;
+
+  return;
+}
+
+void
+MediaEngineRemoteVideoSource::Shutdown()
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!mInitDone) {
+    return;
+  }
+  if (mState == kStarted) {
+    SourceMediaStream *source;
+    bool empty;
+
+    while (1) {
+      {
+        MonitorAutoLock lock(mMonitor);
+        empty = mSources.IsEmpty();
+        if (empty) {
+          break;
+        }
+        source = mSources[0];
+      }
+      Stop(source, kVideoTrack); // XXX change to support multiple tracks
+    }
+    MOZ_ASSERT(mState == kStopped);
+  }
+
+  if (mState == kAllocated || mState == kStopped) {
+    Deallocate();
+  }
+
+  mozilla::camera::Shutdown();
+
+  mState = kReleased;
+  mInitDone = false;
+  return;
+}
+
+nsresult
+MediaEngineRemoteVideoSource::Allocate(const dom::MediaTrackConstraints& aConstraints,
+                                       const MediaEnginePrefs& aPrefs,
+                                       const nsString& aDeviceId)
+{
+  LOG((__PRETTY_FUNCTION__));
+
+  if (mState == kReleased && mInitDone) {
+    // Note: if shared, we don't allow a later opener to affect the resolution.
+    // (This may change depending on spec changes for Constraints/settings)
+
+    if (!ChooseCapability(aConstraints, aPrefs, aDeviceId)) {
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    if (mozilla::camera::AllocateCaptureDevice(mCapEngine,
+                                               GetUUID().get(),
+                                               kMaxUniqueIdLength, mCaptureIndex)) {
+      return NS_ERROR_FAILURE;
+    }
+    mState = kAllocated;
+    LOG(("Video device %d allocated", mCaptureIndex));
+  } else if (MOZ_LOG_TEST(GetMediaManagerLog(), mozilla::LogLevel::Debug)) {
+    MonitorAutoLock lock(mMonitor);
+    if (mSources.IsEmpty()) {
+      LOG(("Video device %d reallocated", mCaptureIndex));
+    } else {
+      LOG(("Video device %d allocated shared", mCaptureIndex));
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+MediaEngineRemoteVideoSource::Deallocate()
+{
+  LOG((__FUNCTION__));
+  bool empty;
+  {
+    MonitorAutoLock lock(mMonitor);
+    empty = mSources.IsEmpty();
+  }
+  if (empty) {
+    if (mState != kStopped && mState != kAllocated) {
+      return NS_ERROR_FAILURE;
+    }
+    mozilla::camera::ReleaseCaptureDevice(mCapEngine, mCaptureIndex);
+    mState = kReleased;
+    LOG(("Video device %d deallocated", mCaptureIndex));
+  } else {
+    LOG(("Video device %d deallocated but still in use", mCaptureIndex));
+  }
+  return NS_OK;
+}
+
+nsresult
+MediaEngineRemoteVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
+{
+  LOG((__PRETTY_FUNCTION__));
+  if (!mInitDone || !aStream) {
+    LOG(("No stream or init not done"));
+    return NS_ERROR_FAILURE;
+  }
+
+  {
+    MonitorAutoLock lock(mMonitor);
+    mSources.AppendElement(aStream);
+  }
+
+  aStream->AddTrack(aID, 0, new VideoSegment(), SourceMediaStream::ADDTRACK_QUEUED);
+
+  if (mState == kStarted) {
+    return NS_OK;
+  }
+  mImageContainer = layers::LayerManager::CreateImageContainer();
+
+  mState = kStarted;
+  mTrackID = aID;
+
+  if (mozilla::camera::StartCapture(mCapEngine,
+                                    mCaptureIndex, mCapability, this)) {
+    LOG(("StartCapture failed"));
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+MediaEngineRemoteVideoSource::Stop(mozilla::SourceMediaStream* aSource,
+                                   mozilla::TrackID aID)
+{
+  LOG((__PRETTY_FUNCTION__));
+  {
+    MonitorAutoLock lock(mMonitor);
+
+    if (!mSources.RemoveElement(aSource)) {
+      // Already stopped - this is allowed
+      return NS_OK;
+    }
+
+    aSource->EndTrack(aID);
+
+    if (!mSources.IsEmpty()) {
+      return NS_OK;
+    }
+    if (mState != kStarted) {
+      return NS_ERROR_FAILURE;
+    }
+
+    mState = kStopped;
+    // Drop any cached image so we don't start with a stale image on next
+    // usage
+    mImage = nullptr;
+  }
+
+  mozilla::camera::StopCapture(mCapEngine, mCaptureIndex);
+
+  return NS_OK;
+}
+
+void
+MediaEngineRemoteVideoSource::NotifyPull(MediaStreamGraph* aGraph,
+                                         SourceMediaStream* aSource,
+                                         TrackID aID, StreamTime aDesiredTime)
+{
+  VideoSegment segment;
+
+  MonitorAutoLock lock(mMonitor);
+  StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID);
+
+  if (delta > 0) {
+    // nullptr images are allowed
+    AppendToTrack(aSource, mImage, aID, delta);
+  }
+}
+
+int
+MediaEngineRemoteVideoSource::FrameSizeChange(unsigned int w, unsigned int h,
+                                              unsigned int streams)
+{
+  mWidth = w;
+  mHeight = h;
+  LOG(("MediaEngineRemoteVideoSource Video FrameSizeChange: %ux%u", w, h));
+  return 0;
+}
+
+int
+MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
+                                           int size,
+                                           uint32_t time_stamp,
+                                           int64_t ntp_time,
+                                           int64_t render_time,
+                                           void *handle)
+{
+  // Check for proper state.
+  if (mState != kStarted) {
+    LOG(("DeliverFrame: video not started"));
+    return 0;
+  }
+
+  if (mWidth*mHeight + 2*(((mWidth+1)/2)*((mHeight+1)/2)) != size) {
+    MOZ_ASSERT(false, "Wrong size frame in DeliverFrame!");
+    return 0;
+  }
+
+  // Create a video frame and append it to the track.
+  nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
+  layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
+
+  uint8_t* frame = static_cast<uint8_t*> (buffer);
+  const uint8_t lumaBpp = 8;
+  const uint8_t chromaBpp = 4;
+
+  // Take lots of care to round up!
+  layers::PlanarYCbCrData data;
+  data.mYChannel = frame;
+  data.mYSize = IntSize(mWidth, mHeight);
+  data.mYStride = (mWidth * lumaBpp + 7)/ 8;
+  data.mCbCrStride = (mWidth * chromaBpp + 7) / 8;
+  data.mCbChannel = frame + mHeight * data.mYStride;
+  data.mCrChannel = data.mCbChannel + ((mHeight+1)/2) * data.mCbCrStride;
+  data.mCbCrSize = IntSize((mWidth+1)/ 2, (mHeight+1)/ 2);
+  data.mPicX = 0;
+  data.mPicY = 0;
+  data.mPicSize = IntSize(mWidth, mHeight);
+  data.mStereoMode = StereoMode::MONO;
+
+  videoImage->SetData(data);
+
+#ifdef DEBUG
+  static uint32_t frame_num = 0;
+  LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %lu, render_time %lu", frame_num++,
+            mWidth, mHeight, time_stamp, ntp_time, render_time));
+#endif
+
+  // we don't touch anything in 'this' until here (except for snapshot,
+  // which has it's own lock)
+  MonitorAutoLock lock(mMonitor);
+
+  // implicitly releases last image
+  mImage = image.forget();
+
+  // Push the frame into the MSG with a minimal duration.  This will likely
+  // mean we'll still get NotifyPull calls which will then return the same
+  // frame again with a longer duration.  However, this means we won't
+  // fail to get the frame in and drop frames.
+
+  // XXX The timestamp for the frame should be based on the Capture time,
+  // not the MSG time, and MSG should never, ever block on a (realtime)
+  // video frame (or even really for streaming - audio yes, video probably no).
+  // Note that MediaPipeline currently ignores the timestamps from MSG
+  uint32_t len = mSources.Length();
+  for (uint32_t i = 0; i < len; i++) {
+    if (mSources[i]) {
+      AppendToTrack(mSources[i], mImage, mTrackID, 1); // shortest possible duration
+    }
+  }
+
+  return 0;
+}
+
+size_t
+MediaEngineRemoteVideoSource::NumCapabilities()
+{
+  int num = mozilla::camera::NumberOfCapabilities(mCapEngine, GetUUID().get());
+  if (num > 0) {
+    return num;
+  }
+
+  switch(mMediaSource) {
+  case dom::MediaSourceEnum::Camera:
+#ifdef XP_MACOSX
+    // Mac doesn't support capabilities.
+    //
+    // Hardcode generic desktop capabilities modeled on OSX camera.
+    // Note: Values are empirically picked to be OSX friendly, as on OSX, values
+    // other than these cause the source to not produce.
+
+    if (mHardcodedCapabilities.IsEmpty()) {
+      for (int i = 0; i < 9; i++) {
+        webrtc::CaptureCapability c;
+        c.width = 1920 - i*128;
+        c.height = 1080 - i*72;
+        c.maxFPS = 30;
+        mHardcodedCapabilities.AppendElement(c);
+      }
+      for (int i = 0; i < 16; i++) {
+        webrtc::CaptureCapability c;
+        c.width = 640 - i*40;
+        c.height = 480 - i*30;
+        c.maxFPS = 30;
+        mHardcodedCapabilities.AppendElement(c);
+      }
+    }
+    break;
+#endif
+  default:
+    webrtc::CaptureCapability c;
+    // The default for devices that don't return discrete capabilities: treat
+    // them as supporting all capabilities orthogonally. E.g. screensharing.
+    c.width = 0; // 0 = accept any value
+    c.height = 0;
+    c.maxFPS = 0;
+    mHardcodedCapabilities.AppendElement(c);
+    break;
+  }
+
+  return mHardcodedCapabilities.Length();
+}
+
+void
+MediaEngineRemoteVideoSource::GetCapability(size_t aIndex,
+                                            webrtc::CaptureCapability& aOut)
+{
+  if (!mHardcodedCapabilities.IsEmpty()) {
+    MediaEngineCameraVideoSource::GetCapability(aIndex, aOut);
+  }
+  mozilla::camera::GetCaptureCapability(mCapEngine,
+                                        GetUUID().get(),
+                                        aIndex,
+                                        aOut);
+}
+
+void MediaEngineRemoteVideoSource::Refresh(int aIndex) {
+  // NOTE: mCaptureIndex might have changed when allocated!
+  // Use aIndex to update information, but don't change mCaptureIndex!!
+  // Caller looked up this source by uniqueId, so it shouldn't change
+  char deviceName[kMaxDeviceNameLength];
+  char uniqueId[kMaxUniqueIdLength];
+
+  if (mozilla::camera::GetCaptureDevice(mCapEngine,
+                                        aIndex,
+                                        deviceName, sizeof(deviceName),
+                                        uniqueId, sizeof(uniqueId))) {
+    return;
+  }
+
+  SetName(NS_ConvertUTF8toUTF16(deviceName));
+#ifdef DEBUG
+  MOZ_ASSERT(GetUUID().Equals(uniqueId));
+#endif
+}
+
+}
new file mode 100644
--- /dev/null
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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 MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_
+#define MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_
+
+#include "prcvar.h"
+#include "prthread.h"
+#include "nsIThread.h"
+#include "nsIRunnable.h"
+
+#include "mozilla/Mutex.h"
+#include "mozilla/Monitor.h"
+#include "nsCOMPtr.h"
+#include "nsThreadUtils.h"
+#include "DOMMediaStream.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsComponentManagerUtils.h"
+
+#include "VideoUtils.h"
+#include "MediaEngineCameraVideoSource.h"
+#include "VideoSegment.h"
+#include "AudioSegment.h"
+#include "StreamBuffer.h"
+#include "MediaStreamGraph.h"
+
+#include "MediaEngineWrapper.h"
+#include "mozilla/dom/MediaStreamTrackBinding.h"
+
+// WebRTC library includes follow
+#include "webrtc/common.h"
+#include "webrtc/video_engine/include/vie_capture.h"
+#include "webrtc/video_engine/include/vie_render.h"
+#include "CamerasChild.h"
+
+#include "NullTransport.h"
+
+namespace mozilla {
+
+/**
+ * The WebRTC implementation of the MediaEngine interface.
+ */
+class MediaEngineRemoteVideoSource : public MediaEngineCameraVideoSource,
+                                     public webrtc::ExternalRenderer
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+
+  // ExternalRenderer
+  virtual int FrameSizeChange(unsigned int w, unsigned int h,
+                              unsigned int streams) override;
+  virtual int DeliverFrame(unsigned char* buffer,
+                           int size,
+                           uint32_t time_stamp,
+                           int64_t ntp_time,
+                           int64_t render_time,
+                           void *handle) override;
+  virtual bool IsTextureSupported() override { return false; };
+
+  // MediaEngineCameraVideoSource
+  MediaEngineRemoteVideoSource(int aIndex, mozilla::camera::CaptureEngine aCapEngine,
+                               dom::MediaSourceEnum aMediaSource,
+                               const char* aMonitorName = "RemoteVideo.Monitor");
+
+  virtual nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
+                            const MediaEnginePrefs& aPrefs,
+                            const nsString& aDeviceId) override;
+  virtual nsresult Deallocate() override;;
+  virtual nsresult Start(SourceMediaStream*, TrackID) override;
+  virtual nsresult Stop(SourceMediaStream*, TrackID) override;
+  virtual void NotifyPull(MediaStreamGraph* aGraph,
+                          SourceMediaStream* aSource,
+                          TrackID aId,
+                          StreamTime aDesiredTime) override;
+  virtual const dom::MediaSourceEnum GetMediaSource() override {
+    return mMediaSource;
+  }
+
+  void Refresh(int aIndex);
+
+  virtual void Shutdown() override;
+
+protected:
+  ~MediaEngineRemoteVideoSource() { Shutdown(); }
+
+private:
+  // Initialize the needed Video engine interfaces.
+  void Init();
+  size_t NumCapabilities() override;
+  void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut) override;
+
+  dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
+  mozilla::camera::CaptureEngine mCapEngine;
+};
+
+}
+
+#endif /* MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_ */
--- a/dom/media/webrtc/MediaEngineWebRTC.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTC.cpp
@@ -1,14 +1,17 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
 /* 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 "nsIPrefService.h"
 #include "nsIPrefBranch.h"
+#include "CamerasUtils.h"
 
 #include "CSFLog.h"
 #include "prenv.h"
 
 #include "mozilla/Logging.h"
 
 static PRLogModuleInfo*
 GetUserMediaLog()
@@ -18,16 +21,18 @@ GetUserMediaLog()
     sLog = PR_NewLogModule("GetUserMedia");
   return sLog;
 }
 
 #include "MediaEngineWebRTC.h"
 #include "ImageContainer.h"
 #include "nsIComponentRegistrar.h"
 #include "MediaEngineTabVideoSource.h"
+#include "MediaEngineRemoteVideoSource.h"
+#include "CamerasChild.h"
 #include "nsITabSource.h"
 #include "MediaTrackConstraints.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidJNIWrapper.h"
 #include "AndroidBridge.h"
 #endif
 
@@ -37,28 +42,19 @@ GetUserMediaLog()
 #endif
 
 #undef LOG
 #define LOG(args) MOZ_LOG(GetUserMediaLog(), mozilla::LogLevel::Debug, args)
 
 namespace mozilla {
 
 MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
-    : mMutex("mozilla::MediaEngineWebRTC")
-    , mScreenEngine(nullptr)
-    , mBrowserEngine(nullptr)
-    , mWinEngine(nullptr)
-    , mAppEngine(nullptr)
-    , mVideoEngine(nullptr)
-    , mVoiceEngine(nullptr)
-    , mVideoEngineInit(false)
-    , mAudioEngineInit(false)
-    , mScreenEngineInit(false)
-    , mBrowserEngineInit(false)
-    , mAppEngineInit(false)
+  : mMutex("mozilla::MediaEngineWebRTC"),
+    mVoiceEngine(nullptr),
+    mAudioEngineInit(false)
 {
 #ifndef MOZ_B2G_CAMERA
   nsCOMPtr<nsIComponentRegistrar> compMgr;
   NS_GetComponentRegistrar(getter_AddRefs(compMgr));
   if (compMgr) {
     compMgr->IsContractIDRegistered(NS_TABSOURCESERVICE_CONTRACTID, &mHasTabVideoSource);
   }
 #else
@@ -117,167 +113,116 @@ MediaEngineWebRTC::EnumerateVideoDevices
       vSource = new MediaEngineGonkVideoSource(i);
       mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
       aVSources->AppendElement(vSource);
     }
   }
 
   return;
 #else
-  ScopedCustomReleasePtr<webrtc::ViEBase> ptrViEBase;
-  ScopedCustomReleasePtr<webrtc::ViECapture> ptrViECapture;
-  webrtc::Config configSet;
-  webrtc::VideoEngine *videoEngine = nullptr;
-  bool *videoEngineInit = nullptr;
+  mozilla::camera::CaptureEngine capEngine = mozilla::camera::InvalidEngine;
 
 #ifdef MOZ_WIDGET_ANDROID
   // get the JVM
   JavaVM* jvm;
   JNIEnv* const env = jni::GetEnvForThread();
   MOZ_ALWAYS_TRUE(!env->GetJavaVM(&jvm));
 
   if (webrtc::VideoEngine::SetAndroidObjects(jvm) != 0) {
     LOG(("VieCapture:SetAndroidObjects Failed"));
     return;
   }
 #endif
 
   switch (aMediaSource) {
     case dom::MediaSourceEnum::Window:
-      mWinEngineConfig.Set<webrtc::CaptureDeviceInfo>(
-          new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Window));
-      if (!mWinEngine) {
-        if (!(mWinEngine = webrtc::VideoEngine::Create(mWinEngineConfig))) {
-          return;
-        }
-      }
-      videoEngine = mWinEngine;
-      videoEngineInit = &mWinEngineInit;
+      capEngine = mozilla::camera::WinEngine;
       break;
     case dom::MediaSourceEnum::Application:
-      mAppEngineConfig.Set<webrtc::CaptureDeviceInfo>(
-          new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Application));
-      if (!mAppEngine) {
-        if (!(mAppEngine = webrtc::VideoEngine::Create(mAppEngineConfig))) {
-          return;
-        }
-      }
-      videoEngine = mAppEngine;
-      videoEngineInit = &mAppEngineInit;
+      capEngine = mozilla::camera::AppEngine;
       break;
     case dom::MediaSourceEnum::Screen:
-      mScreenEngineConfig.Set<webrtc::CaptureDeviceInfo>(
-          new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Screen));
-      if (!mScreenEngine) {
-        if (!(mScreenEngine = webrtc::VideoEngine::Create(mScreenEngineConfig))) {
-          return;
-        }
-      }
-      videoEngine = mScreenEngine;
-      videoEngineInit = &mScreenEngineInit;
+      capEngine = mozilla::camera::ScreenEngine;
       break;
     case dom::MediaSourceEnum::Browser:
-      mBrowserEngineConfig.Set<webrtc::CaptureDeviceInfo>(
-          new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Browser));
-      if (!mBrowserEngine) {
-        if (!(mBrowserEngine = webrtc::VideoEngine::Create(mBrowserEngineConfig))) {
-          return;
-        }
-      }
-      videoEngine = mBrowserEngine;
-      videoEngineInit = &mBrowserEngineInit;
+      capEngine = mozilla::camera::BrowserEngine;
       break;
     case dom::MediaSourceEnum::Camera:
-      // fall through
-    default:
-      if (!mVideoEngine) {
-        if (!(mVideoEngine = webrtc::VideoEngine::Create())) {
-          return;
-        }
-      }
-      videoEngine = mVideoEngine;
-      videoEngineInit = &mVideoEngineInit;
+      capEngine = mozilla::camera::CameraEngine;
       break;
-  }
-
-  ptrViEBase = webrtc::ViEBase::GetInterface(videoEngine);
-  if (!ptrViEBase) {
-    return;
-  }
-  if (ptrViEBase->Init() < 0) {
-    return;
-  }
-  *videoEngineInit = true;
-
-  ptrViECapture = webrtc::ViECapture::GetInterface(videoEngine);
-  if (!ptrViECapture) {
-    return;
+    default:
+      // BOOM
+      MOZ_CRASH("No valid video engine");
+      break;
   }
 
   /**
    * We still enumerate every time, in case a new device was plugged in since
    * the last call. TODO: Verify that WebRTC actually does deal with hotplugging
    * new devices (with or without new engine creation) and accordingly adjust.
    * Enumeration is not neccessary if GIPS reports the same set of devices
    * for a given instance of the engine. Likewise, if a device was plugged out,
    * mVideoSources must be updated.
    */
-  int num = ptrViECapture->NumberOfCaptureDevices();
+  int num;
+  num = mozilla::camera::NumberOfCaptureDevices(capEngine);
   if (num <= 0) {
     return;
   }
 
   for (int i = 0; i < num; i++) {
     char deviceName[MediaEngineSource::kMaxDeviceNameLength];
     char uniqueId[MediaEngineSource::kMaxUniqueIdLength];
 
     // paranoia
     deviceName[0] = '\0';
     uniqueId[0] = '\0';
-    int error = ptrViECapture->GetCaptureDevice(i, deviceName,
-                                                sizeof(deviceName), uniqueId,
-                                                sizeof(uniqueId));
+    int error;
+
+    error = mozilla::camera::GetCaptureDevice(capEngine,
+                                              i, deviceName,
+                                              sizeof(deviceName), uniqueId,
+                                              sizeof(uniqueId));
 
     if (error) {
-      LOG((" VieCapture:GetCaptureDevice: Failed %d",
-           ptrViEBase->LastError() ));
+      LOG(("camera:GetCaptureDevice: Failed %d", error ));
       continue;
     }
 #ifdef DEBUG
     LOG(("  Capture Device Index %d, Name %s", i, deviceName));
 
     webrtc::CaptureCapability cap;
-    int numCaps = ptrViECapture->NumberOfCapabilities(uniqueId,
-                                                      MediaEngineSource::kMaxUniqueIdLength);
+    int numCaps = mozilla::camera::NumberOfCapabilities(capEngine,
+                                                        uniqueId);
     LOG(("Number of Capabilities %d", numCaps));
     for (int j = 0; j < numCaps; j++) {
-      if (ptrViECapture->GetCaptureCapability(uniqueId,
-                                              MediaEngineSource::kMaxUniqueIdLength,
-                                              j, cap ) != 0 ) {
-        break;
+      if (mozilla::camera::GetCaptureCapability(capEngine,
+                                                uniqueId,
+                                                j, cap ) != 0 ) {
+       break;
       }
       LOG(("type=%d width=%d height=%d maxFPS=%d",
            cap.rawType, cap.width, cap.height, cap.maxFPS ));
     }
 #endif
 
     if (uniqueId[0] == '\0') {
       // In case a device doesn't set uniqueId!
       strncpy(uniqueId, deviceName, sizeof(uniqueId));
       uniqueId[sizeof(uniqueId)-1] = '\0'; // strncpy isn't safe
     }
 
     nsRefPtr<MediaEngineVideoSource> vSource;
     NS_ConvertUTF8toUTF16 uuid(uniqueId);
     if (mVideoSources.Get(uuid, getter_AddRefs(vSource))) {
       // We've already seen this device, just refresh and append.
-      static_cast<MediaEngineWebRTCVideoSource*>(vSource.get())->Refresh(i);
+      static_cast<MediaEngineRemoteVideoSource*>(vSource.get())->Refresh(i);
       aVSources->AppendElement(vSource.get());
     } else {
-      vSource = new MediaEngineWebRTCVideoSource(videoEngine, i, aMediaSource);
+      vSource = new MediaEngineRemoteVideoSource(i, capEngine, aMediaSource);
       mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
       aVSources->AppendElement(vSource);
     }
   }
 
   if (mHasTabVideoSource || dom::MediaSourceEnum::Browser == aMediaSource) {
     aVSources->AppendElement(new MediaEngineTabVideoSource());
   }
@@ -412,50 +357,24 @@ MediaEngineWebRTC::Shutdown()
   LOG(("%s", __FUNCTION__));
   // Shutdown all the sources, since we may have dangling references to the
   // sources in nsDOMUserMediaStreams waiting for GC/CC
   mVideoSources.EnumerateRead(ClearVideoSource, nullptr);
   mAudioSources.EnumerateRead(ClearAudioSource, nullptr);
   mVideoSources.Clear();
   mAudioSources.Clear();
 
-  // Clear callbacks before we go away since the engines may outlive us
-  if (mVideoEngine) {
-    mVideoEngine->SetTraceCallback(nullptr);
-    webrtc::VideoEngine::Delete(mVideoEngine);
-  }
-
-  if (mScreenEngine) {
-    mScreenEngine->SetTraceCallback(nullptr);
-    webrtc::VideoEngine::Delete(mScreenEngine);
-  }
-  if (mWinEngine) {
-    mWinEngine->SetTraceCallback(nullptr);
-    webrtc::VideoEngine::Delete(mWinEngine);
-  }
-  if (mBrowserEngine) {
-    mBrowserEngine->SetTraceCallback(nullptr);
-    webrtc::VideoEngine::Delete(mBrowserEngine);
-  }
-  if (mAppEngine) {
-    mAppEngine->SetTraceCallback(nullptr);
-    webrtc::VideoEngine::Delete(mAppEngine);
-  }
-
   if (mVoiceEngine) {
     mVoiceEngine->SetTraceCallback(nullptr);
     webrtc::VoiceEngine::Delete(mVoiceEngine);
   }
 
-  mVideoEngine = nullptr;
   mVoiceEngine = nullptr;
-  mScreenEngine = nullptr;
-  mWinEngine = nullptr;
-  mBrowserEngine = nullptr;
-  mAppEngine = nullptr;
+
+  mozilla::camera::Shutdown();
 
   if (mThread) {
     mThread->Shutdown();
     mThread = nullptr;
   }
 }
 
 }
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -43,101 +43,23 @@
 
 // Video Engine
 // conflicts with #include of scoped_ptr.h
 #undef FF
 #include "webrtc/video_engine/include/vie_base.h"
 #include "webrtc/video_engine/include/vie_codec.h"
 #include "webrtc/video_engine/include/vie_render.h"
 #include "webrtc/video_engine/include/vie_capture.h"
+#include "CamerasChild.h"
 
 #include "NullTransport.h"
 #include "AudioOutputObserver.h"
 
 namespace mozilla {
 
-/**
- * The WebRTC implementation of the MediaEngine interface.
- */
-class MediaEngineWebRTCVideoSource : public MediaEngineCameraVideoSource
-                                   , public webrtc::ExternalRenderer
-{
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  // ViEExternalRenderer.
-  virtual int FrameSizeChange(unsigned int w, unsigned int h, unsigned int streams) override;
-  virtual int DeliverFrame(unsigned char* buffer,
-                           int size,
-                           uint32_t time_stamp,
-                           int64_t ntp_time_ms,
-                           int64_t render_time,
-                           void *handle) override;
-  /**
-   * Does DeliverFrame() support a null buffer and non-null handle
-   * (video texture)?
-   * XXX Investigate!  Especially for Android/B2G
-   */
-  virtual bool IsTextureSupported() override { return false; }
-
-  MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr, int aIndex,
-                               dom::MediaSourceEnum aMediaSource = dom::MediaSourceEnum::Camera)
-    : MediaEngineCameraVideoSource(aIndex, "WebRTCCamera.Monitor")
-    , mVideoEngine(aVideoEnginePtr)
-    , mMinFps(-1)
-    , mMediaSource(aMediaSource)
-  {
-    MOZ_ASSERT(aVideoEnginePtr);
-    MOZ_ASSERT(aMediaSource != dom::MediaSourceEnum::Other);
-    Init();
-  }
-
-  virtual nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
-                            const MediaEnginePrefs& aPrefs,
-                            const nsString& aDeviceId) override;
-  virtual nsresult Deallocate() override;
-  virtual nsresult Start(SourceMediaStream*, TrackID) override;
-  virtual nsresult Stop(SourceMediaStream*, TrackID) override;
-  virtual void NotifyPull(MediaStreamGraph* aGraph,
-                          SourceMediaStream* aSource,
-                          TrackID aId,
-                          StreamTime aDesiredTime) override;
-
-  virtual const dom::MediaSourceEnum GetMediaSource() override {
-    return mMediaSource;
-  }
-  virtual nsresult TakePhoto(PhotoCallback* aCallback) override
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-
-  void Refresh(int aIndex);
-
-  virtual void Shutdown() override;
-
-protected:
-  ~MediaEngineWebRTCVideoSource() { Shutdown(); }
-
-private:
-  // Initialize the needed Video engine interfaces.
-  void Init();
-
-  // Engine variables.
-  webrtc::VideoEngine* mVideoEngine; // Weak reference, don't free.
-  ScopedCustomReleasePtr<webrtc::ViEBase> mViEBase;
-  ScopedCustomReleasePtr<webrtc::ViECapture> mViECapture;
-  ScopedCustomReleasePtr<webrtc::ViERender> mViERender;
-
-  int mMinFps; // Min rate we want to accept
-  dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
-
-  size_t NumCapabilities() override;
-  void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut) override;
-};
-
 class MediaEngineWebRTCAudioCaptureSource : public MediaEngineAudioSource
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   explicit MediaEngineWebRTCAudioCaptureSource(const char* aUuid)
     : MediaEngineAudioSource(kReleased)
   {
@@ -261,19 +183,19 @@ public:
       const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets,
       const nsString& aDeviceId) override;
 
   // VoEMediaProcess.
   void Process(int channel, webrtc::ProcessingTypes type,
                int16_t audio10ms[], int length,
                int samplingFreq, bool isStereo) override;
 
-  NS_DECL_THREADSAFE_ISUPPORTS
+  virtual void Shutdown() override;
 
-  virtual void Shutdown() override;
+  NS_DECL_THREADSAFE_ISUPPORTS
 
 protected:
   ~MediaEngineWebRTCMicrophoneSource() { Shutdown(); }
 
 private:
   void Init();
 
   webrtc::VoiceEngine* mVoiceEngine;
@@ -325,39 +247,21 @@ private:
 #if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
     AsyncLatencyLogger::Get()->Release();
 #endif
     gFarendObserver = nullptr;
   }
 
   nsCOMPtr<nsIThread> mThread;
 
+  // gUM runnables can e.g. Enumerate from multiple threads
   Mutex mMutex;
-
-  // protected with mMutex:
-  webrtc::VideoEngine* mScreenEngine;
-  webrtc::VideoEngine* mBrowserEngine;
-  webrtc::VideoEngine* mWinEngine;
-  webrtc::VideoEngine* mAppEngine;
-  webrtc::VideoEngine* mVideoEngine;
   webrtc::VoiceEngine* mVoiceEngine;
+  bool mAudioEngineInit;
 
-  // specialized configurations
-  webrtc::Config mAppEngineConfig;
-  webrtc::Config mWinEngineConfig;
-  webrtc::Config mScreenEngineConfig;
-  webrtc::Config mBrowserEngineConfig;
-
-  // Need this to avoid unneccesary WebRTC calls while enumerating.
-  bool mVideoEngineInit;
-  bool mAudioEngineInit;
-  bool mScreenEngineInit;
-  bool mBrowserEngineInit;
-  bool mWinEngineInit;
-  bool mAppEngineInit;
   bool mHasTabVideoSource;
 
   // Store devices we've already seen in a hashtable for quick return.
   // Maps UUID to MediaEngineSource (one set for audio, one for video).
   nsRefPtrHashtable<nsStringHashKey, MediaEngineVideoSource> mVideoSources;
   nsRefPtrHashtable<nsStringHashKey, MediaEngineAudioSource> mAudioSources;
 };
 
deleted file mode 100644
--- a/dom/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ /dev/null
@@ -1,449 +0,0 @@
-/* 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 "MediaEngineWebRTC.h"
-#include "Layers.h"
-#include "ImageTypes.h"
-#include "ImageContainer.h"
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "nsMemory.h"
-#include "mtransport/runnable_utils.h"
-#include "MediaTrackConstraints.h"
-
-namespace mozilla {
-
-using namespace mozilla::gfx;
-using dom::ConstrainLongRange;
-using dom::ConstrainDoubleRange;
-using dom::MediaTrackConstraintSet;
-
-extern PRLogModuleInfo* GetMediaManagerLog();
-#define LOG(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Debug, msg)
-#define LOGFRAME(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Verbose, msg)
-
-/**
- * Webrtc video source.
- */
-
-NS_IMPL_ISUPPORTS0(MediaEngineWebRTCVideoSource)
-
-int
-MediaEngineWebRTCVideoSource::FrameSizeChange(
-   unsigned int w, unsigned int h, unsigned int streams)
-{
-  mWidth = w;
-  mHeight = h;
-  LOG(("Video FrameSizeChange: %ux%u", w, h));
-  return 0;
-}
-
-// ViEExternalRenderer Callback. Process every incoming frame here.
-int
-MediaEngineWebRTCVideoSource::DeliverFrame(
-   unsigned char* buffer, int size, uint32_t time_stamp,
-   int64_t ntp_time_ms, int64_t render_time, void *handle)
-{
-  // Check for proper state.
-  if (mState != kStarted) {
-    LOG(("DeliverFrame: video not started"));
-    return 0;
-  }
-
-  if (mWidth*mHeight + 2*(((mWidth+1)/2)*((mHeight+1)/2)) != size) {
-    MOZ_ASSERT(false, "Wrong size frame in DeliverFrame!");
-    return 0;
-  }
-
-  // Create a video frame and append it to the track.
-  nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
-
-  layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
-
-  uint8_t* frame = static_cast<uint8_t*> (buffer);
-  const uint8_t lumaBpp = 8;
-  const uint8_t chromaBpp = 4;
-
-  // Take lots of care to round up!
-  layers::PlanarYCbCrData data;
-  data.mYChannel = frame;
-  data.mYSize = IntSize(mWidth, mHeight);
-  data.mYStride = (mWidth * lumaBpp + 7)/ 8;
-  data.mCbCrStride = (mWidth * chromaBpp + 7) / 8;
-  data.mCbChannel = frame + mHeight * data.mYStride;
-  data.mCrChannel = data.mCbChannel + ((mHeight+1)/2) * data.mCbCrStride;
-  data.mCbCrSize = IntSize((mWidth+1)/ 2, (mHeight+1)/ 2);
-  data.mPicX = 0;
-  data.mPicY = 0;
-  data.mPicSize = IntSize(mWidth, mHeight);
-  data.mStereoMode = StereoMode::MONO;
-
-  videoImage->SetData(data);
-
-#ifdef DEBUG
-  static uint32_t frame_num = 0;
-  LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %lu, render_time %lu", frame_num++,
-            mWidth, mHeight, time_stamp, ntp_time_ms, render_time));
-#endif
-
-  // we don't touch anything in 'this' until here (except for snapshot,
-  // which has it's own lock)
-  MonitorAutoLock lock(mMonitor);
-
-  // implicitly releases last image
-  mImage = image.forget();
-
-  // Push the frame into the MSG with a minimal duration.  This will likely
-  // mean we'll still get NotifyPull calls which will then return the same
-  // frame again with a longer duration.  However, this means we won't
-  // fail to get the frame in and drop frames.
-
-  // XXX The timestamp for the frame should be based on the Capture time,
-  // not the MSG time, and MSG should never, ever block on a (realtime)
-  // video frame (or even really for streaming - audio yes, video probably no).
-  // Note that MediaPipeline currently ignores the timestamps from MSG
-  uint32_t len = mSources.Length();
-  for (uint32_t i = 0; i < len; i++) {
-    if (mSources[i]) {
-      AppendToTrack(mSources[i], mImage, mTrackID, 1); // shortest possible duration
-    }
-  }
-
-  return 0;
-}
-
-// Called if the graph thinks it's running out of buffered video; repeat
-// the last frame for whatever minimum period it think it needs.  Note that
-// this means that no *real* frame can be inserted during this period.
-void
-MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
-                                         SourceMediaStream* aSource,
-                                         TrackID aID,
-                                         StreamTime aDesiredTime)
-{
-  VideoSegment segment;
-
-  MonitorAutoLock lock(mMonitor);
-  // B2G does AddTrack, but holds kStarted until the hardware changes state.
-  // So mState could be kReleased here.  We really don't care about the state,
-  // though.
-
-  StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID);
-  LOGFRAME(("NotifyPull, desired = %ld, delta = %ld %s", (int64_t) aDesiredTime,
-            (int64_t) delta, mImage.get() ? "" : "<null>"));
-
-  // Bug 846188 We may want to limit incoming frames to the requested frame rate
-  // mFps - if you want 30FPS, and the camera gives you 60FPS, this could
-  // cause issues.
-  // We may want to signal if the actual frame rate is below mMinFPS -
-  // cameras often don't return the requested frame rate especially in low
-  // light; we should consider surfacing this so that we can switch to a
-  // lower resolution (which may up the frame rate)
-
-  // Don't append if we've already provided a frame that supposedly goes past the current aDesiredTime
-  // Doing so means a negative delta and thus messes up handling of the graph
-  if (delta > 0) {
-    // nullptr images are allowed
-    AppendToTrack(aSource, mImage, aID, delta);
-  }
-}
-
-size_t
-MediaEngineWebRTCVideoSource::NumCapabilities()
-{
-  int num = mViECapture->NumberOfCapabilities(GetUUID().get(), kMaxUniqueIdLength);
-  if (num > 0) {
-    return num;
-  }
-
-  switch (mMediaSource) {
-    case dom::MediaSourceEnum::Camera:
-#ifdef XP_MACOSX
-      // Mac doesn't support capabilities.
-      //
-      // Hardcode generic desktop capabilities modeled on OSX camera.
-      // Note: Values are empirically picked to be OSX friendly, as on OSX,
-      // values other than these cause the source to not produce.
-
-      if (mHardcodedCapabilities.IsEmpty()) {
-        for (int i = 0; i < 9; i++) {
-          webrtc::CaptureCapability c;
-          c.width = 1920 - i*128;
-          c.height = 1080 - i*72;
-          c.maxFPS = 30;
-          mHardcodedCapabilities.AppendElement(c);
-        }
-        for (int i = 0; i < 16; i++) {
-          webrtc::CaptureCapability c;
-          c.width = 640 - i*40;
-          c.height = 480 - i*30;
-          c.maxFPS = 30;
-          mHardcodedCapabilities.AppendElement(c);
-        }
-      }
-      break;
-#endif
-    default:
-      // The default for devices that don't return discrete capabilities: treat
-      // them as supporting all capabilities orthogonally. E.g. screensharing.
-      webrtc::CaptureCapability c;
-      c.width = 0; // 0 = accept any value
-      c.height = 0;
-      c.maxFPS = 0;
-      mHardcodedCapabilities.AppendElement(c);
-      break;
-  }
-  return mHardcodedCapabilities.Length();
-}
-
-void
-MediaEngineWebRTCVideoSource::GetCapability(size_t aIndex,
-                                            webrtc::CaptureCapability& aOut)
-{
-  if (!mHardcodedCapabilities.IsEmpty()) {
-    MediaEngineCameraVideoSource::GetCapability(aIndex, aOut);
-  }
-  mViECapture->GetCaptureCapability(GetUUID().get(), kMaxUniqueIdLength, aIndex, aOut);
-}
-
-nsresult
-MediaEngineWebRTCVideoSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
-                                       const MediaEnginePrefs &aPrefs,
-                                       const nsString& aDeviceId)
-{
-  LOG((__FUNCTION__));
-  if (mState == kReleased && mInitDone) {
-    // Note: if shared, we don't allow a later opener to affect the resolution.
-    // (This may change depending on spec changes for Constraints/settings)
-
-    if (!ChooseCapability(aConstraints, aPrefs, aDeviceId)) {
-      return NS_ERROR_UNEXPECTED;
-    }
-    if (mViECapture->AllocateCaptureDevice(GetUUID().get(),
-                                           kMaxUniqueIdLength, mCaptureIndex)) {
-      return NS_ERROR_FAILURE;
-    }
-    mState = kAllocated;
-    LOG(("Video device %d allocated", mCaptureIndex));
-  } else if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) {
-    MonitorAutoLock lock(mMonitor);
-    if (mSources.IsEmpty()) {
-      LOG(("Video device %d reallocated", mCaptureIndex));
-    } else {
-      LOG(("Video device %d allocated shared", mCaptureIndex));
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-MediaEngineWebRTCVideoSource::Deallocate()
-{
-  LOG((__FUNCTION__));
-  bool empty;
-  {
-    MonitorAutoLock lock(mMonitor);
-    empty = mSources.IsEmpty();
-  }
-  if (empty) {
-    // If empty, no callbacks to deliver data should be occuring
-    if (mState != kStopped && mState != kAllocated) {
-      return NS_ERROR_FAILURE;
-    }
-#ifdef XP_MACOSX
-    // Bug 829907 - on mac, in shutdown, the mainthread stops processing
-    // 'native' events, and the QTKit code uses events to the main native CFRunLoop
-    // in order to provide thread safety.  In order to avoid this locking us up,
-    // release the ViE capture device synchronously on MainThread (so the native
-    // event isn't needed).
-    // XXX Note if MainThread Dispatch()es NS_DISPATCH_SYNC to us we can deadlock.
-    // XXX It might be nice to only do this if we're in shutdown...  Hard to be
-    // sure when that is though.
-    // Thread safety: a) we call this synchronously, and don't use ViECapture from
-    // another thread anywhere else, b) ViEInputManager::DestroyCaptureDevice() grabs
-    // an exclusive object lock and deletes it in a critical section, so all in all
-    // this should be safe threadwise.
-    NS_DispatchToMainThread(WrapRunnable(mViECapture.get(),
-                                         &webrtc::ViECapture::ReleaseCaptureDevice,
-                                         mCaptureIndex),
-                            NS_DISPATCH_SYNC);
-#else
-    mViECapture->ReleaseCaptureDevice(mCaptureIndex);
-#endif
-    mState = kReleased;
-    LOG(("Video device %d deallocated", mCaptureIndex));
-  } else {
-    LOG(("Video device %d deallocated but still in use", mCaptureIndex));
-  }
-  return NS_OK;
-}
-
-nsresult
-MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
-{
-  LOG((__FUNCTION__));
-  int error = 0;
-  if (!mInitDone || !aStream) {
-    return NS_ERROR_FAILURE;
-  }
-
-  {
-    MonitorAutoLock lock(mMonitor);
-    mSources.AppendElement(aStream);
-  }
-
-  aStream->AddTrack(aID, 0, new VideoSegment(), SourceMediaStream::ADDTRACK_QUEUED);
-
-  if (mState == kStarted) {
-    return NS_OK;
-  }
-  mImageContainer = layers::LayerManager::CreateImageContainer();
-
-  mState = kStarted;
-  mTrackID = aID;
-
-  error = mViERender->AddRenderer(mCaptureIndex, webrtc::kVideoI420, (webrtc::ExternalRenderer*)this);
-  if (error == -1) {
-    return NS_ERROR_FAILURE;
-  }
-
-  error = mViERender->StartRender(mCaptureIndex);
-  if (error == -1) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (mViECapture->StartCapture(mCaptureIndex, mCapability) < 0) {
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
-nsresult
-MediaEngineWebRTCVideoSource::Stop(SourceMediaStream *aSource, TrackID aID)
-{
-  LOG((__FUNCTION__));
-  {
-    MonitorAutoLock lock(mMonitor);
-
-    if (!mSources.RemoveElement(aSource)) {
-      // Already stopped - this is allowed
-      return NS_OK;
-    }
-
-    aSource->EndTrack(aID);
-
-    if (!mSources.IsEmpty()) {
-      return NS_OK;
-    }
-    if (mState != kStarted) {
-      return NS_ERROR_FAILURE;
-    }
-
-    mState = kStopped;
-    // Drop any cached image so we don't start with a stale image on next
-    // usage
-    mImage = nullptr;
-  }
-  mViERender->StopRender(mCaptureIndex);
-  mViERender->RemoveRenderer(mCaptureIndex);
-  mViECapture->StopCapture(mCaptureIndex);
-
-  return NS_OK;
-}
-
-void
-MediaEngineWebRTCVideoSource::Init()
-{
-  // fix compile warning for these being unused. (remove once used)
-  (void) mFps;
-  (void) mMinFps;
-
-  LOG((__FUNCTION__));
-  if (mVideoEngine == nullptr) {
-    return;
-  }
-
-  mViEBase = webrtc::ViEBase::GetInterface(mVideoEngine);
-  if (mViEBase == nullptr) {
-    return;
-  }
-
-  // Get interfaces for capture, render for now
-  mViECapture = webrtc::ViECapture::GetInterface(mVideoEngine);
-  mViERender = webrtc::ViERender::GetInterface(mVideoEngine);
-
-  if (mViECapture == nullptr || mViERender == nullptr) {
-    return;
-  }
-
-  char deviceName[kMaxDeviceNameLength];
-  char uniqueId[kMaxUniqueIdLength];
-  if (mViECapture->GetCaptureDevice(mCaptureIndex,
-                                    deviceName, kMaxDeviceNameLength,
-                                    uniqueId, kMaxUniqueIdLength)) {
-    return;
-  }
-  SetName(NS_ConvertUTF8toUTF16(deviceName));
-  SetUUID(uniqueId);
-
-  mInitDone = true;
-}
-
-void
-MediaEngineWebRTCVideoSource::Shutdown()
-{
-  LOG((__FUNCTION__));
-  if (!mInitDone) {
-    return;
-  }
-  if (mState == kStarted) {
-    SourceMediaStream *source;
-    bool empty;
-
-    while (1) {
-      {
-        MonitorAutoLock lock(mMonitor);
-        empty = mSources.IsEmpty();
-        if (empty) {
-          break;
-        }
-        source = mSources[0];
-      }
-      Stop(source, kVideoTrack); // XXX change to support multiple tracks
-    }
-    MOZ_ASSERT(mState == kStopped);
-  }
-
-  if (mState == kAllocated || mState == kStopped) {
-    Deallocate();
-  }
-  mViECapture = nullptr;
-  mViERender = nullptr;
-  mViEBase = nullptr;
-
-  mState = kReleased;
-  mInitDone = false;
-}
-
-void MediaEngineWebRTCVideoSource::Refresh(int aIndex) {
-  // NOTE: mCaptureIndex might have changed when allocated!
-  // Use aIndex to update information, but don't change mCaptureIndex!!
-  // Caller looked up this source by uniqueId, so it shouldn't change
-  char deviceName[kMaxDeviceNameLength];
-  char uniqueId[kMaxUniqueIdLength];
-
-  if (mViECapture->GetCaptureDevice(aIndex,
-                                    deviceName, sizeof(deviceName),
-                                    uniqueId, sizeof(uniqueId))) {
-    return;
-  }
-
-  SetName(NS_ConvertUTF8toUTF16(deviceName));
-#ifdef DEBUG
-  MOZ_ASSERT(GetUUID().Equals(uniqueId));
-#endif
-}
-
-} // namespace mozilla
--- a/dom/media/webrtc/moz.build
+++ b/dom/media/webrtc/moz.build
@@ -16,23 +16,24 @@ EXPORTS += [
     'MediaEngine.h',
     'MediaEngineCameraVideoSource.h',
     'MediaEngineDefault.h',
     'MediaTrackConstraints.h',
 ]
 
 if CONFIG['MOZ_WEBRTC']:
     EXPORTS += ['AudioOutputObserver.h',
+                'MediaEngineRemoteVideoSource.h',
                 'MediaEngineWebRTC.h']
     EXPORTS.mozilla.dom += [ 'RTCIdentityProviderRegistrar.h' ]
     UNIFIED_SOURCES += [
         'MediaEngineCameraVideoSource.cpp',
+        'MediaEngineRemoteVideoSource.cpp',
         'MediaEngineTabVideoSource.cpp',
         'MediaEngineWebRTCAudio.cpp',
-        'MediaEngineWebRTCVideo.cpp',
         'MediaTrackConstraints.cpp',
         'RTCCertificate.cpp',
         'RTCIdentityProviderRegistrar.cpp',
     ]
     # MediaEngineWebRTC.cpp needs to be built separately.
     SOURCES += [
         'MediaEngineWebRTC.cpp',
     ]
@@ -73,20 +74,19 @@ EXPORTS.mozilla.dom += [
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 # Suppress some GCC/clang warnings being treated as errors:
 #  - about attributes on forward declarations for types that are already
 #    defined, which complains about important MOZ_EXPORT attributes for
 #    android API types
 if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
-  CXXFLAGS += [
-    '-Wno-error=attributes'
-  ]
+    CXXFLAGS += [
+        '-Wno-error=attributes'
+    ]
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['_MSC_VER']:
-  CXXFLAGS += [
-    '-wd4275', # non dll-interface class used as base for dll-interface class
-  ]
-
-FAIL_ON_WARNINGS = True
+    CXXFLAGS += [
+        '-wd4275', # non dll-interface class used as base for dll-interface class
+    ]
+    DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__'
--- a/dom/media/webspeech/recognition/moz.build
+++ b/dom/media/webspeech/recognition/moz.build
@@ -62,10 +62,8 @@ LOCAL_INCLUDES += [
 if CONFIG['MOZ_WEBSPEECH_POCKETSPHINX']:
     LOCAL_INCLUDES += [
         '/media/pocketsphinx',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/media/webspeech/recognition/test/mochitest.ini
+++ b/dom/media/webspeech/recognition/test/mochitest.ini
@@ -1,24 +1,23 @@
 [DEFAULT]
 tags=msg
+skip-if = buildapp == 'b2g' # Bug 1191270, bug 1037287, bug 967606, bug 1096400, etc
 support-files =
   head.js
   hello.ogg
   hello.ogg^headers^
   silence.ogg
   silence.ogg^headers^
 
 [test_abort.html]
-skip-if = toolkit == 'android' || toolkit == 'gonk' # bug 1037287
+skip-if = toolkit == 'android' # bug 1037287
 [test_audio_capture_error.html]
-skip-if = toolkit == 'gonk' # Bug 1191270
 [test_call_start_from_end_handler.html]
 tags=capturestream
-skip-if = (android_version == '18' && debug) || buildapp == 'b2g' # bug 967606
+skip-if = (android_version == '18' && debug) # bug 967606
 [test_nested_eventloop.html]
-skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog)
+skip-if = buildapp == 'mulet' || toolkit == 'android' || e10s # b2g(showmodaldialog)
 [test_preference_enable.html]
 [test_recognition_service_error.html]
-skip-if = buildapp == 'b2g' # b2g(timed out)
 [test_success_without_recognition_service.html]
 [test_timeout.html]
 skip-if = os == "win"
--- a/dom/media/webspeech/synth/moz.build
+++ b/dom/media/webspeech/synth/moz.build
@@ -46,16 +46,14 @@ if CONFIG['MOZ_WEBSPEECH']:
     elif CONFIG['MOZ_SYNTH_PICO']:
         DIRS = ['pico']
 
 IPDL_SOURCES += [
     'ipc/PSpeechSynthesis.ipdl',
     'ipc/PSpeechSynthesisRequest.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     'ipc',
 ]
--- a/dom/media/webspeech/synth/nsSpeechTask.cpp
+++ b/dom/media/webspeech/synth/nsSpeechTask.cpp
@@ -138,17 +138,17 @@ nsSpeechTask::~nsSpeechTask()
     mPort = nullptr;
   }
 }
 
 void
 nsSpeechTask::Init(ProcessedMediaStream* aStream)
 {
   if (aStream) {
-    mStream = MediaStreamGraph::GetInstance()->CreateSourceStream(nullptr);
+    mStream = aStream->Graph()->CreateSourceStream(nullptr);
     mPort = aStream->AllocateInputPort(mStream, 0);
     mIndirectAudio = false;
   } else {
     mIndirectAudio = true;
   }
   mInited = true;
 }
 
--- a/dom/media/webspeech/synth/nsSynthVoiceRegistry.cpp
+++ b/dom/media/webspeech/synth/nsSynthVoiceRegistry.cpp
@@ -773,17 +773,19 @@ nsSynthVoiceRegistry::SpeakImpl(VoiceDat
 
   DebugOnly<nsresult> rv = aVoice->mService->GetServiceType(&serviceType);
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get speech service type");
 
   if (serviceType == nsISpeechService::SERVICETYPE_INDIRECT_AUDIO) {
     aTask->Init(nullptr);
   } else {
     if (!mStream) {
-      mStream = MediaStreamGraph::GetInstance()->CreateTrackUnionStream(nullptr);
+      mStream =
+        MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
+                                      AudioChannel::Normal)->CreateTrackUnionStream(nullptr);
     }
     aTask->Init(mStream);
   }
 
   aVoice->mService->Speak(aText, aVoice->mUri, aVolume, aRate, aPitch, aTask);
 }
 
 } // namespace dom
--- a/dom/media/webspeech/synth/pico/moz.build
+++ b/dom/media/webspeech/synth/pico/moz.build
@@ -3,12 +3,11 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'nsPicoService.cpp',
     'PicoModule.cpp'
 ]
-FAIL_ON_WARNINGS = True
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/messagechannel/moz.build
+++ b/dom/messagechannel/moz.build
@@ -32,9 +32,8 @@ LOCAL_INCLUDES += [
     '../base',
     '../events',
     '../workers',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-FAIL_ON_WARNINGS = True
--- a/dom/mobileconnection/moz.build
+++ b/dom/mobileconnection/moz.build
@@ -67,15 +67,13 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
             'gonk/MobileConnectionService.js',
             'gonk/MobileConnectionService.manifest',
         ]
 
 LOCAL_INCLUDES += [
     '/dom/system/gonk',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 XPIDL_MODULE = 'dom_mobileconnection'
--- a/dom/mobilemessage/moz.build
+++ b/dom/mobilemessage/moz.build
@@ -68,17 +68,15 @@ UNIFIED_SOURCES += [
 
 IPDL_SOURCES += [
     'ipc/PMobileMessageCursor.ipdl',
     'ipc/PSms.ipdl',
     'ipc/PSmsRequest.ipdl',
     'ipc/SmsTypes.ipdlh',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/network/moz.build
+++ b/dom/network/moz.build
@@ -74,13 +74,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
     ]
 
 IPDL_SOURCES += [
     'PTCPServerSocket.ipdl',
     'PTCPSocket.ipdl',
     'PUDPSocket.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/nfc/moz.build
+++ b/dom/nfc/moz.build
@@ -43,12 +43,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
     ]
     EXTRA_JS_MODULES += [
         'gonk/nfc_consts.js',
     ]
     XPCSHELL_TESTS_MANIFESTS += [
         'tests/unit/xpcshell.ini'
     ]
 
-FAIL_ON_WARNINGS = True
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/notification/moz.build
+++ b/dom/notification/moz.build
@@ -22,18 +22,16 @@ EXPORTS.mozilla.dom += [
 ]
 
 UNIFIED_SOURCES += [
     'DesktopNotification.cpp',
     'Notification.cpp',
     'NotificationEvent.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/ipc',
     '/dom/workers',
 ]
--- a/dom/offline/moz.build
+++ b/dom/offline/moz.build
@@ -6,15 +6,13 @@
 
 EXPORTS += [
     'nsDOMOfflineResourceList.h',
 ]
 UNIFIED_SOURCES += [
     'nsDOMOfflineResourceList.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/permission/moz.build
+++ b/dom/permission/moz.build
@@ -41,11 +41,9 @@ if CONFIG['MOZ_B2G_BT']:
     MOCHITEST_MANIFESTS += ['tests/mochitest-bt.ini']
 
 if CONFIG['MOZ_WEBSMS_BACKEND']:
     MOCHITEST_MANIFESTS += ['tests/mochitest-websms.ini']
 
 if CONFIG['MOZ_TIME_MANAGER']:
     MOCHITEST_MANIFESTS += ['tests/mochitest-time.ini']
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/plugins/base/android/moz.build
+++ b/dom/plugins/base/android/moz.build
@@ -18,18 +18,16 @@ SOURCES += [
     'ANPNativeWindow.cpp',
     'ANPOpenGL.cpp',
     'ANPSurface.cpp',
     'ANPSystem.cpp',
     'ANPVideo.cpp',
     'ANPWindow.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/plugins/base',
     '/gfx/gl',
     '/widget',
     '/widget/android',
--- a/dom/plugins/base/moz.build
+++ b/dom/plugins/base/moz.build
@@ -81,18 +81,16 @@ else:
         UNIFIED_SOURCES += [
             'nsPluginNativeWindowQt.cpp',
         ]
     else:
         UNIFIED_SOURCES += [
             'nsPluginNativeWindow.cpp',
         ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/plugins/ipc',
     '/layout/generic',
     '/layout/xul',
     '/netwerk/base',
     '/widget',
     '/widget/android',
--- a/dom/plugins/ipc/hangui/moz.build
+++ b/dom/plugins/ipc/hangui/moz.build
@@ -1,16 +1,14 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-FAIL_ON_WARNINGS = True
-
 Program('plugin-hang-ui')
 
 UNIFIED_SOURCES += [
     'MiniShmChild.cpp',
     'PluginHangUIChild.cpp',
 ]
 include('/ipc/chromium/chromium-config.mozbuild')
 
--- a/dom/plugins/ipc/interpose/moz.build
+++ b/dom/plugins/ipc/interpose/moz.build
@@ -9,11 +9,9 @@ SharedLibrary('plugin_child_interpose')
 UNIFIED_SOURCES += [ "%s.mm" % (LIBRARY_NAME) ]
 
 UNIFIED_SOURCES += [
     'plugin_child_quirks.mm',
 ]
 
 OS_LIBS += ['-framework Carbon']
 
-FAIL_ON_WARNINGS = True
-
 DIST_INSTALL = True
--- a/dom/plugins/ipc/moz.build
+++ b/dom/plugins/ipc/moz.build
@@ -114,18 +114,16 @@ IPDL_SOURCES += [
     'PPluginInstance.ipdl',
     'PPluginModule.ipdl',
     'PPluginScriptableObject.ipdl',
     'PPluginStream.ipdl',
     'PPluginSurface.ipdl',
     'PStreamNotify.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../base',
     '/xpcom/base/',
 ]
 
--- a/dom/plugins/test/testplugin/moz.build
+++ b/dom/plugins/test/testplugin/moz.build
@@ -3,12 +3,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/.
 
 DIRS += ['secondplugin', 'javaplugin', 'thirdplugin', 'flashplugin']
 
 SharedLibrary('nptest')
 
-FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
+if CONFIG['_MSC_VER']:
+    ALLOW_COMPILER_WARNINGS = True
 
 relative_path = '.'
 include('testplugin.mozbuild')
--- a/dom/power/moz.build
+++ b/dom/power/moz.build
@@ -22,16 +22,14 @@ EXPORTS.mozilla.dom.power += [
 ]
 
 UNIFIED_SOURCES += [
     'PowerManager.cpp',
     'PowerManagerService.cpp',
     'WakeLock.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/dom/presentation/moz.build
+++ b/dom/presentation/moz.build
@@ -45,13 +45,11 @@ EXTRA_JS_MODULES += [
     'PresentationDeviceInfoManager.jsm',
 ]
 
 IPDL_SOURCES += [
     'ipc/PPresentation.ipdl',
     'ipc/PPresentationRequest.ipdl'
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/presentation/provider/moz.build
+++ b/dom/presentation/provider/moz.build
@@ -9,12 +9,10 @@ EXTRA_COMPONENTS += [
     'TCPPresentationServer.js'
 ]
 
 UNIFIED_SOURCES += [
     'MulticastDNSDeviceProvider.cpp',
     'PresentationDeviceProviderModule.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'xul'
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -15,18 +15,16 @@ EXPORTS.mozilla.dom += [
 
 UNIFIED_SOURCES += [
     'AbortablePromise.cpp',
     'Promise.cpp',
     'PromiseCallback.cpp',
     'PromiseDebugging.cpp'
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
     '../ipc',
     '../workers',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
--- a/dom/push/moz.build
+++ b/dom/push/moz.build
@@ -36,15 +36,13 @@ EXPORTS.mozilla.dom += [
 
 UNIFIED_SOURCES += [
     'PushManager.cpp',
 ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../workers',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/quota/moz.build
+++ b/dom/quota/moz.build
@@ -23,17 +23,15 @@ EXPORTS.mozilla.dom.quota += [
     'Utilities.h',
 ]
 
 UNIFIED_SOURCES += [
     'FileStreams.cpp',
     'QuotaManager.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/caps',
 ]
 
--- a/dom/requestsync/moz.build
+++ b/dom/requestsync/moz.build
@@ -23,10 +23,9 @@ EXTRA_JS_MODULES += [
 ]
 
 SOURCES += [
     'RequestSyncWifiService.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-FAIL_ON_WARNINGS = True
 FINAL_LIBRARY = 'xul'
--- a/dom/secureelement/moz.build
+++ b/dom/secureelement/moz.build
@@ -35,12 +35,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
         'tests/unit/xpcshell.ini'
     ]
     if CONFIG['MOZ_B2G_RIL']:
         EXTRA_COMPONENTS += [
             'gonk/UiccConnector.js',
             'gonk/UiccConnector.manifest',
         ]
 
-FAIL_ON_WARNINGS = True
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/security/moz.build
+++ b/dom/security/moz.build
@@ -28,18 +28,16 @@ UNIFIED_SOURCES += [
     'nsCSPParser.cpp',
     'nsCSPService.cpp',
     'nsCSPUtils.cpp',
     'nsMixedContentBlocker.cpp',
     'SRICheck.cpp',
     'SRIMetadata.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/caps',
     '/netwerk/base',
 ]
 
 if CONFIG['GNU_CC']:
     CFLAGS += ['-Wshadow', '-Wformat-security']
--- a/dom/smil/moz.build
+++ b/dom/smil/moz.build
@@ -57,18 +57,16 @@ UNIFIED_SOURCES += [
     'nsSMILValue.cpp',
     'SMILBoolType.cpp',
     'SMILEnumType.cpp',
     'SMILIntegerType.cpp',
     'SMILStringType.cpp',
     'TimeEvent.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/svg',
     '/layout/base',
     '/layout/style',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/speakermanager/moz.build
+++ b/dom/speakermanager/moz.build
@@ -13,13 +13,11 @@ EXPORTS += [
 ]
 
 UNIFIED_SOURCES += [
     'SpeakerManager.cpp',
     'SpeakerManagerService.cpp',
     'SpeakerManagerServiceChild.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/storage/moz.build
+++ b/dom/storage/moz.build
@@ -17,18 +17,16 @@ UNIFIED_SOURCES += [
     'DOMStorageManager.cpp',
     'DOMStorageObserver.cpp',
 ]
 
 IPDL_SOURCES += [
     'PStorage.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 if CONFIG['ENABLE_TESTS']:
--- a/dom/svg/moz.build
+++ b/dom/svg/moz.build
@@ -244,18 +244,16 @@ UNIFIED_SOURCES += [
     'SVGTransformListSMILType.cpp',
     'SVGTSpanElement.cpp',
     'SVGUseElement.cpp',
     'SVGViewBoxSMILType.cpp',
     'SVGViewElement.cpp',
     'SVGZoomEvent.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom',
     '/dom/base',
     '/dom/html',
     '/dom/smil',
--- a/dom/system/android/moz.build
+++ b/dom/system/android/moz.build
@@ -4,17 +4,15 @@
 # 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/.
 
 SOURCES += [
     'AndroidLocationProvider.cpp',
     'nsHapticFeedback.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/geolocation',
 ]
 
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -108,18 +108,16 @@ if CONFIG['MOZ_B2G_RIL']:
     if not CONFIG['DISABLE_MOZ_RIL_GEOLOC']:
         EXTRA_COMPONENTS += [
             'DataCallInterfaceService.js',
             'DataCallInterfaceService.manifest',
             'RadioInterfaceLayer.js',
             'RadioInterfaceLayer.manifest',
         ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/bluetooth/common',
     '/dom/geolocation',
     '/dom/wifi',
 ]
--- a/dom/system/mac/moz.build
+++ b/dom/system/mac/moz.build
@@ -1,17 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 SOURCES += ['CoreLocationLocationProvider.mm']
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/geolocation',
 ]
 
--- a/dom/system/moz.build
+++ b/dom/system/moz.build
@@ -43,18 +43,16 @@ EXTRA_COMPONENTS += [
     'SystemUpdate.manifest',
     'SystemUpdateManager.js',
 ]
 
 EXTRA_JS_MODULES += [
     'SystemUpdateService.jsm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 # We fire the nsDOMDeviceAcceleration
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/bindings',
     '/js/xpconnect/loader',
--- a/dom/system/qt/moz.build
+++ b/dom/system/qt/moz.build
@@ -16,13 +16,11 @@ if CONFIG['MOZ_ENABLE_QT5GEOPOSITION']:
         '/dom/geolocation',
     ]
 
 if CONFIG['MOZ_ENABLE_QT5FEEDBACK']:
     SOURCES += [
         'QtHapticFeedback.cpp',
     ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/system/windows/moz.build
+++ b/dom/system/windows/moz.build
@@ -8,11 +8,9 @@ SOURCES += [
     'nsHapticFeedback.cpp',
     'WindowsLocationProvider.cpp'
 ]
 
 LOCAL_INCLUDES += [
     '/dom/geolocation'
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/dom/telephony/moz.build
+++ b/dom/telephony/moz.build
@@ -71,12 +71,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
             'gonk/TelephonyService.js',
             'gonk/TelephonyService.manifest',
         ]
     EXTRA_JS_MODULES += [
         'gonk/DialNumberUtils.jsm',
         'gonk/TelephonyUtils.jsm',
     ]
 
-FAIL_ON_WARNINGS = True
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/time/moz.build
+++ b/dom/time/moz.build
@@ -19,13 +19,11 @@ EXPORTS.mozilla.dom.time += [
 
 UNIFIED_SOURCES += [
     'DateCacheCleaner.cpp',
     'TimeChangeObserver.cpp',
     'TimeManager.cpp',
     'TimeService.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/tv/moz.build
+++ b/dom/tv/moz.build
@@ -40,10 +40,8 @@ XPIDL_MODULE = 'dom_tv'
 
 MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/voicemail/moz.build
+++ b/dom/voicemail/moz.build
@@ -39,17 +39,15 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
         'gonk/nsIGonkVoicemailService.idl',
     ]
     if not CONFIG['DISABLE_MOZ_RIL_GEOLOC']:
         EXTRA_COMPONENTS += [
             'gonk/VoicemailService.js',
             'gonk/VoicemailService.manifest',
         ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/vr/moz.build
+++ b/dom/vr/moz.build
@@ -7,16 +7,14 @@
 EXPORTS.mozilla.dom += [
     'VRDevice.h',
     ]
 
 UNIFIED_SOURCES = [
     'VRDevice.cpp',
     ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base'
 ]
--- a/dom/wifi/moz.build
+++ b/dom/wifi/moz.build
@@ -33,10 +33,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
     UNIFIED_SOURCES = [
         'WifiCertService.cpp',
         'WifiHotspotUtils.cpp',
         'WifiProxyService.cpp',
         'WifiUtils.cpp',
     ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -88,18 +88,16 @@ UNIFIED_SOURCES += [
     'XMLHttpRequestUpload.cpp',
 ]
 
 IPDL_SOURCES += [
     'PServiceWorkerManager.ipdl',
     'ServiceWorkerRegistrarTypes.ipdlh',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
     '../system',
     '/dom/base',
     '/xpcom/build',
     '/xpcom/threads',
 ]
 
--- a/dom/workers/test/gtest/moz.build
+++ b/dom/workers/test/gtest/moz.build
@@ -5,9 +5,12 @@
 # file, you can obtain one at http://mozilla.org/MPL/2.0/.
 
 UNIFIED_SOURCES = [
     'TestReadWrite.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
+# XXX: We should fix these warnings.
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'xul-gtest'
--- a/dom/workers/test/serviceworkers/fetch/fetch_tests.js
+++ b/dom/workers/test/serviceworkers/fetch/fetch_tests.js
@@ -144,22 +144,33 @@ fetchXHR('hello-after-extracting.gz', fu
 });
 
 fetchXHR('http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*', function(xhr) {
   my_ok(xhr.status == 200, "cross origin load with correct headers should be successful");
   my_ok(xhr.getResponseHeader("access-control-allow-origin") == null, "cors headers should be filtered out");
   finish();
 });
 
-// Test that CORS preflight requests cannot be intercepted
+// Test that CORS preflight requests cannot be intercepted. Performs a
+// cross-origin XHR that the SW chooses not to intercept. This requires a
+// preflight request, which the SW must not be allowed to intercept.
 fetchXHR('http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*', null, function(xhr) {
   my_ok(xhr.status == 0, "cross origin load with incorrect headers should be a failure");
   finish();
 }, [["X-Unsafe", "unsafe"]]);
 
+// Test that CORS preflight requests cannot be intercepted. Performs a
+// cross-origin XHR that the SW chooses to intercept and respond with a
+// cross-origin fetch. This requires a preflight request, which the SW must not
+// be allowed to intercept.
+fetchXHR('http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*', null, function(xhr) {
+  my_ok(xhr.status == 0, "cross origin load with incorrect headers should be a failure");
+  finish();
+}, [["X-Unsafe", "unsafe"]]);
+
 // Test that when the page fetches a url the controlling SW forces a redirect to
 // another location. This other location fetch should also be intercepted by
 // the SW.
 fetchXHR('something.txt', function(xhr) {
   my_ok(xhr.status == 200, "load should be successful");
   my_ok(xhr.responseText == "something else response body", "load should have something else");
   finish();
 });
--- a/dom/workers/test/serviceworkers/fetch_event_worker.js
+++ b/dom/workers/test/serviceworkers/fetch_event_worker.js
@@ -9,16 +9,18 @@ onfetch = function(ev) {
 
   else if (ev.request.url.includes('file_CrossSiteXHR_server.sjs')) {
     // N.B. this response would break the rules of CORS if it were allowed, but
     //      this test relies upon the preflight request not being intercepted and
     //      thus this response should not be used.
     if (ev.request.method == 'OPTIONS') {
       ev.respondWith(new Response('', {headers: {'Access-Control-Allow-Origin': '*',
                                                  'Access-Control-Allow-Headers': 'X-Unsafe'}}))
+    } else if (ev.request.url.includes('example.org')) {
+      ev.respondWith(fetch(ev.request));
     }
   }
 
   else if (ev.request.url.includes("synthesized-404.txt")) {
     ev.respondWith(Promise.resolve(
       new Response("synthesized response body", { status: 404 })
     ));
   }
--- a/dom/xbl/moz.build
+++ b/dom/xbl/moz.build
@@ -31,18 +31,16 @@ UNIFIED_SOURCES += [
     'nsXBLPrototypeResources.cpp',
     'nsXBLResourceLoader.cpp',
     'nsXBLSerialize.cpp',
     'nsXBLService.cpp',
     'nsXBLWindowKeyHandler.cpp',
     'XBLChildrenElement.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
     '/dom/xml',
     '/dom/xul',
     '/layout/style',
 ]
 
--- a/dom/xml/moz.build
+++ b/dom/xml/moz.build
@@ -29,18 +29,16 @@ UNIFIED_SOURCES += [
     'ProcessingInstruction.cpp',
     'XMLDocument.cpp',
     'XMLStylesheetProcessingInstruction.cpp',
 ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/base',
     '/dom/html',
     '/dom/xul',
     '/layout/style',
--- a/dom/xslt/base/moz.build
+++ b/dom/xslt/base/moz.build
@@ -8,18 +8,16 @@ UNIFIED_SOURCES += [
     'txDouble.cpp',
     'txExpandedName.cpp',
     'txExpandedNameMap.cpp',
     'txList.cpp',
     'txNamespaceMap.cpp',
     'txURIUtils.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '..',
     '../xml',
     '../xpath',
     '../xslt',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/xslt/xml/moz.build
+++ b/dom/xslt/xml/moz.build
@@ -7,18 +7,16 @@
 UNIFIED_SOURCES += [
     'txXMLParser.cpp',
     'txXMLUtils.cpp',
 ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
     '../xpath',
     '../xslt',
     '/dom/base',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/xslt/xpath/moz.build
+++ b/dom/xslt/xpath/moz.build
@@ -45,17 +45,15 @@ UNIFIED_SOURCES += [
     'txVariableRefExpr.cpp',
     'txXPathOptimizer.cpp',
     'txXPCOMExtensionFunction.cpp',
     'XPathEvaluator.cpp',
     'XPathExpression.cpp',
     'XPathResult.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '../base',
     '../xml',
     '../xslt',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/xslt/xslt/moz.build
+++ b/dom/xslt/xslt/moz.build
@@ -41,18 +41,16 @@ UNIFIED_SOURCES += [
     'txXSLTProcessor.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'txEXSLTRegExFunctions.js',
     'txEXSLTRegExFunctions.manifest',
 ]
 
-FAIL_ON_WARNINGS = True
-
 # For nsAutoJSString
 LOCAL_INCLUDES += ["/dom/base"]
 
 LOCAL_INCLUDES += [
     '../base',
     '../xml',
     '../xpath',
     '/dom/base',
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -35,18 +35,16 @@ XPIDL_SOURCES += [
 ]
 
 XPIDL_MODULE = 'xul'
 
 UNIFIED_SOURCES += [
     'nsXULControllers.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/html',
     '/dom/xbl',
     '/dom/xml',
     '/dom/xul/templates',
     '/layout/base',
--- a/dom/xul/templates/moz.build
+++ b/dom/xul/templates/moz.build
@@ -48,10 +48,8 @@ UNIFIED_SOURCES += [
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/xul',
     '/layout/xul/tree/',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/editor/composer/moz.build
+++ b/editor/composer/moz.build
@@ -20,18 +20,16 @@ UNIFIED_SOURCES += [
     'nsComposerController.cpp',
     'nsComposerDocumentCommands.cpp',
     'nsComposerRegistration.cpp',
     'nsComposeTxtSrvFilter.cpp',
     'nsEditingSession.cpp',
     'nsEditorSpellCheck.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 RESOURCE_FILES += [
     'res/EditorOverride.css',
     'res/grabber.gif',
     'res/table-add-column-after-active.gif',
     'res/table-add-column-after-hover.gif',
     'res/table-add-column-after.gif',
     'res/table-add-column-before-active.gif',
--- a/editor/libeditor/moz.build
+++ b/editor/libeditor/moz.build
@@ -53,18 +53,16 @@ UNIFIED_SOURCES += [
     'nsWSRunObject.cpp',
     'PlaceholderTxn.cpp',
     'SetDocTitleTxn.cpp',
     'SplitNodeTxn.cpp',
     'TextEditorTest.cpp',
     'TypeInState.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/editor/txmgr',
     '/extensions/spellcheck/src',
     '/layout/generic',
     '/layout/style',
     '/layout/tables',
     '/layout/xul',
--- a/editor/txmgr/moz.build
+++ b/editor/txmgr/moz.build
@@ -22,11 +22,9 @@ EXPORTS += [
 UNIFIED_SOURCES += [
     'nsTransactionItem.cpp',
     'nsTransactionList.cpp',
     'nsTransactionManager.cpp',
     'nsTransactionManagerFactory.cpp',
     'nsTransactionStack.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/editor/txmgr/tests/moz.build
+++ b/editor/txmgr/tests/moz.build
@@ -2,10 +2,8 @@
 # vim: set filetype=python:
 # 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/.
 
 GeckoCppUnitTests([
     'TestTXMgr',
 ])
-
-FAIL_ON_WARNINGS = True
--- a/editor/txtsvc/moz.build
+++ b/editor/txtsvc/moz.build
@@ -18,11 +18,9 @@ EXPORTS += [
     'nsTextServicesCID.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsFilteredContentIterator.cpp',
     'nsTextServicesDocument.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/browser/build/moz.build
+++ b/embedding/browser/build/moz.build
@@ -3,15 +3,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/.
 
 SOURCES += [
     'nsWebBrowserModule.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '..',
 ]
 
--- a/embedding/browser/moz.build
+++ b/embedding/browser/moz.build
@@ -41,15 +41,13 @@ UNIFIED_SOURCES += [
     'nsCommandHandler.cpp',
     'nsContextMenuInfo.cpp',
     'nsDocShellTreeOwner.cpp',
     'nsEmbedStream.cpp',
     'nsWebBrowser.cpp',
     'nsWebBrowserContentPolicy.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/svg',
 ]
--- a/embedding/components/appstartup/moz.build
+++ b/embedding/components/appstartup/moz.build
@@ -7,11 +7,9 @@
 EXPORTS += [
     'nsIAppStartupNotifier.h',
 ]
 
 SOURCES += [
     'nsAppStartupNotifier.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/components/build/moz.build
+++ b/embedding/components/build/moz.build
@@ -3,18 +3,16 @@
 # 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/.
 
 SOURCES += [
     'nsEmbeddingModule.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../appstartup',
     '../commandhandler',
     '../find',
     '../printingui/ipc',
     '../webbrowserpersist',
     '../windowwatcher',
--- a/embedding/components/commandhandler/moz.build
+++ b/embedding/components/commandhandler/moz.build
@@ -18,11 +18,9 @@ XPIDL_MODULE = 'commandhandler'
 UNIFIED_SOURCES += [
     'nsBaseCommandController.cpp',
     'nsCommandGroup.cpp',
     'nsCommandManager.cpp',
     'nsCommandParams.cpp',
     'nsControllerCommandTable.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/components/find/moz.build
+++ b/embedding/components/find/moz.build
@@ -11,11 +11,9 @@ XPIDL_SOURCES += [
 
 XPIDL_MODULE = 'find'
 
 UNIFIED_SOURCES += [
     'nsFind.cpp',
     'nsWebBrowserFind.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/components/printingui/ipc/moz.build
+++ b/embedding/components/printingui/ipc/moz.build
@@ -27,11 +27,9 @@ IPDL_SOURCES += [
     'PPrinting.ipdl',
     'PPrintingTypes.ipdlh',
     'PPrintProgressDialog.ipdl',
     'PPrintSettingsDialog.ipdl',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/components/printingui/mac/moz.build
+++ b/embedding/components/printingui/mac/moz.build
@@ -8,11 +8,9 @@ UNIFIED_SOURCES += [
     'nsPrintProgress.cpp',
     'nsPrintProgressParams.cpp',
 ]
 
 SOURCES += [
     'nsPrintingPromptServiceX.mm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/components/printingui/unixshared/moz.build
+++ b/embedding/components/printingui/unixshared/moz.build
@@ -5,11 +5,9 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 UNIFIED_SOURCES += [
     'nsPrintingPromptService.cpp',
     'nsPrintProgress.cpp',
     'nsPrintProgressParams.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/components/printingui/win/moz.build
+++ b/embedding/components/printingui/win/moz.build
@@ -10,11 +10,9 @@ UNIFIED_SOURCES += [
     'nsPrintProgress.cpp',
     'nsPrintProgressParams.cpp',
 ]
 
 EXPORTS += [
     'nsPrintDialogUtil.h',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/embedding/components/webbrowserpersist/moz.build
+++ b/embedding/components/webbrowserpersist/moz.build
@@ -32,17 +32,15 @@ SOURCES += [
 ]
 
 EXPORTS.mozilla += [
     'WebBrowserPersistDocumentChild.h',
     'WebBrowserPersistDocumentParent.h',
     'WebBrowserPersistLocalDocument.h',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
 ]
--- a/embedding/components/windowwatcher/moz.build
+++ b/embedding/components/windowwatcher/moz.build
@@ -29,15 +29,13 @@ EXPORTS += [
     'nsWindowWatcher.h',
 ]
 
 if CONFIG['MOZ_XUL']:
     UNIFIED_SOURCES += [
         'nsDialogParamBlock.cpp',
     ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 # For nsJSUtils
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
--- a/extensions/auth/moz.build
+++ b/extensions/auth/moz.build
@@ -20,10 +20,8 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     ]
     DEFINES['USE_SSPI'] = True
 else:
     UNIFIED_SOURCES += [
         'nsAuthSambaNTLM.cpp',
     ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/extensions/cookie/moz.build
+++ b/extensions/cookie/moz.build
@@ -20,10 +20,8 @@ UNIFIED_SOURCES += [
     'nsPermission.cpp',
     'nsPermissionManager.cpp',
     'nsPopupWindowManager.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/extensions/gio/moz.build
+++ b/extensions/gio/moz.build
@@ -3,13 +3,11 @@
 # 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/.
 
 SOURCES += [
     'nsGIOProtocolHandler.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 CXXFLAGS += CONFIG['MOZ_GIO_CFLAGS']
--- a/extensions/permissions/moz.build
+++ b/extensions/permissions/moz.build
@@ -5,10 +5,8 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 UNIFIED_SOURCES += [
     'nsContentBlocker.cpp',
     'nsModuleFactory.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/extensions/pref/autoconfig/src/moz.build
+++ b/extensions/pref/autoconfig/src/moz.build
@@ -7,10 +7,8 @@
 UNIFIED_SOURCES += [
     'nsAutoConfig.cpp',
     'nsConfigFactory.cpp',
     'nsJSConfigTriggers.cpp',
     'nsReadConfig.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/extensions/spellcheck/hunspell/src/moz.build
+++ b/extensions/spellcheck/hunspell/src/moz.build
@@ -34,19 +34,20 @@ else:
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/editor/libeditor',
     '/extensions/spellcheck/src',
 ]
 
-# Suppress warnings in third-party code.
-if CONFIG['CLANG_CXX']:
-    CXXFLAGS += ['-Wno-unused-private-field']
+# XXX: This directory is a mix of Mozilla code and third-party code. We should
+# put the Mozilla code in a separate directory and disallow compiler warnings
+# there (bug 1200065). Until then, allow warnings for all of the code.
+ALLOW_COMPILER_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 IPDL_SOURCES = [
     'PRemoteSpellcheckEngine.ipdl',
 ]
 
 EXPORTS.mozilla += [
--- a/extensions/spellcheck/src/moz.build
+++ b/extensions/spellcheck/src/moz.build
@@ -21,10 +21,8 @@ FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../hunspell/src',
     '/dom/base',
     '/editor/libeditor',
 ]
 EXPORTS.mozilla += [
      'mozSpellChecker.h',
 ]
-
-FAIL_ON_WARNINGS = True
--- a/extensions/universalchardet/src/base/moz.build
+++ b/extensions/universalchardet/src/base/moz.build
@@ -15,10 +15,8 @@ UNIFIED_SOURCES += [
     'nsMBCSGroupProber.cpp',
     'nsMBCSSM.cpp',
     'nsSJISProber.cpp',
     'nsUniversalDetector.cpp',
     'nsUTF8Prober.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/extensions/universalchardet/src/xpcom/moz.build
+++ b/extensions/universalchardet/src/xpcom/moz.build
@@ -9,10 +9,8 @@ UNIFIED_SOURCES += [
     'nsUniversalCharDetModule.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../base',
 ]
-
-FAIL_ON_WARNINGS = True
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -151,18 +151,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'MacIOSurface.cpp',
         'QuartzSupport.mm',
     ]
 
 if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
     SOURCES += ['BlurNEON.cpp']
     SOURCES['BlurNEON.cpp'].flags += ['-mfpu=neon']
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 for var in ('USE_CAIRO', 'MOZ2D_HAS_MOZ_CAIRO'):
     DEFINES[var] = True
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -129,9 +129,11 @@ LOCAL_INCLUDES += [ 'include', 'src' ]
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 # This tells ANGLE to build the translator with declspec(dllexport) on Windows
 # which we need to get these symbols exported from gkmedias
 DEFINES['COMPONENT_BUILD'] = True
 DEFINES['ANGLE_TRANSLATOR_IMPLEMENTATION'] = True
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
--- a/gfx/angle/src/libGLESv2/moz.build
+++ b/gfx/angle/src/libGLESv2/moz.build
@@ -206,17 +206,17 @@ if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
 DEFINES['ANGLE_COMPILE_OPTIMIZATION_LEVEL'] = 'D3DCOMPILE_OPTIMIZATION_LEVEL1'
 DEFINES['ANGLE_NO_EXCEPTIONS'] = True
 
 # We need these defined to nothing so that we don't get bogus dllimport declspecs
 DEFINES['GL_APICALL'] = ""
 DEFINES['GL_GLEXT_PROTOTYPES'] = ""
 DEFINES['EGLAPI'] = ""
 
-
+ALLOW_COMPILER_WARNINGS = True
 
 LOCAL_INCLUDES += [ '../../include', '../../src' ]
 
 if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
   OS_LIBS += [ 'd3d9', 'dxguid' ]
 else:
   EXTRA_DSO_LDOPTS += [
     '\'%s/lib/%s/d3d9.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
--- a/gfx/cairo/cairo/src/moz.build
+++ b/gfx/cairo/cairo/src/moz.build
@@ -180,16 +180,18 @@ UNIFIED_SOURCES += [
     'cairo-traps.c',
     'cairo-unicode.c',
     'cairo-user-font.c',
     'cairo-version.c',
     'cairo-wideint.c',
     'cairo.c',
 ]
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 
 for var in ('CAIRO_HAS_PTHREAD', '_GNU_SOURCE'):
     DEFINES[var] = True
 
--- a/gfx/cairo/libpixman/src/moz.build
+++ b/gfx/cairo/libpixman/src/moz.build
@@ -53,16 +53,18 @@ SOURCES += [
     'pixman-region32.c',
     'pixman-solid-fill.c',
     'pixman-trap.c',
     'pixman-utils.c',
     'pixman-x86.c',
     'pixman.c',
 ]
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     '../../cairo/src',
 ]
 
 if CONFIG['MOZ_USE_PTHREADS']:
     DEFINES['HAVE_PTHREAD_SETSPECIFIC'] = True
 
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -139,18 +139,16 @@ UNIFIED_SOURCES += [
     'SharedSurface.cpp',
     'SharedSurfaceEGL.cpp',
     'SharedSurfaceGL.cpp',
     'SurfaceTypes.cpp',
     'TextureGarbageBin.cpp',
     'TextureImageEGL.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']:
     DEFINES['MOZ_D3DCOMPILER_VISTA_DLL'] = CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']
 if CONFIG['MOZ_D3DCOMPILER_XP_DLL']:
     DEFINES['MOZ_D3DCOMPILER_XP_DLL'] = CONFIG['MOZ_D3DCOMPILER_XP_DLL']
--- a/gfx/graphite2/src/moz.build
+++ b/gfx/graphite2/src/moz.build
@@ -62,16 +62,18 @@ UNIFIED_SOURCES += [
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
     DEFINES['GRAPHITE2_EXPORTING'] = True
 else:
     # tell graphite2 not to export symbols, we'll be linking it directly with
     # thebes
     DEFINES['GRAPHITE2_STATIC'] = True
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 
 # disable features we don't need in the graphite2 code, to reduce code size
 for var in ('GRAPHITE2_NFILEFACE', 'GRAPHITE2_NTRACING', 'GRAPHITE2_NSEGCACHE'):
     DEFINES[var] = True
--- a/gfx/harfbuzz/src/moz.build
+++ b/gfx/harfbuzz/src/moz.build
@@ -54,15 +54,17 @@ UNIFIED_SOURCES += [
     'hb-ot-tag.cc',
     'hb-set.cc',
     'hb-shape.cc',
     'hb-shaper.cc',
     'hb-unicode.cc',
     'hb-warning.cc',
 ]
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 DEFINES['HAVE_OT'] = 1
 DEFINES['HB_NO_MT'] = True
 DEFINES['HB_NO_UNICODE_FUNCS'] = True
--- a/gfx/ipc/moz.build
+++ b/gfx/ipc/moz.build
@@ -31,10 +31,8 @@ IPDL_SOURCES = [
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
-
-FAIL_ON_WARNINGS = True
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -376,18 +376,16 @@ IPDL_SOURCES = [
     'ipc/PImageBridge.ipdl',
     'ipc/PImageContainer.ipdl',
     'ipc/PLayer.ipdl',
     'ipc/PLayerTransaction.ipdl',
     'ipc/PSharedBufferManager.ipdl',
     'ipc/PTexture.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/docshell/base',  # for nsDocShell.h
     '/layout/base',    # for TouchManager.h
     '/layout/generic', # for nsTextFrame.h
 ]
 
--- a/gfx/ots/src/moz.build
+++ b/gfx/ots/src/moz.build
@@ -45,16 +45,18 @@ UNIFIED_SOURCES += [
     'vhea.cc',
     'vmtx.cc',
     'woff2.cc',
 ]
 
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     DEFINES['OTS_DLL'] = True
     DEFINES['OTS_DLL_EXPORTS'] = True
--- a/gfx/qcms/moz.build
+++ b/gfx/qcms/moz.build
@@ -12,16 +12,19 @@ EXPORTS += [
 SOURCES += [
     'chain.c',
     'iccread.c',
     'matrix.c',
     'transform.c',
     'transform_util.c',
 ]
 
+# XXX: We should fix these warnings.
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['GNU_CC']:
     CFLAGS += ['-Wno-missing-field-initializers']
 
 use_sse1 = False
 use_sse2 = False
 use_altivec = False
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -44,16 +44,18 @@ if CONFIG['INTEL_ARCHITECTURE'] and CONF
         SOURCES += [
             'skia/src/opts/SkBlitRow_opts_SSE4_x64_asm.S',
         ]
     else:
         SOURCES += [
             'skia/src/opts/SkBlitRow_opts_SSE4_asm.S',
         ]
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'skia/include/config',
     'skia/include/core',
     'skia/include/effects',
     'skia/include/gpu',
     'skia/include/images',
     'skia/include/pathops',
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -578,16 +578,18 @@ if CONFIG['INTEL_ARCHITECTURE'] and CONF
         SOURCES += [
             'skia/src/opts/SkBlitRow_opts_SSE4_x64_asm.S',
         ]
     else:
         SOURCES += [
             'skia/src/opts/SkBlitRow_opts_SSE4_asm.S',
         ]
 
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'skia/include/config',
     'skia/include/core',
     'skia/include/effects',
     'skia/include/gpu',
     'skia/include/images',
     'skia/include/pathops',
--- a/gfx/src/moz.build
+++ b/gfx/src/moz.build
@@ -70,18 +70,16 @@ UNIFIED_SOURCES += [
     'nsTransform2D.cpp',
 ]
 
 # nsDeviceContext.cpp cannot be built in unified mode because it pulls in OS X system headers.
 SOURCES += [
     'nsDeviceContext.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/dom/ipc',  # for ContentChild.h
 ]
 
 FINAL_LIBRARY = 'xul'
 
--- a/gfx/tests/gtest/moz.build
+++ b/gfx/tests/gtest/moz.build
@@ -45,10 +45,8 @@ LOCAL_INCLUDES += [
     '/gfx/2d/unittest',
     '/gfx/layers',
     '/gfx/qcms',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
-
-FAIL_ON_WARNINGS = True
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -255,17 +255,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
 # available if we're building with the Intl API enabled:
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
     CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
     USE_LIBS += [
         'icu',
     ]
 
-FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
+if CONFIG['_MSC_VER']:
+    ALLOW_COMPILER_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_FILES = [
     'DeprecatedPremultiplyTables.h',
 ]
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -32,14 +32,15 @@ SOURCES += [
 #CXXFLAGS += ["-Ic:/proj/ovr/OculusSDK-0.6.0-beta/LibOVR/Include"]
 #CFLAGS += ["-Ic:/proj/ovr/OculusSDK-0.6.0-beta/LibOVR/Include"]
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CFLAGS += CONFIG['TK_CFLAGS']
 
-FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
+if CONFIG['_MSC_VER']:
+    ALLOW_COMPILER_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
--- a/gfx/ycbcr/moz.build
+++ b/gfx/ycbcr/moz.build
@@ -59,10 +59,8 @@ if CONFIG['CPU_ARCH'] == 'arm' and CONFI
     SOURCES += [
         'yuv_row_arm.s',
     ]
     SOURCES += [
         'yuv_convert_arm.cpp',
     ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -149,18 +149,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'cocoa/CocoaSensor.mm',
         'cocoa/smslib.mm',
     ]
 
 IPDL_SOURCES = [
     'sandbox/PHal.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_GAMEPAD']:
     LOCAL_INCLUDES += [
         '/dom/base',
     ]
--- a/image/build/moz.build
+++ b/image/build/moz.build
@@ -7,18 +7,16 @@
 EXPORTS += [
     'nsImageModule.h',
 ]
 
 SOURCES += [
     'nsImageModule.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/image',
     '/image/encoders/bmp',
     '/image/encoders/ico',
     '/image/encoders/jpeg',
     '/image/encoders/png',
 ]
--- a/image/decoders/icon/android/moz.build
+++ b/image/decoders/icon/android/moz.build
@@ -3,13 +3,11 @@
 # 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/.
 
 SOURCES += [
     'nsIconChannel.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/image/decoders/icon/gtk/moz.build
+++ b/image/decoders/icon/gtk/moz.build
@@ -3,16 +3,14 @@
 # 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/.
 
 SOURCES += [
     'nsIconChannel.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_ENABLE_GNOMEUI']:
     CXXFLAGS += CONFIG['MOZ_GNOMEUI_CFLAGS']
 else:
     CXXFLAGS += CONFIG['TK_CFLAGS']
--- a/image/decoders/icon/mac/moz.build
+++ b/image/decoders/icon/mac/moz.build
@@ -3,11 +3,9 @@
 # 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/.
 
 SOURCES += [
     'nsIconChannelCocoa.mm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/image/decoders/icon/moz.build
+++ b/image/decoders/icon/moz.build
@@ -5,18 +5,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 UNIFIED_SOURCES += [
     'nsIconModule.cpp',
     'nsIconProtocolHandler.cpp',
     'nsIconURI.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 platform = None
 
 if CONFIG['MOZ_WIDGET_GTK']:
     platform = 'gtk'
--- a/image/decoders/icon/win/moz.build
+++ b/image/decoders/icon/win/moz.build
@@ -3,11 +3,9 @@
 # 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/.
 
 SOURCES += [
     'nsIconChannel.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/image/decoders/moz.build
+++ b/image/decoders/moz.build
@@ -27,16 +27,14 @@ UNIFIED_SOURCES += [
     'nsBMPDecoder.cpp',
     'nsGIFDecoder2.cpp',
     'nsICODecoder.cpp',
     'nsIconDecoder.cpp',
     'nsJPEGDecoder.cpp',
     'nsPNGDecoder.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 # Decoders need RasterImage.h
 LOCAL_INCLUDES += [
     '/image',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/image/encoders/bmp/moz.build
+++ b/image/encoders/bmp/moz.build
@@ -3,15 +3,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/.
 
 SOURCES += [
     'nsBMPEncoder.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/image',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/image/encoders/ico/moz.build
+++ b/image/encoders/ico/moz.build
@@ -3,18 +3,16 @@
 # 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/.
 
 SOURCES += [
     'nsICOEncoder.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 # Decoders need RasterImage.h
 LOCAL_INCLUDES += [
     '/image',
     '/image/encoders/bmp',
     '/image/encoders/png',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/image/encoders/jpeg/moz.build
+++ b/image/encoders/jpeg/moz.build
@@ -3,11 +3,9 @@
 # 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/.
 
 SOURCES += [
     'nsJPEGEncoder.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
--- a/image/encoders/png/moz.build
+++ b/image/encoders/png/moz.build
@@ -3,15 +3,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/.
 
 SOURCES += [
     'nsPNGEncoder.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 LOCAL_INCLUDES += [
     '/image',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/image/moz.build
+++ b/image/moz.build
@@ -80,18 +80,16 @@ if CONFIG['MOZ_ENABLE_SKIA']:
 SOURCES += [
     'imgLoader.cpp',
     'imgRequest.cpp',
     'imgRequestProxy.cpp',
     'ProgressTracker.cpp',
     'RasterImage.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     # Because SVGDocumentWrapper.cpp includes "mozilla/dom/SVGSVGElement.h"
     '/dom/base',
     '/dom/svg',
--- a/image/test/gtest/moz.build
+++ b/image/test/gtest/moz.build
@@ -1,18 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 Library('imagetest')
 
-FAIL_ON_WARNINGS = True
-
 UNIFIED_SOURCES = [
     'Common.cpp',
     'TestCopyOnWrite.cpp',
     'TestDecoders.cpp',
     'TestDecodeToSurface.cpp',
     'TestMetadata.cpp',
 ]
 
--- a/intl/chardet/moz.build
+++ b/intl/chardet/moz.build
@@ -12,10 +12,8 @@ EXPORTS += [
 ]
 
 UNIFIED_SOURCES += [
     'nsChardetModule.cpp',
     'nsCyrillicDetector.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/intl/hyphenation/moz.build
+++ b/intl/hyphenation/moz.build
@@ -24,10 +24,10 @@ FINAL_LIBRARY = 'xul'
 
 # Suppress warnings in third-party code.
 if CONFIG['GNU_CC']:
     CFLAGS += [
         '-Wno-sign-compare',
         '-Wno-type-limits',
     ]
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
--- a/intl/locale/mac/moz.build
+++ b/intl/locale/mac/moz.build
@@ -10,10 +10,8 @@ UNIFIED_SOURCES += [
     'nsMacCharset.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
 LOCAL_INCLUDES += [
     '..',
 ]
-
-FAIL_ON_WARNINGS = True
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -63,10 +63,8 @@ GENERATED_FILES += [
     'langGroups.properties.h',
 ]
 langgroups = GENERATED_FILES['langGroups.properties.h']
 langgroups.script = 'props2arrays.py'
 langgroups.inputs = ['langGroups.properties']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
     CXXFLAGS += CONFIG['MOZ_QT_CFLAGS']
-
-FAIL_ON_WARNINGS = True
--- a/intl/lwbrk/moz.build
+++ b/intl/lwbrk/moz.build
@@ -43,10 +43,8 @@ else:
     SOURCES += [
         'rulebrk.c',
     ]
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_WIDGET_GTK']:
     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
-
-FAIL_ON_WARNINGS = True
--- a/intl/strres/moz.build
+++ b/intl/strres/moz.build
@@ -14,10 +14,8 @@ XPIDL_SOURCES += [
 XPIDL_MODULE = 'intl'
 
 UNIFIED_SOURCES += [
     'nsStringBundle.cpp',
     'nsStringBundleTextOverride.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/intl/unicharutil/moz.build
+++ b/intl/unicharutil/moz.build
@@ -26,10 +26,8 @@ UNIFIED_SOURCES += [
     'nsCaseConversionImp2.cpp',
     'nsCategoryImp.cpp',
     'nsEntityConverter.cpp',
     'nsSaveAsCharset.cpp',
     'nsUnicodeNormalizer.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/intl/unicharutil/tests/moz.build
+++ b/intl/unicharutil/tests/moz.build
@@ -3,9 +3,12 @@
 # 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/.
 
 SOURCES += [
     'NormalizationTest.cpp',
 ]
 
+# XXX: We should fix these warnings.
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'xul-gtest'
--- a/intl/unicharutil/util/internal/moz.build
+++ b/intl/unicharutil/util/internal/moz.build
@@ -16,11 +16,9 @@ FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '..',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
 
-FAIL_ON_WARNINGS = True
-
 DIST_INSTALL = True
--- a/intl/unicharutil/util/moz.build
+++ b/intl/unicharutil/util/moz.build
@@ -37,12 +37,12 @@ if CONFIG['_MSC_VER']:
     DEFINES['_USE_ANSI_CPP'] = True
     # Don't include directives about which CRT to use
     CFLAGS += ['-Zl']
     CXXFLAGS += ['-Zl']
 
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
 
 DIST_INSTALL = True
--- a/ipc/app/moz.build
+++ b/ipc/app/moz.build
@@ -96,16 +96,16 @@ LDFLAGS += [CONFIG['MOZ_ALLOW_HEAP_EXECU
 # The default heap size is 1MB on Win32.
 # The heap will grow if need be.
 #
 # Set it to 256k.  See bug 127069.
 if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
     LDFLAGS += ['/HEAP:0x40000']
 
 # Windows builds have dll linkage warnings due to msvcrt static linkage
-if CONFIG['OS_ARCH'] != 'WINNT':
-    FAIL_ON_WARNINGS = True
+if CONFIG['OS_ARCH'] == 'WINNT':
+    ALLOW_COMPILER_WARNINGS = True
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     OS_LIBS += [
         'binder',
         'utils',
     ]
--- a/ipc/app/pie/moz.build
+++ b/ipc/app/pie/moz.build
@@ -23,10 +23,8 @@ if CONFIG['MOZ_SANDBOX']:
 
     # gcc lto likes to put the top level asm in syscall.cc in a different partition
     # from the function using it which breaks the build.  Work around that by
     # forcing there to be only one partition.
     if '-flto' in CONFIG['OS_CXXFLAGS'] and not CONFIG['CLANG_CXX']:
 	LDFLAGS += ['--param lto-partitions=1']
 
 LDFLAGS += ['-pie']
-
-FAIL_ON_WARNINGS = True
--- a/ipc/chromium/moz.build
+++ b/ipc/chromium/moz.build
@@ -249,9 +249,12 @@ if os_bsd:
 ost = CONFIG['OS_TEST']
 if '86' not in ost and 'arm' not in ost and 'mips' not in ost:
     SOURCES += [
         'src/base/atomicops_internals_mutex.cc',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
+# XXX: We should fix these warnings.
+ALLOW_COMPILER_WARNINGS = True
+
 FINAL_LIBRARY = 'xul'
--- a/ipc/dbus/moz.build
+++ b/ipc/dbus/moz.build
@@ -13,15 +13,13 @@ SOURCES += [
     'DBusUtils.cpp',
     'RawDBusConnection.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
-FAIL_ON_WARNINGS = True
-
 if CONFIG['MOZ_ENABLE_DBUS']:
     CFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
     CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
     CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -3,16 +3,18 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BackgroundChildImpl.h"
 
 #include "ActorsChild.h" // IndexedDB
 #include "BroadcastChannelChild.h"
 #include "ServiceWorkerManagerChild.h"
 #include "FileDescriptorSetChild.h"
+#include "CamerasChild.h"
+#include "mozilla/media/MediaChild.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/PBlobChild.h"
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/MessagePortChild.h"
 #include "mozilla/dom/NuwaChild.h"
@@ -260,16 +262,33 @@ BackgroundChildImpl::DeallocPBroadcastCh
                                                  PBroadcastChannelChild* aActor)
 {
   nsRefPtr<dom::BroadcastChannelChild> child =
     dont_AddRef(static_cast<dom::BroadcastChannelChild*>(aActor));
   MOZ_ASSERT(child);
   return true;
 }
 
+camera::PCamerasChild*
+BackgroundChildImpl::AllocPCamerasChild()
+{
+  nsRefPtr<camera::CamerasChild> agent =
+    new camera::CamerasChild();
+  return agent.forget().take();
+}
+
+bool
+BackgroundChildImpl::DeallocPCamerasChild(camera::PCamerasChild *aActor)
+{
+  nsRefPtr<camera::CamerasChild> child =
+      dont_AddRef(static_cast<camera::CamerasChild*>(aActor));
+  MOZ_ASSERT(aActor);
+  return true;
+}
+
 // -----------------------------------------------------------------------------
 // ServiceWorkerManager
 // -----------------------------------------------------------------------------
 
 dom::PServiceWorkerManagerChild*
 BackgroundChildImpl::AllocPServiceWorkerManagerChild()
 {
   nsRefPtr<dom::workers::ServiceWorkerManagerChild> agent =
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -66,16 +66,22 @@ protected:
 
   virtual PFileDescriptorSetChild*
   AllocPFileDescriptorSetChild(const FileDescriptor& aFileDescriptor)
                                override;
 
   virtual bool
   DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor) override;
 
+  virtual PCamerasChild*
+  AllocPCamerasChild() override;
+
+  virtual bool
+  DeallocPCamerasChild(PCamerasChild* aActor) override;
+
   virtual PVsyncChild*
   AllocPVsyncChild() override;
 
   virtual bool
   DeallocPVsyncChild(PVsyncChild* aActor) override;
 
   virtual PUDPSocketChild*
   AllocPUDPSocketChild(const OptionalPrincipalInfo& aPrincipalInfo,
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -1,16 +1,18 @@
 /* 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 "BackgroundParentImpl.h"
 
 #include "BroadcastChannelParent.h"
 #include "FileDescriptorSetParent.h"
+#include "CamerasParent.h"
+#include "mozilla/media/MediaParent.h"
 #include "mozilla/AppProcessChecker.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/NuwaParent.h"
 #include "mozilla/dom/PBlobParent.h"
 #include "mozilla/dom/MessagePortParent.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
@@ -277,16 +279,39 @@ BackgroundParentImpl::DeallocPVsyncParen
   MOZ_ASSERT(aActor);
 
   // This actor already has one ref-count. Please check AllocPVsyncParent().
   nsRefPtr<mozilla::layout::VsyncParent> actor =
       dont_AddRef(static_cast<mozilla::layout::VsyncParent*>(aActor));
   return true;
 }
 
+camera::PCamerasParent*
+BackgroundParentImpl::AllocPCamerasParent()
+{
+  AssertIsInMainProcess();
+  AssertIsOnBackgroundThread();
+
+  nsRefPtr<mozilla::camera::CamerasParent> actor =
+      mozilla::camera::CamerasParent::Create();
+  return actor.forget().take();
+}
+
+bool
+BackgroundParentImpl::DeallocPCamerasParent(camera::PCamerasParent *aActor)
+{
+  AssertIsInMainProcess();
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(aActor);
+
+  nsRefPtr<mozilla::camera::CamerasParent> actor =
+      dont_AddRef(static_cast<mozilla::camera::CamerasParent*>(aActor));
+  return true;
+}
+
 namespace {
 
 class InitUDPSocketParentCallback final : public nsRunnable
 {
 public:
   InitUDPSocketParentCallback(UDPSocketParent* aActor,
                               const nsACString& aFilter)
     : mActor(aActor)
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -96,16 +96,22 @@ protected:
   DeallocPNuwaParent(PNuwaParent* aActor) override;
 
   virtual PServiceWorkerManagerParent*
   AllocPServiceWorkerManagerParent() override;
 
   virtual bool
   DeallocPServiceWorkerManagerParent(PServiceWorkerManagerParent* aActor) override;
 
+  virtual PCamerasParent*
+  AllocPCamerasParent() override;
+
+  virtual bool
+  DeallocPCamerasParent(PCamerasParent* aActor) override;
+
   virtual bool
   RecvShutdownServiceWorkerRegistrar() override;
 
   virtual dom::cache::PCacheStorageParent*
   AllocPCacheStorageParent(const dom::cache::Namespace& aNamespace,
                            const PrincipalInfo& aPrincipalInfo) override;
 
   virtual bool
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -7,16 +7,17 @@ include protocol PBackgroundIDBFactory;
 include protocol PBackgroundTest;
 include protocol PBlob;
 include protocol PBroadcastChannel;
 include protocol PCache;
 include protocol PCacheStorage;
 include protocol PCacheStreamControl;
 include protocol PFileDescriptorSet;
 include protocol PMessagePort;
+include protocol PCameras;
 include protocol PNuwa;
 include protocol PServiceWorkerManager;
 include protocol PUDPSocket;
 include protocol PVsync;
 
 include DOMTypes;
 include PBackgroundSharedTypes;
 include PBackgroundIDBSharedTypes;
@@ -42,29 +43,32 @@ sync protocol PBackground
   manages PBackgroundTest;
   manages PBlob;
   manages PBroadcastChannel;
   manages PCache;
   manages PCacheStorage;
   manages PCacheStreamControl;
   manages PFileDescriptorSet;
   manages PMessagePort;
+  manages PCameras;
   manages PNuwa;
   manages PServiceWorkerManager;
   manages PUDPSocket;
   manages PVsync;
 
 parent:
   // Only called at startup during mochitests to check the basic infrastructure.
   PBackgroundTest(nsCString testArg);
 
   PBackgroundIDBFactory(LoggingInfo loggingInfo);
 
   PVsync();
 
+  PCameras();
+
   PUDPSocket(OptionalPrincipalInfo pInfo, nsCString filter);
   PBroadcastChannel(PrincipalInfo pInfo, nsCString origin, nsString channel,
                     bool privateBrowsing);
 
   PServiceWorkerManager();
 
   ShutdownServiceWorkerRegistrar();
 
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -135,16 +135,17 @@ SOURCES += [
     'URIUtils.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/broadcastchannel',
     '/dom/indexedDB',
     '/dom/workers',
+    '/media/webrtc/trunk',
     '/xpcom/build',
 ]
 
 IPDL_SOURCES = [
     'InputStreamParams.ipdlh',
     'PBackground.ipdl',
     'PBackgroundSharedTypes.ipdlh',
     'PBackgroundTest.ipdl',
@@ -173,10 +174,8 @@ LOCAL_INCLUDES += [
 ]
 
 if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += [
         '/security/sandbox/chromium',
         '/security/sandbox/chromium-shim',
         '/security/sandbox/win/src/sandboxbroker',
     ]
-
-FAIL_ON_WARNINGS = True
--- a/ipc/hal/moz.build
+++ b/ipc/hal/moz.build
@@ -19,10 +19,8 @@ UNIFIED_SOURCES += [
     'DaemonSocketConsumer.cpp',
     'DaemonSocketPDU.cpp',
     'DaemonSocketPDUHelpers.cpp'
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/ipc/ipdl/moz.build
+++ b/ipc/ipdl/moz.build
@@ -2,17 +2,15 @@
 # vim: set filetype=python:
 # 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/.
 
 if CONFIG['MOZ_IPDL_TESTS']:
     DIRS += ['test']
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 # We #include some things in the dom/plugins/ directory that rely on
 # toolkit libraries.
 CXXFLAGS += CONFIG['TK_CFLAGS']
--- a/ipc/keystore/moz.build
+++ b/ipc/keystore/moz.build
@@ -8,13 +8,11 @@ EXPORTS.mozilla.ipc += [
   'KeyStore.h'
 ]
 
 SOURCES += [
   'KeyStore.cpp',
   'KeyStoreConnector.cpp'
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/ipc/netd/moz.build
+++ b/ipc/netd/moz.build
@@ -10,10 +10,8 @@ EXPORTS.mozilla.ipc += [
 
 SOURCES += [
     'Netd.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/ipc/nfc/moz.build
+++ b/ipc/nfc/moz.build
@@ -9,10 +9,8 @@ if CONFIG['MOZ_NFC']:
     ]
     SOURCES += [
         'NfcConnector.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/ipc/ril/moz.build
+++ b/ipc/ril/moz.build
@@ -15,10 +15,8 @@ SOURCES += [
     'RilConnector.cpp',
     'RilSocket.cpp',
     'RilSocketConsumer.cpp'
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/ipc/testshell/moz.build
+++ b/ipc/testshell/moz.build
@@ -18,18 +18,16 @@ SOURCES += [
     'XPCShellEnvironment.cpp',
 ]
 
 IPDL_SOURCES = [
     'PTestShell.ipdl',
     'PTestShellCommand.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 # For xpcshell error messages and nsAutoJSString
 LOCAL_INCLUDES += [
     '/dom/base',
     '/js/xpconnect/src',
--- a/ipc/unixfd/moz.build
+++ b/ipc/unixfd/moz.build
@@ -11,13 +11,11 @@ EXPORTS.mozilla.ipc += [
 ]
 
 SOURCES += [
     'UnixFdWatcher.cpp',
     'UnixFileWatcher.cpp',
     'UnixSocketWatcher.cpp'
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/ipc/unixsocket/moz.build
+++ b/ipc/unixsocket/moz.build
@@ -21,13 +21,11 @@ SOURCES += [
     'ListenSocket.cpp',
     'ListenSocketConsumer.cpp',
     'SocketBase.cpp',
     'StreamSocket.cpp',
     'StreamSocketConsumer.cpp',
     'UnixSocketConnector.cpp'
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/js/ductwork/debugger/moz.build
+++ b/js/ductwork/debugger/moz.build
@@ -16,10 +16,8 @@ SOURCES += [
     'JSDebugger.cpp',
 ]
 
 EXTRA_JS_MODULES += [
     'jsdebugger.jsm',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-FAIL_ON_WARNINGS = True
--- a/js/ipc/moz.build
+++ b/js/ipc/moz.build
@@ -13,18 +13,16 @@ UNIFIED_SOURCES += [
     'WrapperOwner.cpp',
 ]
 
 IPDL_SOURCES += [
     'JavaScriptTypes.ipdlh',
     'PJavaScript.ipdl',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG['BIN_SUFFIX']
 
 EXPORTS.mozilla.jsipc = [
     'CpowHolder.h',
--- a/js/src/editline/moz.build
+++ b/js/src/editline/moz.build
@@ -11,10 +11,8 @@ UNIFIED_SOURCES += [
     'sysunix.c',
 ]
 
 FORCE_STATIC_LIB = True
 
 for var in ('ANSI_ARROWS', 'HAVE_TCGETATTR', 'HIDE', 'USE_DIRENT', 'SYS_UNIX',
             'HAVE_STDLIB', 'UNIQUE_HISTORY'):
     DEFINES[var] = True
-
-FAIL_ON_WARNINGS = True
--- a/js/src/gdb/moz.build
+++ b/js/src/gdb/moz.build
@@ -26,10 +26,8 @@ DEFINES['EXPORT_JS_API'] = True
 LOCAL_INCLUDES += ['..']
 GENERATED_INCLUDES += ['..']
 
 USE_LIBS += [
     'static:js',
 ]
 
 OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
-
-FAIL_ON_WARNINGS = True
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -106,10 +106,10 @@ LOCAL_INCLUDES += ['..']
 GENERATED_INCLUDES += ['..']
 
 USE_LIBS += [
     'static:js',
 ]
 
 OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -616,14 +616,14 @@ if CONFIG['OS_ARCH'] == 'SunOS':
         'dl',
         'nsl',
         'socket',
     ]
 
 CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
 CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
 
 NO_EXPAND_LIBS = True
 
 DIST_INSTALL = True
--- a/js/src/shell/moz.build
+++ b/js/src/shell/moz.build
@@ -25,10 +25,10 @@ if CONFIG['_MSC_VER']:
     NO_PGO = True
 
 LOCAL_INCLUDES += ['..']
 GENERATED_INCLUDES += ['..']
 
 OS_LIBS += CONFIG['EDITLINE_LIBS']
 OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
 
-if CONFIG['GNU_CXX']:
-    FAIL_ON_WARNINGS = True
+if not CONFIG['GNU_CXX']:
+    ALLOW_COMPILER_WARNINGS = True
--- a/js/xpconnect/loader/moz.build
+++ b/js/xpconnect/loader/moz.build
@@ -11,18 +11,16 @@ SOURCES += [
     'mozJSSubScriptLoader.cpp',
 ]
 
 EXTRA_JS_MODULES += [
     'ISO8601DateUtils.jsm',
     'XPCOMUtils.jsm',
 ]
 
-FAIL_ON_WARNINGS = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../src',
     '../wrappers',
     '/dom/base',
 ]
 
--- a/js/xpconnect/shell/moz.build
+++ b/js/xpconnect/shell/moz.build
@@ -30,10 +30,8 @@ if CONFIG['_MSC_VER']:
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     RCINCLUDE = 'xpcshell.rc'
 
 CFLAGS += CONFIG['TK_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 OS_LIBS += CONFIG['TK_LIBS']
-
-FAIL_ON_WARNINGS = True
--- a/js/xpconnect/src/moz.build
+++ b/js/xpconnect/src/moz.build
@@ -46,18 +46,16 @@ UNIFIED_SOURCES += [
     'XPCWrapper.cpp',
 ]
 
 # XPCComponents.cpp cannot be built in unified mode because it uses plarena.h.
 SOURCES += [
     'XPCComponents.cpp',
 ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../loader',
     '../wrappers',
     '/caps',
--- a/js/xpconnect/tests/components/native/moz.build
+++ b/js/xpconnect/tests/components/native/moz.build
@@ -15,10 +15,8 @@ UNIFIED_SOURCES += [
 
 XPCOMBinaryComponent('xpctest')
 
 DEFINES['LIBRARY_FILENAME'] = '%s%s%s' % (
     CONFIG['DLL_PREFIX'],
     LIBRARY_NAME,
     CONFIG['DLL_SUFFIX']
 )
-
-FAIL_ON_WARNINGS = True
--- a/js/xpconnect/wrappers/moz.build
+++ b/js/xpconnect/wrappers/moz.build
@@ -23,18 +23,16 @@ SOURCES += [
 ]
 
 # warning C4661 for FilteringWrapper
 if CONFIG['_MSC_VER']:
     CXXFLAGS += [
         '-wd4661', # no suitable definition provided for explicit template instantiation request
     ]
 
-FAIL_ON_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../../../dom/base',
     '../src',
 ]
--- a/layout/base/gtest/moz.build
+++ b/layout/base/gtest/moz.build
@@ -18,10 +18,8 @@ LOCAL_INCLUDES += [
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
 # Workaround bug 1142396. Suppress the warning from gmock library for clang.
 if CONFIG['CLANG_CXX']:
     CXXFLAGS += ['-Wno-null-dereference']
 
 FINAL_LIBRARY = 'xul-gtest'
-
-FAIL_ON_WARNINGS = True
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -156,18 +156,16 @@ UNIFIED_SOURCES += [
 SOURCES += [
     'nsPresArena.cpp',
     'nsRefreshDriver.cpp',
 ]
 
 if CONFIG['ENABLE_TESTS']:
     DIRS += ['gtest']
 
-FAIL_ON_WARNINGS = True