Merge mozilla-central into holly
authorMike Conley <mconley@mozilla.com>
Sat, 07 Dec 2013 13:07:27 -0500
changeset 224579 8f33dd2600ce10c7b45e5e0e0445040a71e1caf0
parent 224578 7bed4c08d9d3b6c7e929530a21dad97da8ed14f3 (current diff)
parent 159216 79d1a5a93b64fe467beb7a4897cc680d2f6b50d4 (diff)
child 224582 3a79902737827be0389239a2ba269bb41b50b9f6
push id6
push userryanvm@gmail.com
push dateMon, 12 Jan 2015 22:04:06 +0000
treeherdermozilla-b2g37_v2_2@895c8fc7b734 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.0a1
Merge mozilla-central into holly
CLOBBER
browser/app/profile/firefox.js
layout/media/symbols.def.in
media/libvpx/update.sh
media/libvpx/vp8/common/asm_com_offsets.c
media/libvpx/vp8/decoder/asm_dec_offsets.c
media/libvpx/vp8/encoder/asm_enc_offsets.c
media/libvpx/vp8/encoder/x86/quantize_sse2.asm
media/libvpx/vp8/encoder/x86/ssim_opt.asm
media/libvpx/vpx/vpx_codec_impl_bottom.h
media/libvpx/vpx/vpx_codec_impl_top.h
media/libvpx/vpx/vpx_integer.h.orig
media/libvpx/vpx_ports/vpxtypes.h
media/libvpx/vpx_scale/generic/vpxscale.c
media/libvpx/vpx_scale/generic/yv12extend_generic.h
media/libvpx/vpx_scale/include/generic/vpxscale_arbitrary.h
media/libvpx/vpx_scale/include/generic/vpxscale_depricated.h
media/libvpx/vpx_scale/scale_mode.h
media/libvpx/vpx_scale/vpxscale.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -13,9 +13,9 @@
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
-Bug 947080 - bug 937317 required clobber on windows
+Bug 933585 - clobber required on windows
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -25,16 +25,17 @@ builtin(include, build/autoconf/frameptr
 builtin(include, build/autoconf/compiler-opts.m4)dnl
 builtin(include, build/autoconf/expandlibs.m4)dnl
 builtin(include, build/autoconf/arch.m4)dnl
 builtin(include, build/autoconf/android.m4)dnl
 builtin(include, build/autoconf/zlib.m4)dnl
 builtin(include, build/autoconf/linux.m4)dnl
 builtin(include, build/autoconf/python-virtualenv.m4)dnl
 builtin(include, build/autoconf/winsdk.m4)dnl
+builtin(include, build/autoconf/icu.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
 
 # Read the user's .mozconfig script.  We can't do this in
 # configure.in: autoconf puts the argument parsing code above anything
 # expanded from configure.in, and we need to get the configure options
 # from .mozconfig in place before that argument parsing code.
 MOZ_READ_MOZCONFIG(.)
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "d10e0357c63bb565db8bdd3c23f062bfb9e21315", 
+    "revision": "63d432c3395f95c0ba19578487b796c1707042bd", 
     "repo_path": "/integration/gaia-central"
 }
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -600,22 +600,23 @@ int main(int argc, char* argv[])
   gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
 #endif
 
   nsIFile *xreDirectory;
 
 #ifdef HAS_DLL_BLOCKLIST
   DllBlocklist_Initialize();
 
+#ifdef DEBUG
   // In order to be effective against AppInit DLLs, the blocklist must be
-  // initialized before user32.dll is loaded into the process. If this assert
-  // ever fires, then the fix for bug 932100 has been defeated and the
-  // blocklist will miss AppInit DLLs. You should use a delayload or reorder
-  // the code to prevent user32.dll from loading during early startup.
-  MOZ_ASSERT(!GetModuleHandleA("user32.dll"));
+  // initialized before user32.dll is loaded into the process (bug 932100).
+  if (GetModuleHandleA("user32.dll")) {
+    fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n");
+  }
+#endif
 #endif
 
   nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
   if (NS_FAILED(rv)) {
     return 255;
   }
 
   XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -570,21 +570,17 @@ pref("browser.gesture.pinch.in.shift", "
 #endif
 pref("browser.gesture.twist.latched", false);
 pref("browser.gesture.twist.threshold", 0);
 pref("browser.gesture.twist.right", "cmd_gestureRotateRight");
 pref("browser.gesture.twist.left", "cmd_gestureRotateLeft");
 pref("browser.gesture.twist.end", "cmd_gestureRotateEnd");
 pref("browser.gesture.tap", "cmd_fullZoomReset");
 
-#ifndef RELEASE_BUILD
-pref("browser.snapshots.limit", 5);
-#else
 pref("browser.snapshots.limit", 0);
-#endif
 
 // 0: Nothing happens
 // 1: Scrolling contents
 // 2: Go back or go forward, in your history
 // 3: Zoom in or out.
 #ifdef XP_MACOSX
 // On OS X, if the wheel has one axis only, shift+wheel comes through as a
 // horizontal scroll event. Thus, we can't assign anything other than normal
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -106,16 +106,21 @@ ifeq (bundle, $(MOZ_FS_LAYOUT))
 BINPATH = $(_BINPATH)
 DEFINES += -DAPPNAME=$(_APPNAME)
 else
 # Every other platform just winds up in dist/bin
 BINPATH = bin
 endif
 DEFINES += -DBINPATH=$(BINPATH)
 
+DEFINES += -DMOZ_ICU_VERSION=$(MOZ_ICU_VERSION)
+ifdef MOZ_SHARED_ICU
+DEFINES += -DMOZ_SHARED_ICU
+endif
+
 libs::
 	$(MAKE) -C $(DEPTH)/browser/locales langpack
 
 ifeq (WINNT,$(OS_ARCH))
 PKGCOMP_FIND_OPTS =
 else
 PKGCOMP_FIND_OPTS = -L
 endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -96,16 +96,37 @@
 @BINPATH@/msvcp120.dll
 @BINPATH@/msvcr120.dll
 #ifdef MOZ_METRO
 @BINPATH@/vccorlib120.dll
 #endif
 #endif
 #endif
 #endif
+#ifdef MOZ_SHARED_ICU
+#ifdef XP_WIN
+#ifdef MOZ_DEBUG
+@BINPATH@/icudtd@MOZ_ICU_VERSION@.dll
+@BINPATH@/icuind@MOZ_ICU_VERSION@.dll
+@BINPATH@/icuucd@MOZ_ICU_VERSION@.dll
+#else
+@BINPATH@/icudt@MOZ_ICU_VERSION@.dll
+@BINPATH@/icuin@MOZ_ICU_VERSION@.dll
+@BINPATH@/icuuc@MOZ_ICU_VERSION@.dll
+#endif
+#elif defined(XP_MACOSX)
+@BINPATH@/libicudata.@MOZ_ICU_VERSION@.dylib
+@BINPATH@/libicui18n.@MOZ_ICU_VERSION@.dylib
+@BINPATH@/libicuuc.@MOZ_ICU_VERSION@.dylib
+#elif defined(XP_UNIX)
+@BINPATH@/libicudata.so.@MOZ_ICU_VERSION@
+@BINPATH@/libicui18n.so.@MOZ_ICU_VERSION@
+@BINPATH@/libicuuc.so.@MOZ_ICU_VERSION@
+#endif
+#endif
 
 [browser]
 ; [Base Browser Files]
 #ifndef XP_UNIX
 @BINPATH@/@MOZ_APP_NAME@.exe
 #else
 @BINPATH@/@MOZ_APP_NAME@-bin
 @BINPATH@/@MOZ_APP_NAME@
--- a/browser/metro/profile/metro.js
+++ b/browser/metro/profile/metro.js
@@ -39,17 +39,16 @@ pref("prompts.tab_modal.enabled", true);
 pref("layers.offmainthreadcomposition.enabled", true);
 pref("layers.async-pan-zoom.enabled", true);
 pref("layers.componentalpha.enabled", false);
 
 // Prefs to control the async pan/zoom behaviour
 pref("apz.touch_start_tolerance", "0.1"); // dpi * tolerance = pixel threshold
 pref("apz.pan_repaint_interval", 50);   // prefer 20 fps
 pref("apz.fling_repaint_interval", 50); // prefer 20 fps
-pref("apz.fling_friction", "0.002");
 pref("apz.fling_stopped_threshold", "0.2");
 
 // 0 = free, 1 = standard, 2 = sticky
 pref("apz.axis_lock_mode", 2);
 pref("apz.cross_slide.enabled", true);
 
 // Enable Microsoft TSF support by default for imes.
 pref("intl.enable_tsf_support", true);
new file mode 100644
--- /dev/null
+++ b/build/autoconf/icu.m4
@@ -0,0 +1,31 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Set the MOZ_ICU_VERSION variable to denote the current version of the
+dnl ICU library, and also the MOZ_SHARED_ICU which would be true if we are
+dnl linking against a shared library of ICU, either one that we build from
+dnl our copy of ICU or the system provided library.
+
+AC_DEFUN([MOZ_CONFIG_ICU], [
+    icudir="$_topsrcdir/intl/icu/source"
+    if test ! -d "$icudir"; then
+        icudir="$_topsrcdir/../../intl/icu/source"
+        if test ! -d "$icudir"; then
+            AC_MSG_ERROR([Cannot find the ICU directory])
+        fi
+    fi
+
+    version=`sed -n 's/^[[:space:]]*#[[:space:]]*define[[:space:]][[:space:]]*U_ICU_VERSION_MAJOR_NUM[[:space:]][[:space:]]*\([0-9][0-9]*\)[[:space:]]*$/\1/p' "$icudir/common/unicode/uvernum.h"`
+    if test x"$version" = x; then
+       AC_MSG_ERROR([cannot determine icu version number from uvernum.h header file $lineno])
+    fi
+    MOZ_ICU_VERSION="$version"
+
+    if test -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
+        MOZ_SHARED_ICU=1
+    fi
+
+    AC_SUBST(MOZ_ICU_VERSION)
+    AC_SUBST(MOZ_SHARED_ICU)
+])
--- a/config/moz.build
+++ b/config/moz.build
@@ -22,8 +22,11 @@ if CONFIG['HOST_OS_ARCH'] != 'WINNT':
     HOST_SOURCES += [
         'nsinstall.c',
         'pathsub.c',
     ]
     HOST_PROGRAM = 'nsinstall_real'
 
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     DEFINES['GKMEDIAS_SHARED_LIBRARY'] = True
+
+if CONFIG['MOZ_SHARED_ICU']:
+    DEFINES['MOZ_SHARED_ICU'] = True
--- a/config/system-headers
+++ b/config/system-headers
@@ -1126,17 +1126,17 @@ gst/video/video.h
 sys/msg.h
 sys/ipc.h
 sys/thr.h
 sys/user.h
 kvm.h
 spawn.h
 err.h
 xlocale.h
-#if MOZ_NATIVE_ICU==1
+#ifdef MOZ_SHARED_ICU
 unicode/locid.h
 unicode/numsys.h
 unicode/ucal.h
 unicode/uclean.h
 unicode/ucol.h
 unicode/udat.h
 unicode/udatpg.h
 unicode/uenum.h
--- a/configure.in
+++ b/configure.in
@@ -3891,16 +3891,27 @@ if test -n "$MOZ_NATIVE_FFI"; then
     if test -z "$GNU_CC"; then
         PKG_CHECK_MODULES(MOZ_FFI, libffi > 3.0.9)
     else
         PKG_CHECK_MODULES(MOZ_FFI, libffi >= 3.0.9)
     fi
     MOZ_JS_STATIC_LIBS="$MOZ_JS_STATIC_LIBS $MOZ_FFI_LIBS"
 fi
 
+# split JS out by default to avoid VS2005 PGO crash (bug 591836).
+if test "$OS_ARCH" = "WINNT"; then
+  JS_SHARED_LIBRARY=1
+fi
+
+MOZ_ARG_ENABLE_BOOL(shared-js,
+[  --enable-shared-js
+                          Create a shared JavaScript library.],
+    JS_SHARED_LIBRARY=1,
+    JS_SHARED_LIBRARY=)
+
 dnl ========================================================
 dnl System ICU Support
 dnl ========================================================
 MOZ_NATIVE_ICU=
 MOZ_ARG_WITH_BOOL(system-icu,
 [  --with-system-icu
                           Use system ICU (located with pkgconfig)],
     MOZ_NATIVE_ICU=1)
@@ -3956,17 +3967,17 @@ MOZ_SRTP=
 MOZ_WEBRTC_SIGNALING=
 MOZ_WEBRTC_ASSERT_ALWAYS=1
 MOZ_SCTP=
 MOZ_MEDIA_PLUGINS=
 MOZ_MEDIA_NAVIGATOR=
 MOZ_OMX_PLUGIN=
 MOZ_VP8=
 MOZ_VP8_ERROR_CONCEALMENT=
-MOZ_VP8_ENCODER=
+MOZ_VP8_ENCODER=1
 MOZ_WEBSPEECH=1
 VPX_AS=
 VPX_ASFLAGS=
 VPX_AS_DASH_C_FLAG=
 VPX_AS_CONVERSION=
 VPX_ASM_SUFFIX=
 VPX_X86_ASM=
 VPX_ARM_ASM=
@@ -5122,17 +5133,16 @@ MOZ_ARG_DISABLE_BOOL(webrtc,
 
 if test -n "$MOZ_WEBRTC"; then
     AC_DEFINE(MOZ_WEBRTC)
     dnl MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
     dnl opt/production builds (via MOZ_CRASH())
     AC_DEFINE(MOZ_WEBRTC_ASSERT_ALWAYS)
     MOZ_RAW=1
     MOZ_VP8=1
-    MOZ_VP8_ENCODER=1
     MOZ_VP8_ERROR_CONCEALMENT=1
 
 dnl enable once Signaling lands
     MOZ_WEBRTC_SIGNALING=1
     AC_DEFINE(MOZ_WEBRTC_SIGNALING)
 dnl enable once PeerConnection lands
     MOZ_PEERCONNECTION=1
     AC_DEFINE(MOZ_PEERCONNECTION)
@@ -5459,17 +5469,17 @@ if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE
         VPX_DASH_C_FLAG="-c"
         VPX_AS_CONVERSION='$(PERL) $(topsrcdir)/media/libvpx/build/make/ads2gas.pl'
         VPX_ASM_SUFFIX="$ASM_SUFFIX"
         VPX_ARM_ASM=1
       fi
     ;;
     *:x86)
       if $CC -E -dM -</dev/null | grep -q __ELF__; then
-        VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
+        VPX_ASFLAGS="-f elf32 -rnasm -pnasm -DPIC"
         VPX_X86_ASM=1
       fi
     ;;
     *:x86_64)
       if $CC -E -dM -</dev/null | grep -q __ELF__; then
         VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
         VPX_X86_ASM=1
       fi
@@ -7722,29 +7732,17 @@ fi
 
 dnl ========================================================
 dnl =
 dnl = Static Build Options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Static build options)
 
-# split JS out by default to avoid VS2005 PGO crash (bug 591836).
-if test "$OS_ARCH" = "WINNT"; then
-  ENABLE_SHARED_JS=1
-fi
-
-MOZ_ARG_ENABLE_BOOL(shared-js,
-[  --enable-shared-js
-                          Create a shared JavaScript library.],
-    ENABLE_SHARED_JS=1,
-    ENABLE_SHARED_JS=)
-
-if test -n "$ENABLE_SHARED_JS"; then
-  JS_SHARED_LIBRARY=1
+if test -n "$JS_SHARED_LIBRARY"; then
   MOZ_JS_LIBS="$MOZ_JS_SHARED_LIBS"
 else
   MOZ_JS_LIBS="$MOZ_JS_STATIC_LIBS"
   AC_DEFINE(MOZ_STATIC_JS)
 fi
 AC_SUBST(JS_SHARED_LIBRARY)
 
 AC_SUBST(LIBXUL_LIBS)
@@ -8783,16 +8781,91 @@ HAVE_STATFS
 HAVE_SYS_STATVFS_H
 HAVE_SYS_STATFS_H
 HAVE_SYS_VFS_H
 HAVE_SYS_MOUNT_H
 "
 
 AC_SUBST(STLPORT_LIBS)
 
+MOZ_ARG_WITH_STRING(intl-api,
+[  --with-intl-api, --with-intl-api=build, --without-intl-api
+    Determine the status of the ECMAScript Internationalization API.  The first
+    (or lack of any of these) builds and exposes the API.  The second builds it
+    but doesn't use ICU or expose the API to script.  The third doesn't build
+    ICU at all.],
+    _INTL_API=$withval,
+    _INTL_API=yes)
+
+WITH_INTL="--with-intl-api=$_INTL_API"
+ENABLE_INTL_API=
+case "$_INTL_API" in
+no)
+    ;;
+build)
+    ENABLE_INTL_API=1
+    ;;
+yes)
+    ENABLE_INTL_API=1
+    ;;
+*)
+    AC_MSG_ERROR([Invalid value passed to --with-intl-api: $_INTL_API])
+    ;;
+esac
+
+if test -n "$ENABLE_INTL_API"; then
+if test "$MOZ_BUILD_APP" = "browser"; then
+    WITH_INTL="--with-intl-api"
+else
+    # Internationalization isn't built or exposed by default in non-desktop
+    # builds.  Bugs to enable:
+    #
+    #   Android:  bug 864843
+    #   B2G:      bug 866301
+    WITH_INTL="--without-intl-api"
+    ENABLE_INTL_API=
+fi
+fi
+
+dnl Settings for the implementation of the ECMAScript Internationalization API
+if test -n "$ENABLE_INTL_API"; then
+    AC_DEFINE(ENABLE_INTL_API)
+
+    MOZ_CONFIG_ICU()
+
+    dnl Build ICU as a shared library for shared js builds.
+    if test -z "$MOZ_NATIVE_ICU" -a -n "$JS_SHARED_LIBRARY"; then
+        case "$OS_TARGET" in
+            WINNT)
+                ICU_LIB_NAMES="icuin icuuc icudt"
+                DBG_SUFFIX=
+                if test -n "$MOZ_DEBUG"; then
+                    DBG_SUFFIX=d
+                fi
+                MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/js/src/intl/icu/target/lib/$(LIB_PREFIX)$(lib)$(DBG_SUFFIX).$(LIB_SUFFIX))'
+                ;;
+            Darwin)
+                ICU_LIB_NAMES="icui18n icuuc icudata"
+                MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/js/src/intl/icu/target/lib/$(DLL_PREFIX)$(lib).$(MOZ_ICU_VERSION)$(DLL_SUFFIX))'
+                ;;
+            Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
+                ICU_LIB_NAMES="icui18n icuuc icudata"
+                MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/js/src/intl/icu/target/lib/$(DLL_PREFIX)$(lib)$(DLL_SUFFIX).$(MOZ_ICU_VERSION))'
+                ;;
+            *)
+                AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
+        esac
+    fi
+fi
+
+AC_SUBST(DBG_SUFFIX)
+AC_SUBST(ENABLE_INTL_API)
+AC_SUBST(ICU_LIB_NAMES)
+AC_SUBST(MOZ_ICU_LIBS)
+
 export WRITE_MOZINFO=1
 AC_OUTPUT()
 unset WRITE_MOZINFO
 
 # Hack around an Apple bug that affects the egrep that comes with OS X 10.7.
 # "env ARCHPREFERENCE=i386,x86_64 arch egrep" first tries to use the 32-bit
 # Intel part of the egrep fat binary, even on 64-bit systems, and falls back on
 # the 64-bit part if it's not a fat binary, as can happen with MacPorts. We
@@ -8961,17 +9034,17 @@ dnl so that regeneration via dependencie
    if test "$?" != 0; then
       AC_MSG_ERROR([failed to generate nICEr Makefiles])
    fi
 fi
 
 # Run jemalloc configure script
 
 if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" && test -n "$MOZ_JEMALLOC3" -o -n "$MOZ_REPLACE_MALLOC"; then
-  ac_configure_args="$_SUBDIR_CONFIG_ARGS --build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
+  ac_configure_args="--build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
   if test -n "$MOZ_REPLACE_MALLOC"; then
     # When using replace_malloc, we always want memalign and valloc exported from jemalloc.
     ac_configure_args="$ac_configure_args ac_cv_func_memalign=yes"
     ac_configure_args="$ac_configure_args ac_cv_func_valloc=yes"
   fi
   if test -n "$MOZ_JEMALLOC3"; then
     case "${OS_ARCH}" in
       WINNT|Darwin)
@@ -9156,36 +9229,16 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
 fi
 
 
 # Run the SpiderMonkey 'configure' script.
 dist=$MOZ_BUILD_ROOT/dist
 ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 ac_configure_args="$ac_configure_args --enable-threadsafe"
 
-MOZ_ARG_WITH_STRING(intl-api,
-[  --with-intl-api, --with-intl-api=build, --without-intl-api
-    Determine the status of the ECMAScript Internationalization API.  The first
-    (or lack of any of these) builds and exposes the API.  The second builds it
-    but doesn't use ICU or expose the API to script.  The third doesn't build
-    ICU at all.],
-    WITH_INTL="--with-intl-api=$withval"
-)
-if test -z "$WITH_INTL"; then
-if test "$MOZ_BUILD_APP" = "browser"; then
-    WITH_INTL="--with-intl-api"
-else
-    # Internationalization isn't built or exposed by default in non-desktop
-    # builds.  Bugs to enable:
-    #
-    #   Android:  bug 864843
-    #   B2G:      bug 866301
-    WITH_INTL="--without-intl-api"
-fi
-fi
 ac_configure_args="$ac_configure_args $WITH_INTL"
 
 if test "$BUILD_CTYPES"; then
     # Build js-ctypes on the platforms we can.
     ac_configure_args="$ac_configure_args --enable-ctypes"
 fi
 if test -z "$JS_SHARED_LIBRARY" ; then
     ac_configure_args="$ac_configure_args --disable-shared-js"
--- a/content/media/DecoderTraits.cpp
+++ b/content/media/DecoderTraits.cpp
@@ -166,19 +166,21 @@ IsWaveType(const nsACString& aType)
 
 #ifdef MOZ_WEBM
 static const char* const gWebMTypes[3] = {
   "video/webm",
   "audio/webm",
   nullptr
 };
 
-static char const *const gWebMCodecs[5] = {
+static char const *const gWebMCodecs[7] = {
   "vp8",
   "vp8.0",
+  "vp9",
+  "vp9.0",
   "vorbis",
   "opus",
   nullptr
 };
 
 static bool
 IsWebMType(const nsACString& aType)
 {
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -416,16 +416,28 @@ bool OmxDecoder::TryLoad() {
   // read video metadata
   if (mVideoSource.get() && !SetVideoFormat()) {
     NS_WARNING("Couldn't set OMX video format");
     return false;
   }
 
   // read audio metadata
   if (mAudioSource.get()) {
+    // For RTSP, we don't read the audio source for now.
+    // The metadata of RTSP will be obtained through SDP at connection time.
+    if (mResource->GetRtspPointer()) {
+      sp<MetaData> meta = mAudioSource->getFormat();
+      if (!meta->findInt32(kKeyChannelCount, &mAudioChannels) ||
+          !meta->findInt32(kKeySampleRate, &mAudioSampleRate)) {
+        NS_WARNING("Couldn't get audio metadata from OMX decoder");
+        return false;
+      }
+      return true;
+    }
+
     // To reliably get the channel and sample rate data we need to read from the
     // audio source until we get a INFO_FORMAT_CHANGE status
     status_t err = mAudioSource->read(&mAudioBuffer);
     if (err != INFO_FORMAT_CHANGED) {
       if (err != OK) {
         NS_WARNING("Couldn't read audio buffer from OMX decoder");
         return false;
       }
--- a/content/media/omx/RtspOmxReader.h
+++ b/content/media/omx/RtspOmxReader.h
@@ -57,16 +57,25 @@ public:
   // we returned are not useful for the MediaDecodeStateMachine. Unlike the
   // ChannelMediaResource, it has a "cache" that can store the whole streaming
   // data so the |GetBuffered| function can retrieve useful time ranges.
   virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered,
                                int64_t aStartTime) MOZ_FINAL MOZ_OVERRIDE {
     return NS_OK;
   }
 
+  // Override FindStartTime() to return null pointer.
+  // For Rtsp, we don't have the first video frame in DECODING_METADATA state.
+  // It will be available until player request Play() and media decoder enters
+  // DECODING state.
+  virtual VideoData* FindStartTime(int64_t& aOutStartTime)
+    MOZ_FINAL MOZ_OVERRIDE {
+    return nullptr;
+  }
+
 private:
   // A pointer to RtspMediaResource for calling the Rtsp specific function.
   // The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder
   // holds the MediaDecoderStateMachine and RtspMediaResource.
   // And MediaDecoderStateMachine holds this RtspOmxReader.
   RtspMediaResource* mRtspResource;
 };
 
--- a/content/media/webm/WebMReader.cpp
+++ b/content/media/webm/WebMReader.cpp
@@ -158,50 +158,47 @@ WebMReader::WebMReader(AbstractMediaDeco
   MOZ_COUNT_CTOR(WebMReader);
 #ifdef PR_LOGGING
   if (!gNesteggLog) {
     gNesteggLog = PR_NewLogModule("Nestegg");
   }
 #endif
   // Zero these member vars to avoid crashes in VP8 destroy and Vorbis clear
   // functions when destructor is called before |Init|.
-  memset(&mVP8, 0, sizeof(vpx_codec_ctx_t));
+  memset(&mVPX, 0, sizeof(vpx_codec_ctx_t));
   memset(&mVorbisBlock, 0, sizeof(vorbis_block));
   memset(&mVorbisDsp, 0, sizeof(vorbis_dsp_state));
   memset(&mVorbisInfo, 0, sizeof(vorbis_info));
   memset(&mVorbisComment, 0, sizeof(vorbis_comment));
 }
 
 WebMReader::~WebMReader()
 {
   Cleanup();
 
   mVideoPackets.Reset();
   mAudioPackets.Reset();
 
-  vpx_codec_destroy(&mVP8);
+  vpx_codec_destroy(&mVPX);
 
   vorbis_block_clear(&mVorbisBlock);
   vorbis_dsp_clear(&mVorbisDsp);
   vorbis_info_clear(&mVorbisInfo);
   vorbis_comment_clear(&mVorbisComment);
 
   if (mOpusDecoder) {
     opus_multistream_decoder_destroy(mOpusDecoder);
     mOpusDecoder = nullptr;
   }
 
   MOZ_COUNT_DTOR(WebMReader);
 }
 
 nsresult WebMReader::Init(MediaDecoderReader* aCloneDonor)
 {
-  if (vpx_codec_dec_init(&mVP8, vpx_codec_vp8_dx(), nullptr, 0)) {
-    return NS_ERROR_FAILURE;
-  }
 
   vorbis_info_init(&mVorbisInfo);
   vorbis_comment_init(&mVorbisComment);
   memset(&mVorbisDsp, 0, sizeof(vorbis_dsp_state));
   memset(&mVorbisBlock, 0, sizeof(vorbis_block));
 
   if (aCloneDonor) {
     mBufferedState = static_cast<WebMReader*>(aCloneDonor)->mBufferedState;
@@ -280,16 +277,28 @@ nsresult WebMReader::ReadMetadata(MediaI
     if (!mHasVideo && type == NESTEGG_TRACK_VIDEO) {
       nestegg_video_params params;
       r = nestegg_track_video_params(mContext, track, &params);
       if (r == -1) {
         Cleanup();
         return NS_ERROR_FAILURE;
       }
 
+      vpx_codec_iface_t* dx = nullptr;
+      mVideoCodec = nestegg_track_codec_id(mContext, track);
+      if (mVideoCodec == NESTEGG_CODEC_VP8) {
+        dx = vpx_codec_vp8_dx();
+      } else if (mVideoCodec == NESTEGG_CODEC_VP9) {
+        dx = vpx_codec_vp9_dx();
+      }
+      if (!dx || vpx_codec_dec_init(&mVPX, dx, nullptr, 0)) {
+        Cleanup();
+        return NS_ERROR_FAILURE;
+      }
+
       // Picture region, taking into account cropping, before scaling
       // to the display size.
       nsIntRect pictureRect(params.crop_left,
                             params.crop_top,
                             params.width - (params.crop_right + params.crop_left),
                             params.height - (params.crop_bottom + params.crop_top));
 
       // If the cropping data appears invalid then use the frame data
@@ -863,43 +872,47 @@ bool WebMReader::DecodeVideoFrame(bool &
     r = nestegg_packet_data(packet, i, &data, &length);
     if (r == -1) {
       return false;
     }
 
     vpx_codec_stream_info_t si;
     memset(&si, 0, sizeof(si));
     si.sz = sizeof(si);
-    vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
+    if (mVideoCodec == NESTEGG_CODEC_VP8) {
+      vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
+    } else if (mVideoCodec == NESTEGG_CODEC_VP9) {
+      vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
+    }
     if (aKeyframeSkip && (!si.is_kf || tstamp_usecs < aTimeThreshold)) {
       // Skipping to next keyframe...
       parsed++; // Assume 1 frame per chunk.
       continue;
     }
 
     if (aKeyframeSkip && si.is_kf) {
       aKeyframeSkip = false;
     }
 
-    if (vpx_codec_decode(&mVP8, data, length, nullptr, 0)) {
+    if (vpx_codec_decode(&mVPX, data, length, nullptr, 0)) {
       return false;
     }
 
     // If the timestamp of the video frame is less than
     // the time threshold required then it is not added
     // to the video queue and won't be displayed.
     if (tstamp_usecs < aTimeThreshold) {
       parsed++; // Assume 1 frame per chunk.
       continue;
     }
 
     vpx_codec_iter_t  iter = nullptr;
     vpx_image_t      *img;
 
-    while ((img = vpx_codec_get_frame(&mVP8, &iter))) {
+    while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
       NS_ASSERTION(img->fmt == IMG_FMT_I420, "WebM image format is not I420");
 
       // Chroma shifts are rounded down as per the decoding examples in the VP8 SDK
       VideoData::YCbCrBuffer b;
       b.mPlanes[0].mData = img->planes[0];
       b.mPlanes[0].mStride = img->stride[0];
       b.mPlanes[0].mHeight = img->d_h;
       b.mPlanes[0].mWidth = img->d_w;
--- a/content/media/webm/WebMReader.h
+++ b/content/media/webm/WebMReader.h
@@ -176,17 +176,17 @@ protected:
   void Cleanup();
 
 private:
   // libnestegg context for webm container. Access on state machine thread
   // or decoder thread only.
   nestegg* mContext;
 
   // VP8 decoder state
-  vpx_codec_ctx_t mVP8;
+  vpx_codec_ctx_t mVPX;
 
   // Vorbis decoder state
   vorbis_info mVorbisInfo;
   vorbis_comment mVorbisComment;
   vorbis_dsp_state mVorbisDsp;
   vorbis_block mVorbisBlock;
   uint32_t mPacketCount;
   uint32_t mChannels;
@@ -229,14 +229,16 @@ private:
   nsIntRect mPicture;
 
   // Booleans to indicate if we have audio and/or video data
   bool mHasVideo;
   bool mHasAudio;
 
   // Codec ID of audio track
   int mAudioCodec;
+  // Codec ID of video track
+  int mVideoCodec;
 
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1251,16 +1251,17 @@ Navigator::GetGamepads(nsTArray<nsRefPtr
                        ErrorResult& aRv)
 {
   if (!mWindow) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
   NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
   nsGlobalWindow* win = static_cast<nsGlobalWindow*>(mWindow.get());
+  win->SetHasGamepadEventListener(true);
   win->GetGamepads(aGamepads);
 }
 #endif
 
 //*****************************************************************************
 //    Navigator::nsIMozNavigatorNetwork
 //*****************************************************************************
 
--- a/dom/bluetooth/ObexBase.cpp
+++ b/dom/bluetooth/ObexBase.cpp
@@ -73,52 +73,62 @@ AppendHeaderConnectionId(uint8_t* aRetBu
 void
 SetObexPacketInfo(uint8_t* aRetBuf, uint8_t aOpcode, int aPacketLength)
 {
   aRetBuf[0] = aOpcode;
   aRetBuf[1] = (aPacketLength & 0xFF00) >> 8;
   aRetBuf[2] = aPacketLength & 0x00FF;
 }
 
-void
+bool
 ParseHeaders(const uint8_t* aHeaderStart,
              int aTotalLength,
              ObexHeaderSet* aRetHandlerSet)
 {
   const uint8_t* ptr = aHeaderStart;
 
   while (ptr - aHeaderStart < aTotalLength) {
     ObexHeaderId headerId = (ObexHeaderId)*ptr++;
 
-    int contentLength = 0;
+    uint16_t contentLength = 0;
     uint8_t highByte, lowByte;
 
     // Defined in 2.1 OBEX Headers, IrOBEX 1.2
     switch (headerId >> 6)
     {
       case 0x00:
         // Null-terminated Unicode text, length prefixed with 2-byte
         // unsigned integer.
       case 0x01:
         // byte sequence, length prefixed with 2 byte unsigned integer.
         highByte = *ptr++;
         lowByte = *ptr++;
-        contentLength = (((int)highByte << 8) | lowByte) - 3;
+        contentLength = (((uint16_t)highByte << 8) | lowByte) - 3;
         break;
 
       case 0x02:
         // 1 byte quantity
         contentLength = 1;
         break;
 
       case 0x03:
         // 4 byte quantity
         contentLength = 4;
         break;
     }
 
+    // Length check to prevent from memory pollusion.
+    if (ptr + contentLength > aHeaderStart + aTotalLength) {
+      // Severe error occurred. We can't even believe the received data, so
+      // clear all headers.
+      MOZ_ASSERT(false);
+      aRetHandlerSet->ClearHeaders();
+      return false;
+    }
+
     aRetHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, ptr));
-
     ptr += contentLength;
   }
+
+  return true;
 }
 
 END_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth/ObexBase.h
+++ b/dom/bluetooth/ObexBase.h
@@ -97,17 +97,18 @@ enum ObexResponseCode {
   ServiceUnavailable = 0xD3,
   GatewayTimeout = 0xD4,
   HttpVersionNotSupported = 0xD5,
 
   DatabaseFull = 0xE0,
   DatabaseLocked = 0xE1,
 };
 
-class ObexHeader {
+class ObexHeader
+{
 public:
   ObexHeader(ObexHeaderId aId, int aDataLength, const uint8_t* aData)
     : mId(aId)
     , mDataLength(aDataLength)
     , mData(nullptr)
   {
     mData = new uint8_t[mDataLength];
     memcpy(mData, aData, aDataLength);
@@ -117,21 +118,19 @@ public:
   {
   }
 
   ObexHeaderId mId;
   int mDataLength;
   nsAutoArrayPtr<uint8_t> mData;
 };
 
-class ObexHeaderSet {
+class ObexHeaderSet
+{
 public:
-  uint8_t mOpcode;
-  nsTArray<nsAutoPtr<ObexHeader> > mHeaders;
-
   ObexHeaderSet(uint8_t aOpcode) : mOpcode(aOpcode)
   {
   }
 
   ~ObexHeaderSet()
   {
   }
 
@@ -236,23 +235,36 @@ public:
     for (int i = 0; i < length; ++i) {
       if (mHeaders[i]->mId == aId) {
         return true;
       }
     }
 
     return false;
   }
+
+  void ClearHeaders()
+  {
+    mHeaders.Clear();
+  }
+
+private:
+  uint8_t mOpcode;
+  nsTArray<nsAutoPtr<ObexHeader> > mHeaders;
 };
 
 int AppendHeaderName(uint8_t* aRetBuf, const char* aName, int aLength);
 int AppendHeaderBody(uint8_t* aRetBuf, uint8_t* aData, int aLength);
 int AppendHeaderEndOfBody(uint8_t* aRetBuf);
 int AppendHeaderLength(uint8_t* aRetBuf, int aObjectLength);
 int AppendHeaderConnectionId(uint8_t* aRetBuf, int aConnectionId);
 void SetObexPacketInfo(uint8_t* aRetBuf, uint8_t aOpcode, int aPacketLength);
-void ParseHeaders(const uint8_t* aHeaderStart,
+
+/**
+ * @return true when the message was parsed without any error, false otherwise.
+ */
+bool ParseHeaders(const uint8_t* aHeaderStart,
                   int aTotalLength,
                   ObexHeaderSet* aRetHanderSet);
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
@@ -798,35 +798,41 @@ BluetoothOppManager::ServerDataHandler(U
     }
   }
 
   ObexHeaderSet pktHeaders(opCode);
   if (opCode == ObexRequestCode::Connect) {
     // Section 3.3.1 "Connect", IrOBEX 1.2
     // [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
     // [Headers:var]
-    ParseHeaders(&aMessage->mData[7],
-                 receivedLength - 7,
-                 &pktHeaders);
+    if (!ParseHeaders(&aMessage->mData[7], receivedLength - 7, &pktHeaders)) {
+      ReplyError(ObexResponseCode::BadRequest);
+      return;
+    }
+
     ReplyToConnect();
     AfterOppConnected();
   } else if (opCode == ObexRequestCode::Abort) {
     // Section 3.3.5 "Abort", IrOBEX 1.2
     // [opcode:1][length:2][Headers:var]
-    ParseHeaders(&aMessage->mData[3],
-                receivedLength - 3,
-                &pktHeaders);
+    if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
+      ReplyError(ObexResponseCode::BadRequest);
+      return;
+    }
+
     ReplyToDisconnectOrAbort();
     DeleteReceivedFile();
   } else if (opCode == ObexRequestCode::Disconnect) {
     // Section 3.3.2 "Disconnect", IrOBEX 1.2
     // [opcode:1][length:2][Headers:var]
-    ParseHeaders(&aMessage->mData[3],
-                receivedLength - 3,
-                &pktHeaders);
+    if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
+      ReplyError(ObexResponseCode::BadRequest);
+      return;
+    }
+
     ReplyToDisconnectOrAbort();
     AfterOppDisconnected();
     FileTransferComplete();
   } else if (opCode == ObexRequestCode::Put ||
              opCode == ObexRequestCode::PutFinal) {
     if (!ComposePacket(opCode, aMessage)) {
       return;
     }
@@ -1192,17 +1198,17 @@ BluetoothOppManager::ReplyToPut(bool aFi
   }
 
   SendObexData(req, opcode, index);
 }
 
 void
 BluetoothOppManager::ReplyError(uint8_t aError)
 {
-  if (!mConnected) return;
+  BT_LOGR("error: %d", aError);
 
   // Section 3.2 "Response Format", IrOBEX 1.2
   // [opcode:1][length:2][Headers:var]
   uint8_t req[255];
   int index = 3;
 
   SendObexData(req, aError, index);
 }
--- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp
@@ -336,19 +336,22 @@ Call::IsActive()
 {
   return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
 }
 #endif // MOZ_B2G_RIL
 
 /**
  *  BluetoothHfpManager
  */
-BluetoothHfpManager::BluetoothHfpManager() : mPhoneType(PhoneType::NONE)
-                                           , mController(nullptr)
+BluetoothHfpManager::BluetoothHfpManager() : mController(nullptr)
 {
+#ifdef MOZ_B2G_RIL
+  mPhoneType = PhoneType::NONE;
+#endif // MOZ_B2G_RIL
+
   Reset();
 }
 
 #ifdef MOZ_B2G_RIL
 void
 BluetoothHfpManager::ResetCallArray()
 {
   mCurrentCallArray.Clear();
--- a/dom/bluetooth/bluez/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothOppManager.cpp
@@ -814,35 +814,41 @@ BluetoothOppManager::ServerDataHandler(U
     }
   }
 
   ObexHeaderSet pktHeaders(opCode);
   if (opCode == ObexRequestCode::Connect) {
     // Section 3.3.1 "Connect", IrOBEX 1.2
     // [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
     // [Headers:var]
-    ParseHeaders(&aMessage->mData[7],
-                 receivedLength - 7,
-                 &pktHeaders);
+    if (!ParseHeaders(&aMessage->mData[7], receivedLength - 7, &pktHeaders)) {
+      ReplyError(ObexResponseCode::BadRequest);
+      return;
+    }
+
     ReplyToConnect();
     AfterOppConnected();
   } else if (opCode == ObexRequestCode::Abort) {
     // Section 3.3.5 "Abort", IrOBEX 1.2
     // [opcode:1][length:2][Headers:var]
-    ParseHeaders(&aMessage->mData[3],
-                receivedLength - 3,
-                &pktHeaders);
+    if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
+      ReplyError(ObexResponseCode::BadRequest);
+      return;
+    }
+
     ReplyToDisconnectOrAbort();
     DeleteReceivedFile();
   } else if (opCode == ObexRequestCode::Disconnect) {
     // Section 3.3.2 "Disconnect", IrOBEX 1.2
     // [opcode:1][length:2][Headers:var]
-    ParseHeaders(&aMessage->mData[3],
-                receivedLength - 3,
-                &pktHeaders);
+    if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
+      ReplyError(ObexResponseCode::BadRequest);
+      return;
+    }
+
     ReplyToDisconnectOrAbort();
     AfterOppDisconnected();
     FileTransferComplete();
   } else if (opCode == ObexRequestCode::Put ||
              opCode == ObexRequestCode::PutFinal) {
     if (!ComposePacket(opCode, aMessage)) {
       return;
     }
@@ -1208,17 +1214,17 @@ BluetoothOppManager::ReplyToPut(bool aFi
   }
 
   SendObexData(req, opcode, index);
 }
 
 void
 BluetoothOppManager::ReplyError(uint8_t aError)
 {
-  if (!mConnected) return;
+  BT_LOGR("error: %d", aError);
 
   // Section 3.2 "Response Format", IrOBEX 1.2
   // [opcode:1][length:2][Headers:var]
   uint8_t req[255];
   int index = 3;
 
   SendObexData(req, aError, index);
 }
--- a/dom/camera/CameraCommon.h
+++ b/dom/camera/CameraCommon.h
@@ -74,16 +74,17 @@ enum {
   CAMERA_PARAM_FOCALLENGTH,
   CAMERA_PARAM_FOCUSDISTANCENEAR,
   CAMERA_PARAM_FOCUSDISTANCEOPTIMUM,
   CAMERA_PARAM_FOCUSDISTANCEFAR,
   CAMERA_PARAM_EXPOSURECOMPENSATION,
   CAMERA_PARAM_PICTURESIZE,
   CAMERA_PARAM_THUMBNAILSIZE,
   CAMERA_PARAM_THUMBNAILQUALITY,
+  CAMERA_PARAM_SENSORANGLE,
 
   CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
   CAMERA_PARAM_SUPPORTED_VIDEOSIZES,
   CAMERA_PARAM_SUPPORTED_PICTURESIZES,
   CAMERA_PARAM_SUPPORTED_PICTUREFORMATS,
   CAMERA_PARAM_SUPPORTED_WHITEBALANCES,
   CAMERA_PARAM_SUPPORTED_SCENEMODES,
   CAMERA_PARAM_SUPPORTED_EFFECTS,
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -263,16 +263,24 @@ CameraControlImpl::Set(uint32_t aKey, co
 
 nsresult
 CameraControlImpl::Get(uint32_t aKey, idl::CameraSize& aSize)
 {
   GetParameter(aKey, aSize);
   return NS_OK;
 }
 
+nsresult
+CameraControlImpl::Get(uint32_t aKey, int32_t* aValue)
+{
+  MOZ_ASSERT(aValue);
+  *aValue = GetParameterInt32(aKey);
+  return NS_OK;
+}
+
 already_AddRefed<RecorderProfileManager>
 CameraControlImpl::GetRecorderProfileManager()
 {
   return GetRecorderProfileManagerImpl();
 }
 
 void
 CameraControlImpl::Shutdown()
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -70,16 +70,17 @@ public:
   nsresult Set(nsICameraClosedCallback* aOnClosed);
   nsresult Get(nsICameraClosedCallback** aOnClosed);
   nsresult Set(nsICameraRecorderStateChange* aOnRecorderStateChange);
   nsresult Get(nsICameraRecorderStateChange** aOnRecorderStateChange);
   nsresult Set(nsICameraPreviewStateChange* aOnPreviewStateChange);
   nsresult Get(nsICameraPreviewStateChange** aOnPreviewStateChange);
   nsresult Set(uint32_t aKey, const idl::CameraSize& aSize);
   nsresult Get(uint32_t aKey, idl::CameraSize& aSize);
+  nsresult Get(uint32_t aKey, int32_t* aValue);
 
   nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue)
   {
     return Set(aCx, CAMERA_PARAM_FOCUSAREAS, aValue, mMaxFocusAreas);
   }
 
   nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue)
   {
@@ -87,16 +88,17 @@ public:
   }
 
   already_AddRefed<RecorderProfileManager> GetRecorderProfileManager();
   uint32_t GetCameraId() { return mCameraId; }
 
   virtual const char* GetParameter(const char* aKey) = 0;
   virtual const char* GetParameterConstChar(uint32_t aKey) = 0;
   virtual double GetParameterDouble(uint32_t aKey) = 0;
+  virtual int32_t GetParameterInt32(uint32_t aKey) = 0;
   virtual void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions) = 0;
   virtual void GetParameter(uint32_t aKey, idl::CameraSize& aSize) = 0;
   virtual void SetParameter(const char* aKey, const char* aValue) = 0;
   virtual void SetParameter(uint32_t aKey, const char* aValue) = 0;
   virtual void SetParameter(uint32_t aKey, double aValue) = 0;
   virtual void SetParameter(uint32_t aKey, const nsTArray<idl::CameraRegion>& aRegions) = 0;
   virtual void SetParameter(uint32_t aKey, const idl::CameraSize& aSize) = 0;
   virtual nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes) = 0;
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -280,16 +280,24 @@ nsDOMCameraControl::SetExposureCompensat
 double
 nsDOMCameraControl::GetExposureCompensation(ErrorResult& aRv)
 {
   double compensation;
   aRv = mCameraControl->Get(CAMERA_PARAM_EXPOSURECOMPENSATION, &compensation);
   return compensation;
 }
 
+int32_t
+nsDOMCameraControl::SensorAngle()
+{
+  int32_t angle;
+  mCameraControl->Get(CAMERA_PARAM_SENSORANGLE, &angle);
+  return angle;
+}
+
 already_AddRefed<nsICameraShutterCallback>
 nsDOMCameraControl::GetOnShutter(ErrorResult& aRv)
 {
   nsCOMPtr<nsICameraShutterCallback> cb;
   aRv = mCameraControl->Get(getter_AddRefs(cb));
   return cb.forget();
 }
 
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -71,16 +71,17 @@ public:
   JS::Value GetThumbnailSize(JSContext* aCx, ErrorResult& aRv);
   void SetThumbnailSize(JSContext* aCx, JS::Handle<JS::Value> aSize, ErrorResult& aRv);
   double GetFocalLength(ErrorResult& aRv);
   double GetFocusDistanceNear(ErrorResult& aRv);
   double GetFocusDistanceOptimum(ErrorResult& aRv);
   double GetFocusDistanceFar(ErrorResult& aRv);
   void SetExposureCompensation(const dom::Optional<double>& aCompensation, ErrorResult& aRv);
   double GetExposureCompensation(ErrorResult& aRv);
+  int32_t SensorAngle();
   already_AddRefed<nsICameraShutterCallback> GetOnShutter(ErrorResult& aRv);
   void SetOnShutter(nsICameraShutterCallback* aCb, ErrorResult& aRv);
   already_AddRefed<nsICameraClosedCallback> GetOnClosed(ErrorResult& aRv);
   void SetOnClosed(nsICameraClosedCallback* aCb, ErrorResult& aRv);
   already_AddRefed<nsICameraRecorderStateChange> GetOnRecorderStateChange(ErrorResult& aRv);
   void SetOnRecorderStateChange(nsICameraRecorderStateChange* aCb, ErrorResult& aRv);
   void AutoFocus(nsICameraAutoFocusCallback* aOnSuccess, const dom::Optional<nsICameraErrorCallback*>& aOnErro, ErrorResult& aRvr);
   void TakePicture(JSContext* aCx, const dom::CameraPictureOptions& aOptions,
--- a/dom/camera/FallbackCameraControl.cpp
+++ b/dom/camera/FallbackCameraControl.cpp
@@ -19,16 +19,17 @@ class RecorderProfileManager;
 class nsFallbackCameraControl : public CameraControlImpl
 {
 public:
   nsFallbackCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId);
 
   const char* GetParameter(const char* aKey);
   const char* GetParameterConstChar(uint32_t aKey);
   double GetParameterDouble(uint32_t aKey);
+  int32_t GetParameterInt32(uint32_t aKey);
   void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions);
   void GetParameter(uint32_t aKey, idl::CameraSize& aSize);
   void SetParameter(const char* aKey, const char* aValue);
   void SetParameter(uint32_t aKey, const char* aValue);
   void SetParameter(uint32_t aKey, double aValue);
   void SetParameter(uint32_t aKey, const nsTArray<idl::CameraRegion>& aRegions);
   void SetParameter(uint32_t aKey, const idl::CameraSize& aSize);
   nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes);
@@ -96,16 +97,22 @@ nsFallbackCameraControl::GetParameterCon
 }
 
 double
 nsFallbackCameraControl::GetParameterDouble(uint32_t aKey)
 {
   return NAN;
 }
 
+int32_t
+nsFallbackCameraControl::GetParameterInt32(uint32_t aKey)
+{
+  return 0;
+}
+
 void
 nsFallbackCameraControl::GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions)
 {
 }
 
 void
 nsFallbackCameraControl::GetParameter(uint32_t aKey, idl::CameraSize& aSize)
 {
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -429,16 +429,35 @@ nsGonkCameraControl::GetParameterDouble(
       DOM_CAMERA_LOGI("index = %d --> compensation = %f\n", index, val);
       return val;
 
     default:
       return mParams.getFloat(key);
   }
 }
 
+int32_t
+nsGonkCameraControl::GetParameterInt32(uint32_t aKey)
+{
+  if (aKey == CAMERA_PARAM_SENSORANGLE) {
+    if (!mCameraHw.get()) {
+      return 0;
+    }
+    return mCameraHw->GetSensorOrientation();
+  }
+
+  const char* key = getKeyText(aKey);
+  if (!key) {
+    return 0;
+  }
+
+  RwAutoLockRead lock(mRwLock);
+  return mParams.getInt(key);
+}
+
 void
 nsGonkCameraControl::GetParameter(uint32_t aKey,
                                   nsTArray<idl::CameraRegion>& aRegions)
 {
   aRegions.Clear();
 
   const char* key = getKeyText(aKey);
   if (!key) {
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -48,16 +48,17 @@ class nsGonkCameraControl : public Camer
 public:
   nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId);
   void DispatchInit(nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId);
   nsresult Init();
 
   const char* GetParameter(const char* aKey);
   const char* GetParameterConstChar(uint32_t aKey);
   double GetParameterDouble(uint32_t aKey);
+  int32_t GetParameterInt32(uint32_t aKey);
   void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions);
   void GetParameter(uint32_t aKey, nsTArray<idl::CameraSize>& aSizes);
   void GetParameter(uint32_t aKey, idl::CameraSize& aSize);
   void SetParameter(const char* aKey, const char* aValue);
   void SetParameter(uint32_t aKey, const char* aValue);
   void SetParameter(uint32_t aKey, double aValue);
   void SetParameter(uint32_t aKey, const nsTArray<idl::CameraRegion>& aRegions);
   void SetParameter(uint32_t aKey, int aValue);
--- a/dom/camera/ICameraControl.h
+++ b/dom/camera/ICameraControl.h
@@ -41,16 +41,17 @@ public:
   virtual nsresult Set(nsICameraClosedCallback* aOnClosed) = 0;
   virtual nsresult Get(nsICameraClosedCallback** aOnClosed) = 0;
   virtual nsresult Set(nsICameraRecorderStateChange* aOnRecorderStateChange) = 0;
   virtual nsresult Get(nsICameraRecorderStateChange** aOnRecorderStateChange) = 0;
   virtual nsresult Set(nsICameraPreviewStateChange* aOnPreviewStateChange) = 0;
   virtual nsresult Get(nsICameraPreviewStateChange** aOnPreviewStateChange) = 0;
   virtual nsresult Set(uint32_t aKey, const idl::CameraSize& aSize) = 0;
   virtual nsresult Get(uint32_t aKey, idl::CameraSize& aSize) = 0;
+  virtual nsresult Get(uint32_t aKey, int32_t* aValue) = 0;
   virtual nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue) = 0;
   virtual nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue) = 0;
   virtual nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes) = 0;
   virtual already_AddRefed<RecorderProfileManager> GetRecorderProfileManager() = 0;
   virtual uint32_t GetCameraId() = 0;
 
   virtual const char* GetParameter(const char* aKey) = 0;
   virtual const char* GetParameterConstChar(uint32_t aKey) = 0;
--- a/dom/datastore/tests/test_certifiedApp.html
+++ b/dom/datastore/tests/test_certifiedApp.html
@@ -61,34 +61,35 @@
     }
 
     // This event is triggered when the app calls "alert".
     ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
     domParent.appendChild(ifr);
   }
 
   var tests = [
-    function() {
-      ok(!("getDataStores" in navigator), "getDataStores should not exist");
-      runTest();
-    },
-
     // Permissions
     function() {
       SpecialPowers.pushPermissions(
         [{ "type": "browser", "allow": 1, "context": document },
          { "type": "embed-apps", "allow": 1, "context": document },
          { "type": "webapps-manage", "allow": 1, "context": document }], runTest);
     },
 
     // Preferences
     function() {
       SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true],
                                          ["dom.datastore.enabled", true],
-                                         ["dom.testing.ignore_ipc_principal", true]]}, runTest);
+                                         ["dom.testing.ignore_ipc_principal", true],
+                                         ["dom.testing.datastore_enabled_for_hosted_apps", false]]}, runTest);
+    },
+
+    function() {
+      ok(!("getDataStores" in navigator), "getDataStores should not exist");
+      runTest();
     },
 
     function() {
       SpecialPowers.setAllAppsLaunchable(true);
       SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
       runTest();
     },
 
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_cursor_cycle.js
@@ -0,0 +1,46 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var testGenerator = testSteps();
+
+function testSteps()
+{
+  const Bob = { ss: "237-23-7732", name: "Bob" };
+
+  let request = indexedDB.open(this.window ? window.location.pathname : "Splendid Test", 1);
+  request.onerror = errorHandler;
+  request.onupgradeneeded = grabEventAndContinueHandler;
+  let event = yield undefined;
+
+  let db = event.target.result;
+  event.target.onsuccess = continueToNextStep;
+
+  let objectStore = db.createObjectStore("foo", { keyPath: "ss" });
+  objectStore.createIndex("name", "name", { unique: true });
+  objectStore.add(Bob);
+  yield undefined;
+
+  // This direct eval causes locals to be aliased, and thus allocated on
+  // the scope chain.  Comment it out (and the workarounds below) and
+  // the test passes.  Bug 943409.
+  eval('');
+
+  db.transaction("foo", "readwrite").objectStore("foo")
+    .index("name").openCursor().onsuccess = function(event) {
+    event.target.transaction.oncomplete = continueToNextStep;
+    let cursor = event.target.result;
+    if (cursor) {
+      let objectStore = event.target.transaction.objectStore("foo");
+      objectStore.delete(Bob.ss)
+                 .onsuccess = function(event) { cursor.continue(); };
+    }
+  };
+  yield undefined;
+  finishTest();
+
+  objectStore = null; // Bug 943409 workaround.
+
+  yield undefined;
+}
--- a/dom/indexedDB/test/unit/test_cursor_mutation.js
+++ b/dom/indexedDB/test/unit/test_cursor_mutation.js
@@ -30,16 +30,21 @@ function testSteps()
   let event = yield undefined;
 
   let db = event.target.result;
   event.target.onsuccess = continueToNextStep;
 
   let objectStore = db.createObjectStore("foo", { keyPath: "ss" });
   objectStore.createIndex("name", "name", { unique: true });
 
+  // This direct eval causes locals to be aliased, and thus allocated on
+  // the scope chain.  Comment it out (and the workarounds below) and
+  // the test passes.  Bug 943409.
+  eval('');
+
   for (let i = 0; i < objectStoreData.length - 1; i++) {
     objectStore.add(objectStoreData[i]);
   }
   yield undefined;
 
   let count = 0;
 
   let sawAdded = false;
@@ -106,10 +111,13 @@ function testSteps()
     };
   yield undefined;
 
   is(count, objectStoreData.length - 1, "Good final count");
   is(sawAdded, true, "Saw item that was added");
   is(sawRemoved, false, "Didn't see item that was removed");
 
   finishTest();
+
+  objectStore = null; // Bug 943409 workaround.
+
   yield undefined;
 }
--- a/dom/indexedDB/test/unit/test_index_object_cursors.js
+++ b/dom/indexedDB/test/unit/test_index_object_cursors.js
@@ -29,16 +29,19 @@ function testSteps()
   request.onupgradeneeded = grabEventAndContinueHandler;
   let event = yield undefined;
 
   let db = event.target.result;
   db.onerror = errorHandler;
 
   event.target.onsuccess = continueToNextStep;
 
+  // Bug 943409.
+  eval('');
+
   for (let objectStoreIndex in objectStoreData) {
     const objectStoreInfo = objectStoreData[objectStoreIndex];
     let objectStore = db.createObjectStore(objectStoreInfo.name,
                                            objectStoreInfo.options);
     for (let indexIndex in indexData) {
       const indexInfo = indexData[indexIndex];
       let index = objectStore.createIndex(indexInfo.name,
                                           indexInfo.keyPath,
@@ -132,14 +135,16 @@ function testSteps()
       yield undefined;
 
       is(keyIndex, 1, "Saw all the items");
 
       db.transaction(objectStoreName, "readwrite")
         .objectStore(objectStoreName).clear()
         .onsuccess = continueToNextStep;
       yield undefined;
+
+      objectStore = index = null; // Bug 943409 workaround.
     }
   }
 
   finishTest();
   yield undefined;
 }
--- a/dom/indexedDB/test/unit/test_index_update_delete.js
+++ b/dom/indexedDB/test/unit/test_index_update_delete.js
@@ -13,16 +13,19 @@ function testSteps()
   request.onupgradeneeded = grabEventAndContinueHandler;
   request.onsuccess = grabEventAndContinueHandler;
 
   let event = yield undefined;
 
   let db = event.target.result;
   db.onerror = errorHandler;
 
+  // Bug 943409.
+  eval('');
+
   for each (let autoIncrement in [false, true]) {
     let objectStore =
       db.createObjectStore(autoIncrement, { keyPath: "id",
                                             autoIncrement: autoIncrement });
 
     for (let i = 0; i < 10; i++) {
       objectStore.add({ id: i, index: i });
     }
@@ -154,14 +157,18 @@ function testSteps()
       is(event.target.result, objectStoreCount,
          "Correct number of entries in objectStore");
 
       index.count().onsuccess = grabEventAndContinueHandler;
       event = yield undefined;
 
       is(event.target.result, indexCount,
          "Correct number of entries in index");
+
+      index = event = null; // Bug 943409 workaround.
     }
+    objectStore = event = null; // Bug 943409 workaround.
   }
 
   finishTest();
+  event = db = request = null; // Bug 943409 workaround.
   yield undefined;
 }
--- a/dom/indexedDB/test/unit/xpcshell.ini
+++ b/dom/indexedDB/test/unit/xpcshell.ini
@@ -16,16 +16,17 @@ support-files =
 [test_autoIncrement.js]
 [test_autoIncrement_indexes.js]
 [test_clear.js]
 [test_complex_keyPaths.js]
 [test_count.js]
 [test_create_index.js]
 [test_create_index_with_integer_keys.js]
 [test_create_objectStore.js]
+[test_cursor_cycle.js]
 [test_cursor_mutation.js]
 [test_cursor_update_updates_indexes.js]
 [test_cursors.js]
 [test_deleteDatabase.js]
 [test_deleteDatabase_interactions.js]
 [test_event_source.js]
 [test_getAll.js]
 [test_globalObjects_ipc.js]
--- a/dom/messages/SystemMessagePermissionsChecker.jsm
+++ b/dom/messages/SystemMessagePermissionsChecker.jsm
@@ -57,16 +57,19 @@ this.SystemMessagePermissionsTable = {
   },
   "connection": { },
   "dummy-system-message": { }, // for system message testing framework
   "headset-button": { },
   "icc-stkcommand": {
     "settings": ["read", "write"]
   },
   "media-button": { },
+  "networkstats-alarm": {
+    "networkstats-manage": []
+  },
   "notification": {
     "desktop-notification": []
   },
   "push": {
   	"push": []
   },
   "push-register": {
   	"push": []
--- a/dom/network/interfaces/nsIDOMNetworkStatsManager.idl
+++ b/dom/network/interfaces/nsIDOMNetworkStatsManager.idl
@@ -15,17 +15,32 @@ interface nsIDOMMozNetworkStatsInterface
   readonly attribute long type;
 
   /**
    * Id value is '0' for wifi or the iccid for mobile (SIM).
    */
   readonly attribute DOMString id;
 };
 
-[scriptable, uuid(5f033d31-c9a2-4e2d-83aa-6a807f1e0c11)]
+dictionary NetworkStatsAlarmOptions
+{
+  jsval startTime; // Date object
+  jsval data;
+};
+
+[scriptable, builtinclass, uuid(063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c)]
+interface nsIDOMMozNetworkStatsAlarm : nsISupports
+{
+  readonly attribute unsigned long alarmId;
+  readonly attribute nsIDOMMozNetworkStatsInterface network;
+  readonly attribute long threshold;
+  readonly attribute jsval data;
+};
+
+[scriptable,  uuid(50d109b8-0d7f-4208-81fe-5f07a759f159)]
 interface nsIDOMMozNetworkStatsManager : nsISupports
 {
   /**
    * Constants for known interface types.
    */
   const long WIFI = 0;
   const long MOBILE = 1;
 
@@ -38,16 +53,51 @@ interface nsIDOMMozNetworkStatsManager :
    * If success, the request result will be an nsIDOMMozNetworkStats object.
    */
   nsIDOMDOMRequest getSamples(in nsIDOMMozNetworkStatsInterface network,
                               in jsval start,
                               in jsval end,
                               [optional] in DOMString manifestURL);
 
   /**
+   * Install an alarm on a network. The network must be in the return of
+   * getAvailableNetworks() otherwise an "InvalidNetwork" exception will
+   * be raised.
+   *
+   * When total data usage reaches threshold bytes, a "networkstats-alarm"
+   * system message is sent to the application, where the optional parameter
+   * |data| must be a cloneable object.
+   *
+   * If success, the |result| field of the DOMRequest keeps the alarm Id.
+   */
+  nsIDOMDOMRequest addAlarm(in nsIDOMMozNetworkStatsInterface network,
+                            in long threshold,
+                            [optional] in jsval options /* NetworkStatsAlarmOptions */);
+
+  /**
+   * Obtain all alarms for those networks returned by getAvailableNetworks().
+   * If a network is provided, only retrieves the alarms for that network.
+   * The network must be one of those returned by getAvailebleNetworks() or an
+   * "InvalidNetwork" exception will be raised.
+   *
+   * Each alarm object has the same fields as that in the system message:
+   *  - alarmId
+   *  - network
+   *  - threshold
+   *  - data
+   */
+  nsIDOMDOMRequest getAllAlarms([optional] in nsIDOMMozNetworkStatsInterface network);
+
+  /**
+   * Remove all network alarms. If an |alarmId| is provided, then only that
+   * alarm is removed.
+   */
+  nsIDOMDOMRequest removeAlarms([optional] in long alarmId);
+
+  /**
    * Remove all stats related with the provided network from DB.
    */
   nsIDOMDOMRequest clearStats(in nsIDOMMozNetworkStatsInterface network);
 
   /**
    * Remove all stats in the database.
    */
   nsIDOMDOMRequest clearAllStats();
--- a/dom/network/src/NetworkStatsDB.jsm
+++ b/dom/network/src/NetworkStatsDB.jsm
@@ -11,59 +11,60 @@ function debug(s) { dump("-*- NetworkSta
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 Cu.importGlobalProperties(["indexedDB"]);
 
 const DB_NAME = "net_stats";
-const DB_VERSION = 4;
-const STORE_NAME = "net_stats";
+const DB_VERSION = 5;
+const STATS_STORE_NAME = "net_stats";
+const ALARMS_STORE_NAME = "net_alarm";
 
 // Constant defining the maximum values allowed per interface. If more, older
 // will be erased.
 const VALUES_MAX_LENGTH = 6 * 30;
 
 // Constant defining the rate of the samples. Daily.
 const SAMPLE_RATE = 1000 * 60 * 60 * 24;
 
 this.NetworkStatsDB = function NetworkStatsDB() {
   if (DEBUG) {
     debug("Constructor");
   }
-  this.initDBHelper(DB_NAME, DB_VERSION, [STORE_NAME]);
+  this.initDBHelper(DB_NAME, DB_VERSION, [STATS_STORE_NAME, ALARMS_STORE_NAME]);
 }
 
 NetworkStatsDB.prototype = {
   __proto__: IndexedDBHelper.prototype,
 
-  dbNewTxn: function dbNewTxn(txn_type, callback, txnCb) {
+  dbNewTxn: function dbNewTxn(store_name, txn_type, callback, txnCb) {
     function successCb(result) {
       txnCb(null, result);
     }
     function errorCb(error) {
       txnCb(error, null);
     }
-    return this.newTxn(txn_type, STORE_NAME, callback, successCb, errorCb);
+    return this.newTxn(txn_type, store_name, callback, successCb, errorCb);
   },
 
   upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
     if (DEBUG) {
       debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
     }
     let db = aDb;
     let objectStore;
     for (let currVersion = aOldVersion; currVersion < aNewVersion; currVersion++) {
       if (currVersion == 0) {
         /**
          * Create the initial database schema.
          */
 
-        objectStore = db.createObjectStore(STORE_NAME, { keyPath: ["connectionType", "timestamp"] });
+        objectStore = db.createObjectStore(STATS_STORE_NAME, { keyPath: ["connectionType", "timestamp"] });
         objectStore.createIndex("connectionType", "connectionType", { unique: false });
         objectStore.createIndex("timestamp", "timestamp", { unique: false });
         objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
         objectStore.createIndex("txBytes", "txBytes", { unique: false });
         objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
         objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
         if (DEBUG) {
           debug("Created object stores and indexes");
@@ -72,34 +73,34 @@ NetworkStatsDB.prototype = {
         // In order to support per-app traffic data storage, the original
         // objectStore needs to be replaced by a new objectStore with new
         // key path ("appId") and new index ("appId").
         // Also, since now networks are identified by their
         // [networkId, networkType] not just by their connectionType,
         // to modify the keyPath is mandatory to delete the object store
         // and create it again. Old data is going to be deleted because the
         // networkId for each sample can not be set.
-        db.deleteObjectStore(STORE_NAME);
+        db.deleteObjectStore(STATS_STORE_NAME);
 
-        objectStore = db.createObjectStore(STORE_NAME, { keyPath: ["appId", "network", "timestamp"] });
+        objectStore = db.createObjectStore(STATS_STORE_NAME, { keyPath: ["appId", "network", "timestamp"] });
         objectStore.createIndex("appId", "appId", { unique: false });
         objectStore.createIndex("network", "network", { unique: false });
         objectStore.createIndex("networkType", "networkType", { unique: false });
         objectStore.createIndex("timestamp", "timestamp", { unique: false });
         objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
         objectStore.createIndex("txBytes", "txBytes", { unique: false });
         objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
         objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
 
         if (DEBUG) {
           debug("Created object stores and indexes for version 3");
         }
       } else if (currVersion == 3) {
         // Delete redundent indexes (leave "network" only).
-        objectStore = aTransaction.objectStore(STORE_NAME);
+        objectStore = aTransaction.objectStore(STATS_STORE_NAME);
         if (objectStore.indexNames.contains("appId")) {
           objectStore.deleteIndex("appId");
         }
         if (objectStore.indexNames.contains("networkType")) {
           objectStore.deleteIndex("networkType");
         }
         if (objectStore.indexNames.contains("timestamp")) {
           objectStore.deleteIndex("timestamp");
@@ -115,28 +116,92 @@ NetworkStatsDB.prototype = {
         }
         if (objectStore.indexNames.contains("txTotalBytes")) {
           objectStore.deleteIndex("txTotalBytes");
         }
 
         if (DEBUG) {
           debug("Deleted redundent indexes for version 4");
         }
+      } else if (currVersion == 4) {
+        // In order to manage alarms, it is necessary to use a global counter
+        // (totalBytes) that will increase regardless of the system reboot.
+        objectStore = aTransaction.objectStore(STATS_STORE_NAME);
+
+        // Now, systemBytes will hold the old totalBytes and totalBytes will
+        // keep the increasing counter. |counters| will keep the track of
+        // accumulated values.
+        let counters = {};
+
+        objectStore.openCursor().onsuccess = function(event) {
+          let cursor = event.target.result;
+          if (!cursor){
+            return;
+          }
+
+          cursor.value.rxSystemBytes = cursor.value.rxTotalBytes;
+          cursor.value.txSystemBytes = cursor.value.txTotalBytes;
+
+          if (cursor.value.appId == 0) {
+            let netId = cursor.value.network[0] + '' + cursor.value.network[1];
+            if (!counters[netId]) {
+              counters[netId] = {
+                rxCounter: 0,
+                txCounter: 0,
+                lastRx: 0,
+                lastTx: 0
+              };
+            }
+
+            let rxDiff = cursor.value.rxSystemBytes - counters[netId].lastRx;
+            let txDiff = cursor.value.txSystemBytes - counters[netId].lastTx;
+            if (rxDiff < 0 || txDiff < 0) {
+              // System reboot between samples, so take the current one.
+              rxDiff = cursor.value.rxSystemBytes;
+              txDiff = cursor.value.txSystemBytes;
+            }
+
+            counters[netId].rxCounter += rxDiff;
+            counters[netId].txCounter += txDiff;
+            cursor.value.rxTotalBytes = counters[netId].rxCounter;
+            cursor.value.txTotalBytes = counters[netId].txCounter;
+
+            counters[netId].lastRx = cursor.value.rxSystemBytes;
+            counters[netId].lastTx = cursor.value.txSystemBytes;
+          } else {
+            cursor.value.rxTotalBytes = cursor.value.rxSystemBytes;
+            cursor.value.txTotalBytes = cursor.value.txSystemBytes;
+          }
+
+          cursor.update(cursor.value);
+          cursor.continue();
+        };
+
+        // Create object store for alarms.
+        objectStore = db.createObjectStore(ALARMS_STORE_NAME, { keyPath: "id", autoIncrement: true });
+        objectStore.createIndex("alarm", ['networkId','threshold'], { unique: false });
+        objectStore.createIndex("manifestURL", "manifestURL", { unique: false });
+
+        if (DEBUG) {
+          debug("Created alarms store for version 5");
+        }
       }
     }
   },
 
   importData: function importData(aStats) {
-    let stats = { appId:        aStats.appId,
-                  network:      [aStats.networkId, aStats.networkType],
-                  timestamp:    aStats.timestamp,
-                  rxBytes:      aStats.rxBytes,
-                  txBytes:      aStats.txBytes,
-                  rxTotalBytes: aStats.rxTotalBytes,
-                  txTotalBytes: aStats.txTotalBytes };
+    let stats = { appId:         aStats.appId,
+                  network:       [aStats.networkId, aStats.networkType],
+                  timestamp:     aStats.timestamp,
+                  rxBytes:       aStats.rxBytes,
+                  txBytes:       aStats.txBytes,
+                  rxSystemBytes: aStats.rxSystemBytes,
+                  txSystemBytes: aStats.txSystemBytes,
+                  rxTotalBytes:  aStats.rxTotalBytes,
+                  txTotalBytes:  aStats.txTotalBytes };
 
     return stats;
   },
 
   exportData: function exportData(aStats) {
     let stats = { appId:        aStats.appId,
                   networkId:    aStats.network[0],
                   networkType:  aStats.network[1],
@@ -155,28 +220,30 @@ NetworkStatsDB.prototype = {
     let timestamp = aDate.getTime() - aDate.getTimezoneOffset() * 60 * 1000;
     timestamp = Math.floor(timestamp / SAMPLE_RATE) * SAMPLE_RATE;
     return timestamp;
   },
 
   saveStats: function saveStats(aStats, aResultCb) {
     let timestamp = this.normalizeDate(aStats.date);
 
-    let stats = { appId:        aStats.appId,
-                  networkId:    aStats.networkId,
-                  networkType:  aStats.networkType,
-                  timestamp:    timestamp,
-                  rxBytes:      (aStats.appId == 0) ? 0 : aStats.rxBytes,
-                  txBytes:      (aStats.appId == 0) ? 0 : aStats.txBytes,
-                  rxTotalBytes: (aStats.appId == 0) ? aStats.rxBytes : 0,
-                  txTotalBytes: (aStats.appId == 0) ? aStats.txBytes : 0 };
+    let stats = { appId:         aStats.appId,
+                  networkId:     aStats.networkId,
+                  networkType:   aStats.networkType,
+                  timestamp:     timestamp,
+                  rxBytes:       (aStats.appId == 0) ? 0 : aStats.rxBytes,
+                  txBytes:       (aStats.appId == 0) ? 0 : aStats.txBytes,
+                  rxSystemBytes: (aStats.appId == 0) ? aStats.rxBytes : 0,
+                  txSystemBytes: (aStats.appId == 0) ? aStats.txBytes : 0,
+                  rxTotalBytes:  (aStats.appId == 0) ? aStats.rxBytes : 0,
+                  txTotalBytes:  (aStats.appId == 0) ? aStats.txBytes : 0 };
 
     stats = this.importData(stats);
 
-    this.dbNewTxn("readwrite", function(aTxn, aStore) {
+    this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
       if (DEBUG) {
         debug("Filtered time: " + new Date(timestamp));
         debug("New stats: " + JSON.stringify(stats));
       }
 
     let request = aStore.index("network").openCursor(stats.network, "prev");
       request.onsuccess = function onsuccess(event) {
         let cursor = event.target.result;
@@ -236,31 +303,39 @@ NetworkStatsDB.prototype = {
             lastSample.timestamp + " - diff: " + diff);
     }
 
     // If the incoming data is obtained from netd (|newSample.appId| is 0),
     // the new |txBytes|/|rxBytes| is assigend by the differnce between the new
     // |txTotalBytes|/|rxTotalBytes| and the last |txTotalBytes|/|rxTotalBytes|.
     // Else, the incoming data is per-app data (|newSample.appId| is not 0),
     // the |txBytes|/|rxBytes| is directly the new |txBytes|/|rxBytes|.
+    let rxDiff = 0;
+    let txDiff = 0;
     if (aNewSample.appId == 0) {
-      let rxDiff = aNewSample.rxTotalBytes - lastSample.rxTotalBytes;
-      let txDiff = aNewSample.txTotalBytes - lastSample.txTotalBytes;
+      rxDiff = aNewSample.rxSystemBytes - lastSample.rxSystemBytes;
+      txDiff = aNewSample.txSystemBytes - lastSample.txSystemBytes;
       if (rxDiff < 0 || txDiff < 0) {
-        rxDiff = aNewSample.rxTotalBytes;
-        txDiff = aNewSample.txTotalBytes;
+        rxDiff = aNewSample.rxSystemBytes;
+        txDiff = aNewSample.txSystemBytes;
       }
       aNewSample.rxBytes = rxDiff;
       aNewSample.txBytes = txDiff;
+
+      aNewSample.rxTotalBytes = lastSample.rxTotalBytes + rxDiff;
+      aNewSample.txTotalBytes = lastSample.txTotalBytes + txDiff;
+    } else {
+      rxDiff = aNewSample.rxBytes;
+      txDiff = aNewSample.txBytes;
     }
 
     if (diff == 1) {
       // New element.
 
-      // If the incoming data is per-data data, new |rxTotalBytes|/|txTotalBytes|
+      // If the incoming data is per-app data, new |rxTotalBytes|/|txTotalBytes|
       // needs to be obtained by adding new |rxBytes|/|txBytes| to last
       // |rxTotalBytes|/|txTotalBytes|.
       if (aNewSample.appId != 0) {
         aNewSample.rxTotalBytes = aNewSample.rxBytes + lastSample.rxTotalBytes;
         aNewSample.txTotalBytes = aNewSample.txBytes + lastSample.txTotalBytes;
       }
 
       this._saveStats(aTxn, aStore, aNewSample);
@@ -272,53 +347,48 @@ NetworkStatsDB.prototype = {
       // Add lost samples with 0 bytes and the actual one.
       if (diff > VALUES_MAX_LENGTH) {
         diff = VALUES_MAX_LENGTH;
       }
 
       let data = [];
       for (let i = diff - 2; i >= 0; i--) {
         let time = aNewSample.timestamp - SAMPLE_RATE * (i + 1);
-        let sample = { appId:        aNewSample.appId,
-                       network:      aNewSample.network,
-                       timestamp:    time,
-                       rxBytes:      0,
-                       txBytes:      0,
-                       rxTotalBytes: lastSample.rxTotalBytes,
-                       txTotalBytes: lastSample.txTotalBytes };
+        let sample = { appId:         aNewSample.appId,
+                       network:       aNewSample.network,
+                       timestamp:     time,
+                       rxBytes:       0,
+                       txBytes:       0,
+                       rxSystemBytes: lastSample.rxSystemBytes,
+                       txSystemBytes: lastSample.txSystemBytes,
+                       rxTotalBytes:  lastSample.rxTotalBytes,
+                       txTotalBytes:  lastSample.txTotalBytes };
 
         data.push(sample);
       }
 
       data.push(aNewSample);
       this._saveStats(aTxn, aStore, data);
       return;
     }
     if (diff == 0 || diff < 0) {
-      // New element received before samplerate period.
-      // It means that device has been restarted (or clock / timezone change).
-      // Update element.
-
-      // If diff < 0, clock or timezone changed back. Place data in the last sample.
-
-      lastSample.rxBytes += aNewSample.rxBytes;
-      lastSample.txBytes += aNewSample.txBytes;
+      // New element received before samplerate period. It means that device has
+      // been restarted (or clock / timezone change).
+      // Update element. If diff < 0, clock or timezone changed back. Place data
+      // in the last sample.
 
-      // If incoming data is obtained from netd, last |rxTotalBytes|/|txTotalBytes|
-      // needs to get updated by replacing the new |rxTotalBytes|/|txTotalBytes|.
-      if (aNewSample.appId == 0) {
-        lastSample.rxTotalBytes = aNewSample.rxTotalBytes;
-        lastSample.txTotalBytes = aNewSample.txTotalBytes;
-      } else {
-        // Else, the incoming data is per-app data, old |rxTotalBytes|/
-        // |txTotalBytes| needs to get updated by adding the new
-        // |rxBytes|/|txBytes| to last |rxTotalBytes|/|txTotalBytes|.
-        lastSample.rxTotalBytes += aNewSample.rxBytes;
-        lastSample.txTotalBytes += aNewSample.txBytes;
-      }
+      // Old |rxTotalBytes|/|txTotalBytes| needs to get updated by adding the
+      // last |rxTotalBytes|/|txTotalBytes|.
+      lastSample.rxBytes += rxDiff;
+      lastSample.txBytes += txDiff;
+      lastSample.rxSystemBytes = aNewSample.rxSystemBytes;
+      lastSample.txSystemBytes = aNewSample.txSystemBytes;
+      lastSample.rxTotalBytes += rxDiff;
+      lastSample.txTotalBytes += txDiff;
+
       if (DEBUG) {
         debug("Update: " + JSON.stringify(lastSample));
       }
       let req = aLastSampleCursor.update(lastSample);
     }
   },
 
   _saveStats: function _saveStats(aTxn, aStore, aNetworkStats) {
@@ -374,17 +444,17 @@ NetworkStatsDB.prototype = {
     };
   },
 
   clearInterfaceStats: function clearInterfaceStats(aNetwork, aResultCb) {
     let network = [aNetwork.id, aNetwork.type];
     let self = this;
 
     // Clear and save an empty sample to keep sync with system counters
-    this.dbNewTxn("readwrite", function(aTxn, aStore) {
+    this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
       let sample = null;
       let request = aStore.index("network").openCursor(network, "prev");
       request.onsuccess = function onsuccess(event) {
         let cursor = event.target.result;
         if (cursor) {
           if (!sample && cursor.value.appId == 0) {
             sample = cursor.value;
           }
@@ -426,29 +496,56 @@ NetworkStatsDB.prototype = {
 
     if (!aNetworks[index]) {
       aResultCb(null, true);
       return;
     }
     this.clearInterfaceStats(aNetworks[index], callback);
   },
 
+  getCurrentStats: function getCurrentStats(aNetwork, aDate, aResultCb) {
+    if (DEBUG) {
+      debug("Get current stats for " + JSON.stringify(aNetwork) + " since " + aDate);
+    }
+
+    this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
+      let request = null;
+      let network = [aNetwork.id, aNetwork.type];
+      if (aDate) {
+        let start = this.normalizeDate(aDate);
+        let lowerFilter = [0, network, start];
+        let range = this.dbGlobal.IDBKeyRange.lowerBound(lowerFilter, false);
+        request = store.openCursor(range);
+      } else {
+        request = store.index("network").openCursor(network, "prev");
+      }
+
+      request.onsuccess = function onsuccess(event) {
+        txn.result = null;
+        let cursor = event.target.result;
+        if (cursor) {
+          txn.result = cursor.value;
+        }
+      };
+    }.bind(this), aResultCb);
+  },
+
   find: function find(aResultCb, aNetwork, aStart, aEnd, aAppId, aManifestURL) {
     let offset = (new Date()).getTimezoneOffset() * 60 * 1000;
     let start = this.normalizeDate(aStart);
     let end = this.normalizeDate(aEnd);
 
     if (DEBUG) {
       debug("Find samples for appId: " + aAppId + " network " +
             JSON.stringify(aNetwork) + " from " + start + " until " + end);
       debug("Start time: " + new Date(start));
       debug("End time: " + new Date(end));
     }
 
-    this.dbNewTxn("readonly", function(aTxn, aStore) {
+    this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
       let network = [aNetwork.id, aNetwork.type];
       let lowerFilter = [aAppId, network, start];
       let upperFilter = [aAppId, network, end];
       let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
 
       let data = [];
 
       if (!aTxn.result) {
@@ -498,17 +595,17 @@ NetworkStatsDB.prototype = {
     while (aEnd > aData[aData.length - 1].date.getTime()) {
       aData.push({ rxBytes: undefined,
                    txBytes: undefined,
                    date: new Date(aData[aData.length - 1].date.getTime() + SAMPLE_RATE) });
     }
   },
 
   getAvailableNetworks: function getAvailableNetworks(aResultCb) {
-    this.dbNewTxn("readonly", function(aTxn, aStore) {
+    this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
       if (!aTxn.result) {
         aTxn.result = [];
       }
 
       let request = aStore.index("network").openKeyCursor(null, "nextunique");
       request.onsuccess = function onsuccess(event) {
         let cursor = event.target.result;
         if (cursor) {
@@ -517,17 +614,17 @@ NetworkStatsDB.prototype = {
           cursor.continue();
           return;
         }
       };
     }, aResultCb);
   },
 
   isNetworkAvailable: function isNetworkAvailable(aNetwork, aResultCb) {
-    this.dbNewTxn("readonly", function(aTxn, aStore) {
+    this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
       if (!aTxn.result) {
         aTxn.result = false;
       }
 
       var network = [aNetwork.id, aNetwork.type];
       let request = aStore.index("network").openKeyCursor(IDBKeyRange.only(network));
       request.onsuccess = function onsuccess(event) {
         if (event.target.result) {
@@ -541,15 +638,164 @@ NetworkStatsDB.prototype = {
     return SAMPLE_RATE;
   },
 
   get maxStorageSamples () {
     return VALUES_MAX_LENGTH;
   },
 
   logAllRecords: function logAllRecords(aResultCb) {
-    this.dbNewTxn("readonly", function(aTxn, aStore) {
+    this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
       aStore.mozGetAll().onsuccess = function onsuccess(event) {
         aTxn.result = event.target.result;
       };
     }, aResultCb);
   },
+
+  alarmToRecord: function alarmToRecord(aAlarm) {
+    let record = { networkId: aAlarm.networkId,
+                   threshold: aAlarm.threshold,
+                   data: aAlarm.data,
+                   manifestURL: aAlarm.manifestURL,
+                   pageURL: aAlarm.pageURL };
+
+    if (aAlarm.id) {
+      record.id = aAlarm.id;
+    }
+
+    return record;
+  },
+
+  recordToAlarm: function recordToalarm(aRecord) {
+    let alarm = { networkId: aRecord.networkId,
+                  threshold: aRecord.threshold,
+                  data: aRecord.data,
+                  manifestURL: aRecord.manifestURL,
+                  pageURL: aRecord.pageURL };
+
+    if (aRecord.id) {
+      alarm.id = aRecord.id;
+    }
+
+    return alarm;
+  },
+
+  addAlarm: function addAlarm(aAlarm, aResultCb) {
+    this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
+      if (DEBUG) {
+        debug("Going to add " + JSON.stringify(aAlarm));
+      }
+
+      let record = this.alarmToRecord(aAlarm);
+      store.put(record).onsuccess = function setResult(aEvent) {
+        txn.result = aEvent.target.result;
+        if (DEBUG) {
+          debug("Request successful. New record ID: " + txn.result);
+        }
+      };
+    }.bind(this), aResultCb);
+  },
+
+  getFirstAlarm: function getFirstAlarm(aNetworkId, aResultCb) {
+    let self = this;
+
+    this.dbNewTxn(ALARMS_STORE_NAME, "readonly", function(txn, store) {
+      if (DEBUG) {
+        debug("Get first alarm for network " + aNetworkId);
+      }
+
+      let lowerFilter = [aNetworkId, 0];
+      let upperFilter = [aNetworkId, ""];
+      let range = IDBKeyRange.bound(lowerFilter, upperFilter);
+
+      store.index("alarm").openCursor(range).onsuccess = function onsuccess(event) {
+        let cursor = event.target.result;
+        txn.result = null;
+        if (cursor) {
+          txn.result = self.recordToAlarm(cursor.value);
+        }
+      };
+    }, aResultCb);
+  },
+
+  removeAlarm: function removeAlarm(aAlarmId, aManifestURL, aResultCb) {
+    this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
+      if (DEBUG) {
+        debug("Remove alarm " + aAlarmId);
+      }
+
+      store.get(aAlarmId).onsuccess = function onsuccess(event) {
+        let record = event.target.result;
+        txn.result = false;
+        if (!record || (aManifestURL && record.manifestURL != aManifestURL)) {
+          return;
+        }
+
+        store.delete(aAlarmId);
+        txn.result = true;
+      }
+    }, aResultCb);
+  },
+
+  removeAlarms: function removeAlarms(aManifestURL, aResultCb) {
+    this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
+      if (DEBUG) {
+        debug("Remove alarms of " + aManifestURL);
+      }
+
+      store.index("manifestURL").openCursor(aManifestURL)
+                                .onsuccess = function onsuccess(event) {
+        let cursor = event.target.result;
+        if (cursor) {
+          cursor.delete();
+          cursor.continue();
+        }
+      }
+    }, aResultCb);
+  },
+
+  updateAlarm: function updateAlarm(aAlarm, aResultCb) {
+    let self = this;
+    this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
+      if (DEBUG) {
+        debug("Update alarm " + aAlarm.id);
+      }
+
+      let record = self.alarmToRecord(aAlarm);
+      store.openCursor(record.id).onsuccess = function onsuccess(event) {
+        let cursor = event.target.result;
+        txn.result = false;
+        if (cursor) {
+          cursor.update(record);
+          txn.result = true;
+        }
+      }
+    }, aResultCb);
+  },
+
+  getAlarms: function getAlarms(aNetworkId, aManifestURL, aResultCb) {
+    this.dbNewTxn(ALARMS_STORE_NAME, "readonly", function(txn, store) {
+      if (DEBUG) {
+        debug("Get alarms for " + aManifestURL);
+      }
+
+      txn.result = [];
+      store.index("manifestURL").openCursor(aManifestURL)
+                                .onsuccess = function onsuccess(event) {
+        let cursor = event.target.result;
+        if (!cursor) {
+          return;
+        }
+
+        if (!aNetworkId || cursor.value.networkId == aNetworkId) {
+          let alarm = { id: cursor.value.id,
+                        networkId: cursor.value.networkId,
+                        threshold: cursor.value.threshold,
+                        data: cursor.value.data };
+
+          txn.result.push(alarm);
+        }
+
+        cursor.continue();
+      }
+    }, aResultCb);
+  }
 };
--- a/dom/network/src/NetworkStatsManager.js
+++ b/dom/network/src/NetworkStatsManager.js
@@ -25,74 +25,74 @@ if (isParentProcess) {
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsISyncMessageSender");
 
 // NetworkStatsData
 const nsIClassInfo              = Ci.nsIClassInfo;
 const NETWORKSTATSDATA_CID      = Components.ID("{3b16fe17-5583-483a-b486-b64a3243221c}");
-const nsIDOMMozNetworkStatsData = Components.interfaces.nsIDOMMozNetworkStatsData;
+const nsIDOMMozNetworkStatsData = Ci.nsIDOMMozNetworkStatsData;
 
 function NetworkStatsData(aData) {
   this.rxBytes = aData.rxBytes;
   this.txBytes = aData.txBytes;
   this.date = aData.date;
 }
 
 NetworkStatsData.prototype = {
   __exposedProps__: {
-                      rxBytes: 'r',
-                      txBytes: 'r',
-                      date:  'r',
-                     },
+    rxBytes: 'r',
+    txBytes: 'r',
+    date:  'r',
+  },
 
   classID : NETWORKSTATSDATA_CID,
   classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATSDATA_CID,
                                      contractID:"@mozilla.org/networkstatsdata;1",
                                      classDescription: "NetworkStatsData",
                                      interfaces: [nsIDOMMozNetworkStatsData],
                                      flags: nsIClassInfo.DOM_OBJECT}),
 
   QueryInterface : XPCOMUtils.generateQI([nsIDOMMozNetworkStatsData])
 };
 
 // NetworkStatsInterface
 const NETWORKSTATSINTERFACE_CONTRACTID = "@mozilla.org/networkstatsinterface;1";
 const NETWORKSTATSINTERFACE_CID        = Components.ID("{f540615b-d803-43ff-8200-2a9d145a5645}");
-const nsIDOMMozNetworkStatsInterface   = Components.interfaces.nsIDOMMozNetworkStatsInterface;
+const nsIDOMMozNetworkStatsInterface   = Ci.nsIDOMMozNetworkStatsInterface;
 
 function NetworkStatsInterface(aNetwork) {
   if (DEBUG) {
     debug("NetworkStatsInterface Constructor");
   }
   this.type = aNetwork.type;
   this.id = aNetwork.id;
 }
 
 NetworkStatsInterface.prototype = {
   __exposedProps__: {
-                      id: 'r',
-                      type: 'r',
-                    },
+    id: 'r',
+    type: 'r',
+  },
 
   classID : NETWORKSTATSINTERFACE_CID,
   classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATSINTERFACE_CID,
                                      contractID: NETWORKSTATSINTERFACE_CONTRACTID,
                                      classDescription: "NetworkStatsInterface",
                                      interfaces: [nsIDOMMozNetworkStatsInterface],
                                      flags: nsIClassInfo.DOM_OBJECT}),
 
   QueryInterface : XPCOMUtils.generateQI([nsIDOMMozNetworkStatsInterface])
 }
 
 // NetworkStats
 const NETWORKSTATS_CONTRACTID = "@mozilla.org/networkstats;1";
 const NETWORKSTATS_CID        = Components.ID("{b6fc4b14-628d-4c99-bf4e-e4ed56916cbe}");
-const nsIDOMMozNetworkStats   = Components.interfaces.nsIDOMMozNetworkStats;
+const nsIDOMMozNetworkStats   = Ci.nsIDOMMozNetworkStats;
 
 function NetworkStats(aWindow, aStats) {
   if (DEBUG) {
     debug("NetworkStats Constructor");
   }
   this.manifestURL = aStats.manifestURL || null;
   this.network = new NetworkStatsInterface(aStats.network);
   this.start = aStats.start || null;
@@ -101,40 +101,69 @@ function NetworkStats(aWindow, aStats) {
   let samples = this.data = Cu.createArrayIn(aWindow);
   for (let i = 0; i < aStats.data.length; i++) {
     samples.push(new NetworkStatsData(aStats.data[i]));
   }
 }
 
 NetworkStats.prototype = {
   __exposedProps__: {
-                      manifestURL: 'r',
-                      network: 'r',
-                      start: 'r',
-                      end:  'r',
-                      data:  'r',
-                    },
+    manifestURL: 'r',
+    network: 'r',
+    start: 'r',
+    end:  'r',
+    data:  'r',
+  },
 
   classID : NETWORKSTATS_CID,
   classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATS_CID,
                                      contractID: NETWORKSTATS_CONTRACTID,
                                      classDescription: "NetworkStats",
                                      interfaces: [nsIDOMMozNetworkStats],
                                      flags: nsIClassInfo.DOM_OBJECT}),
 
   QueryInterface : XPCOMUtils.generateQI([nsIDOMMozNetworkStats,
                                           nsIDOMMozNetworkStatsData,
                                           nsIDOMMozNetworkStatsInterface])
 }
 
+// NetworkStatsAlarm
+const NETWORKSTATSALARM_CID      = Components.ID("{063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c}");
+const nsIDOMMozNetworkStatsAlarm = Ci.nsIDOMMozNetworkStatsAlarm;
+
+function NetworkStatsAlarm(aAlarm) {
+  this.alarmId = aAlarm.id;
+  this.network = new NetworkStatsInterface(aAlarm.network);
+  this.threshold = aAlarm.threshold;
+  this.data = aAlarm.data;
+}
+
+NetworkStatsAlarm.prototype = {
+  __exposedProps__: {
+    alarmId: 'r',
+    network: 'r',
+    threshold: 'r',
+    data: 'r',
+  },
+
+  classID : NETWORKSTATSALARM_CID,
+  classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATSALARM_CID,
+                                     contractID:"@mozilla.org/networkstatsalarm;1",
+                                     classDescription: "NetworkStatsAlarm",
+                                     interfaces: [nsIDOMMozNetworkStatsAlarm],
+                                     flags: nsIClassInfo.DOM_OBJECT}),
+
+  QueryInterface : XPCOMUtils.generateQI([nsIDOMMozNetworkStatsAlarm])
+};
+
 // NetworkStatsManager
 
 const NETWORKSTATSMANAGER_CONTRACTID = "@mozilla.org/networkStatsManager;1";
-const NETWORKSTATSMANAGER_CID        = Components.ID("{5f033d31-c9a2-4e2d-83aa-6a807f1e0c11}");
-const nsIDOMMozNetworkStatsManager   = Components.interfaces.nsIDOMMozNetworkStatsManager;
+const NETWORKSTATSMANAGER_CID        = Components.ID("{50d109b8-0d7f-4208-81fe-5f07a759f159}");
+const nsIDOMMozNetworkStatsManager   = Ci.nsIDOMMozNetworkStatsManager;
 
 function NetworkStatsManager() {
   if (DEBUG) {
     debug("Constructor");
   }
 }
 
 NetworkStatsManager.prototype = {
@@ -184,16 +213,62 @@ NetworkStatsManager.prototype = {
     this.checkPrivileges();
 
     let request = this.createRequest();
     cpmm.sendAsyncMessage("NetworkStats:ClearAll",
                           {id: this.getRequestId(request)});
     return request;
   },
 
+  addAlarm: function addAlarm(aNetwork, aThreshold, aOptions) {
+    this.checkPrivileges();
+
+    if (!aOptions) {
+      aOptions = Object.create(null);
+    }
+
+    let request = this.createRequest();
+    cpmm.sendAsyncMessage("NetworkStats:SetAlarm",
+                          {id: this.getRequestId(request),
+                           data: {network: aNetwork,
+                                  threshold: aThreshold,
+                                  startTime: aOptions.startTime,
+                                  data: aOptions.data,
+                                  manifestURL: this.manifestURL,
+                                  pageURL: this.pageURL}});
+    return request;
+  },
+
+  getAllAlarms: function getAllAlarms(aNetwork) {
+    this.checkPrivileges();
+
+    let request = this.createRequest();
+    cpmm.sendAsyncMessage("NetworkStats:GetAlarms",
+                          {id: this.getRequestId(request),
+                           data: {network: aNetwork,
+                                  manifestURL: this.manifestURL}});
+    return request;
+  },
+
+  removeAlarms: function removeAlarms(aAlarmId) {
+    this.checkPrivileges();
+
+    if (aAlarmId == 0) {
+      aAlarmId = -1;
+    }
+
+    let request = this.createRequest();
+    cpmm.sendAsyncMessage("NetworkStats:RemoveAlarms",
+                          {id: this.getRequestId(request),
+                           data: {alarmId: aAlarmId,
+                                  manifestURL: this.manifestURL}});
+
+    return request;
+  },
+
   getAvailableNetworks: function getAvailableNetworks() {
     this.checkPrivileges();
 
     let request = this.createRequest();
     cpmm.sendAsyncMessage("NetworkStats:GetAvailableNetworks",
                           { id: this.getRequestId(request) });
     return request;
   },
@@ -207,18 +282,18 @@ NetworkStatsManager.prototype = {
     this.checkPrivileges();
     return cpmm.sendSyncMessage("NetworkStats:MaxStorageAge")[0];
   },
 
   receiveMessage: function(aMessage) {
     if (DEBUG) {
       debug("NetworkStatsmanager::receiveMessage: " + aMessage.name);
     }
+
     let msg = aMessage.json;
-
     let req = this.takeRequest(msg.id);
     if (!req) {
       if (DEBUG) {
         debug("No request stored with id " + msg.id);
       }
       return;
     }
 
@@ -255,16 +330,40 @@ NetworkStatsManager.prototype = {
         if (msg.error) {
           Services.DOMRequest.fireError(req, msg.error);
           return;
         }
 
         Services.DOMRequest.fireSuccess(req, true);
         break;
 
+      case "NetworkStats:SetAlarm:Return":
+      case "NetworkStats:RemoveAlarms:Return":
+        if (msg.error) {
+          Services.DOMRequest.fireError(req, msg.error);
+          return;
+        }
+
+        Services.DOMRequest.fireSuccess(req, msg.result);
+        break;
+
+      case "NetworkStats:GetAlarms:Return":
+        if (msg.error) {
+          Services.DOMRequest.fireError(req, msg.error);
+          return;
+        }
+
+        let alarms = Cu.createArrayIn(this._window);
+        for (let i = 0; i < msg.result.length; i++) {
+          alarms.push(new NetworkStatsAlarm(msg.result[i]));
+        }
+
+        Services.DOMRequest.fireSuccess(req, alarms);
+        break;
+
       default:
         if (DEBUG) {
           debug("Wrong message: " + aMessage.name);
         }
     }
   },
 
   init: function(aWindow) {
@@ -288,17 +387,31 @@ NetworkStatsManager.prototype = {
 
     if (!this.hasPrivileges) {
       return null;
     }
 
     this.initDOMRequestHelper(aWindow, ["NetworkStats:Get:Return",
                                         "NetworkStats:GetAvailableNetworks:Return",
                                         "NetworkStats:Clear:Return",
-                                        "NetworkStats:ClearAll:Return"]);
+                                        "NetworkStats:ClearAll:Return",
+                                        "NetworkStats:SetAlarm:Return",
+                                        "NetworkStats:GetAlarms:Return",
+                                        "NetworkStats:RemoveAlarms:Return"]);
+
+    // Init app properties.
+    let appsService = Cc["@mozilla.org/AppsService;1"]
+                        .getService(Ci.nsIAppsService);
+
+    this.manifestURL = appsService.getManifestURLByLocalId(principal.appId);
+
+    let isApp = !!this.manifestURL.length;
+    if (isApp) {
+      this.pageURL = principal.URI.spec;
+    }
   },
 
   // Called from DOMRequestIpcHelper
   uninit: function uninit() {
     if (DEBUG) {
       debug("uninit call");
     }
   },
@@ -311,12 +424,13 @@ NetworkStatsManager.prototype = {
 
   classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATSMANAGER_CID,
                                      contractID: NETWORKSTATSMANAGER_CONTRACTID,
                                      classDescription: "NetworkStatsManager",
                                      interfaces: [nsIDOMMozNetworkStatsManager],
                                      flags: nsIClassInfo.DOM_OBJECT})
 }
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsData,
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsAlarm,
+                                                     NetworkStatsData,
                                                      NetworkStatsInterface,
                                                      NetworkStats,
                                                      NetworkStatsManager]);
--- a/dom/network/src/NetworkStatsManager.manifest
+++ b/dom/network/src/NetworkStatsManager.manifest
@@ -2,11 +2,14 @@ component {3b16fe17-5583-483a-b486-b64a3
 contract @mozilla.org/networkStatsdata;1 {3b16fe17-5583-483a-b486-b64a3243221c}
 
 component {b6fc4b14-628d-4c99-bf4e-e4ed56916cbe} NetworkStatsManager.js
 contract @mozilla.org/networkStats;1 {b6fc4b14-628d-4c99-bf4e-e4ed56916cbe}
 
 component {f540615b-d803-43ff-8200-2a9d145a5645} NetworkStatsManager.js
 contract @mozilla.org/networkstatsinterface;1 {f540615b-d803-43ff-8200-2a9d145a5645}
 
-component {5f033d31-c9a2-4e2d-83aa-6a807f1e0c11} NetworkStatsManager.js
-contract @mozilla.org/networkStatsManager;1 {5f033d31-c9a2-4e2d-83aa-6a807f1e0c11}
+component {063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c} NetworkStatsManager.js
+contract @mozilla.org/networkstatsalarm;1 {063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c}
+
+component {50d109b8-0d7f-4208-81fe-5f07a759f159} NetworkStatsManager.js
+contract @mozilla.org/networkStatsManager;1 {50d109b8-0d7f-4208-81fe-5f07a759f159}
 category JavaScript-navigator-property mozNetworkStats @mozilla.org/networkStatsManager;1
--- a/dom/network/src/NetworkStatsService.jsm
+++ b/dom/network/src/NetworkStatsService.jsm
@@ -17,16 +17,18 @@ this.EXPORTED_SYMBOLS = ["NetworkStatsSe
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetworkStatsDB.jsm");
 
 const NET_NETWORKSTATSSERVICE_CONTRACTID = "@mozilla.org/network/netstatsservice;1";
 const NET_NETWORKSTATSSERVICE_CID = Components.ID("{18725604-e9ac-488a-8aa0-2471e7f6c0a4}");
 
+const TOPIC_BANDWIDTH_CONTROL = "netd-bandwidth-control"
+
 const TOPIC_INTERFACE_REGISTERED   = "network-interface-registered";
 const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
 const NET_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
 const NET_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
 
 // The maximum traffic amount can be saved in the |cachedAppStats|.
 const MAX_CACHED_TRAFFIC = 500 * 1000 * 1000; // 500 MB
 
@@ -45,23 +47,28 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyServiceGetter(this, "appsService",
                                    "@mozilla.org/AppsService;1",
                                    "nsIAppsService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
 
+XPCOMUtils.defineLazyServiceGetter(this, "messenger",
+                                   "@mozilla.org/system-message-internal;1",
+                                   "nsISystemMessagesInternal");
+
 this.NetworkStatsService = {
   init: function() {
     debug("Service started");
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
     Services.obs.addObserver(this, TOPIC_INTERFACE_REGISTERED, false);
     Services.obs.addObserver(this, TOPIC_INTERFACE_UNREGISTERED, false);
+    Services.obs.addObserver(this, TOPIC_BANDWIDTH_CONTROL, false);
     Services.obs.addObserver(this, "profile-after-change", false);
 
     this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 
     // Object to store network interfaces, each network interface is composed
     // by a network object (network type and network Id) and a interfaceName
     // that contains the name of the physical interface (wlan0, rmnet0, etc.).
     // The network type can be 0 for wifi or 1 for mobile. On the other hand,
@@ -82,16 +89,19 @@ this.NetworkStatsService = {
     let netId = this.getNetworkId('0', NET_TYPE_WIFI);
     this._networks[netId] = { network:       { id: '0',
                                                type: NET_TYPE_WIFI },
                               interfaceName: null };
 
     this.messages = ["NetworkStats:Get",
                      "NetworkStats:Clear",
                      "NetworkStats:ClearAll",
+                     "NetworkStats:SetAlarm",
+                     "NetworkStats:GetAlarms",
+                     "NetworkStats:RemoveAlarms",
                      "NetworkStats:GetAvailableNetworks",
                      "NetworkStats:SampleRate",
                      "NetworkStats:MaxStorageAge"];
 
     this.messages.forEach(function(aMsgName) {
       ppmm.addMessageListener(aMsgName, this);
     }, this);
 
@@ -102,16 +112,19 @@ this.NetworkStatsService = {
                                 Ci.nsITimer.TYPE_REPEATING_PRECISE);
 
     // App stats are firstly stored in the cached.
     this.cachedAppStats = Object.create(null);
     this.cachedAppStatsDate = new Date();
 
     this.updateQueue = [];
     this.isQueueRunning = false;
+
+    this._currentAlarms = {};
+    this.initAlarms();
   },
 
   receiveMessage: function(aMessage) {
     if (!aMessage.target.assertPermission("networkstats-manage")) {
       return;
     }
 
     debug("receiveMessage " + aMessage.name);
@@ -124,16 +137,25 @@ this.NetworkStatsService = {
         this.getSamples(mm, msg);
         break;
       case "NetworkStats:Clear":
         this.clearInterfaceStats(mm, msg);
         break;
       case "NetworkStats:ClearAll":
         this.clearDB(mm, msg);
         break;
+      case "NetworkStats:SetAlarm":
+        this.setAlarm(mm, msg);
+        break;
+      case "NetworkStats:GetAlarms":
+        this.getAlarms(mm, msg);
+        break;
+      case "NetworkStats:RemoveAlarms":
+        this.removeAlarms(mm, msg);
+        break;
       case "NetworkStats:GetAvailableNetworks":
         this.getAvailableNetworks(mm, msg);
         break;
       case "NetworkStats:SampleRate":
         // This message is sync.
         return this._db.sampleRate;
       case "NetworkStats:MaxStorageAge":
         // This message is sync.
@@ -141,42 +163,61 @@ this.NetworkStatsService = {
     }
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case TOPIC_INTERFACE_REGISTERED:
       case TOPIC_INTERFACE_UNREGISTERED:
 
-        // If new interface is registered (notified from NetworkManager),
+        // If new interface is registered (notified from NetworkService),
         // the stats are updated for the new interface without waiting to
         // complete the updating period.
 
         let network = aSubject.QueryInterface(Ci.nsINetworkInterface);
         debug("Network " + network.name + " of type " + network.type + " status change");
 
         let netId = this.convertNetworkInterface(network);
         if (!netId) {
           break;
         }
 
+        this._updateCurrentAlarm(netId);
+
         debug("NetId: " + netId);
         this.updateStats(netId);
         break;
+
+      case TOPIC_BANDWIDTH_CONTROL:
+        debug("Bandwidth message from netd: " + JSON.stringify(aData));
+
+        let interfaceName = aData.substring(aData.lastIndexOf(" ") + 1);
+        for (let networkId in this._networks) {
+          if (interfaceName == this._networks[networkId].interfaceName) {
+            let currentAlarm = this._currentAlarms[networkId];
+            if (Object.getOwnPropertyNames(currentAlarm).length !== 0) {
+              this._fireAlarm(currentAlarm.alarm);
+            }
+            break;
+          }
+        }
+        break;
+
       case "xpcom-shutdown":
         debug("Service shutdown");
 
         this.messages.forEach(function(aMsgName) {
           ppmm.removeMessageListener(aMsgName, this);
         }, this);
 
         Services.obs.removeObserver(this, "xpcom-shutdown");
         Services.obs.removeObserver(this, "profile-after-change");
         Services.obs.removeObserver(this, TOPIC_INTERFACE_REGISTERED);
         Services.obs.removeObserver(this, TOPIC_INTERFACE_UNREGISTERED);
+        Services.obs.removeObserver(this, TOPIC_BANDWIDTH_CONTROL);
 
         this.timer.cancel();
         this.timer = null;
 
         // Update stats before shutdown
         this.updateAllStats();
         break;
     }
@@ -261,16 +302,35 @@ this.NetworkStatsService = {
         }
       }
 
       mm.sendAsyncMessage("NetworkStats:GetAvailableNetworks:Return",
                           { id: msg.id, error: aError, result: aResult });
     });
   },
 
+  initAlarms: function initAlarms() {
+    debug("Init usage alarms");
+    let self = this;
+
+    for (let netId in this._networks) {
+      this._currentAlarms[netId] = Object.create(null);
+
+      this._db.getFirstAlarm(netId, function getResult(error, result) {
+        if (!error && result) {
+          self._setAlarm(result, function onSet(error, success) {
+            if (error == "InvalidStateError") {
+              self._fireAlarm(result);
+            }
+          });
+        }
+      });
+    }
+  },
+
   /*
    * Function called from manager to get stats from database.
    * In order to return updated stats, first is performed a call to
    * updateAllStats function, which will get last stats from netd
    * and update the database.
    * Then, depending on the request (stats per appId or total stats)
    * it retrieve them from database and return to the manager.
    */
@@ -477,18 +537,18 @@ this.NetworkStatsService = {
       let item = this.updateQueue.shift();
       for (let callback of item.callbacks) {
         if(callback) {
           callback(aResult, aMessage);
         }
       }
     } else {
       // The caller is a function that has pushed new elements to the queue,
-      // if isQueueRunning is false it means there is no processing currently being
-      // done, so start.
+      // if isQueueRunning is false it means there is no processing currently
+      // being done, so start.
       if (this.isQueueRunning) {
         if(this.updateQueue.length > 1) {
           return;
         }
       } else {
         this.isQueueRunning = true;
       }
     }
@@ -510,17 +570,17 @@ this.NetworkStatsService = {
         aCallback(false, "Invalid network " + aNetId);
       }
       return;
     }
 
     let interfaceName = this._networks[aNetId].interfaceName;
     debug("Update stats for " + interfaceName);
 
-    // Request stats to NetworkManager, which will get stats from netd, passing
+    // Request stats to NetworkService, which will get stats from netd, passing
     // 'networkStatsAvailable' as a callback.
     if (interfaceName) {
       networkService.getNetworkInterfaceStats(interfaceName,
                 this.networkStatsAvailable.bind(this, aCallback, aNetId));
       return;
     }
 
     if (aCallback) {
@@ -701,11 +761,267 @@ this.NetworkStatsService = {
         return;
       }
 
       debug("===== LOG =====");
       debug("There are " + aResult.length + " items");
       debug(JSON.stringify(aResult));
     });
   },
+
+  getAlarms: function getAlarms(mm, msg) {
+    let network = msg.data.network;
+    let manifestURL = msg.data.manifestURL;
+
+    let netId = null;
+    if (network) {
+      netId = this.getNetworkId(network.id, network.type);
+      if (!this._networks[netId]) {
+        mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
+                            { id: msg.id, error: "InvalidInterface", result: null });
+        return;
+      }
+    }
+
+    let self = this;
+    this._db.getAlarms(netId, manifestURL, function onCompleted(error, result) {
+      if (error) {
+        mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
+                            { id: msg.id, error: error, result: result });
+        return;
+      }
+
+      let alarms = []
+      // NetworkStatsManager must return the network instead of the networkId.
+      for (let i = 0; i < result.length; i++) {
+        let alarm = result[i];
+        alarms.push({ id: alarm.id,
+                      network: self._networks[alarm.networkId].network,
+                      threshold: alarm.threshold,
+                      data: alarm.data });
+      }
+
+      mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
+                          { id: msg.id, error: null, result: alarms });
+    });
+  },
+
+  removeAlarms: function removeAlarms(mm, msg) {
+    let alarmId = msg.data.alarmId;
+    let manifestURL = msg.data.manifestURL;
+
+    let self = this;
+    let callback = function onRemove(error, result) {
+      if (error) {
+        mm.sendAsyncMessage("NetworkStats:RemoveAlarms:Return",
+                            { id: msg.id, error: error, result: result });
+        return;
+      }
+
+      for (let i in self._currentAlarms) {
+        let currentAlarm = self._currentAlarms[i].alarm;
+        if (currentAlarm && ((alarmId == currentAlarm.id) ||
+            (alarmId == -1 && currentAlarm.manifestURL == manifestURL))) {
+
+          self._updateCurrentAlarm(currentAlarm.networkId);
+        }
+      }
+
+      mm.sendAsyncMessage("NetworkStats:RemoveAlarms:Return",
+                          { id: msg.id, error: error, result: true });
+    };
+
+    if (alarmId == -1) {
+      this._db.removeAlarms(manifestURL, callback);
+    } else {
+      this._db.removeAlarm(alarmId, manifestURL, callback);
+    }
+  },
+
+  /*
+   * Function called from manager to set an alarm.
+   */
+  setAlarm: function setAlarm(mm, msg) {
+    let options = msg.data;
+    let network = options.network;
+    let threshold = options.threshold;
+
+    debug("Set alarm at " + threshold + " for " + JSON.stringify(network));
+
+    if (threshold < 0) {
+      mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
+                          { id: msg.id, error: "InvalidThresholdValue", result: null });
+      return;
+    }
+
+    let netId = this.getNetworkId(network.id, network.type);
+    if (!this._networks[netId]) {
+      mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
+                          { id: msg.id, error: "InvalidiConnectionType", result: null });
+      return;
+    }
+
+    let newAlarm = {
+      id: null,
+      networkId: netId,
+      threshold: threshold,
+      absoluteThreshold: null,
+      startTime: options.startTime,
+      data: options.data,
+      pageURL: options.pageURL,
+      manifestURL: options.manifestURL
+    };
+
+    let self = this;
+    this._updateThreshold(newAlarm, function onUpdate(error, _threshold) {
+      if (error) {
+        mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
+                            { id: msg.id, error: error, result: null });
+        return;
+      }
+
+      newAlarm.absoluteThreshold = _threshold.absoluteThreshold;
+      self._db.addAlarm(newAlarm, function addSuccessCb(error, newId) {
+        if (error) {
+          mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
+                              { id: msg.id, error: error, result: null });
+          return;
+        }
+
+        newAlarm.id = newId;
+        self._setAlarm(newAlarm, function onSet(error, success) {
+          mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
+                              { id: msg.id, error: error, result: newId });
+
+          if (error == "InvalidStateError") {
+            self._fireAlarm(newAlarm);
+          }
+        });
+      });
+    });
+  },
+
+  _setAlarm: function _setAlarm(aAlarm, aCallback) {
+    let currentAlarm = this._currentAlarms[aAlarm.networkId];
+    if (Object.getOwnPropertyNames(currentAlarm).length !== 0 &&
+        aAlarm.absoluteThreshold > currentAlarm.alarm.absoluteThreshold) {
+      aCallback(null, true);
+      return;
+    }
+
+    let self = this;
+
+    this._updateThreshold(aAlarm, function onUpdate(aError, aThreshold) {
+      if (aError) {
+        aCallback(aError, null);
+        return;
+      }
+
+      let callback = function onAlarmSet(aError) {
+        if (aError) {
+          debug("Set alarm error: " + aError);
+          aCallback("netdError", null);
+          return;
+        }
+
+        self._currentAlarms[aAlarm.networkId].alarm = aAlarm;
+
+        aCallback(null, true);
+      };
+
+      debug("Set alarm " + JSON.stringify(aAlarm));
+      let interfaceName = self._networks[aAlarm.networkId].interfaceName;
+      if (interfaceName) {
+        networkService.setNetworkInterfaceAlarm(interfaceName,
+                                                aThreshold.systemThreshold,
+                                                callback);
+        return;
+      }
+
+      aCallback(null, true);
+    });
+  },
+
+  _updateThreshold: function _updateThreshold(aAlarm, aCallback) {
+    let self = this;
+    this.updateStats(aAlarm.networkId, function onStatsUpdated(aResult, aMessage) {
+      self._db.getCurrentStats(self._networks[aAlarm.networkId].network,
+                               aAlarm.startTime,
+                               function onStatsFound(error, result) {
+        if (error) {
+          debug("Error getting stats for " +
+                JSON.stringify(self._networks[aAlarm.networkId]) + ": " + error);
+          aCallback(error, result);
+          return;
+        }
+
+        let offset = aAlarm.threshold - result.rxTotalBytes - result.txTotalBytes;
+
+        // Alarm set to a threshold lower than current rx/tx bytes.
+        if (offset <= 0) {
+          aCallback("InvalidStateError", null);
+          return;
+        }
+
+        let threshold = {
+          systemThreshold: result.rxSystemBytes + result.txSystemBytes + offset,
+          absoluteThreshold: result.rxTotalBytes + result.txTotalBytes + offset
+        };
+
+        aCallback(null, threshold);
+      });
+    });
+  },
+
+  _fireAlarm: function _fireAlarm(aAlarm) {
+    debug("Fire alarm");
+
+    let self = this;
+    this._db.removeAlarm(aAlarm.id, null, function onRemove(aError, aResult){
+      if (!aError && !aResult) {
+        return;
+      }
+
+      self._fireSystemMessage(aAlarm);
+      self._updateCurrentAlarm(aAlarm.networkId);
+    });
+  },
+
+  _updateCurrentAlarm: function _updateCurrentAlarm(aNetworkId) {
+    this._currentAlarms[aNetworkId] = Object.create(null);
+
+    let self = this;
+    this._db.getFirstAlarm(aNetworkId, function onGet(error, result){
+      if (error) {
+        debug("Error getting the first alarm");
+        return;
+      }
+
+      if (!result) {
+        let interfaceName = self._networks[aNetworkId].interfaceName;
+        networkService.setNetworkInterfaceAlarm(interfaceName, -1,
+                                                function onComplete(){});
+        return;
+      }
+
+      self._setAlarm(result, function onSet(error, success){
+        if (error == "InvalidStateError") {
+          self._fireAlarm(result);
+          return;
+        }
+      });
+    });
+  },
+
+  _fireSystemMessage: function _fireSystemMessage(aAlarm) {
+    debug("Fire system message: " + JSON.stringify(aAlarm));
+
+    let manifestURI = Services.io.newURI(aAlarm.manifestURL, null, null);
+    let pageURI = Services.io.newURI(aAlarm.pageURL, null, null);
+
+    let alarm = { "id":        aAlarm.id,
+                  "threshold": aAlarm.threshold,
+                  "data":      aAlarm.data };
+    messenger.sendMessage("networkstats-alarm", alarm, pageURI, manifestURI);
+  }
 };
 
 NetworkStatsService.init();
--- a/dom/network/tests/Makefile.in
+++ b/dom/network/tests/Makefile.in
@@ -10,10 +10,11 @@ MOCHITEST_FILES = \
   $(NULL)
 
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 MOCHITEST_FILES = \
   test_networkstats_basics.html \
   test_networkstats_disabled.html \
   test_networkstats_enabled_no_perm.html \
   test_networkstats_enabled_perm.html \
+  test_networkstats_alarms.html \
   $(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/test_networkstats_alarms.html
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for NetworkStats alarms</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+function test() {
+  ok(true, "Checking if no alarms are set.");
+
+  req = navigator.mozNetworkStats.getAllAlarms();
+
+  req.onsuccess = function () {
+    ok(true, "Succeeded to get alarms.");
+    ok(Array.isArray(req.result) && req.result.length == 0,
+       "There are no alarms set.");
+    next();
+  };
+
+  req.onerror = function () {
+    ok(false, "getAllAlarms() shouldn't fail!");
+  }
+}
+
+var req;
+var index = -1;
+
+var wifi = {'type': 0, 'id': '0'};
+var mobile = {'type': 1, 'id': '1'};
+
+var steps = [
+  function () {
+    ok(true, "Calling getAllAlarms() with invalid network.");
+
+    req = navigator.mozNetworkStats.getAllAlarms(mobile);
+
+    req.onsuccess = function () {
+      ok(false, "getAllAlarms() shouldn't succeed!");
+    };
+
+    req.onerror = function () {
+      ok(req.error.name == "InvalidInterface", "Get InvalidInterface error");
+      next();
+    }
+  },
+  function () {
+    ok(true, "Calling addAlarm() with invalid network or parameters.");
+
+    try {
+      navigator.mozNetworkStats.addAlarm();
+    } catch(ex) {
+      ok(ex.result == SpecialPowers.Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS,
+         "addAlarm() throws NS_ERROR_XPC_NOT_ENOUGH_ARGS exception when no parameters");
+    }
+
+    try {
+      navigator.mozNetworkStats.addAlarm(100000);
+    } catch(ex) {
+      ok(ex.result == SpecialPowers.Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS,
+         "addAlarm() throws NS_ERROR_XPC_NOT_ENOUGH_ARGS exception when no network");
+    }
+
+    try {
+      navigator.mozNetworkStats.addAlarm(wifi);
+    } catch(ex) {
+      ok(ex.result == SpecialPowers.Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS,
+         "addAlarm() throws NS_ERROR_XPC_NOT_ENOUGH_ARGS exception when no threshold");
+    }
+
+    req = navigator.mozNetworkStats.addAlarm(mobile, -100000);
+
+    req.onsuccess = function () {
+      ok(false, "addAlarm() shouldn't succeed with negative threshold.");
+    };
+
+    req.onerror = function () {
+      ok(req.error.name == "InvalidThresholdValue", "Get InvalidThresholdValue error");
+      next();
+    }
+  },
+  function () {
+    ok(true, "Calling addAlarm()");
+
+    req = navigator.mozNetworkStats.addAlarm(wifi, 1000000);
+
+    req.onsuccess = function () {
+      ok(true, "Succeeded to add alarm. AlarmId: " + req.result);
+      next();
+    };
+    req.onerror = function () {
+      ok(false, "addAlarm() shouldn't fail.");
+    };
+  },
+  function () {
+    ok(true, "Calling getAllAlarms()");
+
+    req = navigator.mozNetworkStats.getAllAlarms(wifi);
+
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Only one alarm");
+      ok(req.result[0].alarmId == 1, "Get correct alarmId");
+      next();
+    };
+
+    req.onerror = function () {
+      ok(false, "getAllAlarms() shouldn't fail.");
+    }
+  },
+  function () {
+    ok(true, "Calling removeAlarms() to remove alarms.");
+
+    req = navigator.mozNetworkStats.removeAlarms();
+
+    req.onsuccess = function () {
+      ok(req.result, "Succeeded to remove alarms.");
+      next();
+    };
+
+    req.onerror = function () {
+      ok(false, "removeAlarms() shouldn't fail.");
+    }
+  },
+  function () {
+    ok(true, "Checking if all alarms are removed.");
+
+    req = navigator.mozNetworkStats.getAllAlarms();
+
+    req.onsuccess = function () {
+      ok(Array.isArray(req.result) && req.result.length == 0,
+         "Succeeded to remove all alarms.");
+      next();
+    };
+
+    req.onerror = function () {
+      ok(false, "getAllAlarms() shouldn't fail.");
+    }
+  },
+  function () {
+    ok(true, "all done!\n");
+    SpecialPowers.removePermission("networkstats-manage", document);
+    SimpleTest.finish();
+    return;
+  }
+];
+
+function next() {
+  index += 1;
+  if (index >= steps.length) {
+    ok(false, "Shouldn't get here!");
+    return;
+  }
+  try {
+    steps[index]();
+  } catch(ex) {
+    ok(false, "Caught exception", ex);
+  }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.addPermission("networkstats-manage", true, document);
+SpecialPowers.pushPrefEnv({'set': [["dom.mozNetworkStats.enabled", true]]}, test);
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/network/tests/test_networkstats_basics.html
+++ b/dom/network/tests/test_networkstats_basics.html
@@ -8,20 +8,18 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 function test() {
-  ok('mozNetworkStats' in navigator, "navigator.mozMozNetworkStats should exist");
-  ok(navigator.mozNetworkStats, "navigator.mozNetworkStats returns an object");
-
-  netStats = navigator.mozNetworkStats;
+  netStats = window.navigator.mozNetworkStats;
+  ok(netStats, "mozNetworkStats exists");
 
   // Test IDL attributes
   ok('sampleRate' in netStats,
    "sampleRate should be a NetworkStats attribute");
   ok(netStats.sampleRate > 0,
    "sampleRate is greater than 0.");
 
   ok('maxStorageAge' in netStats,
--- a/dom/network/tests/unit_stats/test_networkstats_db.js
+++ b/dom/network/tests/unit_stats/test_networkstats_db.js
@@ -2,22 +2,38 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/NetworkStatsDB.jsm");
 
 const netStatsDb = new NetworkStatsDB();
 
-function clearWholeDB(callback) {
-  netStatsDb.dbNewTxn("readwrite", function(aTxn, aStore) {
-    aStore.delete();
+function clearStore(store, callback) {
+  netStatsDb.dbNewTxn(store, "readwrite", function(aTxn, aStore) {
+    aStore.openCursor().onsuccess = function (event) {
+      let cursor = event.target.result;
+      if (cursor){
+        cursor.delete();
+        cursor.continue();
+      }
+    };
   }, callback);
 }
 
+add_test(function prepareDatabase() {
+  // Clear whole database to avoid starting tests with unknown state
+  // due to the previous tests.
+  clearStore('net_stats', function() {
+    clearStore('net_alarm', function() {
+      run_next_test();
+    });
+  });
+});
+
 function filterTimestamp(date) {
   var sampleRate = netStatsDb.sampleRate;
   var offset = date.getTimezoneOffset() * 60 * 1000;
   return Math.floor((date.getTime() - offset) / sampleRate) * sampleRate;
 }
 
 function getNetworks() {
   return [{ id: '0', type: Ci.nsIDOMMozNetworkStatsManager.WIFI },
@@ -117,37 +133,41 @@ add_test(function test_clear_interface()
     do_check_eq(error, null);
     run_next_test();
   });
 });
 
 add_test(function test_internalSaveStats_singleSample() {
   var networks = getNetworks();
 
-  var stats = { appId:        0,
-                network:      [networks[0].id, networks[0].type],
-                timestamp:    Date.now(),
-                rxBytes:      0,
-                txBytes:      0,
-                rxTotalBytes: 1234,
-                txTotalBytes: 1234 };
+  var stats = { appId:         0,
+                network:       [networks[0].id, networks[0].type],
+                timestamp:     Date.now(),
+                rxBytes:       0,
+                txBytes:       0,
+                rxSystemBytes: 1234,
+                txSystemBytes: 1234,
+                rxTotalBytes:  1234,
+                txTotalBytes:  1234 };
 
-  netStatsDb.dbNewTxn("readwrite", function(txn, store) {
+  netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
     netStatsDb._saveStats(txn, store, stats);
   }, function(error, result) {
     do_check_eq(error, null);
 
     netStatsDb.logAllRecords(function(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.length, 1);
       do_check_eq(result[0].appId, stats.appId);
       do_check_true(compareNetworks(result[0].network, stats.network));
       do_check_eq(result[0].timestamp, stats.timestamp);
       do_check_eq(result[0].rxBytes, stats.rxBytes);
       do_check_eq(result[0].txBytes, stats.txBytes);
+      do_check_eq(result[0].rxSystemBytes, stats.rxSystemBytes);
+      do_check_eq(result[0].txSystemBytes, stats.txSystemBytes);
       do_check_eq(result[0].rxTotalBytes, stats.rxTotalBytes);
       do_check_eq(result[0].txTotalBytes, stats.txTotalBytes);
       run_next_test();
     });
   });
 });
 
 add_test(function test_internalSaveStats_arraySamples() {
@@ -156,45 +176,48 @@ add_test(function test_internalSaveStats
   netStatsDb.clearStats(networks, function (error, result) {
     do_check_eq(error, null);
 
     var network = [networks[0].id, networks[0].type];
 
     var samples = 2;
     var stats = [];
     for (var i = 0; i < samples; i++) {
-      stats.push({ appId:        0,
-                   network:      network,
-                   timestamp:    Date.now() + (10 * i),
-                   rxBytes:      0,
-                   txBytes:      0,
-                   rxTotalBytes: 1234,
-                   txTotalBytes: 1234 });
+      stats.push({ appId:         0,
+                   network:       network,
+                   timestamp:     Date.now() + (10 * i),
+                   rxBytes:       0,
+                   txBytes:       0,
+                   rxSystemBytes: 1234,
+                   txSystemBytes: 1234,
+                   rxTotalBytes:  1234,
+                   txTotalBytes:  1234 });
     }
 
-    netStatsDb.dbNewTxn("readwrite", function(txn, store) {
+    netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
       netStatsDb._saveStats(txn, store, stats);
     }, function(error, result) {
       do_check_eq(error, null);
 
       netStatsDb.logAllRecords(function(error, result) {
         do_check_eq(error, null);
 
         // Result has one sample more than samples because clear inserts
         // an empty sample to keep totalBytes synchronized with netd counters
         result.shift();
         do_check_eq(result.length, samples);
-
         var success = true;
         for (var i = 1; i < samples; i++) {
           if (result[i].appId != stats[i].appId ||
               !compareNetworks(result[i].network, stats[i].network) ||
               result[i].timestamp != stats[i].timestamp ||
               result[i].rxBytes != stats[i].rxBytes ||
               result[i].txBytes != stats[i].txBytes ||
+              result[i].rxSystemBytes != stats[i].rxSystemBytes ||
+              result[i].txSystemBytes != stats[i].txSystemBytes ||
               result[i].rxTotalBytes != stats[i].rxTotalBytes ||
               result[i].txTotalBytes != stats[i].txTotalBytes) {
             success = false;
             break;
           }
         }
         do_check_true(success);
         run_next_test();
@@ -208,28 +231,30 @@ add_test(function test_internalRemoveOld
 
   netStatsDb.clearStats(networks, function (error, result) {
     do_check_eq(error, null);
 
     var network = [networks[0].id, networks[0].type];
     var samples = 10;
     var stats = [];
     for (var i = 0; i < samples - 1; i++) {
-      stats.push({ appId:              0,
-                   network:      network, timestamp:    Date.now() + (10 * i),
-                   rxBytes:            0, txBytes:      0,
-                   rxTotalBytes:    1234, txTotalBytes: 1234 });
+      stats.push({ appId:               0,
+                   network:       network, timestamp:     Date.now() + (10 * i),
+                   rxBytes:             0, txBytes:       0,
+                   rxSystemBytes:    1234, txSystemBytes: 1234,
+                   rxTotalBytes:     1234, txTotalBytes:  1234 });
     }
 
-    stats.push({ appId:              0,
-                 network:      network, timestamp:    Date.now() + (10 * samples),
-                 rxBytes:            0, txBytes:      0,
-                 rxTotalBytes:    1234, txTotalBytes: 1234 });
+    stats.push({ appId:               0,
+                 network:       network, timestamp:     Date.now() + (10 * samples),
+                 rxBytes:             0, txBytes:       0,
+                 rxSystemBytes:    1234, txSystemBytes: 1234,
+                 rxTotalBytes:     1234, txTotalBytes:  1234 });
 
-    netStatsDb.dbNewTxn("readwrite", function(txn, store) {
+    netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
       netStatsDb._saveStats(txn, store, stats);
       var date = stats[stats.length - 1].timestamp
                  + (netStatsDb.sampleRate * netStatsDb.maxStorageSamples - 1) - 1;
       netStatsDb._removeOldStats(txn, store, 0, network, date);
     }, function(error, result) {
       do_check_eq(error, null);
 
       netStatsDb.logAllRecords(function(error, result) {
@@ -240,20 +265,20 @@ add_test(function test_internalRemoveOld
       });
     });
   });
 });
 
 function processSamplesDiff(networks, lastStat, newStat, callback) {
   netStatsDb.clearStats(networks, function (error, result){
     do_check_eq(error, null);
-    netStatsDb.dbNewTxn("readwrite", function(txn, store) {
+    netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
       netStatsDb._saveStats(txn, store, lastStat);
     }, function(error, result) {
-      netStatsDb.dbNewTxn("readwrite", function(txn, store) {
+      netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
         let request = store.index("network").openCursor(newStat.network, "prev");
         request.onsuccess = function onsuccess(event) {
           let cursor = event.target.result;
           do_check_neq(cursor, null);
           netStatsDb._processSamplesDiff(txn, store, cursor, newStat);
         };
       }, function(error, result) {
         do_check_eq(error, null);
@@ -268,122 +293,135 @@ function processSamplesDiff(networks, la
 
 add_test(function test_processSamplesDiffSameSample() {
   var networks = getNetworks();
   var network = [networks[0].id, networks[0].type];
 
   var sampleRate = netStatsDb.sampleRate;
   var date = filterTimestamp(new Date());
 
-  var lastStat = { appId:              0,
-                   network:      network, timestamp:    date,
-                   rxBytes:            0, txBytes:      0,
-                   rxTotalBytes:    1234, txTotalBytes: 1234 };
+  var lastStat = { appId:               0,
+                   network:       network, timestamp:     date,
+                   rxBytes:             0, txBytes:       0,
+                   rxSystemBytes:    1234, txSystemBytes: 1234,
+                   rxTotalBytes:     2234, txTotalBytes:  2234 };
 
-  var newStat = { appId:              0,
-                  network:      network, timestamp:    date,
-                  rxBytes:            0, txBytes:      0,
-                  rxTotalBytes:    2234, txTotalBytes: 2234 };
+  var newStat = { appId:               0,
+                  network:       network, timestamp:     date,
+                  rxBytes:             0, txBytes:       0,
+                  rxSystemBytes:    2234, txSystemBytes: 2234,
+                  rxTotalBytes:     2234, txTotalBytes:  2234 };
 
   processSamplesDiff(networks, lastStat, newStat, function(result) {
     do_check_eq(result.length, 1);
     do_check_eq(result[0].appId, newStat.appId);
     do_check_true(compareNetworks(result[0].network, newStat.network));
     do_check_eq(result[0].timestamp, newStat.timestamp);
-    do_check_eq(result[0].rxBytes, newStat.rxTotalBytes - lastStat.rxTotalBytes);
-    do_check_eq(result[0].txBytes, newStat.txTotalBytes - lastStat.txTotalBytes);
-    do_check_eq(result[0].rxTotalBytes, newStat.rxTotalBytes);
-    do_check_eq(result[0].txTotalBytes, newStat.txTotalBytes);
+    do_check_eq(result[0].rxBytes, newStat.rxSystemBytes - lastStat.rxSystemBytes);
+    do_check_eq(result[0].txBytes, newStat.txSystemBytes - lastStat.txSystemBytes);
+    do_check_eq(result[0].rxTotalBytes, lastStat.rxTotalBytes + newStat.rxSystemBytes - lastStat.rxSystemBytes);
+    do_check_eq(result[0].txTotalBytes, lastStat.txTotalBytes + newStat.txSystemBytes - lastStat.txSystemBytes);
+    do_check_eq(result[0].rxSystemBytes, newStat.rxSystemBytes);
+    do_check_eq(result[0].txSystemBytes, newStat.txSystemBytes);
     run_next_test();
   });
 });
 
 add_test(function test_processSamplesDiffNextSample() {
   var networks = getNetworks();
   var network = [networks[0].id, networks[0].type];
 
   var sampleRate = netStatsDb.sampleRate;
   var date = filterTimestamp(new Date());
 
-  var lastStat = { appId:              0,
-                   network:      network, timestamp:    date,
-                   rxBytes:            0, txBytes:      0,
-                   rxTotalBytes:    1234, txTotalBytes: 1234 };
+  var lastStat = { appId:               0,
+                   network:       network, timestamp:     date,
+                   rxBytes:             0, txBytes:       0,
+                   rxSystemBytes:    1234, txSystemBytes: 1234,
+                   rxTotalBytes:     2234, txTotalBytes:  2234 };
 
-  var newStat = { appId:              0,
-                  network:      network, timestamp:    date + sampleRate,
-                  rxBytes:            0, txBytes:      0,
-                  rxTotalBytes:     500, txTotalBytes: 500 };
+  var newStat = { appId:               0,
+                  network:       network, timestamp:     date + sampleRate,
+                  rxBytes:             0, txBytes:       0,
+                  rxSystemBytes:    1734, txSystemBytes: 1734,
+                  rxTotalBytes:        0, txTotalBytes:  0 };
 
   processSamplesDiff(networks, lastStat, newStat, function(result) {
     do_check_eq(result.length, 2);
     do_check_eq(result[1].appId, newStat.appId);
     do_check_true(compareNetworks(result[1].network, newStat.network));
     do_check_eq(result[1].timestamp, newStat.timestamp);
-    do_check_eq(result[1].rxBytes, newStat.rxTotalBytes);
-    do_check_eq(result[1].txBytes, newStat.txTotalBytes);
-    do_check_eq(result[1].rxTotalBytes, newStat.rxTotalBytes);
-    do_check_eq(result[1].txTotalBytes, newStat.txTotalBytes);
+    do_check_eq(result[1].rxBytes, newStat.rxSystemBytes - lastStat.rxSystemBytes);
+    do_check_eq(result[1].txBytes, newStat.txSystemBytes - lastStat.txSystemBytes);
+    do_check_eq(result[1].rxSystemBytes, newStat.rxSystemBytes);
+    do_check_eq(result[1].txSystemBytes, newStat.txSystemBytes);
+    do_check_eq(result[1].rxTotalBytes, lastStat.rxTotalBytes + newStat.rxSystemBytes - lastStat.rxSystemBytes);
+    do_check_eq(result[1].txTotalBytes, lastStat.txTotalBytes + newStat.txSystemBytes - lastStat.txSystemBytes);
     run_next_test();
   });
 });
 
 add_test(function test_processSamplesDiffSamplesLost() {
   var networks = getNetworks();
   var network = [networks[0].id, networks[0].type];
   var samples = 5;
   var sampleRate = netStatsDb.sampleRate;
   var date = filterTimestamp(new Date());
-  var lastStat = { appId:             0,
-                   network:     network, timestamp:    date,
-                   rxBytes:           0, txBytes:      0,
-                   rxTotalBytes:   1234, txTotalBytes: 1234 };
+  var lastStat = { appId:              0,
+                   network:      network, timestamp:     date,
+                   rxBytes:            0, txBytes:       0,
+                   rxSystemBytes:   1234, txSystemBytes: 1234,
+                   rxTotalBytes:    2234, txTotalBytes:  2234};
 
-  var newStat = { appId:              0,
-                  network:      network, timestamp:    date + (sampleRate * samples),
-                  rxBytes:            0, txBytes:      0,
-                  rxTotalBytes:    2234, txTotalBytes: 2234 };
+  var newStat = { appId:               0,
+                  network:       network, timestamp:     date + (sampleRate * samples),
+                  rxBytes:             0, txBytes:       0,
+                  rxSystemBytes:    2234, txSystemBytes: 2234,
+                  rxTotalBytes:        0, txTotalBytes:  0 };
 
   processSamplesDiff(networks, lastStat, newStat, function(result) {
     do_check_eq(result.length, samples + 1);
     do_check_eq(result[0].appId, newStat.appId);
     do_check_true(compareNetworks(result[samples].network, newStat.network));
     do_check_eq(result[samples].timestamp, newStat.timestamp);
     do_check_eq(result[samples].rxBytes, newStat.rxTotalBytes - lastStat.rxTotalBytes);
     do_check_eq(result[samples].txBytes, newStat.txTotalBytes - lastStat.txTotalBytes);
-    do_check_eq(result[samples].rxTotalBytes, newStat.rxTotalBytes);
-    do_check_eq(result[samples].txTotalBytes, newStat.txTotalBytes);
+    do_check_eq(result[samples].rxSystemBytes, newStat.rxSystemBytes);
+    do_check_eq(result[samples].txSystemBytes, newStat.txSystemBytes);
+    do_check_eq(result[samples].rxTotalBytes, lastStat.rxTotalBytes + newStat.rxSystemBytes - lastStat.rxSystemBytes);
+    do_check_eq(result[samples].txTotalBytes, lastStat.txTotalBytes + newStat.txSystemBytes - lastStat.txSystemBytes);
     run_next_test();
   });
 });
 
 add_test(function test_saveStats() {
   var networks = getNetworks();
   var network = [networks[0].id, networks[0].type];
 
   var stats = { appId:       0,
                 networkId:   networks[0].id,
                 networkType: networks[0].type,
                 date:        new Date(),
                 rxBytes:     2234,
                 txBytes:     2234};
 
-  netStatsDb.clearStats(networks, function (error, result) {
-    do_check_eq(error, null);
+  clearStore('net_stats', function() {
     netStatsDb.saveStats(stats, function(error, result) {
       do_check_eq(error, null);
       netStatsDb.logAllRecords(function(error, result) {
         do_check_eq(error, null);
         do_check_eq(result.length, 1);
         do_check_eq(result[0].appId, stats.appId);
         do_check_true(compareNetworks(result[0].network, network));
         let timestamp = filterTimestamp(stats.date);
         do_check_eq(result[0].timestamp, timestamp);
-        do_check_eq(result[0].rxBytes, 0);
-        do_check_eq(result[0].txBytes, 0);
+        do_check_eq(result[0].rxBytes, stats.rxBytes);
+        do_check_eq(result[0].txBytes, stats.txBytes);
+        do_check_eq(result[0].rxSystemBytes, stats.rxBytes);
+        do_check_eq(result[0].txSystemBytes, stats.txBytes);
         do_check_eq(result[0].rxTotalBytes, stats.rxBytes);
         do_check_eq(result[0].txTotalBytes, stats.txBytes);
         run_next_test();
       });
     });
   });
 });
 
@@ -411,28 +449,30 @@ add_test(function test_saveAppStats() {
         // past tests and the new one for appId 1
         do_check_eq(result.length, 2);
         do_check_eq(result[1].appId, stats.appId);
         do_check_true(compareNetworks(result[1].network, network));
         let timestamp = filterTimestamp(stats.date);
         do_check_eq(result[1].timestamp, timestamp);
         do_check_eq(result[1].rxBytes, stats.rxBytes);
         do_check_eq(result[1].txBytes, stats.txBytes);
+        do_check_eq(result[1].rxSystemBytes, 0);
+        do_check_eq(result[1].txSystemBytes, 0);
         do_check_eq(result[1].rxTotalBytes, 0);
         do_check_eq(result[1].txTotalBytes, 0);
         run_next_test();
       });
     });
   });
 });
 
 function prepareFind(network, stats, callback) {
   netStatsDb.clearStats(network, function (error, result) {
     do_check_eq(error, null);
-    netStatsDb.dbNewTxn("readwrite", function(txn, store) {
+    netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
       netStatsDb._saveStats(txn, store, stats);
     }, function(error, result) {
         callback(error, result);
     });
   });
 }
 
 add_test(function test_find () {
@@ -444,25 +484,28 @@ add_test(function test_find () {
   var samples = 5;
   var sampleRate = netStatsDb.sampleRate;
   var start = Date.now();
   var saveDate = filterTimestamp(new Date());
   var end = new Date(start + (sampleRate * (samples - 1)));
   start = new Date(start - sampleRate);
   var stats = [];
   for (var i = 0; i < samples; i++) {
-    stats.push({ appId:              appId,
-                 network:      networkWifi, timestamp:    saveDate + (sampleRate * i),
-                 rxBytes:                0, txBytes:      10,
-                 rxTotalBytes:           0, txTotalBytes: 0 });
+    stats.push({ appId:               appId,
+                 network:       networkWifi, timestamp:     saveDate + (sampleRate * i),
+                 rxBytes:                 0, txBytes:       10,
+                 rxSystemBytes:           0, txSystemBytes: 0,
+                 rxTotalBytes:            0, txTotalBytes:  0});
 
-    stats.push({ appId:                appId,
-                 network:      networkMobile, timestamp:    saveDate + (sampleRate * i),
-                 rxBytes:                  0, txBytes:      10,
-                 rxTotalBytes:             0, txTotalBytes: 0 });
+
+    stats.push({ appId:                 appId,
+                 network:       networkMobile, timestamp:     saveDate + (sampleRate * i),
+                 rxBytes:                   0, txBytes:       10,
+                 rxSystemBytes:             0, txSystemBytes: 0,
+                 rxTotalBytes:              0, txTotalBytes:  0});
   }
 
   prepareFind(networks[0], stats, function(error, result) {
     do_check_eq(error, null);
     netStatsDb.find(function (error, result) {
       do_check_eq(error, null);
       do_check_eq(result.network.id, networks[0].id);
       do_check_eq(result.network.type, networks[0].type);
@@ -549,40 +592,217 @@ add_test(function test_saveMultipleAppSt
   netStatsDb.clearStats(networks, function (error, result) {
     do_check_eq(error, null);
     netStatsDb.saveStats(cached[keys[index]],
       function callback(error, result) {
         do_check_eq(error, null);
 
         if (index == keys.length - 1) {
           netStatsDb.logAllRecords(function(error, result) {
-          // Again, result has two samples more than expected samples because
-          // clear inserts one empty sample for each network to keep totalBytes
-          // synchronized with netd counters. so the first two samples have to
-          // be discarted.
-          result.shift();
-          result.shift();
+            // Again, result has two samples more than expected samples because
+            // clear inserts one empty sample for each network to keep totalBytes
+            // synchronized with netd counters. so the first two samples have to
+            // be discarted.
+            result.shift();
+            result.shift();
 
-          do_check_eq(error, null);
-          do_check_eq(result.length, 4);
-          do_check_eq(result[0].appId, 1);
-          do_check_true(compareNetworks(result[0].network,[networkWifi.id, networkWifi.type]));
-          do_check_eq(result[0].rxBytes, 0);
-          do_check_eq(result[0].txBytes, 10);
-          run_next_test();
+            do_check_eq(error, null);
+            do_check_eq(result.length, 4);
+            do_check_eq(result[0].appId, 1);
+            do_check_true(compareNetworks(result[0].network, [networkWifi.id, networkWifi.type]));
+            do_check_eq(result[0].rxBytes, 0);
+            do_check_eq(result[0].txBytes, 10);
+            run_next_test();
           });
+         return;
         }
 
         index += 1;
         netStatsDb.saveStats(cached[keys[index]], callback);
     });
   });
 });
 
+var networkWifi = '00';
+var networkMobile = '11';
+
+var examplePageURL = "http://example.com/index.html";
+var exampleManifestURL = "http://example.com/manifest.webapp";
+
+var testPageURL = "http://test.com/index.html";
+var testManifestURL = "http://test.com/manifest.webapp";
+
+var alarms = [{ id:             null,
+                networkId:      networkWifi,
+                threshold:      10000,
+                data:           {foo: "something"},
+                pageURL:        examplePageURL,
+                manifestURL:    exampleManifestURL },
+              { id:             null,
+                networkId:      networkWifi,
+                threshold:      1000,
+                data:           {foo: "else"},
+                pageURL:        examplePageURL,
+                manifestURL:    exampleManifestURL },
+              { id:             null,
+                networkId:      networkMobile,
+                threshold:      100,
+                data:           {foo: "to"},
+                pageURL:        examplePageURL,
+                manifestURL:    exampleManifestURL },
+              { id:             null,
+                networkId:      networkMobile,
+                threshold:      10,
+                data:           {foo: "test"},
+                pageURL:        testPageURL,
+                manifestURL:    testManifestURL }];
+
+var alarmsDbId = 1;
+
+add_test(function test_addAlarm() {
+  // Add alarms[0] -> DB: [ alarms[0] (id: 1) ]
+  // Check the insertion is OK.
+  netStatsDb.addAlarm(alarms[0], function(error, result) {
+    do_check_eq(error, null);
+    alarmsDbId = result;
+    netStatsDb.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, exampleManifestURL, function(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.length, 1);
+      do_check_eq(result[0].id, alarmsDbId);
+      do_check_eq(result[0].networkId, alarms[0].networkId);
+      do_check_eq(result[0].threshold, alarms[0].threshold);
+      do_check_eq(result[0].data.foo, alarms[0].data.foo);
+      run_next_test();
+    });
+  });
+});
+
+add_test(function test_getFirstAlarm() {
+  // Add alarms[1] -> DB: [ alarms[0] (id: 1), alarms[1] (id: 2) ]
+  // Check first alarm is alarms[1] because threshold is lower.
+  alarmsDbId += 1;
+  netStatsDb.addAlarm(alarms[1], function (error, result) {
+    do_check_eq(error, null);
+    do_check_eq(result, alarmsDbId);
+    netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.id, alarmsDbId);
+      do_check_eq(result.networkId, alarms[1].networkId);
+      do_check_eq(result.threshold, alarms[1].threshold);
+      do_check_eq(result.data.foo, alarms[1].data.foo);
+      do_check_eq(result.pageURL, alarms[1].pageURL);
+      do_check_eq(result.manifestURL, alarms[1].manifestURL);
+      run_next_test();
+    });
+  });
+});
+
+add_test(function test_removeAlarm() {
+  // Remove alarms[1] (id: 2) -> DB: [ alarms[0] (id: 1) ]
+  // Check get first return alarms[0].
+  netStatsDb.removeAlarm(alarmsDbId, alarms[0].manifestURL, function (error, result) {
+    do_check_eq(error, null);
+    netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.id, alarmsDbId - 1);
+      do_check_eq(result.networkId, alarms[0].networkId);
+      do_check_eq(result.threshold, alarms[0].threshold);
+      do_check_eq(result.data.foo, alarms[0].data.foo);
+      do_check_eq(result.pageURL, alarms[0].pageURL);
+      do_check_eq(result.manifestURL, alarms[0].manifestURL);
+      run_next_test();
+    });
+  });
+});
+
+add_test(function test_removeAppAlarm() {
+  // Remove alarms[0] (id: 1) -> DB: [ ]
+  netStatsDb.removeAlarm(alarmsDbId - 1, alarms[0].manifestURL, function (error, result) {
+    do_check_eq(error, null);
+    netStatsDb.getAlarms(networkWifi, exampleManifestURL, function(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.length, 0);
+      run_next_test();
+    });
+  });
+});
+
+add_test(function test_getAlarms() {
+  // Add all alarms -> DB: [ alarms[0] (id: 3),
+  //                         alarms[1] (id: 4),
+  //                         alarms[2] (id: 5),
+  //                         alarms[3] (id: 6) ]
+  // Check that getAlarms for wifi returns 2 alarms.
+  // Check that getAlarms for all connections returns 3 alarms.
+
+  var callback = function () {
+    netStatsDb.getAlarms(networkWifi, exampleManifestURL, function(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.length, 2);
+      netStatsDb.getAlarms(null, exampleManifestURL, function(error, result) {
+        do_check_eq(error, null);
+        do_check_eq(result.length, 3);
+        run_next_test();
+      });
+    });
+  };
+
+  var index = 0;
+
+  var addFunction = function () {
+    alarmsDbId += 1;
+    netStatsDb.addAlarm(alarms[index], function (error, result) {
+      do_check_eq(error, null);
+      index += 1;
+      do_check_eq(result, alarmsDbId);
+      if (index >= alarms.length) {
+        callback();
+        return;
+      }
+      addFunction();
+    });
+  };
+
+  addFunction();
+});
+
+add_test(function test_removeAppAllAlarms() {
+  // Remove all alarms for exampleManifestURL -> DB: [ alarms[3] (id: 6) ]
+  netStatsDb.removeAlarms(exampleManifestURL, function (error, result) {
+    do_check_eq(error, null);
+    netStatsDb.getAlarms(null, exampleManifestURL, function(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.length, 0);
+      netStatsDb.getAlarms(null, testManifestURL, function(error, result) {
+        do_check_eq(error, null);
+        do_check_eq(result.length, 1);
+        run_next_test();
+      });
+    });
+  });
+});
+
+add_test(function test_updateAlarm() {
+  // Update alarms[3] (id: 6) -> DB: [ alarms[3]* (id: 6) ]
+
+  var updatedAlarm = alarms[1];
+  updatedAlarm.id = alarmsDbId;
+  updatedAlarm.threshold = 10;
+
+  netStatsDb.updateAlarm(updatedAlarm, function (error, result) {
+    do_check_eq(error, null);
+    netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.id, updatedAlarm.id);
+      do_check_eq(result.networkId, updatedAlarm.networkId);
+      do_check_eq(result.threshold, updatedAlarm.threshold);
+      do_check_eq(result.data.foo, updatedAlarm.data.foo);
+      do_check_eq(result.pageURL, updatedAlarm.pageURL);
+      do_check_eq(result.manifestURL, updatedAlarm.manifestURL);
+      run_next_test();
+    });
+  });
+});
+
 function run_test() {
   do_get_profile();
-
-  // Clear whole database to avoid start tests with unknown state
-  // due to previous tests.
-  clearWholeDB(function(){
-    run_next_test();
-  });
+  run_next_test();
 }
--- a/dom/network/tests/unit_stats/test_networkstats_service.js
+++ b/dom/network/tests/unit_stats/test_networkstats_service.js
@@ -134,17 +134,105 @@ add_test(function test_queue() {
   NetworkStatsService.updateStats(netId1, callback);
   NetworkStatsService.updateStats(netId2, callback);
 
   do_check_eq(NetworkStatsService.updateQueue.length, 2);
   do_check_eq(NetworkStatsService.updateQueue[0].callbacks.length, 2);
   do_check_eq(NetworkStatsService.updateQueue[0].callbacks[0], null);
   do_check_neq(NetworkStatsService.updateQueue[0].callbacks[1], null);
 
+  // Clear queue because in test environment requests for mobile networks
+  // can not be handled.
+  NetworkStatsService.updateQueue =  [];
   run_next_test();
 });
 
+var wifiId = '00';
+
+add_test(function test_updateThreshold() {
+  let alarm = { networkId: wifiId, threshold: 10000 };
+
+  NetworkStatsService._updateThreshold(alarm, function onSet(error, threshold){
+    do_check_eq(error, null);
+    do_check_neq(threshold.systemThreshold, undefined);
+    do_check_neq(threshold.absoluteThreshold, undefined);
+    run_next_test();
+  });
+});
+
+var testPageURL = "http://test.com";
+var testManifestURL = "http://test.com/manifest.webapp";
+
+add_test(function test_setAlarm() {
+  let alarm = { id: null,
+                networkId: wifiId,
+                threshold: 10000,
+                absoluteThreshold: null,
+                alarmStart: null,
+                alarmEnd: null,
+                data: null,
+                pageURL: testPageURL,
+                manifestURL: testManifestURL };
+
+  NetworkStatsService._setAlarm(alarm, function onSet(error, result) {
+    do_check_eq(result, 1);
+    run_next_test();
+  });
+});
+
+add_test(function test_setAlarm_invalid_threshold() {
+  let alarm = { id: null,
+                networkId: wifiId,
+                threshold: -10000,
+                absoluteThreshold: null,
+                alarmStart: null,
+                alarmEnd: null,
+                data: null,
+                pageURL: testPageURL,
+                manifestURL: testManifestURL };
+
+  NetworkStatsService._setAlarm(alarm, function onSet(error, result) {
+    do_check_eq(error, "InvalidStateError");
+    run_next_test();
+  });
+});
+
+add_test(function test_fireAlarm() {
+  // Add a fake alarm into database.
+  let alarm = { id: null,
+                networkId: wifiId,
+                threshold: 10000,
+                absoluteThreshold: null,
+                alarmStart: null,
+                alarmEnd: null,
+                data: null,
+                pageURL: testPageURL,
+                manifestURL: testManifestURL };
+
+  NetworkStatsService._db.addAlarm(alarm, function addSuccessCb(error, newId) {
+    NetworkStatsService._db.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
+                                      testManifestURL, function onGet(error, result) {
+      do_check_eq(error, null);
+      do_check_eq(result.length, 1);
+
+      // Result of getAlarms is based on expected child's data format, so
+      // some changes are needed to be able to use it.
+      result[0].networkId = wifiId;
+      result[0].pageURL = testPageURL;
+      result[0].manifestURL = testManifestURL;
+
+      NetworkStatsService._fireAlarm(result[0], false);
+      NetworkStatsService._db.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
+                                        testManifestURL, function onGet(error, result) {
+        do_check_eq(error, undefined);
+        do_check_eq(result.length, 0);
+        run_next_test();
+      });
+    });
+  });
+});
+
 function run_test() {
   do_get_profile();
 
   Cu.import("resource://gre/modules/NetworkStatsService.jsm");
   run_next_test();
 }
--- a/dom/nfc/MozNdefRecord.cpp
+++ b/dom/nfc/MozNdefRecord.cpp
@@ -3,60 +3,112 @@
 /* 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/. */
 
 /* Copyright © 2013 Deutsche Telekom, Inc. */
 
 #include "MozNdefRecord.h"
 #include "mozilla/dom/MozNdefRecordBinding.h"
+#include "mozilla/HoldDropJSObjects.h"
 #include "nsContentUtils.h"
 
+
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(MozNdefRecord, mWindow)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(MozNdefRecord)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MozNdefRecord)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MozNdefRecord)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(MozNdefRecord)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mType)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mId)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPayload)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
 NS_IMPL_CYCLE_COLLECTING_ADDREF(MozNdefRecord)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(MozNdefRecord)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MozNdefRecord)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
+void
+MozNdefRecord::HoldData()
+{
+  mozilla::HoldJSObjects(this);
+}
+
+void
+MozNdefRecord::DropData()
+{
+  if (mType) {
+    mType = nullptr;
+  }
+  if (mId) {
+    mId = nullptr;
+  }
+  if (mPayload) {
+    mPayload = nullptr;
+  }
+  mozilla::DropJSObjects(this);
+}
+
 /* static */
 already_AddRefed<MozNdefRecord>
 MozNdefRecord::Constructor(const GlobalObject& aGlobal,
-                           uint8_t aTnf, const nsAString& aType,
-                           const nsAString& aId, const nsAString& aPayload,
+                           uint8_t aTnf, const Uint8Array& aType,
+                           const Uint8Array& aId, const Uint8Array& aPayload,
                            ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobal.GetAsSupports());
   if (!win) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
-  nsRefPtr<MozNdefRecord> ndefrecord =
-    new MozNdefRecord(win, aTnf, aType, aId, aPayload);
+
+  nsRefPtr<MozNdefRecord> ndefrecord = new MozNdefRecord(aGlobal.GetContext(),
+                                                         win, aTnf, aType, aId,
+                                                         aPayload);
+  if (!ndefrecord) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
   return ndefrecord.forget();
 }
 
-MozNdefRecord::MozNdefRecord(nsPIDOMWindow* aWindow,
-                             uint8_t aTnf, const nsAString& aType,
-                             const nsAString& aId, const nsAString& aPayload)
+MozNdefRecord::MozNdefRecord(JSContext* aCx, nsPIDOMWindow* aWindow,
+                             uint8_t aTnf, const Uint8Array& aType,
+                             const Uint8Array& aId, const Uint8Array& aPayload)
   : mTnf(aTnf)
-  , mType(aType)
-  , mId(aId)
-  , mPayload(aPayload)
 {
-  mWindow = aWindow;
+  mWindow = aWindow; // For GetParentObject()
+
+  mType = Uint8Array::Create(aCx, this, aType.Length(), aType.Data());
+  mId = Uint8Array::Create(aCx, this, aId.Length(), aId.Data());
+  mPayload = Uint8Array::Create(aCx, this, aPayload.Length(), aPayload.Data());
+
   SetIsDOMBinding();
+  HoldData();
 }
 
 MozNdefRecord::~MozNdefRecord()
 {
+  DropData();
 }
 
 JSObject*
 MozNdefRecord::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return MozNdefRecordBinding::Wrap(aCx, aScope, this);
 }
 
--- a/dom/nfc/MozNdefRecord.h
+++ b/dom/nfc/MozNdefRecord.h
@@ -12,77 +12,96 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 #include "jsapi.h"
 
 #include "nsIDocument.h"
 
+#include "mozilla/dom/TypedArray.h"
+#include "jsfriendapi.h"
+#include "js/GCAPI.h"
+
 struct JSContext;
 
 namespace mozilla {
 namespace dom {
 
 class MozNdefRecord MOZ_FINAL : public nsISupports,
                                 public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MozNdefRecord)
 
 public:
 
-  MozNdefRecord(nsPIDOMWindow* aWindow,
-                uint8_t aTnf, const nsAString& aType,
-                const nsAString& aId, const nsAString& aPlayload);
+  MozNdefRecord(JSContext* aCx, nsPIDOMWindow* aWindow, uint8_t aTnf,
+                const Uint8Array& aType, const Uint8Array& aId,
+                const Uint8Array& aPlayload);
 
   ~MozNdefRecord();
 
   nsIDOMWindow* GetParentObject() const
   {
     return mWindow;
   }
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
-  static already_AddRefed<MozNdefRecord> Constructor(
-                                           const GlobalObject& aGlobal,
-                                           uint8_t aTnf, const nsAString& aType,
-                                           const nsAString& aId,
-                                           const nsAString& aPayload,
-                                           ErrorResult& aRv);
+  static already_AddRefed<MozNdefRecord>
+                  Constructor(const GlobalObject& aGlobal, uint8_t aTnf,
+                              const Uint8Array& aType, const Uint8Array& aId,
+                              const Uint8Array& aPayload, ErrorResult& aRv);
 
   uint8_t Tnf() const
   {
     return mTnf;
   }
 
-  void GetType(nsString& aType) const
+  JSObject* Type(JSContext* cx) const
   {
-    aType = mType;
+    return GetTypeObject();
+  }
+  JSObject* GetTypeObject() const
+  {
+    JS::ExposeObjectToActiveJS(mType);
+    return mType;
   }
 
-  void GetId(nsString& aId) const
+  JSObject* Id(JSContext* cx) const
   {
-    aId = mId;
+    return GetIdObject();
+  }
+  JSObject* GetIdObject() const
+  {
+    JS::ExposeObjectToActiveJS(mId);
+    return mId;
   }
 
-  void GetPayload(nsString& aPayload) const
+  JSObject* Payload(JSContext* cx) const
   {
-    aPayload = mPayload;
+    return GetPayloadObject();
+  }
+  JSObject* GetPayloadObject() const
+  {
+    JS::ExposeObjectToActiveJS(mPayload);
+    return mPayload;
   }
 
 private:
   MozNdefRecord() MOZ_DELETE;
   nsRefPtr<nsPIDOMWindow> mWindow;
+  void HoldData();
+  void DropData();
 
   uint8_t mTnf;
-  nsString mType;
-  nsString mId;
-  nsString mPayload;
+  JS::Heap<JSObject*> mType;
+  JS::Heap<JSObject*> mId;
+  JS::Heap<JSObject*> mPayload;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_MozNdefRecord_h__
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -127,29 +127,39 @@ void nsPluginTag::InitMime(const char* c
                            const char* const* aExtensions,
                            uint32_t aVariantCount)
 {
   if (!aMimeTypes) {
     return;
   }
 
   for (uint32_t i = 0; i < aVariantCount; i++) {
-    if (!aMimeTypes[i] || !nsPluginHost::IsTypeWhitelisted(aMimeTypes[i])) {
+    if (!aMimeTypes[i]) {
+      continue;
+    }
+
+    nsAutoCString mimeType(aMimeTypes[i]);
+
+    // Convert the MIME type, which is case insensitive, to lowercase in order
+    // to properly handle a mixed-case type.
+    ToLowerCase(mimeType);
+
+    if (!nsPluginHost::IsTypeWhitelisted(mimeType.get())) {
       continue;
     }
 
     // Look for certain special plugins.
-    if (nsPluginHost::IsJavaMIMEType(aMimeTypes[i])) {
+    if (nsPluginHost::IsJavaMIMEType(mimeType.get())) {
       mIsJavaPlugin = true;
-    } else if (strcmp(aMimeTypes[i], "application/x-shockwave-flash") == 0) {
+    } else if (mimeType.EqualsLiteral("application/x-shockwave-flash")) {
       mIsFlashPlugin = true;
     }
 
     // Fill in our MIME type array.
-    mMimeTypes.AppendElement(nsCString(aMimeTypes[i]));
+    mMimeTypes.AppendElement(mimeType);
 
     // Now fill in the MIME descriptions.
     if (aMimeDescriptions && aMimeDescriptions[i]) {
       // we should cut off the list of suffixes which the mime
       // description string may have, see bug 53895
       // it is usually in form "some description (*.sf1, *.sf2)"
       // so we can search for the opening round bracket
       char cur = '\0';
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/mixed_case_mime.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response)
+{
+  response.processAsync();
+  response.setHeader("Content-Type", "application/x-Second-Test", false);
+
+  response.write("Hello world.\n");
+  response.finish();
+}
--- a/dom/plugins/test/mochitest/mochitest.ini
+++ b/dom/plugins/test/mochitest/mochitest.ini
@@ -6,16 +6,17 @@ support-files =
   file_bug863792.html
   large-pic.jpg
   loremipsum.txt
   loremipsum.xtest
   loremipsum.xtest^headers^
   loremipsum_file.txt
   loremipsum_nocache.txt
   loremipsum_nocache.txt^headers^
+  mixed_case_mime.sjs
   neverending.sjs
   npruntime_identifiers_subpage.html
   plugin-stream-referer.sjs
   plugin_window.html
   pluginstream.js
   post.sjs
   utils.js
 
@@ -36,16 +37,17 @@ support-files =
 [test_enumerate.html]
 [test_fullpage.html]
 [test_getauthenticationinfo.html]
 [test_instance_re-parent.html]
 [test_instance_unparent1.html]
 [test_instance_unparent2.html]
 [test_instance_unparent3.html]
 [test_instantiation.html]
+[test_mixed_case_mime.html]
 [test_multipleinstanceobjects.html]
 [test_newstreamondestroy.html]
 [test_npn_asynccall.html]
 [test_npn_timers.html]
 [test_npobject_getters.html]
 [test_npruntime_construct.html]
 [test_npruntime_identifiers.html]
 [test_npruntime_npnevaluate.html]
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_mixed_case_mime.html
@@ -0,0 +1,29 @@
+<body>
+<head>
+  <title>Test mixed case mimetype for plugins</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="utils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script>
+  SimpleTest.expectAssertions(0, 1);
+
+  SimpleTest.waitForExplicitFinish();
+  setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in");
+
+  function frameLoaded() {
+    var contentDocument = document.getElementById('testframe').contentDocument;
+    ok(contentDocument.body.innerHTML.length > 0, "Frame content shouldn't be empty.");
+    ok(contentDocument.plugins.length > 0, "Frame content should have a plugin.");
+    var plugin = contentDocument.plugins[0];
+    is(plugin.type.toLowerCase(), "application/x-second-test", "Should have loaded the second test plugin.");
+    SimpleTest.finish();
+  }
+</script>
+</head>
+<body>
+  <p id="display"></p>
+
+  <iframe id="testframe" name="testframe" onload="frameLoaded()" src="mixed_case_mime.sjs"></iframe>
+
+</body>
+</html>
--- a/dom/plugins/test/testplugin/secondplugin/Info.plist
+++ b/dom/plugins/test/testplugin/secondplugin/Info.plist
@@ -19,17 +19,17 @@
 	<key>CFBundleVersion</key>
 	<string>1.0.0.0</string>
 	<key>WebPluginName</key>
 	<string>Second Test Plug-in</string>
 	<key>WebPluginDescription</key>
 	<string>Second plug-in for testing purposes.</string>
 	<key>WebPluginMIMETypes</key>
 	<dict>
-		<key>application/x-second-test</key>
+		<key>application/x-Second-Test</key>
 		<dict>
 			<key>WebPluginExtensions</key>
 			<array>
 				<string>ts2</string>
 			</array>
 			<key>WebPluginTypeDescription</key>
 			<string>Second test type</string>
 		</dict>
--- a/dom/plugins/test/testplugin/secondplugin/nptest.rc
+++ b/dom/plugins/test/testplugin/secondplugin/nptest.rc
@@ -24,17 +24,17 @@ BEGIN
         BLOCK "040904e4"
         BEGIN
             VALUE "CompanyName", "mozilla.org"
             VALUE "FileDescription", L"Second plug-in for testing purposes."
             VALUE "FileExtents", "ts2"
             VALUE "FileOpenName", "Second test type"
             VALUE "FileVersion", "1.0"
             VALUE "InternalName", "npsecondtest"
-            VALUE "MIMEType", "application/x-second-test"
+            VALUE "MIMEType", "application/x-Second-Test"
             VALUE "OriginalFilename", "npsecondtest.dll"
             VALUE "ProductName", "Second Test Plug-in"
             VALUE "ProductVersion", "1.0"
         END
     END
     BLOCK "VarFileInfo"
     BEGIN
         VALUE "Translation", 0x409, 1252
--- a/dom/plugins/test/testplugin/secondplugin/nptest_name.cpp
+++ b/dom/plugins/test/testplugin/secondplugin/nptest_name.cpp
@@ -1,7 +1,7 @@
 /* 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/. */
 
 const char *sPluginName = "Second Test Plug-in";
 const char *sPluginDescription = "Second plug-in for testing purposes.";
-const char *sMimeDescription = "application/x-second-test:ts2:Second test type";
+const char *sMimeDescription = "application/x-Second-Test:ts2:Second test type";
--- a/dom/system/gonk/NetworkService.js
+++ b/dom/system/gonk/NetworkService.js
@@ -5,17 +5,17 @@
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
-const NETWORKSERVICE_CID = Components.ID("{a6c58260-46df-11e3-8f96-0800200c9a66}");
+const NETWORKSERVICE_CID = Components.ID("{c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c}");
 
 // 1xx - Requested action is proceeding
 const NETD_COMMAND_PROCEEDING   = 100;
 // 2xx - Requested action has been successfully completed
 const NETD_COMMAND_OKAY         = 200;
 // 4xx - The command is accepted but the requested action didn't
 // take place.
 const NETD_COMMAND_FAIL         = 400;
@@ -112,23 +112,99 @@ NetworkService.prototype = {
       cmd: "getNetworkInterfaceStats",
       ifname: networkName
     };
 
     params.report = true;
     params.isAsync = true;
 
     this.controlMessage(params, function(result) {
-      let success = result.resultCode >= NETD_COMMAND_OKAY &&
-                    result.resultCode < NETD_COMMAND_ERROR;
+      let success = !isError(result.resultCode);
       callback.networkStatsAvailable(success, result.rxBytes,
                                      result.txBytes, result.date);
     });
   },
 
+  setNetworkInterfaceAlarm: function setNetworkInterfaceAlarm(networkName, threshold, callback) {
+    if (!networkName) {
+      callback.networkUsageAlarmResult(-1);
+      return;
+    }
+
+    if (threshold < 0) {
+      this._disableNetworkInterfaceAlarm(networkName, callback);
+      return;
+    }
+
+    this._setNetworkInterfaceAlarm(networkName, threshold, callback);
+  },
+
+  _setNetworkInterfaceAlarm: function _setNetworkInterfaceAlarm(networkName, threshold, callback) {
+    debug("setNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
+
+    let params = {
+      cmd: "setNetworkInterfaceAlarm",
+      ifname: networkName,
+      threshold: threshold
+    };
+
+    params.report = true;
+    params.isAsync = true;
+
+    this.controlMessage(params, function(result) {
+      if (!isError(result.resultCode)) {
+        callback.networkUsageAlarmResult(null);
+        return;
+      }
+
+      this._enableNetworkInterfaceAlarm(networkName, threshold, callback);
+    });
+  },
+
+  _enableNetworkInterfaceAlarm: function _enableNetworkInterfaceAlarm(networkName, threshold, callback) {
+    debug("enableNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
+
+    let params = {
+      cmd: "enableNetworkInterfaceAlarm",
+      ifname: networkName,
+      threshold: threshold
+    };
+
+    params.report = true;
+    params.isAsync = true;
+
+    this.controlMessage(params, function(result) {
+      if (!isError(result.resultCode)) {
+        callback.networkUsageAlarmResult(null);
+        return;
+      }
+      callback.networkUsageAlarmResult(result.reason);
+    });
+  },
+
+  _disableNetworkInterfaceAlarm: function _disableNetworkInterfaceAlarm(networkName, callback) {
+    debug("disableNetworkInterfaceAlarm for " + networkName);
+
+    let params = {
+      cmd: "disableNetworkInterfaceAlarm",
+      ifname: networkName,
+    };
+
+    params.report = true;
+    params.isAsync = true;
+
+    this.controlMessage(params, function(result) {
+      if (!isError(result.resultCode)) {
+        callback.networkUsageAlarmResult(null);
+        return;
+      }
+      callback.networkUsageAlarmResult(result.reason);
+    });
+  },
+
   setWifiOperationMode: function setWifiOperationMode(interfaceName, mode, callback) {
     if(DEBUG) debug("setWifiOperationMode on " + interfaceName + " to " + mode);
 
     let params = {
       cmd: "setWifiOperationMode",
       ifname: interfaceName,
       mode: mode
     };
--- a/dom/system/gonk/NetworkService.manifest
+++ b/dom/system/gonk/NetworkService.manifest
@@ -1,3 +1,3 @@
 # NetworkService.js
-component {a6c58260-46df-11e3-8f96-0800200c9a66} NetworkService.js
-contract @mozilla.org/network/service;1 {a6c58260-46df-11e3-8f96-0800200c9a66}
+component {c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c} NetworkService.js
+contract @mozilla.org/network/service;1 {c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c}
--- a/dom/system/gonk/net_worker.js
+++ b/dom/system/gonk/net_worker.js
@@ -146,17 +146,29 @@ function networkInterfaceStatsFail(param
   // Notify the main thread.
   postMessage(params);
   return true;
 }
 
 function networkInterfaceStatsSuccess(params) {
   // Notify the main thread.
   params.txBytes = parseFloat(params.resultReason);
+  postMessage(params);
+  return true;
+}
 
+function networkInterfaceAlarmFail(params) {
+  // Notify the main thread.
+  postMessage(params);
+  return true;
+}
+
+function networkInterfaceAlarmSuccess(params) {
+  // Notify the main thread.
+  params.error = parseFloat(params.resultReason);
   postMessage(params);
   return true;
 }
 
 function updateUpStreamSuccess(params) {
   // Notify the main thread.
   postMessage(params);
   return true;
@@ -602,16 +614,41 @@ function getRxBytes(params, callback) {
 
 function getTxBytes(params, callback) {
   params.rxBytes = parseFloat(params.resultReason);
 
   let command = "interface readtxcounter " + params.ifname;
   return doCommand(command, callback);
 }
 
+function enableAlarm(params, callback) {
+  let command = "bandwidth enable";
+  return doCommand(command, callback);
+}
+
+function disableAlarm(params, callback) {
+  let command = "bandwidth disable";
+  return doCommand(command, callback);
+}
+
+function setQuota(params, callback) {
+  let command = "bandwidth setiquota " + params.ifname + " " + parseInt('0xffffffffffffffff');
+  return doCommand(command, callback);
+}
+
+function removeQuota(params, callback) {
+  let command = "bandwidth removeiquota " + params.ifname;
+  return doCommand(command, callback);
+}
+
+function setAlarm(params, callback) {
+  let command = "bandwidth setinterfacealert " + params.ifname + " " + params.threshold;
+  return doCommand(command, callback);
+}
+
 function escapeQuote(str) {
   str = str.replace(/\\/g, "\\\\");
   return str.replace(/"/g, "\\\"");
 }
 
 /**
  * Command format for sdk version < 16
  *   Arguments:
@@ -909,16 +946,49 @@ function getNetworkInterfaceStats(params
   params.rxBytes = -1;
   params.txBytes = -1;
   params.date = new Date();
 
   chain(params, gNetworkInterfaceStatsChain, networkInterfaceStatsFail);
   return true;
 }
 
+let gNetworkInterfaceEnableAlarmChain = [enableAlarm,
+                                         setQuota,
+                                         setAlarm,
+                                         networkInterfaceAlarmSuccess];
+
+function enableNetworkInterfaceAlarm(params) {
+  debug("enableNetworkInterfaceAlarms: " + params.ifname);
+
+  chain(params, gNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
+  return true;
+}
+
+let gNetworkInterfaceDisableAlarmChain = [removeQuota,
+                                          disableAlarm,
+                                          networkInterfaceAlarmSuccess];
+
+function disableNetworkInterfaceAlarm(params) {
+  debug("disableNetworkInterfaceAlarms: " + params.ifname);
+
+  chain(params, gNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
+  return true;
+}
+
+let gNetworkInterfaceSetAlarmChain = [setAlarm,
+                                      networkInterfaceAlarmSuccess];
+
+function setNetworkInterfaceAlarm(params) {
+  debug("setNetworkInterfaceAlarms: " + params.ifname);
+
+  chain(params, gNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
+  return true;
+}
+
 let gWifiOperationModeChain = [wifiFirmwareReload,
                                wifiOperationModeSuccess];
 
 /**
  * handling main thread's reload Wifi firmware request
  */
 function setWifiOperationMode(params) {
   debug("setWifiOperationMode: " + params.ifname + " " + params.mode);
--- a/dom/system/gonk/nfc_consts.js
+++ b/dom/system/gonk/nfc_consts.js
@@ -43,18 +43,17 @@ this.NFC_RESPONSE_READ_NDEF = 1003;
 this.NFC_NOTIFICATION_INITIALIZED = 2000;
 this.NFC_NOTIFICATION_TECH_DISCOVERED = 2001;
 this.NFC_NOTIFICATION_TECH_LOST = 2002;
 
 this.NFC_TECHS = {
   0:'NDEF',
   1:'NDEF_WRITEABLE',
   2:'NDEF_FORMATABLE',
-  3:'P2P',
-  4:'NFC_A'
+  3:'P2P'
 };
 
 // TODO: Bug 933595. Fill-in all error codes for Gonk/nfcd protocol
 this.GECKO_NFC_ERROR_SUCCESS             = 0;
 this.GECKO_NFC_ERROR_GENERIC_FAILURE     = 1;
 
 // NFC powerlevels must match config PDUs.
 this.NFC_POWER_LEVEL_UNKNOWN        = -1;
--- a/dom/system/gonk/nfc_worker.js
+++ b/dom/system/gonk/nfc_worker.js
@@ -107,43 +107,34 @@ let NfcWorker = {
     let numOfRecords = Buf.readInt32();
     debug("numOfRecords = " + numOfRecords);
     if (numOfRecords <= 0) {
       return null;
     }
     let records = [];
 
     for (let i = 0; i < numOfRecords; i++) {
-      let tnf        = Buf.readInt32();
+      let tnf        = Buf.readInt32() & 0xff;
       let typeLength = Buf.readInt32();
-      let type = [];
-      for (let i = 0; i < typeLength; i++) {
-        type.push(Buf.readUint8());
-      }
+      let type       = Buf.readUint8Array(typeLength);
       let padding    = getPaddingLen(typeLength);
       for (let i = 0; i < padding; i++) {
         Buf.readUint8();
       }
 
       let idLength = Buf.readInt32();
-      let id = [];
-      for (let i = 0; i < idLength; i++) {
-        id.push(Buf.readUint8());
-      }
+      let id       = Buf.readUint8Array(idLength);
       padding      = getPaddingLen(idLength);
       for (let i = 0; i < padding; i++) {
         Buf.readUint8();
       }
 
       let payloadLength = Buf.readInt32();
-      let payload = [];
-      for (let i = 0; i < payloadLength; i++) {
-        payload.push(Buf.readUint8());
-      }
-      padding = getPaddingLen(payloadLength);
+      let payload       = Buf.readUint8Array(payloadLength);
+      padding           = getPaddingLen(payloadLength);
       for (let i = 0; i < padding; i++) {
         Buf.readUint8();
       }
       records.push({tnf: tnf,
                     type: type,
                     id: id,
                     payload: payload});
     }
@@ -191,40 +182,40 @@ let NfcWorker = {
     Buf.writeInt32(message.sessionId);
     let records    = message.records;
     let numRecords = records.length;
     Buf.writeInt32(numRecords);
     for (let i = 0; i < numRecords; i++) {
       let record = records[i];
       Buf.writeInt32(record.tnf);
 
-      let typeLength = record.type.length;
+      let typeLength = record.type ? record.type.length : 0;
       Buf.writeInt32(typeLength);
       for (let j = 0; j < typeLength; j++) {
-        Buf.writeUint8(record.type.charCodeAt(j));
+        Buf.writeUint8(record.type[j]);
       }
       let padding = getPaddingLen(typeLength);
       for (let i = 0; i < padding; i++) {
         Buf.writeUint8(0x00);
       }
 
-      let idLength = record.id.length;
+      let idLength = record.id ? record.id.length : 0;
       Buf.writeInt32(idLength);
       for (let j = 0; j < idLength; j++) {
-        Buf.writeUint8(record.id.charCodeAt(j));
+        Buf.writeUint8(record.id[j]);
       }
       padding = getPaddingLen(idLength);
       for (let i = 0; i < padding; i++) {
         Buf.writeUint8(0x00);
       }
 
-      let payloadLength = record.payload && record.payload.length;
+      let payloadLength = record.payload ? record.payload.length : 0;
       Buf.writeInt32(payloadLength);
       for (let j = 0; j < payloadLength; j++) {
-        Buf.writeUint8(record.payload.charCodeAt(j));
+        Buf.writeUint8(record.payload[j]);
       }
       padding = getPaddingLen(payloadLength);
       for (let i = 0; i < padding; i++) {
         Buf.writeUint8(0x00);
       }
     }
 
     Buf.sendParcel();
@@ -377,17 +368,20 @@ NfcWorker[NFC_NOTIFICATION_INITIALIZED] 
 NfcWorker[NFC_NOTIFICATION_TECH_DISCOVERED] = function NFC_NOTIFICATION_TECH_DISCOVERED() {
   debug("NFC_NOTIFICATION_TECH_DISCOVERED");
   let techs     = [];
   let ndefMsgs  = [];
 
   let sessionId = Buf.readInt32();
   let techCount = Buf.readInt32();
   for (let count = 0; count < techCount; count++) {
-    techs.push(NFC_TECHS[Buf.readUint8()]);
+    let tech = NFC_TECHS[Buf.readUint8()];
+    if (tech) {
+      techs.push(tech);
+    }
   }
 
   let padding   = getPaddingLen(techCount);
   for (let i = 0; i < padding; i++) {
     Buf.readUint8();
   }
 
   let ndefMsgCount = Buf.readInt32();
--- a/dom/system/gonk/nsINetworkService.idl
+++ b/dom/system/gonk/nsINetworkService.idl
@@ -23,16 +23,22 @@ interface nsIWifiTetheringCallback : nsI
 interface nsINetworkStatsCallback : nsISupports
 {
   void networkStatsAvailable(in boolean success,
                              in unsigned long rxBytes,
                              in unsigned long txBytes,
                              in jsval date);
 };
 
+[scriptable, function, uuid(0706bfa2-ac2d-11e2-9a8d-7b6d988d4767)]
+interface nsINetworkUsageAlarmCallback : nsISupports
+{
+  void networkUsageAlarmResult(in jsval error);
+};
+
 [scriptable, function, uuid(9ede8720-f8bc-11e2-b778-0800200c9a66)]
 interface nsIWifiOperationModeCallback : nsISupports
 {
   /**
    * Callback function used to report result to WifiManager.
    *
    * @param error
    *        An error message if the operation wasn't successful,
@@ -93,17 +99,17 @@ interface nsIUpdateUpStreamCallback : ns
    *        The external interface name.
    */
   void updateUpStreamResult(in boolean success, in DOMString externalIfname);
 };
 
 /**
  * Provide network services.
  */
-[scriptable, uuid(a6c58260-46df-11e3-8f96-0800200c9a66)]
+[scriptable, uuid(c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c)]
 interface nsINetworkService : nsISupports
 {
   /**
    * Enable or disable Wifi Tethering
    *
    * @param enabled
    *        Boolean that indicates whether tethering should be enabled (true) or disabled (false).
    * @param config
@@ -147,16 +153,34 @@ interface nsINetworkService : nsISupport
    *
    * @param callback
    *        Callback to notify result and provide stats, connectionType
    *        and the date when stats are retrieved
    */
   void getNetworkInterfaceStats(in DOMString networkName, in nsINetworkStatsCallback callback);
 
   /**
+   * Set Alarm of usage per interface
+   *
+   * @param networkName
+   *        Select the Network interface to set an alarm.
+   *
+   * @param threshold
+   *        Amount of data that will trigger the alarm.
+   *
+   * @param callback
+   *        Callback to notify the result.
+   *
+   * @return false if there is no interface registered for the networkType param.
+   */
+  boolean setNetworkInterfaceAlarm(in DOMString networkName,
+                                   in long threshold,
+                                   in nsINetworkUsageAlarmCallback callback);
+
+  /**
    * Reload Wifi firmware to specific operation mode.
    *
    * @param interfaceName
    *        Wifi Network interface name.
    *
    * @param mode
    *        AP  - Access pointer mode.
    *        P2P - Peer to peer connection mode.
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3009,17 +3009,16 @@ let RIL = {
       // Other types of ICC we can send Terminal_Profile immediately.
       if (this.appType == CARD_APPTYPE_SIM) {
         SimRecordHelper.readSimPhase();
       } else if (RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD) {
         this.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
       }
 
       ICCRecordHelper.fetchICCRecords();
-      this.reportStkServiceIsRunning();
     }
 
     this.cardState = newCardState;
     this.sendChromeMessage({rilMessageType: "cardstatechange",
                             cardState: this.cardState});
   },
 
    /**
@@ -11220,16 +11219,17 @@ let ICCRecordHelper = {
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
       RIL.iccInfo.iccid = GsmPDUHelper.readSwappedNibbleBcdString(octetLen);
       Buf.readStringDelimiter(strLen);
 
       if (DEBUG) debug("ICCID: " + RIL.iccInfo.iccid);
       if (RIL.iccInfo.iccid) {
         ICCUtilsHelper.handleICCInfoChange();
+        RIL.reportStkServiceIsRunning();
       }
     }
 
     ICCIOHelper.loadTransparentEF({fileId: ICC_EF_ICCID,
                                    callback: callback.bind(this)});
   },
 
   /**
--- a/dom/webidl/CameraControl.webidl
+++ b/dom/webidl/CameraControl.webidl
@@ -147,16 +147,22 @@ interface CameraControl {
        one; an object with 'height' and 'width' properties that corresponds
        to one of the options returned by capabilities.pictureSizes.
        
        this setting should be considered a hint: the implementation will
        respect it when possible, and override it if necessary. */
     [Throws]
     attribute any thumbnailSize;
 
+    /* the angle, in degrees, that the image sensor is mounted relative
+       to the display; e.g. if 'sensorAngle' is 270 degrees (or -90 degrees),
+       then the preview stream needs to be rotated +90 degrees to have the
+       same orientation as the real world. */
+    readonly attribute long sensorAngle;
+
     /* tell the camera to attempt to focus the image */
     [Throws]
     void autoFocus(CameraAutoFocusCallback onSuccess, optional CameraErrorCallback onError);
 
     /* capture an image and return it as a blob to the 'onSuccess' callback;
        if the camera supports it, this may be invoked while the camera is
        already recording video.
 
--- a/dom/webidl/MozNdefRecord.webidl
+++ b/dom/webidl/MozNdefRecord.webidl
@@ -1,38 +1,43 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Copyright © 2013 Deutsche Telekom, Inc. */
 
-[Constructor(octet tnf, DOMString type, DOMString id, DOMString payload)]
+[Constructor(octet tnf, Uint8Array type, Uint8Array id, Uint8Array payload)]
 interface MozNdefRecord
 {
   /**
    * Type Name Field (3-bits) - Specifies the NDEF record type in general.
    *   tnf_empty: 0x00
    *   tnf_well_known: 0x01
    *   tnf_mime_media: 0x02
    *   tnf_absolute_uri: 0x03
    *   tnf_external type: 0x04
    *   tnf_unknown: 0x05
    *   tnf_unchanged: 0x06
    *   tnf_reserved: 0x07
    */
+  [Constant]
   readonly attribute octet tnf;
 
   /**
    * type - Describes the content of the payload. This can be a mime type.
    */
-  readonly attribute DOMString type;
+  [Constant]
+  readonly attribute Uint8Array type;
 
   /**
    * id - Identifer is application dependent.
    */
-  readonly attribute DOMString id;
+  [Constant]
+  readonly attribute Uint8Array id;
 
   /**
-   * payload - Binary data blob. The meaning of this field is application dependent.
+   * payload - Binary data blob. The meaning of this field is application
+   * dependent.
    */
-  readonly attribute DOMString payload;
+  [Constant]
+  readonly attribute Uint8Array payload;
 };
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -7,16 +7,125 @@
 #include "GLBlitHelper.h"
 #include "GLContext.h"
 #include "ScopedGLHelpers.h"
 #include "mozilla/Preferences.h"
 
 namespace mozilla {
 namespace gl {
 
+static void
+RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples,
+                             GLenum aInternalFormat, const gfxIntSize& aSize)
+{
+    if (aSamples) {
+        aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
+                                             aSamples,
+                                             aInternalFormat,
+                                             aSize.width, aSize.height);
+    } else {
+        aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
+                                  aInternalFormat,
+                                  aSize.width, aSize.height);
+    }
+}
+
+
+GLuint
+CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
+              GLenum aType, const gfxIntSize& aSize)
+{
+    GLuint tex = 0;
+    aGL->fGenTextures(1, &tex);
+    ScopedBindTexture autoTex(aGL, tex);
+
+    aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+    aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+    aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
+    aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
+
+    aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
+                     0,
+                     aInternalFormat,
+                     aSize.width, aSize.height,
+                     0,
+                     aFormat,
+                     aType,
+                     nullptr);
+
+    return tex;
+}
+
+
+GLuint
+CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
+                          const gfxIntSize& aSize)
+{
+    MOZ_ASSERT(aFormats.color_texInternalFormat);
+    MOZ_ASSERT(aFormats.color_texFormat);
+    MOZ_ASSERT(aFormats.color_texType);
+
+    return CreateTexture(aGL,
+                         aFormats.color_texInternalFormat,
+                         aFormats.color_texFormat,
+                         aFormats.color_texType,
+                         aSize);
+}
+
+
+GLuint
+CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
+                   const gfxIntSize& aSize)
+{
+    GLuint rb = 0;
+    aGL->fGenRenderbuffers(1, &rb);
+    ScopedBindRenderbuffer autoRB(aGL, rb);
+
+    RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize);
+
+    return rb;
+}
+
+
+void
+CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
+                                const gfxIntSize& aSize, bool aMultisample,
+                                GLuint* aColorMSRB, GLuint* aDepthRB,
+                                GLuint* aStencilRB)
+{
+    GLsizei samples = aMultisample ? aFormats.samples : 0;
+    if (aColorMSRB) {
+        MOZ_ASSERT(aFormats.samples > 0);
+        MOZ_ASSERT(aFormats.color_rbFormat);
+
+        *aColorMSRB = CreateRenderbuffer(aGL, aFormats.color_rbFormat, samples, aSize);
+    }
+
+    if (aDepthRB &&
+        aStencilRB &&
+        aFormats.depthStencil)
+    {
+        *aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize);
+        *aStencilRB = *aDepthRB;
+    } else {
+        if (aDepthRB) {
+            MOZ_ASSERT(aFormats.depth);
+
+            *aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize);
+        }
+
+        if (aStencilRB) {
+            MOZ_ASSERT(aFormats.stencil);
+
+            *aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize);
+        }
+    }
+}
+
+
 GLBlitHelper::GLBlitHelper(GLContext* gl)
     : mGL(gl)
     , mTexBlit_Buffer(0)
     , mTexBlit_VertShader(0)
     , mTex2DBlit_FragShader(0)
     , mTex2DRectBlit_FragShader(0)
     , mTex2DBlit_Program(0)
     , mTex2DRectBlit_Program(0)
@@ -318,17 +427,17 @@ GLBlitHelper::BlitFramebufferToFramebuff
     MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB));
 
     if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
         BlitFramebufferToFramebuffer(srcFB, destFB,
                                      srcSize, destSize);
         return;
     }
 
-    GLuint tex = mGL->CreateTextureForOffscreen(srcFormats, srcSize);
+    GLuint tex = CreateTextureForOffscreen(mGL, srcFormats, srcSize);
     MOZ_ASSERT(tex);
 
     BlitFramebufferToTexture(srcFB, tex, srcSize, srcSize);
     BlitTextureToFramebuffer(tex, destFB, srcSize, destSize);
 
     mGL->fDeleteTextures(1, &tex);
 }
 
--- a/gfx/gl/GLBlitHelper.h
+++ b/gfx/gl/GLBlitHelper.h
@@ -4,25 +4,69 @@
  * 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 GLBLITHELPER_H_
 #define GLBLITHELPER_H_
 
 #include "GLContextTypes.h"
 #include "GLConsts.h"
+#include "nsSize.h"
 #include "mozilla/Attributes.h"
 
 struct nsIntSize;
 
 namespace mozilla {
 namespace gl {
 
 class GLContext;
 
+/**
+ * Helper function that creates a 2D texture aSize.width x aSize.height with
+ * storage type specified by aFormats. Returns GL texture object id.
+ *
+ * See mozilla::gl::CreateTexture.
+ */
+GLuint CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
+                                 const gfxIntSize& aSize);
+
+/**
+ * Helper function that creates a 2D texture aSize.width x aSize.height with
+ * storage type aInternalFormat. Returns GL texture object id.
+ *
+ * Initialize textyre parameters to:
+ *    GL_TEXTURE_MIN_FILTER = GL_LINEAR
+ *    GL_TEXTURE_MAG_FILTER = GL_LINEAR
+ *    GL_TEXTURE_WRAP_S = GL_CLAMP_TO_EDGE
+ *    GL_TEXTURE_WRAP_T = GL_CLAMP_TO_EDGE
+ */
+GLuint CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
+                     GLenum aType, const gfxIntSize& aSize);
+
+/**
+ * Helper function to create, potentially, multisample render buffers suitable
+ * for offscreen rendering. Buffers of size aSize.width x aSize.height with
+ * storage specified by aFormat. returns GL render buffer object id.
+ */
+GLuint CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
+                          const gfxIntSize& aSize);
+
+/**
+ * Helper function to create, potentially, multisample render buffers suitable
+ * for offscreen rendering. Buffers of size aSize.width x aSize.height with
+ * storage specified by aFormats. GL render buffer object ids are returned via
+ * aColorMSRB, aDepthRB, and aStencilRB
+ */
+void CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
+                                     const gfxIntSize& aSize, bool aMultisample,
+                                     GLuint* aColorMSRB, GLuint* aDepthRB,
+                                     GLuint* aStencilRB);
+
+
+/** Buffer blitting helper */
 class GLBlitHelper MOZ_FINAL
 {
     // The GLContext is the sole owner of the GLBlitHelper.
     GLContext* mGL;
 
     GLuint mTexBlit_Buffer;
     GLuint mTexBlit_VertShader;
     GLuint mTex2DBlit_FragShader;
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -1340,114 +1340,16 @@ GLContext::ChooseGLFormats(const Surface
         formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
     }
 
     formats.stencil = LOCAL_GL_STENCIL_INDEX8;
 
     return formats;
 }
 
-GLuint
-GLContext::CreateTextureForOffscreen(const GLFormats& formats, const gfxIntSize& size)
-{
-    MOZ_ASSERT(formats.color_texInternalFormat);
-    MOZ_ASSERT(formats.color_texFormat);
-    MOZ_ASSERT(formats.color_texType);
-
-    return CreateTexture(formats.color_texInternalFormat,
-                         formats.color_texFormat,
-                         formats.color_texType,
-                         size);
-}
-
-GLuint
-GLContext::CreateTexture(GLenum internalFormat, GLenum format, GLenum type, const gfxIntSize& size)
-{
-    GLuint tex = 0;
-    fGenTextures(1, &tex);
-    ScopedBindTexture autoTex(this, tex);
-
-    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
-    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
-    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
-    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
-
-    fTexImage2D(LOCAL_GL_TEXTURE_2D,
-                0,
-                internalFormat,
-                size.width, size.height,
-                0,
-                format,
-                type,
-                nullptr);
-
-    return tex;
-}
-
-static inline void
-RenderbufferStorageBySamples(GLContext* gl, GLsizei samples, GLenum internalFormat, const gfxIntSize& size)
-{
-    if (samples) {
-        gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
-                                            samples,
-                                            internalFormat,
-                                            size.width, size.height);
-    } else {
-        gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
-                                 internalFormat,
-                                 size.width, size.height);
-    }
-}
-
-GLuint
-GLContext::CreateRenderbuffer(GLenum format, GLsizei samples, const gfxIntSize& size)
-{
-    GLuint rb = 0;
-    fGenRenderbuffers(1, &rb);
-    ScopedBindRenderbuffer autoRB(this, rb);
-
-    RenderbufferStorageBySamples(this, samples, format, size);
-
-    return rb;
-}
-
-void
-GLContext::CreateRenderbuffersForOffscreen(const GLFormats& formats, const gfxIntSize& size,
-                                           bool multisample,
-                                           GLuint* colorMSRB, GLuint* depthRB, GLuint* stencilRB)
-{
-    GLsizei samples = multisample ? formats.samples : 0;
-    if (colorMSRB) {
-        MOZ_ASSERT(formats.samples > 0);
-        MOZ_ASSERT(formats.color_rbFormat);
-
-        *colorMSRB = CreateRenderbuffer(formats.color_rbFormat, samples, size);
-    }
-
-    if (depthRB &&
-        stencilRB &&
-        formats.depthStencil)
-    {
-        *depthRB = CreateRenderbuffer(formats.depthStencil, samples, size);
-        *stencilRB = *depthRB;
-    } else {
-        if (depthRB) {
-            MOZ_ASSERT(formats.depth);
-
-            *depthRB = CreateRenderbuffer(formats.depth, samples, size);
-        }
-
-        if (stencilRB) {
-            MOZ_ASSERT(formats.stencil);
-
-            *stencilRB = CreateRenderbuffer(formats.stencil, samples, size);
-        }
-    }
-}
-
 bool
 GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus)
 {
     MOZ_ASSERT(fb);
 
     ScopedBindFramebuffer autoFB(this, fb);
     MOZ_ASSERT(fIsFramebuffer(fb));
 
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2410,26 +2410,16 @@ public:
 #endif
         return MakeCurrentImpl(aForce);
     }
 
     virtual bool SetupLookupFunction() = 0;
 
     virtual void ReleaseSurface() {}
 
-    void *GetUserData(void *aKey) {
-        void *result = nullptr;
-        mUserData.Get(aKey, &result);
-        return result;
-    }
-
-    void SetUserData(void *aKey, void *aValue) {
-        mUserData.Put(aKey, aValue);
-    }
-
     // Mark this context as destroyed.  This will nullptr out all
     // the GL function pointers!
     void MarkDestroyed();
 
     bool IsDestroyed() {
         // MarkDestroyed will mark all these as null.
         return mSymbols.fUseProgram == nullptr;
     }
@@ -2817,35 +2807,18 @@ public:
     PixelBufferFormat QueryPixelFormat();
     void UpdatePixelFormat();
 
     const PixelBufferFormat& GetPixelFormat() const {
         MOZ_ASSERT(mPixelFormat);
         return *mPixelFormat;
     }
 
-
-    GLuint CreateTextureForOffscreen(const GLFormats& formats,
-                                     const gfxIntSize& size);
-    GLuint CreateTexture(GLenum internalFormat,
-                         GLenum format, GLenum type,
-                         const gfxIntSize& size);
-    GLuint CreateRenderbuffer(GLenum format,
-                              GLsizei samples,
-                              const gfxIntSize& size);
     bool IsFramebufferComplete(GLuint fb, GLenum* status = nullptr);
 
-    // Pass null to an RB arg to disable its creation.
-    void CreateRenderbuffersForOffscreen(const GLFormats& formats,
-                                         const gfxIntSize& size,
-                                         bool multisample,
-                                         GLuint* colorMSRB,
-                                         GLuint* depthRB,
-                                         GLuint* stencilRB);
-
     // Does not check completeness.
     void AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
                            GLuint depthRB, GLuint stencilRB,
                            GLuint fb, GLenum target = LOCAL_GL_TEXTURE_2D);
 
     // Passing null is fine if the value you'd get is 0.
     bool AssembleOffscreenFBs(const GLuint colorMSRB,
                               const GLuint depthRB,
@@ -2905,18 +2878,16 @@ public:
         return mTexGarbageBin;
     }
 
     void EmptyTexGarbageBin();
 
     bool IsOffscreenSizeAllowed(const gfxIntSize& aSize) const;
 
 protected:
-    nsDataHashtable<nsPtrHashKey<void>, void*> mUserData;
-
     GLuint mReadTextureImagePrograms[4];
 
     bool InitWithPrefix(const char *prefix, bool trygl);
 
     void InitExtensions();
 
     nsTArray<nsIntRect> mViewportStack;
     nsTArray<nsIntRect> mScissorStack;
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -3,16 +3,17 @@
  * 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 "GLScreenBuffer.h"
 
 #include <cstring>
 #include "gfxImageSurface.h"
 #include "GLContext.h"
+#include "GLBlitHelper.h"
 #include "SharedSurfaceGL.h"
 #include "SurfaceStream.h"
 #ifdef MOZ_WIDGET_GONK
 #include "SharedSurfaceGralloc.h"
 #include "nsXULAppAPI.h"
 #endif
 #ifdef XP_MACOSX
 #include "SharedSurfaceIO.h"
@@ -542,18 +543,18 @@ DrawBuffer::Create(GLContext* const gl,
     } else {
         if (!formats.depth)
             pDepthRB = nullptr;
 
         if (!formats.stencil)
             pStencilRB = nullptr;
     }
 
-    gl->CreateRenderbuffersForOffscreen(formats, size, caps.antialias,
-                                        pColorMSRB, pDepthRB, pStencilRB);
+    CreateRenderbuffersForOffscreen(gl, formats, size, caps.antialias,
+                                    pColorMSRB, pDepthRB, pStencilRB);
 
     GLuint fb = 0;
     gl->fGenFramebuffers(1, &fb);
     gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb);
     MOZ_ASSERT(gl->IsFramebufferComplete(fb));
 
     return new DrawBuffer(gl, size, fb, colorMSRB, depthRB, stencilRB);
 }
@@ -595,18 +596,18 @@ ReadBuffer::Create(GLContext* gl,
     }
 
     GLuint depthRB = 0;
     GLuint stencilRB = 0;
 
     GLuint* pDepthRB   = caps.depth   ? &depthRB   : nullptr;
     GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr;
 
-    gl->CreateRenderbuffersForOffscreen(formats, surf->Size(), caps.antialias,
-                                        nullptr, pDepthRB, pStencilRB);
+    CreateRenderbuffersForOffscreen(gl, formats, surf->Size(), caps.antialias,
+                                    nullptr, pDepthRB, pStencilRB);
 
     GLuint colorTex = 0;
     GLuint colorRB = 0;
     GLenum target = 0;
 
     switch (surf->AttachType()) {
     case AttachmentType::GLTexture:
         colorTex = surf->Texture();
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -27,17 +27,17 @@ SharedSurface_EGLImage::Create(GLContext
 {
     GLLibraryEGL* egl = prodGL->GetLibraryEGL();
     MOZ_ASSERT(egl);
 
     if (!HasExtensions(egl, prodGL))
         return nullptr;
 
     MOZ_ALWAYS_TRUE(prodGL->MakeCurrent());
-    GLuint prodTex = prodGL->CreateTextureForOffscreen(formats, size);
+    GLuint prodTex = CreateTextureForOffscreen(prodGL, formats, size);
     if (!prodTex)
         return nullptr;
 
     return new SharedSurface_EGLImage(prodGL, egl,
                                       size, hasAlpha,
                                       formats, prodTex);
 }
 
@@ -125,17 +125,17 @@ static bool
 CreateTexturePipe(GLLibraryEGL* const egl, GLContext* const gl,
                   const GLFormats& formats, const gfxIntSize& size,
                   GLuint* const out_tex, EGLImage* const out_image)
 {
     MOZ_ASSERT(out_tex && out_image);
     *out_tex = 0;
     *out_image = 0;
 
-    GLuint tex = gl->CreateTextureForOffscreen(formats, size);
+    GLuint tex = CreateTextureForOffscreen(gl, formats, size);
     if (!tex)
         return false;
 
     EGLContext context = gl->GetEGLContext();
     MOZ_ASSERT(context);
     EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(tex);
     EGLImage image = egl->fCreateImage(egl->Display(), context,
                                        LOCAL_EGL_GL_TEXTURE_2D, buffer,
--- a/gfx/gl/SharedSurfaceGL.cpp
+++ b/gfx/gl/SharedSurfaceGL.cpp
@@ -242,20 +242,20 @@ SurfaceFactory_GL::ChooseBufferBits(cons
 
 SharedSurface_Basic*
 SharedSurface_Basic::Create(GLContext* gl,
                             const GLFormats& formats,
                             const gfxIntSize& size,
                             bool hasAlpha)
 {
     gl->MakeCurrent();
-    GLuint tex = gl->CreateTexture(formats.color_texInternalFormat,
-                                   formats.color_texFormat,
-                                   formats.color_texType,
-                                   size);
+    GLuint tex = CreateTexture(gl, formats.color_texInternalFormat,
+                               formats.color_texFormat,
+                               formats.color_texType,
+                               size);
 
     gfxImageFormat format = gfxImageFormatRGB24;
     switch (formats.color_texInternalFormat) {
     case LOCAL_GL_RGB:
     case LOCAL_GL_RGB8:
         if (formats.color_texType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
             format = gfxImageFormatRGB16_565;
         else
@@ -314,17 +314,17 @@ SharedSurface_GLTexture::Create(GLContex
                              const GLFormats& formats,
                              const gfxIntSize& size,
                              bool hasAlpha)
 {
     MOZ_ASSERT(prodGL);
     MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL));
 
     prodGL->MakeCurrent();
-    GLuint tex = prodGL->CreateTextureForOffscreen(formats, size);
+    GLuint tex = CreateTextureForOffscreen(prodGL, formats, size);
 
     return new SharedSurface_GLTexture(prodGL, consGL, size, hasAlpha, tex);
 }
 
 SharedSurface_GLTexture::~SharedSurface_GLTexture()
 {
     if (!mGL->MakeCurrent())
         return;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -208,17 +208,22 @@ MemoryTextureClient::ToSurfaceDescriptor
                                         GetFormat());
   return true;
 }
 
 bool
 MemoryTextureClient::Allocate(uint32_t aSize)
 {
   MOZ_ASSERT(!mBuffer);
-  mBuffer = new uint8_t[aSize];
+  static const fallible_t fallible = fallible_t();
+  mBuffer = new(fallible) uint8_t[aSize];
+  if (!mBuffer) {
+    NS_WARNING("Failed to allocate buffer");
+    return false;
+  }
   GfxMemoryImageReporter::DidAlloc(mBuffer);
   mBufSize = aSize;
   return true;
 }
 
 MemoryTextureClient::MemoryTextureClient(CompositableClient* aCompositable,
                                          gfx::SurfaceFormat aFormat,
                                          TextureFlags aFlags)
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1213,16 +1213,31 @@ const CSSRect AsyncPanZoomController::Ca
     scrollOffset.x = scrollableRect.x;
   }
   if (scrollOffset.y + compositionBounds.height > scrollableRect.height) {
     scrollOffset.y -= compositionBounds.height + scrollOffset.y - scrollableRect.height;
   } else if (scrollOffset.y < scrollableRect.y) {
     scrollOffset.y = scrollableRect.y;
   }
 
+  // FIXME/bug 936500: Make sure the displayport contains the composition
+  // bounds. This is to work around a layout bug that means if a display item's
+  // corresponding displayport doesn't contain its frame's bounds, it may get
+  // optimised out and the layer won't get created.
+  if (displayPort.x + displayPort.width < compositionBounds.width) {
+    displayPort.x = -(displayPort.width - compositionBounds.width);
+  } else if (displayPort.x > 0) {
+    displayPort.x = 0;
+  }
+  if (displayPort.y + displayPort.height < compositionBounds.height) {
+    displayPort.y = -(displayPort.height - compositionBounds.height);
+  } else if (displayPort.y > 0) {
+    displayPort.y = 0;
+  }
+
   CSSRect shiftedDisplayPort = displayPort + scrollOffset;
   return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset;
 }
 
 void AsyncPanZoomController::ScheduleComposite() {
   if (mCompositorParent) {
     mCompositorParent->ScheduleRenderOnCompositorThread();
   }
--- a/gfx/layers/ipc/Axis.cpp
+++ b/gfx/layers/ipc/Axis.cpp
@@ -26,17 +26,17 @@ namespace layers {
  * or we get a touch point very far away from the previous position for some
  * reason.
  */
 static float gMaxEventAcceleration = 999.0f;
 
 /**
  * Amount of friction applied during flings.
  */
-static float gFlingFriction = 0.006f;
+static float gFlingFriction = 0.002f;
 
 /**
  * Threshold for velocity beneath which we turn off any acceleration we had
  * during repeated flings.
  */
 static float gVelocityThreshold = 0.14f;
 
 /**
--- a/gfx/layers/ipc/SharedRGBImage.cpp
+++ b/gfx/layers/ipc/SharedRGBImage.cpp
@@ -79,18 +79,21 @@ CreateSharedRGBImage(ImageContainer *aIm
 
     if (!rgbImageDep->AllocateBuffer(aSize, aImageFormat)) {
       NS_WARNING("Failed to allocate shared memory for DeprecatedSharedRGBImage");
       return nullptr;
     }
     return rgbImageDep.forget();
   }
   nsRefPtr<SharedRGBImage> rgbImage = static_cast<SharedRGBImage*>(image.get());
-  rgbImage->Allocate(gfx::ToIntSize(aSize),
-                     gfx::ImageFormatToSurfaceFormat(aImageFormat));
+  if (!rgbImage->Allocate(gfx::ToIntSize(aSize),
+                          gfx::ImageFormatToSurfaceFormat(aImageFormat))) {
+    NS_WARNING("Failed to allocate a shared image");
+    return nullptr;
+  }
   return image.forget();
 }
 
 uint8_t *
 DeprecatedSharedRGBImage::GetBuffer()
 {
   return mShmem->get<uint8_t>();
 }
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -228,20 +228,16 @@ FPSState::DrawFPS(TimeStamp aNow,
   aProgram->SetRenderOffset(0, 0);
 
   aContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO,
                                LOCAL_GL_ONE, LOCAL_GL_ZERO);
 
   DrawQuads(aContext, mVBOs, aProgram, rects);
 }
 
-#ifdef CHECK_CURRENT_PROGRAM
-int ShaderProgramOGL::sCurrentProgramKey = 0;
-#endif
-
 CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
                              int aSurfaceHeight, bool aUseExternalSurfaceSize)
   : mWidget(aWidget)
   , mWidgetSize(-1, -1)
   , mSurfaceSize(aSurfaceWidth, aSurfaceHeight)
   , mHasBGRA(0)
   , mUseExternalSurfaceSize(aUseExternalSurfaceSize)
   , mFrameInProgress(false)
--- a/gfx/layers/opengl/OGLShaderProgram.cpp
+++ b/gfx/layers/opengl/OGLShaderProgram.cpp
@@ -444,19 +444,17 @@ ShaderProgramOGL::Activate()
   if (mProgramState == STATE_NEW) {
     if (!Initialize()) {
       NS_WARNING("Shader could not be initialised");
       return;
     }
   }
   NS_ASSERTION(HasInitialized(), "Attempting to activate a program that's not in use!");
   mGL->fUseProgram(mProgram);
-#if CHECK_CURRENT_PROGRAM
-  mGL->SetUserData(&sCurrentProgramKey, this);
-#endif
+
   // check and set the projection matrix
   if (mIsProjectionMatrixStale) {
     SetProjectionMatrix(mProjectionMatrix);
   }
 }
 
 
 void
--- a/gfx/layers/opengl/OGLShaderProgram.h
+++ b/gfx/layers/opengl/OGLShaderProgram.h
@@ -194,21 +194,24 @@ private:
     mHasMatrixProj(false) {}
 };
 
 
 #if defined(DEBUG)
 #define CHECK_CURRENT_PROGRAM 1
 #define ASSERT_THIS_PROGRAM                                             \
   do {                                                                  \
-    NS_ASSERTION(mGL->GetUserData(&sCurrentProgramKey) == this, \
+    GLuint currentProgram;                                              \
+    mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &currentProgram);       \
+    NS_ASSERTION(currentProgram == mProgram,                            \
                  "SetUniform with wrong program active!");              \
   } while (0)
 #else
-#define ASSERT_THIS_PROGRAM
+#define ASSERT_THIS_PROGRAM                                             \
+  do { } while (0)
 #endif
 
 /**
  * Represents an OGL shader program. The details of a program are represented
  * by a ProgramProfileOGL
  */
 class ShaderProgramOGL
 {
@@ -380,19 +383,16 @@ protected:
   ProgramProfileOGL mProfile;
   enum {
     STATE_NEW,
     STATE_OK,
     STATE_ERROR
   } mProgramState;
 
   GLint mTexCoordMultiplierUniformLocation;
-#ifdef CHECK_CURRENT_PROGRAM
-  static int sCurrentProgramKey;
-#endif
 
   void SetUniform(GLint aLocation, float aFloatValue);
   void SetUniform(GLint aLocation, const gfxRGBA& aColor);
   void SetUniform(GLint aLocation, int aLength, float *aFloatValues);
   void SetUniform(GLint aLocation, GLint aIntValue);
   void SetMatrixUniform(GLint aLocation, const gfx3DMatrix& aMatrix);
   void SetMatrixUniform(GLint aLocation, const float *aFloatValues);
 
new file mode 100644
--- /dev/null
+++ b/intl/icu-patches/bug-915735
@@ -0,0 +1,29 @@
+Bug 915735 - Fix linking the ICU libraries on Mac
+
+diff --git a/intl/icu/source/config/mh-darwin b/intl/icu/source/config/mh-darwin
+index 97d6bfc..fe1490e 100644
+--- a/intl/icu/source/config/mh-darwin
++++ b/intl/icu/source/config/mh-darwin
+@@ -23,21 +23,17 @@ ARFLAGS += -c
+ COMPILE.c=	$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -fno-common -c
+ COMPILE.cc=	$(CXX) $(DEFS) $(CPPFLAGS) $(CXXFLAGS) -fno-common -c
+ 
+ ## Commands to make a shared library
+ SHLIB.c=	$(CC) -dynamiclib -dynamic $(CFLAGS) $(LDFLAGS) $(LD_SOOPTIONS)
+ SHLIB.cc=	$(CXX) -dynamiclib -dynamic $(CXXFLAGS) $(LDFLAGS) $(LD_SOOPTIONS)
+ 
+ ## Compiler switches to embed a library name and version information
+-ifeq ($(ENABLE_RPATH),YES)
+-LD_SONAME = -Wl,-compatibility_version -Wl,$(SO_TARGET_VERSION_MAJOR) -Wl,-current_version -Wl,$(SO_TARGET_VERSION) -install_name $(libdir)/$(notdir $(MIDDLE_SO_TARGET))
+-else
+-LD_SONAME = -Wl,-compatibility_version -Wl,$(SO_TARGET_VERSION_MAJOR) -Wl,-current_version -Wl,$(SO_TARGET_VERSION) -install_name $(notdir $(MIDDLE_SO_TARGET))
+-endif
++LD_SONAME = -Wl,-compatibility_version -Wl,$(SO_TARGET_VERSION_MAJOR) -Wl,-current_version -Wl,$(SO_TARGET_VERSION) -install_name @executable_path/$(notdir $(MIDDLE_SO_TARGET))
+ 
+ ## Compiler switch to embed a runtime search path
+ LD_RPATH=
+ LD_RPATH_PRE= -Wl,-rpath,
+ 
+ ## Environment variable to set a runtime search path
+ LDLIBRARYPATH_ENVVAR = DYLD_LIBRARY_PATH
+ 
--- a/intl/icu/source/config/mh-darwin
+++ b/intl/icu/source/config/mh-darwin
@@ -23,21 +23,17 @@ ARFLAGS += -c
 COMPILE.c=	$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -fno-common -c
 COMPILE.cc=	$(CXX) $(DEFS) $(CPPFLAGS) $(CXXFLAGS) -fno-common -c
 
 ## Commands to make a shared library
 SHLIB.c=	$(CC) -dynamiclib -dynamic $(CFLAGS) $(LDFLAGS) $(LD_SOOPTIONS)
 SHLIB.cc=	$(CXX) -dynamiclib -dynamic $(CXXFLAGS) $(LDFLAGS) $(LD_SOOPTIONS)
 
 ## Compiler switches to embed a library name and version information
-ifeq ($(ENABLE_RPATH),YES)
-LD_SONAME = -Wl,-compatibility_version -Wl,$(SO_TARGET_VERSION_MAJOR) -Wl,-current_version -Wl,$(SO_TARGET_VERSION) -install_name $(libdir)/$(notdir $(MIDDLE_SO_TARGET))
-else
-LD_SONAME = -Wl,-compatibility_version -Wl,$(SO_TARGET_VERSION_MAJOR) -Wl,-current_version -Wl,$(SO_TARGET_VERSION) -install_name $(notdir $(MIDDLE_SO_TARGET))
-endif
+LD_SONAME = -Wl,-compatibility_version -Wl,$(SO_TARGET_VERSION_MAJOR) -Wl,-current_version -Wl,$(SO_TARGET_VERSION) -install_name @executable_path/$(notdir $(MIDDLE_SO_TARGET))
 
 ## Compiler switch to embed a runtime search path
 LD_RPATH=
 LD_RPATH_PRE= -Wl,-rpath,
 
 ## Environment variable to set a runtime search path
 LDLIBRARYPATH_ENVVAR = DYLD_LIBRARY_PATH
 
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -114,16 +114,54 @@ ifdef HAVE_DTRACE
 export_files += $(CURDIR)/javascript-trace.h
 endif
 
 INSTALL_TARGETS += jsconfig
 jsconfig_FILES = $(export_files)
 jsconfig_DEST = $(DIST)/include
 jsconfig_TARGET := export
 
+# Ensure that this happens before using $(MOZ_PSEUDO_DERECURSE)
+include $(topsrcdir)/config/config.mk
+
+# Ensure that this happens before including rules.mk
+ifdef ENABLE_INTL_API
+ifndef MOZ_NATIVE_ICU
+ifeq ($(OS_ARCH),WINNT)
+  # Library names: On Windows, ICU uses modified library names for static
+  # and debug libraries.
+  ifdef MOZ_DEBUG
+    ICU_LIB_SUFFIX=d
+  endif
+  ifdef JS_SHARED_LIBRARY
+    ICU_FILES := $(foreach libname,$(ICU_LIB_NAMES),intl/icu/target/lib/$(libname)$(ICU_LIB_SUFFIX)$(MOZ_ICU_VERSION).dll)
+  else
+    ICU_LIB_RENAME = $(foreach libname,$(ICU_LIB_NAMES),\
+                       cp -p intl/icu/target/lib/s$(libname)$(ICU_LIB_SUFFIX).lib intl/icu/target/lib/$(libname).lib;)
+  endif
+else
+  ifeq ($(OS_ARCH),Darwin)
+    ifdef JS_SHARED_LIBRARY
+      ICU_FILES := $(foreach libname,$(ICU_LIB_NAMES),intl/icu/target/lib/$(DLL_PREFIX)$(libname).$(MOZ_ICU_VERSION)$(DLL_SUFFIX))
+    endif
+  else
+    ifdef JS_SHARED_LIBRARY
+      ICU_FILES := $(foreach libname,$(ICU_LIB_NAMES),intl/icu/target/lib/$(DLL_PREFIX)$(libname)$(DLL_SUFFIX).$(MOZ_ICU_VERSION))
+    endif
+  endif
+endif
+ifdef ICU_FILES
+  ICU_DEST := $(DIST)/bin
+  INSTALL_TARGETS += ICU
+  $(ICU_FILES): buildicu
+  ICU_TARGET := $(if $(MOZ_PSEUDO_DERECURSE),compile,export)
+endif
+endif
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 .PHONY: buildffi buildicu
 buildffi buildicu:
 $(if $(MOZ_PSEUDO_DERECURSE),compile,export):: buildffi buildicu
 
 ifdef JS_HAS_CTYPES
 ifndef MOZ_NATIVE_FFI
@@ -150,24 +188,31 @@ LOCAL_INCLUDES += \
   -I$(topsrcdir)/../../intl/icu/source/common \
   -I$(topsrcdir)/../../intl/icu/source/i18n \
   $(NULL)
 endif
 
 ifdef ENABLE_INTL_API
 ifndef MOZ_NATIVE_ICU
 
-ifeq ($(OS_ARCH),WINNT)
-  # Library names: On Windows, ICU uses modified library names for static
-  # and debug libraries.
-  ifdef MOZ_DEBUG
-    ICU_LIB_SUFFIX=d
-  endif
-  ICU_LIB_RENAME = $(foreach libname,$(ICU_LIB_NAMES),\
-                     cp -p intl/icu/target/lib/s$(libname)$(ICU_LIB_SUFFIX).lib intl/icu/target/lib/$(libname).lib;)
+ifdef _MSC_VER
+OS_LIBS += $(call EXPAND_LIBNAME,delayimp)
+ifdef MOZ_DEBUG
+EXTRA_DSO_LDOPTS += \
+  -DELAYLOAD:icudtd$(MOZ_ICU_VERSION).dll \
+  -DELAYLOAD:icuind$(MOZ_ICU_VERSION).dll \
+  -DELAYLOAD:icuucd$(MOZ_ICU_VERSION).dll \
+  $(NULL)
+else
+EXTRA_DSO_LDOPTS += \
+  -DELAYLOAD:icudt$(MOZ_ICU_VERSION).dll \
+  -DELAYLOAD:icuin$(MOZ_ICU_VERSION).dll \
+  -DELAYLOAD:icuuc$(MOZ_ICU_VERSION).dll \
+  $(NULL)
+endif
 endif
 
 ifdef .PYMAKE
 ICU_MAKE = $(GMAKE)
 else
 ICU_MAKE = $(MAKE)
 endif
 
@@ -318,17 +363,17 @@ CFLAGS += $(MOZ_ZLIB_CFLAGS)
 EXTRA_LIBS += $(MOZ_ZLIB_LIBS)
 # Enable zlib usage if zlib has been located. When building the browser on
 # Windows, MOZ_ZLIB_LIBS is empty because zlib is part of libmozglue. We thus
 # also enable zlib if mozglue is present.
 ifneq (,$(MOZ_ZLIB_LIBS)$(MOZ_GLUE_LDFLAGS))
 DEFINES += -DUSE_ZLIB
 endif
 
-ifdef MOZ_NATIVE_ICU
+ifdef MOZ_SHARED_ICU
 EXTRA_DSO_LDOPTS += $(MOZ_ICU_LIBS)
 else
 SHARED_LIBRARY_LIBS += $(MOZ_ICU_LIBS)
 endif
 
 # Prevent floating point errors caused by VC++ optimizations
 ifdef _MSC_VER
 # XXX We should add this to CXXFLAGS, too?
--- a/js/src/aclocal.m4
+++ b/js/src/aclocal.m4
@@ -24,10 +24,11 @@ builtin(include, build/autoconf/frameptr
 builtin(include, build/autoconf/compiler-opts.m4)dnl
 builtin(include, build/autoconf/expandlibs.m4)dnl
 builtin(include, build/autoconf/arch.m4)dnl
 builtin(include, build/autoconf/android.m4)dnl
 builtin(include, build/autoconf/zlib.m4)dnl
 builtin(include, build/autoconf/linux.m4)dnl
 builtin(include, build/autoconf/python-virtualenv.m4)dnl
 builtin(include, build/autoconf/winsdk.m4)dnl
+builtin(include, build/autoconf/icu.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
new file mode 100644
--- /dev/null
+++ b/js/src/build/autoconf/icu.m4
@@ -0,0 +1,31 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Set the MOZ_ICU_VERSION variable to denote the current version of the
+dnl ICU library, and also the MOZ_SHARED_ICU which would be true if we are
+dnl linking against a shared library of ICU, either one that we build from
+dnl our copy of ICU or the system provided library.
+
+AC_DEFUN([MOZ_CONFIG_ICU], [
+    icudir="$_topsrcdir/intl/icu/source"
+    if test ! -d "$icudir"; then
+        icudir="$_topsrcdir/../../intl/icu/source"
+        if test ! -d "$icudir"; then
+            AC_MSG_ERROR([Cannot find the ICU directory])
+        fi
+    fi
+
+    version=`sed -n 's/^[[:space:]]*#[[:space:]]*define[[:space:]][[:space:]]*U_ICU_VERSION_MAJOR_NUM[[:space:]][[:space:]]*\([0-9][0-9]*\)[[:space:]]*$/\1/p' "$icudir/common/unicode/uvernum.h"`
+    if test x"$version" = x; then
+       AC_MSG_ERROR([cannot determine icu version number from uvernum.h header file $lineno])
+    fi
+    MOZ_ICU_VERSION="$version"
+
+    if test -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
+        MOZ_SHARED_ICU=1
+    fi
+
+    AC_SUBST(MOZ_ICU_VERSION)
+    AC_SUBST(MOZ_SHARED_ICU)
+])
--- a/js/src/config/moz.build
+++ b/js/src/config/moz.build
@@ -19,8 +19,11 @@ if CONFIG['HOST_OS_ARCH'] != 'WINNT':
         'nsinstall.c',
         'pathsub.c',
     ]
     HOST_PROGRAM = 'nsinstall_real'
 
 # Force wrap zlib system header if building js as a shared library.
 if CONFIG['JS_SHARED_LIBRARY'] or CONFIG['MOZ_NATIVE_ZLIB']:
     DEFINES['MOZ_NATIVE_ZLIB'] = 1
+
+if CONFIG['MOZ_SHARED_ICU']:
+    DEFINES['MOZ_SHARED_ICU'] = True
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -1126,17 +1126,17 @@ gst/video/video.h
 sys/msg.h
 sys/ipc.h
 sys/thr.h
 sys/user.h
 kvm.h
 spawn.h
 err.h
 xlocale.h
-#if MOZ_NATIVE_ICU==1
+#ifdef MOZ_SHARED_ICU
 unicode/locid.h
 unicode/numsys.h
 unicode/ucal.h
 unicode/uclean.h
 unicode/ucol.h
 unicode/udat.h
 unicode/udatpg.h
 unicode/uenum.h
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4202,40 +4202,65 @@ esac
 if test -n "$EXPOSE_INTL_API"; then
     AC_DEFINE(EXPOSE_INTL_API)
 fi
 
 dnl Settings for the implementation of the ECMAScript Internationalization API
 if test -n "$ENABLE_INTL_API"; then
     AC_DEFINE(ENABLE_INTL_API)
 
+    MOZ_CONFIG_ICU()
+
     if test -z "$MOZ_NATIVE_ICU"; then
         case "$OS_TARGET" in
             WINNT)
                 ICU_LIB_NAMES="icuin icuuc icudt"
+                if test "$DISABLE_SHARED_JS" != "1"; then
+                    DBG_SUFFIX=
+                    if test -n "$MOZ_DEBUG"; then
+                        DBG_SUFFIX=d
+                    fi
+                    MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib/$(LIB_PREFIX)$(lib)$(DBG_SUFFIX).$(LIB_SUFFIX))'
+                fi
                 ;;
-            Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
+            Darwin)
                 ICU_LIB_NAMES="icui18n icuuc icudata"
+                if test "$DISABLE_SHARED_JS" != "1"; then
+                   MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib/$(DLL_PREFIX)$(lib).$(MOZ_ICU_VERSION)$(DLL_SUFFIX))'
+                fi
+                ;;
+            Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
+                ICU_LIB_NAMES="icui18n icuuc icudata"
+                if test "$DISABLE_SHARED_JS" != "1"; then
+                   MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib/$(DLL_PREFIX)$(lib)$(DLL_SUFFIX).$(MOZ_ICU_VERSION))'
+                fi
                 ;;
             *)
                 AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
         esac
-        MOZ_ICU_LIBS='$(call EXPAND_LIBNAME_PATH,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib)'
+        if test "$DISABLE_SHARED_JS" = "1"; then
+            MOZ_ICU_LIBS='$(call EXPAND_LIBNAME_PATH,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib)'
+        fi
     fi
 fi
 
+AC_SUBST(DBG_SUFFIX)
 AC_SUBST(ENABLE_INTL_API)
 AC_SUBST(ICU_LIB_NAMES)
 AC_SUBST(MOZ_ICU_LIBS)
 AC_SUBST(MOZ_NATIVE_ICU)
 
 dnl Settings for ICU
 if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
-    dnl We build ICU as a static library.
-    AC_DEFINE(U_STATIC_IMPLEMENTATION)
+    dnl We build ICU as a static library for non-shared js builds and as a shared library for shared js builds.
+    if test "$DISABLE_SHARED_JS" = "1"; then
+        AC_DEFINE(U_STATIC_IMPLEMENTATION)
+    else
+        AC_DEFINE(U_COMBINED_IMPLEMENTATION)
+    fi
 
     dnl Source files that use ICU should have control over which parts of the ICU
     dnl namespace they want to use.
     AC_DEFINE(U_USING_ICU_NAMESPACE,0)
 
     # Set ICU compile options
     ICU_CPPFLAGS=""
     # don't use icu namespace automatically in client code
@@ -4317,18 +4342,22 @@ if test -n "$ENABLE_INTL_API" -a -z "$MO
         ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH"
         ICU_TARGET_OPT="--build=$build --host=$target"
     else
         # CROSS_COMPILE isn't set build and target are i386 and x86-64.
         # So we must set target for --build and --host.
         ICU_TARGET_OPT="--build=$target --host=$target"
     fi
 
-    # To reduce library size, use static linking
-    ICU_LINK_OPTS="--enable-static --disable-shared"
+    if test "$DISABLE_SHARED_JS" = "1"; then
+        # To reduce library size, use static linking
+        ICU_LINK_OPTS="--enable-static --disable-shared"
+    else
+        ICU_LINK_OPTS="--disable-static --enable-shared"
+    fi
     # Force the ICU static libraries to be position independent code
     ICU_CFLAGS="$DSO_PIC_CFLAGS $CFLAGS"
     ICU_CXXFLAGS="$DSO_PIC_CFLAGS $CXXFLAGS"
 
     ICU_BUILD_OPTS=""
     if test -n "$MOZ_DEBUG" -o "MOZ_DEBUG_SYMBOLS"; then
         ICU_CFLAGS="$ICU_CFLAGS $MOZ_DEBUG_FLAGS"
         ICU_CXXFLAGS="$ICU_CXXFLAGS $MOZ_DEBUG_FLAGS"
--- a/js/src/gdb/Makefile.in
+++ b/js/src/gdb/Makefile.in
@@ -3,17 +3,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/.
 
 LIBS = $(DEPTH)/$(LIB_PREFIX)js_static.$(LIB_SUFFIX) $(NSPR_LIBS) $(MOZ_ZLIB_LIBS)
 
 LOCAL_INCLUDES += -I$(topsrcdir) -I..
 
-ifdef MOZ_NATIVE_ICU
+ifdef MOZ_SHARED_ICU
 EXTRA_LIBS += $(MOZ_ICU_LIBS)
 endif
 
 EXTRA_LIBS += $(MOZ_FFI_LIBS)
 
 # Place a GDB Python auto-load file next to the gdb-tests executable, both
 # in the build directory and in the dist/bin directory.
 PP_TARGETS += GDB_AUTOLOAD
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -3,17 +3,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/.
 
 LIBS      = $(DEPTH)/$(LIB_PREFIX)js_static.$(LIB_SUFFIX) $(NSPR_LIBS) $(MOZ_ZLIB_LIBS)
 
 LOCAL_INCLUDES += -I$(topsrcdir) -I..
 
-ifdef MOZ_NATIVE_ICU
+ifdef MOZ_SHARED_ICU
 EXTRA_LIBS += $(MOZ_ICU_LIBS)
 endif
 
 EXTRA_LIBS += $(MOZ_FFI_LIBS)
 
 ifdef QEMU_EXE
 MOZ_POST_PROGRAM_COMMAND = $(topsrcdir)/build/qemu-wrap --qemu $(QEMU_EXE) --libdir $(CROSS_LIB)
 endif
--- a/js/src/shell/Makefile.in
+++ b/js/src/shell/Makefile.in
@@ -10,17 +10,17 @@ ifdef _MSC_VER
 # for PGO.
 NO_PROFILE_GUIDED_OPTIMIZE := 1
 endif
 
 LIBS      = $(NSPR_LIBS) $(EDITLINE_LIBS) $(DEPTH)/$(LIB_PREFIX)js_static.$(LIB_SUFFIX) $(MOZ_ZLIB_LIBS)
 ifdef MOZ_NATIVE_FFI
 EXTRA_LIBS += $(MOZ_FFI_LIBS)
 endif
-ifdef MOZ_NATIVE_ICU
+ifdef MOZ_SHARED_ICU
 EXTRA_LIBS += $(MOZ_ICU_LIBS)
 endif
 
 LOCAL_INCLUDES += -I$(topsrcdir) -I..
 
 ifeq ($(OS_ARCH),Darwin)
 ifeq ($(TARGET_CPU),x86_64)
 DARWIN_EXE_LDFLAGS += -pagezero_size 10000 -image_base 100000000
--- a/layout/media/symbols.def.in
+++ b/layout/media/symbols.def.in
@@ -33,21 +33,23 @@ nestegg_sniff
 #ifndef MOZ_NATIVE_LIBVPX
 vpx_codec_control_
 vpx_codec_dec_init_ver
 vpx_codec_decode
 vpx_codec_destroy
 vpx_codec_get_frame
 vpx_codec_peek_stream_info
 vpx_codec_vp8_dx
+vpx_codec_vp9_dx
 vpx_img_free
 vpx_codec_enc_config_set
 vpx_codec_enc_init_ver
 #ifdef MOZ_VP8_ENCODER
 vpx_codec_vp8_cx
+vpx_codec_vp9_cx
 #endif
 vpx_img_set_rect
 vpx_img_wrap
 vpx_codec_get_cx_data
 vpx_codec_enc_config_default
 vpx_img_alloc
 vpx_codec_encode
 #endif
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/conditional3/css-supports-042.xht
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+  <title>CSS Test: An @supports rule condition with an unexpected token before the closing paren of a supports_condition_in_parens should parse as a general_enclosed</title>
+  <link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au" />
+  <link rel="help" href="http://www.w3.org/TR/css3-conditional/#at-supports" />
+  <meta name="flags" content="" />
+  <meta name="assert" content="An @supports rule condition that has an unexpected token before the closing paren of a supports_condition_in_parens should parse as a general_enclosed and evaluate to false rather than fail to parse."/>
+  <link rel="match" href="support/pass.xht" />
+  <style type="text/css"><![CDATA[
+    @supports ((color: green) bad) or (color: green) {
+      html { background-color: green }
+    }
+  ]]></style>
+ </head>
+ <body>
+ </body>
+</html>
--- a/layout/reftests/w3c-css/submitted/conditional3/reftest.list
+++ b/layout/reftests/w3c-css/submitted/conditional3/reftest.list
@@ -36,8 +36,9 @@ default-preferences pref(layout.css.supp
 == css-supports-034.xht support/pass.xht
 == css-supports-035.xht support/pass.xht
 == css-supports-036.xht support/pass.xht
 == css-supports-037.xht support/pass.xht
 == css-supports-038.xht support/pass.xht
 == css-supports-039.xht support/pass.xht
 == css-supports-040.xht support/pass.xht
 == css-supports-041.xht support/pass.xht
+== css-supports-042.xht support/pass.xht
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-baseline-multi-line-horiz-1-ref.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-baseline-multi-line-horiz-1-ref.html
@@ -7,18 +7,16 @@
      baseline-aligned items aligned using specific font-size / line-heights,
      and with unaligned children taken out of baseline-alignment using
      "vertical-align:top".
 -->
 <html>
 <head>
   <title>CSS Reftest Reference</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-  <link rel="help" href="http://www.w3.org/TR/css3-flexbox/#flex-baselines">
-  <link rel="match" href="flexbox-baseline-multi-line-horiz-1-ref.html">
   <meta charset="utf-8">
   <style>
     .flexContainer {
       display: inline-block;
       flex-wrap: wrap;
       width: 40px;
       height: 40px;
       background: lightblue;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-baseline-multi-line-horiz-2-ref.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-baseline-multi-line-horiz-2-ref.html
@@ -7,18 +7,16 @@
      baseline-aligned items aligned using specific font-size / line-heights,
      and with unaligned children taken out of baseline-alignment using
      "vertical-align:top".
 -->
 <html>
 <head>
   <title>CSS Reftest Reference</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-  <link rel="help" href="http://www.w3.org/TR/css3-flexbox/#flex-baselines">
-  <link rel="match" href="flexbox-baseline-multi-line-horiz-1-ref.html">
   <meta charset="utf-8">
   <style>
     .flexContainer {
       display: inline-block;
       flex-wrap: wrap;
       width: 40px;
       /* Split testcase's 40px height into 20px of padding-top and 20px of
          height, to set aside space for the testcase's (invisible) second line
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-1a.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-1a.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-before in horizontal multi-line flex containers</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-horiz-1-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       flex-wrap: wrap;
       border: 1px dashed black;
       width: 60px;
       height: 20px;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-1b.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-1b.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-after in horizontal multi-line flex containers</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-horiz-1-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       flex-wrap: wrap;
       border: 1px dashed black;
       width: 60px;
       height: 20px;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-2a.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-2a.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-before in horizontal single-line flex containers (should have no effect)</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-horiz-2-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       border: 1px dashed black;
       width: 60px;
       height: 20px;
       margin: 2px;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-2b.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-horiz-2b.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-after in horizontal single-line flex containers (should have no effect)</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-horiz-2-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       border: 1px dashed black;
       width: 60px;
       height: 20px;
       margin: 2px;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-1a.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-1a.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-before in vertical multi-line flex containers</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-vert-1-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       flex-direction: column;
       flex-wrap: wrap;
       border: 1px dashed black;
       width: 20px;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-1b.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-1b.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-after in vertical multi-line flex containers</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-vert-1-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       flex-direction: column;
       flex-wrap: wrap;
       border: 1px dashed black;
       width: 20px;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-2a.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-2a.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-before in vertical single-line flex containers (should have no effect)</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-vert-2-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       flex-direction: column;
       border: 1px dashed black;
       width: 20px;
       height: 60px;
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-2b.html
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-break-request-vert-2b.html
@@ -3,17 +3,17 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
 <head>
   <title>CSS Test: Testing page-break-after in vertical single-line flex containers (should have no effect)</title>
   <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
   <link rel="help" href="http://dev.w3.org/csswg/css-flexbox/#algo-line-break">
-  <link rel="match" href="flexbox-flex-wrap-horiz-3-ref.html">
+  <link rel="match" href="flexbox-break-request-vert-2-ref.html">
   <meta charset="utf-8">
   <style>
     div.flexbox {
       display: flex;
       flex-direction: column;
       border: 1px dashed black;
       width: 20px;
       height: 60px;
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -892,16 +892,17 @@ input[type="number"] {
   width: 149px; /* to match type=text */
 }
 
 input[type=number]::-moz-number-wrapper {
   /* Prevent styling that would change the type of frame we construct. */
   display: flex;
   float: none !important;
   position: static !important;
+  height: 100%;
 }
 
 input[type=number]::-moz-number-text {
   -moz-appearance: none;
   /* work around autofocus bug 939248 on initial load */
   -moz-user-modify: read-write;
   /* This pseudo-element is also an 'input' element (nested inside and
    * distinct from the <input type=number> element) so we need to prevent the
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -2784,19 +2784,19 @@ CSSParserImpl::ParseSupportsConditionInP
       REPORT_UNEXPECTED_EOF(PESupportsConditionInParensEOF);
       return false;
     }
     aConditionMet = false;
     return true;
   }
 
   if (!(ExpectSymbol(')', true))) {
-    REPORT_UNEXPECTED_TOKEN(PESupportsConditionExpectedCloseParen);
     SkipUntil(')');
-    return false;
+    aConditionMet = false;
+    return true;
   }
 
   return true;
 }
 
 // supports_condition_in_parens_inside_parens
 //   : core_declaration
 //   | supports_condition_negation
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -464,17 +464,17 @@ nsSVGImageFrame::ReflowSVG()
 
   NS_ABORT_IF_FALSE(!(GetStateBits() & NS_FRAME_IS_NONDISPLAY),
                     "ReflowSVG mechanism not designed for this");
 
   if (!nsSVGUtils::NeedsReflowSVG(this)) {
     return;
   }
 
-  nsRefPtr<gfxContext> tmpCtx = new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
+  gfxContext tmpCtx(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
 
   // We'd like to just pass the identity matrix to GeneratePath, but if
   // this frame's user space size is _very_ large/small then the extents we
   // obtain below might have overflowed or otherwise be broken. This would
   // cause us to end up with a broken mRect and visual overflow rect and break
   // painting of this frame. This is particularly noticeable if the transforms
   // between us and our nsSVGOuterSVGFrame scale this frame to a reasonable
   // size. To avoid this we sadly have to do extra work to account for the
@@ -483,20 +483,20 @@ nsSVGImageFrame::ReflowSVG()
   // XXX Will Azure eventually save us from having to do this?
   gfxSize scaleFactors = GetCanvasTM(FOR_OUTERSVG_TM).ScaleFactors(true);
   bool applyScaling = fabs(scaleFactors.width) >= 1e-6 &&
                       fabs(scaleFactors.height) >= 1e-6;
   gfxMatrix scaling;
   if (applyScaling) {
     scaling.Scale(scaleFactors.width, scaleFactors.height);
   }
-  tmpCtx->Save();
-  GeneratePath(tmpCtx, scaling);
-  tmpCtx->Restore();
-  gfxRect extent = tmpCtx->GetUserPathExtent();
+  tmpCtx.Save();
+  GeneratePath(&tmpCtx, scaling);
+  tmpCtx.Restore();
+  gfxRect extent = tmpCtx.GetUserPathExtent();
   if (applyScaling) {
     extent.Scale(1 / scaleFactors.width, 1 / scaleFactors.height);
   }
 
   if (!extent.IsEmpty()) {
     mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent, 
               PresContext()->AppUnitsPerCSSPixel());
   } else {
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -240,17 +240,18 @@ nsSVGPathGeometryFrame::GetFrameForPoint
     if (!hitTestFlags || ((hitTestFlags & SVG_HIT_TEST_CHECK_MRECT) &&
                           !mRect.Contains(point)))
       return nullptr;
     fillRule = StyleSVG()->mFillRule;
   }
 
   bool isHit = false;
 
-  nsRefPtr<gfxContext> tmpCtx = new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
+  nsRefPtr<gfxContext> tmpCtx =
+    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
 
   GeneratePath(tmpCtx, canvasTM);
   gfxPoint userSpacePoint =
     tmpCtx->DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x),
                                   PresContext()->AppUnitsToGfxUnits(aPoint.y)));
 
   if (fillRule == NS_STYLE_FILL_RULE_EVENODD)
     tmpCtx->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
@@ -402,17 +403,18 @@ nsSVGPathGeometryFrame::GetBBoxContribut
 {
   SVGBBox bbox;
 
   if (aToBBoxUserspace.IsSingular()) {
     // XXX ReportToConsole
     return bbox;
   }
 
-  nsRefPtr<gfxContext> tmpCtx = new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
+  nsRefPtr<gfxContext> tmpCtx =
+    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
 
   GeneratePath(tmpCtx, aToBBoxUserspace);
   tmpCtx->IdentityMatrix();
 
   // Be careful when replacing the following logic to get the fill and stroke
   // extents independently (instead of computing the stroke extents from the
   // path extents). You may think that you can just use the stroke extents if
   // there is both a fill and a stroke. In reality it's necessary to calculate
--- a/media/libvpx/Makefile.in
+++ b/media/libvpx/Makefile.in
@@ -17,19 +17,19 @@ ifeq ($(OS_TARGET),Android)
 LOCAL_INCLUDES += -I$(ANDROID_NDK)/sources/android/cpufeatures
 ifndef MOZ_WEBRTC
 # For cpu-features.c
 VPATH += $(ANDROID_NDK)/sources/android/cpufeatures
 CSRCS += cpu-features.c
 endif
 endif
 
-ASM_OFFSETS = asm_com_offsets.asm
+ASM_OFFSETS = vpx_scale_asm_offsets.asm
 ifdef MOZ_VP8_ENCODER
-ASM_OFFSETS += asm_enc_offsets.asm
+ASM_OFFSETS += vp8_asm_enc_offsets.asm
 endif
 
 
 ifdef VPX_AS_CONVERSION
 # The ARM asm is written in ARM RVCT syntax, but we actually build it with
 # gas using GNU syntax. Add some rules to perform the conversion.
 
 GENERATED_DIRS += $(dir $(ASFILES))
@@ -48,107 +48,109 @@ ifdef VPX_NEED_OBJ_INT_EXTRACT
 # parse that format, and so only has limited support for cross-compilation.
 
 ifdef VPX_ARM_ASM
 VPX_OIE_FORMAT := rvds
 else
 VPX_OIE_FORMAT := gas
 endif
 
-GARBAGE += asm_com_offsets.$(OBJ_SUFFIX) asm_com_offsets.asm
+GARBAGE += vpx_scale_asm_offsets.$(OBJ_SUFFIX) vpx_scale_asm_offsets.asm
 
 ifdef MOZ_VP8_ENCODER
 
-GARBAGE += asm_enc_offsets.$(OBJ_SUFFIX) asm_enc_offsets.asm
+GARBAGE += vp8_asm_enc_offsets.$(OBJ_SUFFIX) vp8_asm_enc_offsets.asm
 endif
 
 else
 
 # We can extract the asm offsets directly from generated assembly using inline
 # asm. This is the preferred method.
 
-asm_com_offsets.s: CFLAGS += -DINLINE_ASM
+vpx_scale_asm_offsets.s: CFLAGS += -DINLINE_ASM
 
 OFFSET_PATTERN := '^[a-zA-Z0-9_]* EQU'
 
-# This rule, as well as the rule for asm_enc_offsets.s further below are here
+# This rule, as well as the rule for vp8_asm_enc_offsets.s further below are here
 # because the generic rule in rules.mk was made to not be implicit, and we
 # can't put the C files in CSRCS.
-asm_com_offsets.s: $(srcdir)/vp8/common/asm_com_offsets.c
+vpx_scale_asm_offsets.s: $(srcdir)/vpx_scale/vpx_scale_asm_offsets.c
 	$(REPORT_BUILD)
 	$(CC) -S $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
-asm_com_offsets.asm: asm_com_offsets.s
+vpx_scale_asm_offsets.asm: vpx_scale_asm_offsets.s
 	grep $(OFFSET_PATTERN) $< | sed -e 's/[$$\#]//g' \
 	    $(if $(VPX_AS_CONVERSION),| $(VPX_AS_CONVERSION)) > $@
 
-GARBAGE += asm_com_offsets.s asm_com_offsets.asm
+GARBAGE += vpx_scale_asm_offsets.s vpx_scale_asm_offsets.asm
 
 ifdef MOZ_VP8_ENCODER
 
-asm_enc_offsets.s: CFLAGS += -DINLINE_ASM
+vp8_asm_enc_offsets.s: CFLAGS += -DINLINE_ASM
 
-asm_enc_offsets.s: $(srcdir)/vp8/encoder/asm_enc_offsets.c
+vp8_asm_enc_offsets.s: $(srcdir)/vp8/encoder/vp8_asm_enc_offsets.c
 	$(REPORT_BUILD)
 	$(CC) -S $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
-asm_enc_offsets.asm: asm_enc_offsets.s
+vp8_asm_enc_offsets.asm: vp8_asm_enc_offsets.s
 	grep $(OFFSET_PATTERN) $< | sed -e 's/[$$\#]//g' \
 	    $(if $(VPX_AS_CONVERSION),| $(VPX_AS_CONVERSION)) > $@
 
-GARBAGE += asm_enc_offsets.s asm_enc_offsets.asm
+GARBAGE += vp8_asm_enc_offsets.s vp8_asm_enc_offsets.asm
 
 
 endif
 
 endif
 
-EXTRA_MDDEPEND_FILES = asm_enc_offsets.s.pp asm_enc_offsets.$(OBJ_SUFFIX).pp asm_com_offsets.s.pp asm_com_offsets.$(OBJ_SUFFIX).pp
+EXTRA_MDDEPEND_FILES = vp8_asm_enc_offsets.s.pp vp8_asm_enc_offsets.$(OBJ_SUFFIX).pp vpx_scale_asm_offsets.s.pp vpx_scale_asm_offsets.$(OBJ_SUFFIX).pp
 
 include $(topsrcdir)/config/rules.mk
 
 # This must be after rules.mk in order to use $(OBJ_SUFFIX) outside a
 # recursively-expanded variable.
 
+# dont add for MSVC
 ifndef _MSC_VER
 %_sse2.$(OBJ_SUFFIX): CFLAGS += -msse2
+%_ssse3.$(OBJ_SUFFIX): CFLAGS += -mssse3
+%_avx2.$(OBJ_SUFFIX): CFLAGS += -mavx2
 endif
 
-quantize_sse2.$(OBJ_SUFFIX): asm_enc_offsets.asm
-quantize_sse4.$(OBJ_SUFFIX): asm_enc_offsets.asm
-quantize_ssse3.$(OBJ_SUFFIX): asm_enc_offsets.asm
+quantize_sse4.$(OBJ_SUFFIX): vp8_asm_enc_offsets.asm
+quantize_ssse3.$(OBJ_SUFFIX): vp8_asm_enc_offsets.asm
 
 ifdef VPX_NEED_OBJ_INT_EXTRACT
 
 # only for MSVC
 ifdef _MSC_VER
-NO_PROFILE_GUIDED_OPTIMIZE := asm_com_offsets.c
+NO_PROFILE_GUIDED_OPTIMIZE := vpx_scale_asm_offsets.c
 endif
 
-asm_com_offsets.asm: asm_com_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
+vpx_scale_asm_offsets.asm: vpx_scale_asm_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
 	./$(HOST_PROGRAM) $(VPX_OIE_FORMAT) $< \
 	    $(if $(VPX_AS_CONVERSION),| $(VPX_AS_CONVERSION)) > $@
 
 # Filter out this object, because we don't want to link against it.
 # It was generated solely so it could be parsed by obj_int_extract.
-OBJS := $(filter-out asm_com_offsets.$(OBJ_SUFFIX),$(OBJS))
+OBJS := $(filter-out vpx_scale_asm_offsets.$(OBJ_SUFFIX),$(OBJS))
 
 ifdef MOZ_VP8_ENCODER
 
 ifdef _MSC_VER
-NO_PROFILE_GUIDED_OPTIMIZE += asm_enc_offsets.c
+NO_PROFILE_GUIDED_OPTIMIZE += vp8_asm_enc_offsets.c
 endif
 
-asm_enc_offsets.asm: asm_enc_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
+vp8_asm_enc_offsets.asm: vp8_asm_enc_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
 	./$(HOST_PROGRAM) $(VPX_OIE_FORMAT) $< \
 	    $(if $(VPX_AS_CONVERSION),| $(VPX_AS_CONVERSION)) > $@
 
 # Filter out this object, because we don't want to link against it.
 # It was generated solely so it could be parsed by obj_int_extract.
-OBJS := $(filter-out asm_enc_offsets.$(OBJ_SUFFIX),$(OBJS))
+OBJS := $(filter-out vp8_asm_enc_offsets.$(OBJ_SUFFIX),$(OBJS))
 
 endif
 endif
 
 # Workaround a bug of Sun Studio (CR 6963410)
 ifdef SOLARIS_SUNPRO_CC
 ifeq (86,$(findstring 86,$(OS_TEST)))
 filter.o: filter.c Makefile.in
--- a/media/libvpx/README_MOZILLA
+++ b/media/libvpx/README_MOZILLA
@@ -1,2 +1,11 @@
-Using the v1.2.0 release pulled from
-http://webm.googlecode.com/files/libvpx-v1.2.0.zip
+The source from this directory was copied from the libvpx
+git repository using the update.py script. The only changes
+made were those applied by update.py and the addition of
+moz.build and Makefile.in build files for the
+Mozilla build system.
+
+The libvpx git repository is:
+
+    https://gerrit.chromium.org/gerrit/webm/libvpx
+
+The git commit ID used was 2e88f2f2ec777259bda1714e72f1ecd2519bceb5
--- a/media/libvpx/build/make/ads2gas.pl
+++ b/media/libvpx/build/make/ads2gas.pl
@@ -12,19 +12,34 @@
 
 # ads2gas.pl
 # Author: Eric Fung (efung (at) acm.org)
 #
 # Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
 #
 # Usage: cat inputfile | perl ads2gas.pl > outputfile
 #
+
+use FindBin;
+use lib $FindBin::Bin;
+use thumb;
+
+my $thumb = 0;
+
+foreach my $arg (@ARGV) {
+    $thumb = 1 if ($arg eq "-thumb");
+}
+
 print "@ This file was created from a .asm file\n";
 print "@  using the ads2gas.pl script.\n";
 print "\t.equ DO1STROUNDING, 0\n";
+if ($thumb) {
+    print "\t.syntax unified\n";
+    print "\t.thumb\n";
+}
 
 # Stack of procedure names.
 @proc_stack = ();
 
 while (<STDIN>)
 {
     undef $comment;
     undef $line;
@@ -146,27 +161,36 @@ while (<STDIN>)
     # Labels need trailing colon
 #   s/^(\w+)/$1:/ if !/EQU/;
     # put the colon at the end of the line in the macro
     s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
 
     # ALIGN directive
     s/\bALIGN\b/.balign/g;
 
-    # ARM code
-    s/\sARM/.arm/g;
+    if ($thumb) {
+        # ARM code - we force everything to thumb with the declaration in the header
+        s/\sARM//g;
+    } else {
+        # ARM code
+        s/\sARM/.arm/g;
+    }
 
     # push/pop
     s/(push\s+)(r\d+)/stmdb sp\!, \{$2\}/g;
     s/(pop\s+)(r\d+)/ldmia sp\!, \{$2\}/g;
 
     # NEON code
     s/(vld1.\d+\s+)(q\d+)/$1\{$2\}/g;
     s/(vtbl.\d+\s+[^,]+),([^,]+)/$1,\{$2\}/g;
 
+    if ($thumb) {
+        thumb::FixThumbInstructions($_, 0);
+    }
+
     # eabi_attributes numerical equivalents can be found in the
     # "ARM IHI 0045C" document.
 
     # REQUIRE8 Stack is required to be 8-byte aligned
     s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
 
     # PRESERVE8 Stack 8-byte align is preserved
     s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
--- a/media/libvpx/build/make/obj_int_extract.c
+++ b/media/libvpx/build/make/obj_int_extract.c
@@ -12,903 +12,816 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "vpx_config.h"
 #include "vpx/vpx_integer.h"
 
-typedef enum
-{
-    OUTPUT_FMT_PLAIN,
-    OUTPUT_FMT_RVDS,
-    OUTPUT_FMT_GAS,
+typedef enum {
+  OUTPUT_FMT_PLAIN,
+  OUTPUT_FMT_RVDS,
+  OUTPUT_FMT_GAS,
 } output_fmt_t;
 
-int log_msg(const char *fmt, ...)
-{
-    int res;
-    va_list ap;
-    va_start(ap, fmt);
-    res = vfprintf(stderr, fmt, ap);
-    va_end(ap);
-    return res;
+int log_msg(const char *fmt, ...) {
+  int res;
+  va_list ap;
+  va_start(ap, fmt);
+  res = vfprintf(stderr, fmt, ap);
+  va_end(ap);
+  return res;
 }
 
 #if defined(__GNUC__) && __GNUC__
 #if defined(__MACH__)
 
 #include <mach-o/loader.h>
 #include <mach-o/nlist.h>
 
-int parse_macho(uint8_t *base_buf, size_t sz)
-{
-    int i, j;
-    struct mach_header header;
-    uint8_t *buf = base_buf;
-    int base_data_section = 0;
-    int bits = 0;
+int print_macho_equ(output_fmt_t mode, uint8_t* name, int val) {
+  switch (mode) {
+    case OUTPUT_FMT_RVDS:
+      printf("%-40s EQU %5d\n", name, val);
+      return 0;
+    case  OUTPUT_FMT_GAS:
+      printf(".set %-40s, %5d\n", name, val);
+      return 0;
+    default:
+      log_msg("Unsupported mode: %d", mode);
+      return 1;
+  }
+}
+
+int parse_macho(uint8_t *base_buf, size_t sz, output_fmt_t mode) {
+  int i, j;
+  struct mach_header header;
+  uint8_t *buf = base_buf;
+  int base_data_section = 0;
+  int bits = 0;
+
+  /* We can read in mach_header for 32 and 64 bit architectures
+   * because it's identical to mach_header_64 except for the last
+   * element (uint32_t reserved), which we don't use. Then, when
+   * we know which architecture we're looking at, increment buf
+   * appropriately.
+   */
+  memcpy(&header, buf, sizeof(struct mach_header));
+
+  if (header.magic == MH_MAGIC) {
+    if (header.cputype == CPU_TYPE_ARM
+        || header.cputype == CPU_TYPE_X86) {
+      bits = 32;
+      buf += sizeof(struct mach_header);
+    } else {
+      log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_[ARM|X86].\n");
+      goto bail;
+    }
+  } else if (header.magic == MH_MAGIC_64) {
+    if (header.cputype == CPU_TYPE_X86_64) {
+      bits = 64;
+      buf += sizeof(struct mach_header_64);
+    } else {
+      log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_X86_64.\n");
+      goto bail;
+    }
+  } else {
+    log_msg("Bad magic number for object file. 0x%x or 0x%x expected, 0x%x found.\n",
+            MH_MAGIC, MH_MAGIC_64, header.magic);
+    goto bail;
+  }
 
-    /* We can read in mach_header for 32 and 64 bit architectures
-     * because it's identical to mach_header_64 except for the last
-     * element (uint32_t reserved), which we don't use. Then, when
-     * we know which architecture we're looking at, increment buf
-     * appropriately.
-     */
-    memcpy(&header, buf, sizeof(struct mach_header));
+  if (header.filetype != MH_OBJECT) {
+    log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
+    goto bail;
+  }
+
+  for (i = 0; i < header.ncmds; i++) {
+    struct load_command lc;
+
+    memcpy(&lc, buf, sizeof(struct load_command));
+
+    if (lc.cmd == LC_SEGMENT) {
+      uint8_t *seg_buf = buf;
+      struct section s;
+      struct segment_command seg_c;
+
+      memcpy(&seg_c, seg_buf, sizeof(struct segment_command));
+      seg_buf += sizeof(struct segment_command);
+
+      /* Although each section is given it's own offset, nlist.n_value
+       * references the offset of the first section. This isn't
+       * apparent without debug information because the offset of the
+       * data section is the same as the first section. However, with
+       * debug sections mixed in, the offset of the debug section
+       * increases but n_value still references the first section.
+       */
+      if (seg_c.nsects < 1) {
+        log_msg("Not enough sections\n");
+        goto bail;
+      }
 
-    if (header.magic == MH_MAGIC)
-    {
-        if (header.cputype == CPU_TYPE_ARM
-            || header.cputype == CPU_TYPE_X86)
-        {
-            bits = 32;
-            buf += sizeof(struct mach_header);
+      memcpy(&s, seg_buf, sizeof(struct section));
+      base_data_section = s.offset;
+    } else if (lc.cmd == LC_SEGMENT_64) {
+      uint8_t *seg_buf = buf;
+      struct section_64 s;
+      struct segment_command_64 seg_c;
+
+      memcpy(&seg_c, seg_buf, sizeof(struct segment_command_64));
+      seg_buf += sizeof(struct segment_command_64);
+
+      /* Explanation in LG_SEGMENT */
+      if (seg_c.nsects < 1) {
+        log_msg("Not enough sections\n");
+        goto bail;
+      }
+
+      memcpy(&s, seg_buf, sizeof(struct section_64));
+      base_data_section = s.offset;
+    } else if (lc.cmd == LC_SYMTAB) {
+      if (base_data_section != 0) {
+        struct symtab_command sc;
+        uint8_t *sym_buf = base_buf;
+        uint8_t *str_buf = base_buf;
+
+        memcpy(&sc, buf, sizeof(struct symtab_command));
+
+        if (sc.cmdsize != sizeof(struct symtab_command)) {
+          log_msg("Can't find symbol table!\n");
+          goto bail;
         }
-        else
-        {
-            log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_[ARM|X86].\n");
-            goto bail;
-        }
-    }
-    else if (header.magic == MH_MAGIC_64)
-    {
-        if (header.cputype == CPU_TYPE_X86_64)
-        {
-            bits = 64;
-            buf += sizeof(struct mach_header_64);
+
+        sym_buf += sc.symoff;
+        str_buf += sc.stroff;
+
+        for (j = 0; j < sc.nsyms; j++) {
+          /* Location of string is cacluated each time from the
+           * start of the string buffer.  On darwin the symbols
+           * are prefixed by "_", so we bump the pointer by 1.
+           * The target value is defined as an int in *_asm_*_offsets.c,
+           * which is 4 bytes on all targets we currently use.
+           */
+          if (bits == 32) {
+            struct nlist nl;
+            int val;
+
+            memcpy(&nl, sym_buf, sizeof(struct nlist));
+            sym_buf += sizeof(struct nlist);
+
+            memcpy(&val, base_buf + base_data_section + nl.n_value,
+                   sizeof(val));
+            print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
+          } else { /* if (bits == 64) */
+            struct nlist_64 nl;
+            int val;
+
+            memcpy(&nl, sym_buf, sizeof(struct nlist_64));
+            sym_buf += sizeof(struct nlist_64);
+
+            memcpy(&val, base_buf + base_data_section + nl.n_value,
+                   sizeof(val));
+            print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
+          }
         }
-        else
-        {
-            log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_X86_64.\n");
-            goto bail;
-        }
-    }
-    else
-    {
-        log_msg("Bad magic number for object file. 0x%x or 0x%x expected, 0x%x found.\n",
-                MH_MAGIC, MH_MAGIC_64, header.magic);
-        goto bail;
-    }
-
-    if (header.filetype != MH_OBJECT)
-    {
-        log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
-        goto bail;
+      }
     }
 
-    for (i = 0; i < header.ncmds; i++)
-    {
-        struct load_command lc;
-
-        memcpy(&lc, buf, sizeof(struct load_command));
-
-        if (lc.cmd == LC_SEGMENT)
-        {
-            uint8_t *seg_buf = buf;
-            struct section s;
-            struct segment_command seg_c;
-
-            memcpy(&seg_c, seg_buf, sizeof(struct segment_command));
-            seg_buf += sizeof(struct segment_command);
-
-            /* Although each section is given it's own offset, nlist.n_value
-             * references the offset of the first section. This isn't
-             * apparent without debug information because the offset of the
-             * data section is the same as the first section. However, with
-             * debug sections mixed in, the offset of the debug section
-             * increases but n_value still references the first section.
-             */
-            if (seg_c.nsects < 1)
-            {
-                log_msg("Not enough sections\n");
-                goto bail;
-            }
-
-            memcpy(&s, seg_buf, sizeof(struct section));
-            base_data_section = s.offset;
-        }
-        else if (lc.cmd == LC_SEGMENT_64)
-        {
-            uint8_t *seg_buf = buf;
-            struct section_64 s;
-            struct segment_command_64 seg_c;
-
-            memcpy(&seg_c, seg_buf, sizeof(struct segment_command_64));
-            seg_buf += sizeof(struct segment_command_64);
-
-            /* Explanation in LG_SEGMENT */
-            if (seg_c.nsects < 1)
-            {
-                log_msg("Not enough sections\n");
-                goto bail;
-            }
+    buf += lc.cmdsize;
+  }
 
-            memcpy(&s, seg_buf, sizeof(struct section_64));
-            base_data_section = s.offset;
-        }
-        else if (lc.cmd == LC_SYMTAB)
-        {
-            if (base_data_section != 0)
-            {
-                struct symtab_command sc;
-                uint8_t *sym_buf = base_buf;
-                uint8_t *str_buf = base_buf;
-
-                memcpy(&sc, buf, sizeof(struct symtab_command));
-
-                if (sc.cmdsize != sizeof(struct symtab_command))
-                {
-                    log_msg("Can't find symbol table!\n");
-                    goto bail;
-                }
-
-                sym_buf += sc.symoff;
-                str_buf += sc.stroff;
-
-                for (j = 0; j < sc.nsyms; j++)
-                {
-                    /* Location of string is cacluated each time from the
-                     * start of the string buffer.  On darwin the symbols
-                     * are prefixed by "_", so we bump the pointer by 1.
-                     * The target value is defined as an int in asm_*_offsets.c,
-                     * which is 4 bytes on all targets we currently use.
-                     */
-                    if (bits == 32)
-                    {
-                        struct nlist nl;
-                        int val;
-
-                        memcpy(&nl, sym_buf, sizeof(struct nlist));
-                        sym_buf += sizeof(struct nlist);
-
-                        memcpy(&val, base_buf + base_data_section + nl.n_value,
-                               sizeof(val));
-                        printf("%-40s EQU %5d\n",
-                               str_buf + nl.n_un.n_strx + 1, val);
-                    }
-                    else /* if (bits == 64) */
-                    {
-                        struct nlist_64 nl;
-                        int val;
-
-                        memcpy(&nl, sym_buf, sizeof(struct nlist_64));
-                        sym_buf += sizeof(struct nlist_64);
-
-                        memcpy(&val, base_buf + base_data_section + nl.n_value,
-                               sizeof(val));
-                        printf("%-40s EQU %5d\n",
-                               str_buf + nl.n_un.n_strx + 1, val);
-                    }
-                }
-            }
-        }
-
-        buf += lc.cmdsize;
-    }
-
-    return 0;
+  return 0;
 bail:
-    return 1;
+  return 1;
 
 }
 
 #elif defined(__ELF__)
 #include "elf.h"
 
 #define COPY_STRUCT(dst, buf, ofst, sz) do {\
-        if(ofst + sizeof((*(dst))) > sz) goto bail;\
-        memcpy(dst, buf+ofst, sizeof((*(dst))));\
-    } while(0)
+    if(ofst + sizeof((*(dst))) > sz) goto bail;\
+    memcpy(dst, buf+ofst, sizeof((*(dst))));\
+  } while(0)
 
 #define ENDIAN_ASSIGN(val, memb) do {\
-        if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
-        (val) = (memb);\
-    } while(0)
+    if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
+    (val) = (memb);\
+  } while(0)
 
 #define ENDIAN_ASSIGN_IN_PLACE(memb) do {\
-        ENDIAN_ASSIGN(memb, memb);\
-    } while(0)
+    ENDIAN_ASSIGN(memb, memb);\
+  } while(0)
 
-typedef struct
-{
-    uint8_t      *buf; /* Buffer containing ELF data */
-    size_t        sz;  /* Buffer size */
-    int           le_data; /* Data is little-endian */
-    unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
-    int           bits; /* 32 or 64 */
-    Elf32_Ehdr    hdr32;
-    Elf64_Ehdr    hdr64;
+typedef struct {
+  uint8_t      *buf; /* Buffer containing ELF data */
+  size_t        sz;  /* Buffer size */
+  int           le_data; /* Data is little-endian */
+  unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+  int           bits; /* 32 or 64 */
+  Elf32_Ehdr    hdr32;
+  Elf64_Ehdr    hdr64;
 } elf_obj_t;
 
-int parse_elf_header(elf_obj_t *elf)
-{
-    int res;
-    /* Verify ELF Magic numbers */
-    COPY_STRUCT(&elf->e_ident, elf->buf, 0, elf->sz);
-    res = elf->e_ident[EI_MAG0] == ELFMAG0;
-    res &= elf->e_ident[EI_MAG1] == ELFMAG1;
-    res &= elf->e_ident[EI_MAG2] == ELFMAG2;
-    res &= elf->e_ident[EI_MAG3] == ELFMAG3;
-    res &= elf->e_ident[EI_CLASS] == ELFCLASS32
-        || elf->e_ident[EI_CLASS] == ELFCLASS64;
-    res &= elf->e_ident[EI_DATA] == ELFDATA2LSB;
+int parse_elf_header(elf_obj_t *elf) {
+  int res;
+  /* Verify ELF Magic numbers */
+  COPY_STRUCT(&elf->e_ident, elf->buf, 0, elf->sz);
+  res = elf->e_ident[EI_MAG0] == ELFMAG0;
+  res &= elf->e_ident[EI_MAG1] == ELFMAG1;
+  res &= elf->e_ident[EI_MAG2] == ELFMAG2;
+  res &= elf->e_ident[EI_MAG3] == ELFMAG3;
+  res &= elf->e_ident[EI_CLASS] == ELFCLASS32
+         || elf->e_ident[EI_CLASS] == ELFCLASS64;
+  res &= elf->e_ident[EI_DATA] == ELFDATA2LSB;
 
-    if (!res) goto bail;
+  if (!res) goto bail;
 
-    elf->le_data = elf->e_ident[EI_DATA] == ELFDATA2LSB;
+  elf->le_data = elf->e_ident[EI_DATA] == ELFDATA2LSB;
 
-    /* Read in relevant values */
-    if (elf->e_ident[EI_CLASS] == ELFCLASS32)
-    {
-        elf->bits = 32;
-        COPY_STRUCT(&elf->hdr32, elf->buf, 0, elf->sz);
+  /* Read in relevant values */
+  if (elf->e_ident[EI_CLASS] == ELFCLASS32) {
+    elf->bits = 32;
+    COPY_STRUCT(&elf->hdr32, elf->buf, 0, elf->sz);
 
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_type);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_machine);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_version);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_entry);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phoff);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shoff);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_flags);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_ehsize);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phentsize);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phnum);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shentsize);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shnum);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shstrndx);
-    }
-    else /* if (elf->e_ident[EI_CLASS] == ELFCLASS64) */
-    {
-        elf->bits = 64;
-        COPY_STRUCT(&elf->hdr64, elf->buf, 0, elf->sz);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_type);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_machine);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_version);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_entry);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phoff);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shoff);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_flags);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_ehsize);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phentsize);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phnum);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shentsize);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shnum);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shstrndx);
+  } else { /* if (elf->e_ident[EI_CLASS] == ELFCLASS64) */
+    elf->bits = 64;
+    COPY_STRUCT(&elf->hdr64, elf->buf, 0, elf->sz);
 
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_type);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_machine);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_version);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_entry);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phoff);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shoff);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_flags);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_ehsize);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phentsize);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phnum);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shentsize);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shnum);
-        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shstrndx);
-    }
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_type);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_machine);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_version);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_entry);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phoff);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shoff);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_flags);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_ehsize);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phentsize);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phnum);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shentsize);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shnum);
+    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shstrndx);
+  }
 
-    return 0;
+  return 0;
 bail:
-    log_msg("Failed to parse ELF file header");
-    return 1;
+  log_msg("Failed to parse ELF file header");
+  return 1;
 }
 
-int parse_elf_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr32, Elf64_Shdr *hdr64)
-{
-    if (hdr32)
-    {
-        if (idx >= elf->hdr32.e_shnum)
-            goto bail;
-
-        COPY_STRUCT(hdr32, elf->buf, elf->hdr32.e_shoff + idx * elf->hdr32.e_shentsize,
-                    elf->sz);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_name);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_type);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_flags);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addr);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_offset);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_size);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_link);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_info);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addralign);
-        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_entsize);
-    }
-    else /* if (hdr64) */
-    {
-        if (idx >= elf->hdr64.e_shnum)
-            goto bail;
-
-        COPY_STRUCT(hdr64, elf->buf, elf->hdr64.e_shoff + idx * elf->hdr64.e_shentsize,
-                    elf->sz);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_name);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_type);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_flags);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addr);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_offset);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_size);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_link);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_info);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addralign);
-        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_entsize);
-    }
-
-    return 0;
-bail:
-    return 1;
-}
-
-char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx)
-{
-    if (elf->bits == 32)
-    {
-        Elf32_Shdr shdr;
-
-        if (parse_elf_section(elf, s_idx, &shdr, NULL))
-        {
-            log_msg("Failed to parse ELF string table: section %d, index %d\n",
-                    s_idx, idx);
-            return "";
-        }
+int parse_elf_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr32, Elf64_Shdr *hdr64) {
+  if (hdr32) {
+    if (idx >= elf->hdr32.e_shnum)
+      goto bail;
 
-        return (char *)(elf->buf + shdr.sh_offset + idx);
-    }
-    else /* if (elf->bits == 64) */
-    {
-        Elf64_Shdr shdr;
-
-        if (parse_elf_section(elf, s_idx, NULL, &shdr))
-        {
-            log_msg("Failed to parse ELF string table: section %d, index %d\n",
-                    s_idx, idx);
-            return "";
-        }
-
-        return (char *)(elf->buf + shdr.sh_offset + idx);
-    }
-}
-
-int parse_elf_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym32, Elf64_Sym *sym64)
-{
-    if (sym32)
-    {
-        COPY_STRUCT(sym32, elf->buf, ofst, elf->sz);
-        ENDIAN_ASSIGN_IN_PLACE(sym32->st_name);
-        ENDIAN_ASSIGN_IN_PLACE(sym32->st_value);
-        ENDIAN_ASSIGN_IN_PLACE(sym32->st_size);
-        ENDIAN_ASSIGN_IN_PLACE(sym32->st_info);
-        ENDIAN_ASSIGN_IN_PLACE(sym32->st_other);
-        ENDIAN_ASSIGN_IN_PLACE(sym32->st_shndx);
-    }
-    else /* if (sym64) */
-    {
-        COPY_STRUCT(sym64, elf->buf, ofst, elf->sz);
-        ENDIAN_ASSIGN_IN_PLACE(sym64->st_name);
-        ENDIAN_ASSIGN_IN_PLACE(sym64->st_value);
-        ENDIAN_ASSIGN_IN_PLACE(sym64->st_size);
-        ENDIAN_ASSIGN_IN_PLACE(sym64->st_info);
-        ENDIAN_ASSIGN_IN_PLACE(sym64->st_other);
-        ENDIAN_ASSIGN_IN_PLACE(sym64->st_shndx);
-    }
-    return 0;
-bail:
-    return 1;
-}
-
-int parse_elf(uint8_t *buf, size_t sz, output_fmt_t mode)
-{
-    elf_obj_t    elf;
-    unsigned int ofst;
-    int          i;
-    Elf32_Off    strtab_off32;
-    Elf64_Off    strtab_off64; /* save String Table offset for later use */
-
-    memset(&elf, 0, sizeof(elf));
-    elf.buf = buf;
-    elf.sz = sz;
-
-    /* Parse Header */
-    if (parse_elf_header(&elf))
+    COPY_STRUCT(hdr32, elf->buf, elf->hdr32.e_shoff + idx * elf->hdr32.e_shentsize,
+                elf->sz);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_name);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_type);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_flags);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addr);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_offset);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_size);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_link);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_info);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addralign);
+    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_entsize);
+  } else { /* if (hdr64) */
+    if (idx >= elf->hdr64.e_shnum)
       goto bail;
 
-    if (elf.bits == 32)
-    {
-        Elf32_Shdr shdr;
-        for (i = 0; i < elf.hdr32.e_shnum; i++)
-        {
-            parse_elf_section(&elf, i, &shdr, NULL);
-
-            if (shdr.sh_type == SHT_STRTAB)
-            {
-                char strtsb_name[128];
+    COPY_STRUCT(hdr64, elf->buf, elf->hdr64.e_shoff + idx * elf->hdr64.e_shentsize,
+                elf->sz);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_name);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_type);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_flags);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addr);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_offset);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_size);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_link);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_info);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addralign);
+    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_entsize);
+  }
 
-                strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
+  return 0;
+bail:
+  return 1;
+}
 
-                if (!(strcmp(strtsb_name, ".shstrtab")))
-                {
-                    /* log_msg("found section: %s\n", strtsb_name); */
-                    strtab_off32 = shdr.sh_offset;
-                    break;
-                }
-            }
-        }
+char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) {
+  if (elf->bits == 32) {
+    Elf32_Shdr shdr;
+
+    if (parse_elf_section(elf, s_idx, &shdr, NULL)) {
+      log_msg("Failed to parse ELF string table: section %d, index %d\n",
+              s_idx, idx);
+      return "";
     }
-    else /* if (elf.bits == 64) */
-    {
-        Elf64_Shdr shdr;
-        for (i = 0; i < elf.hdr64.e_shnum; i++)
-        {
-            parse_elf_section(&elf, i, NULL, &shdr);
 
-            if (shdr.sh_type == SHT_STRTAB)
-            {
-                char strtsb_name[128];
+    return (char *)(elf->buf + shdr.sh_offset + idx);
+  } else { /* if (elf->bits == 64) */
+    Elf64_Shdr shdr;
 
-                strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
-
-                if (!(strcmp(strtsb_name, ".shstrtab")))
-                {
-                    /* log_msg("found section: %s\n", strtsb_name); */
-                    strtab_off64 = shdr.sh_offset;
-                    break;
-                }
-            }
-        }
+    if (parse_elf_section(elf, s_idx, NULL, &shdr)) {
+      log_msg("Failed to parse ELF string table: section %d, index %d\n",
+              s_idx, idx);
+      return "";
     }
 
-    /* Parse all Symbol Tables */
-    if (elf.bits == 32)
-    {
-        Elf32_Shdr shdr;
-        for (i = 0; i < elf.hdr32.e_shnum; i++)
-        {
-            parse_elf_section(&elf, i, &shdr, NULL);
-
-            if (shdr.sh_type == SHT_SYMTAB)
-            {
-                for (ofst = shdr.sh_offset;
-                     ofst < shdr.sh_offset + shdr.sh_size;
-                     ofst += shdr.sh_entsize)
-                {
-                    Elf32_Sym sym;
-
-                    parse_elf_symbol(&elf, ofst, &sym, NULL);
+    return (char *)(elf->buf + shdr.sh_offset + idx);
+  }
+}
 
-                    /* For all OBJECTS (data objects), extract the value from the
-                     * proper data segment.
-                     */
-                    /* if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
-                        log_msg("found data object %s\n",
-                                parse_elf_string_table(&elf,
-                                                       shdr.sh_link,
-                                                       sym.st_name));
-                     */
+int parse_elf_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym32, Elf64_Sym *sym64) {
+  if (sym32) {
+    COPY_STRUCT(sym32, elf->buf, ofst, elf->sz);
+    ENDIAN_ASSIGN_IN_PLACE(sym32->st_name);
+    ENDIAN_ASSIGN_IN_PLACE(sym32->st_value);
+    ENDIAN_ASSIGN_IN_PLACE(sym32->st_size);
+    ENDIAN_ASSIGN_IN_PLACE(sym32->st_info);
+    ENDIAN_ASSIGN_IN_PLACE(sym32->st_other);
+    ENDIAN_ASSIGN_IN_PLACE(sym32->st_shndx);
+  } else { /* if (sym64) */
+    COPY_STRUCT(sym64, elf->buf, ofst, elf->sz);
+    ENDIAN_ASSIGN_IN_PLACE(sym64->st_name);
+    ENDIAN_ASSIGN_IN_PLACE(sym64->st_value);
+    ENDIAN_ASSIGN_IN_PLACE(sym64->st_size);
+    ENDIAN_ASSIGN_IN_PLACE(sym64->st_info);
+    ENDIAN_ASSIGN_IN_PLACE(sym64->st_other);
+    ENDIAN_ASSIGN_IN_PLACE(sym64->st_shndx);
+  }
+  return 0;
+bail:
+  return 1;
+}
 
-                    if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
-                        && sym.st_size == 4)
-                    {
-                        Elf32_Shdr dhdr;
-                        int val = 0;
-                        char section_name[128];
+int parse_elf(uint8_t *buf, size_t sz, output_fmt_t mode) {
+  elf_obj_t    elf;
+  unsigned int ofst;
+  int          i;
+  Elf32_Off    strtab_off32;
+  Elf64_Off    strtab_off64; /* save String Table offset for later use */
 
-                        parse_elf_section(&elf, sym.st_shndx, &dhdr, NULL);
-
-                        /* For explanition - refer to _MSC_VER version of code */
-                        strcpy(section_name, (char *)(elf.buf + strtab_off32 + dhdr.sh_name));
-                        /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
+  memset(&elf, 0, sizeof(elf));
+  elf.buf = buf;
+  elf.sz = sz;
 
-                        if (strcmp(section_name, ".bss"))
-                        {
-                            if (sizeof(val) != sym.st_size)
-                            {
-                                /* The target value is declared as an int in
-                                 * asm_*_offsets.c, which is 4 bytes on all
-                                 * targets we currently use. Complain loudly if
-                                 * this is not true.
-                                 */
-                                log_msg("Symbol size is wrong\n");
-                                goto bail;
-                            }
+  /* Parse Header */
+  if (parse_elf_header(&elf))
+    goto bail;
 
-                            memcpy(&val,
-                                   elf.buf + dhdr.sh_offset + sym.st_value,
-                                   sym.st_size);
-                        }
+  if (elf.bits == 32) {
+    Elf32_Shdr shdr;
+    for (i = 0; i < elf.hdr32.e_shnum; i++) {
+      parse_elf_section(&elf, i, &shdr, NULL);
 
-                        if (!elf.le_data)
-                        {
-                            log_msg("Big Endian data not supported yet!\n");
-                            goto bail;
-                        }
+      if (shdr.sh_type == SHT_STRTAB) {
+        char strtsb_name[128];
+
+        strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
 
-                        switch (mode)
-                        {
-                            case OUTPUT_FMT_RVDS:
-                                printf("%-40s EQU %5d\n",
-                                       parse_elf_string_table(&elf,
-                                                              shdr.sh_link,
-                                                              sym.st_name),
-                                       val);
-                                break;
-                            case OUTPUT_FMT_GAS:
-                                printf(".equ %-40s, %5d\n",
-                                       parse_elf_string_table(&elf,
-                                                              shdr.sh_link,
-                                                              sym.st_name),
-                                       val);
-                                break;
-                            default:
-                                printf("%s = %d\n",
-                                       parse_elf_string_table(&elf,
-                                                              shdr.sh_link,
-                                                              sym.st_name),
-                                       val);
-                        }
-                    }
-                }
-            }
+        if (!(strcmp(strtsb_name, ".shstrtab"))) {
+          /* log_msg("found section: %s\n", strtsb_name); */
+          strtab_off32 = shdr.sh_offset;
+          break;
         }
+      }
+    }
+  } else { /* if (elf.bits == 64) */
+    Elf64_Shdr shdr;
+    for (i = 0; i < elf.hdr64.e_shnum; i++) {
+      parse_elf_section(&elf, i, NULL, &shdr);
+
+      if (shdr.sh_type == SHT_STRTAB) {
+        char strtsb_name[128];
+
+        strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
+
+        if (!(strcmp(strtsb_name, ".shstrtab"))) {
+          /* log_msg("found section: %s\n", strtsb_name); */
+          strtab_off64 = shdr.sh_offset;
+          break;
+        }
+      }
     }
-    else /* if (elf.bits == 64) */
-    {
-        Elf64_Shdr shdr;
-        for (i = 0; i < elf.hdr64.e_shnum; i++)
-        {
-            parse_elf_section(&elf, i, NULL, &shdr);
+  }
+
+  /* Parse all Symbol Tables */
+  if (elf.bits == 32) {
+    Elf32_Shdr shdr;
+    for (i = 0; i < elf.hdr32.e_shnum; i++) {
+      parse_elf_section(&elf, i, &shdr, NULL);
 
-            if (shdr.sh_type == SHT_SYMTAB)
-            {
-                for (ofst = shdr.sh_offset;
-                     ofst < shdr.sh_offset + shdr.sh_size;
-                     ofst += shdr.sh_entsize)
-                {
-                    Elf64_Sym sym;
+      if (shdr.sh_type == SHT_SYMTAB) {
+        for (ofst = shdr.sh_offset;
+             ofst < shdr.sh_offset + shdr.sh_size;
+             ofst += shdr.sh_entsize) {
+          Elf32_Sym sym;
+
+          parse_elf_symbol(&elf, ofst, &sym, NULL);
 
-                    parse_elf_symbol(&elf, ofst, NULL, &sym);
+          /* For all OBJECTS (data objects), extract the value from the
+           * proper data segment.
+           */
+          /* if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
+              log_msg("found data object %s\n",
+                      parse_elf_string_table(&elf,
+                                             shdr.sh_link,
+                                             sym.st_name));
+           */
 
-                    /* For all OBJECTS (data objects), extract the value from the
-                     * proper data segment.
-                     */
-                    /* if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
-                        log_msg("found data object %s\n",
-                                parse_elf_string_table(&elf,
-                                                       shdr.sh_link,
-                                                       sym.st_name));
-                     */
+          if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
+              && sym.st_size == 4) {
+            Elf32_Shdr dhdr;
+            int val = 0;
+            char section_name[128];
+
+            parse_elf_section(&elf, sym.st_shndx, &dhdr, NULL);
+
+            /* For explanition - refer to _MSC_VER version of code */
+            strcpy(section_name, (char *)(elf.buf + strtab_off32 + dhdr.sh_name));
+            /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
 
-                    if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT
-                        && sym.st_size == 4)
-                    {
-                        Elf64_Shdr dhdr;
-                        int val = 0;
-                        char section_name[128];
+            if (strcmp(section_name, ".bss")) {
+              if (sizeof(val) != sym.st_size) {
+                /* The target value is declared as an int in
+                 * *_asm_*_offsets.c, which is 4 bytes on all
+                 * targets we currently use. Complain loudly if
+                 * this is not true.
+                 */
+                log_msg("Symbol size is wrong\n");
+                goto bail;
+              }
 
-                        parse_elf_section(&elf, sym.st_shndx, NULL, &dhdr);
+              memcpy(&val,
+                     elf.buf + dhdr.sh_offset + sym.st_value,
+                     sym.st_size);
+            }
 
-                        /* For explanition - refer to _MSC_VER version of code */
-                        strcpy(section_name, (char *)(elf.buf + strtab_off64 + dhdr.sh_name));
-                        /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
+            if (!elf.le_data) {
+              log_msg("Big Endian data not supported yet!\n");
+              goto bail;
+            }
 
-                        if ((strcmp(section_name, ".bss")))
-                        {
-                            if (sizeof(val) != sym.st_size)
-                            {
-                                /* The target value is declared as an int in
-                                 * asm_*_offsets.c, which is 4 bytes on all
-                                 * targets we currently use. Complain loudly if
-                                 * this is not true.
-                                 */
-                                log_msg("Symbol size is wrong\n");
-                                goto bail;
-                            }
+            switch (mode) {
+              case OUTPUT_FMT_RVDS:
+                printf("%-40s EQU %5d\n",
+                       parse_elf_string_table(&elf,
+                                              shdr.sh_link,
+                                              sym.st_name),
+                       val);
+                break;
+              case OUTPUT_FMT_GAS:
+                printf(".equ %-40s, %5d\n",
+                       parse_elf_string_table(&elf,
+                                              shdr.sh_link,
+                                              sym.st_name),
+                       val);
+                break;
+              default:
+                printf("%s = %d\n",
+                       parse_elf_string_table(&elf,
+                                              shdr.sh_link,
+                                              sym.st_name),
+                       val);
+            }
+          }
+        }
+      }
+    }
+  } else { /* if (elf.bits == 64) */
+    Elf64_Shdr shdr;
+    for (i = 0; i < elf.hdr64.e_shnum; i++) {
+      parse_elf_section(&elf, i, NULL, &shdr);
 
-                            memcpy(&val,
-                                   elf.buf + dhdr.sh_offset + sym.st_value,
-                                   sym.st_size);
-                        }
+      if (shdr.sh_type == SHT_SYMTAB) {
+        for (ofst = shdr.sh_offset;
+             ofst < shdr.sh_offset + shdr.sh_size;
+             ofst += shdr.sh_entsize) {
+          Elf64_Sym sym;
+
+          parse_elf_symbol(&elf, ofst, NULL, &sym);
 
-                        if (!elf.le_data)
-                        {
-                            log_msg("Big Endian data not supported yet!\n");
-                            goto bail;
-                        }
+          /* For all OBJECTS (data objects), extract the value from the
+           * proper data segment.
+           */
+          /* if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
+              log_msg("found data object %s\n",
+                      parse_elf_string_table(&elf,
+                                             shdr.sh_link,
+                                             sym.st_name));
+           */
+
+          if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT
+              && sym.st_size == 4) {
+            Elf64_Shdr dhdr;
+            int val = 0;
+            char section_name[128];
+
+            parse_elf_section(&elf, sym.st_shndx, NULL, &dhdr);
 
-                        switch (mode)
-                        {
-                            case OUTPUT_FMT_RVDS:
-                                printf("%-40s EQU %5d\n",
-                                       parse_elf_string_table(&elf,
-                                                              shdr.sh_link,
-                                                              sym.st_name),
-                                       val);
-                                break;
-                            case OUTPUT_FMT_GAS:
-                                printf(".equ %-40s, %5d\n",
-                                       parse_elf_string_table(&elf,
-                                                              shdr.sh_link,
-                                                              sym.st_name),
-                                       val);
-                                break;
-                            default:
-                                printf("%s = %d\n",
-                                       parse_elf_string_table(&elf,
-                                                              shdr.sh_link,
-                                                              sym.st_name),
-                                       val);
-                        }
-                    }
-                }
+            /* For explanition - refer to _MSC_VER version of code */
+            strcpy(section_name, (char *)(elf.buf + strtab_off64 + dhdr.sh_name));
+            /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
+
+            if ((strcmp(section_name, ".bss"))) {
+              if (sizeof(val) != sym.st_size) {
+                /* The target value is declared as an int in
+                 * *_asm_*_offsets.c, which is 4 bytes on all
+                 * targets we currently use. Complain loudly if
+                 * this is not true.
+                 */
+                log_msg("Symbol size is wrong\n");
+                goto bail;
+              }
+
+              memcpy(&val,
+                     elf.buf + dhdr.sh_offset + sym.st_value,
+                     sym.st_size);
+            }
+
+            if (!elf.le_data) {
+              log_msg("Big Endian data not supported yet!\n");
+              goto bail;
             }
-        }
-    }
 
-    if (mode == OUTPUT_FMT_RVDS)
-        printf("    END\n");
+            switch (mode) {
+              case OUTPUT_FMT_RVDS:
+                printf("%-40s EQU %5d\n",
+                       parse_elf_string_table(&elf,
+                                              shdr.sh_link,
+                                              sym.st_name),
+                       val);
+                break;
+              case OUTPUT_FMT_GAS:
+                printf(".equ %-40s, %5d\n",
+                       parse_elf_string_table(&elf,
+                                              shdr.sh_link,
+                                              sym.st_name),
+                       val);
+                break;
+              default:
+                printf("%s = %d\n",
+                       parse_elf_string_table(&elf,
+                                              shdr.sh_link,
+                                              sym.st_name),
+                       val);
+            }
+          }
+        }
+      }
+    }
+  }
 
-    return 0;
+  if (mode == OUTPUT_FMT_RVDS)
+    printf("    END\n");
+
+  return 0;
 bail:
-    log_msg("Parse error: File does not appear to be valid ELF32 or ELF64\n");
-    return 1;
+  log_msg("Parse error: File does not appear to be valid ELF32 or ELF64\n");
+  return 1;
 }
 
 #endif
 #endif /* defined(__GNUC__) && __GNUC__ */
 
 
 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
 /*  See "Microsoft Portable Executable and Common Object File Format Specification"
     for reference.
 */
 #define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 )
 #define get_le16(x) ((*(x)) | (*(x+1)) << 8)
 
-int parse_coff(uint8_t *buf, size_t sz)
-{
-    unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
-    unsigned int sectionrawdata_ptr;
-    unsigned int i;
-    uint8_t *ptr;
-    uint32_t symoffset;
+int parse_coff(uint8_t *buf, size_t sz) {
+  unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
+  unsigned int sectionrawdata_ptr;
+  unsigned int i;
+  uint8_t *ptr;
+  uint32_t symoffset;
+
+  char **sectionlist;  // this array holds all section names in their correct order.
+  // it is used to check if the symbol is in .bss or .rdata section.
 
-    char **sectionlist;  //this array holds all section names in their correct order.
-    //it is used to check if the symbol is in .bss or .rdata section.
+  nsections = get_le16(buf + 2);
+  symtab_ptr = get_le32(buf + 8);
+  symtab_sz = get_le32(buf + 12);
+  strtab_ptr = symtab_ptr + symtab_sz * 18;
+
+  if (nsections > 96) {
+    log_msg("Too many sections\n");
+    return 1;
+  }
+
+  sectionlist = malloc(nsections * sizeof(sectionlist));
 
-    nsections = get_le16(buf + 2);
-    symtab_ptr = get_le32(buf + 8);
-    symtab_sz = get_le32(buf + 12);
-    strtab_ptr = symtab_ptr + symtab_sz * 18;
+  if (sectionlist == NULL) {
+    log_msg("Allocating first level of section list failed\n");
+    return 1;
+  }
+
+  // log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
+
+  /*
+  The size of optional header is always zero for an obj file. So, the section header
+  follows the file header immediately.
+  */
 
-    if (nsections > 96)
-    {
-        log_msg("Too many sections\n");
-        return 1;
-    }
+  ptr = buf + 20;     // section header
 
-    sectionlist = malloc(nsections * sizeof(sectionlist));
+  for (i = 0; i < nsections; i++) {
+    char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    strncpy(sectionname, ptr, 8);
+    // log_msg("COFF: Parsing section %s\n",sectionname);
 
-    if (sectionlist == NULL)
-    {
-        log_msg("Allocating first level of section list failed\n");
-        return 1;
+    sectionlist[i] = malloc(strlen(sectionname) + 1);
+
+    if (sectionlist[i] == NULL) {
+      log_msg("Allocating storage for %s failed\n", sectionname);
+      goto bail;
     }
+    strcpy(sectionlist[i], sectionname);
 
-    //log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
+    if (!strcmp(sectionname, ".rdata")) sectionrawdata_ptr = get_le32(ptr + 20);
+
+    ptr += 40;
+  }
+
+  // log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
+  // log_msg("COFF: raw data pointer ofset for section .rdata is %u\n", sectionrawdata_ptr);
 
-    /*
-    The size of optional header is always zero for an obj file. So, the section header
-    follows the file header immediately.
-    */
+  /*  The compiler puts the data with non-zero offset in .rdata section, but puts the data with
+      zero offset in .bss section. So, if the data in in .bss section, set offset=0.
+      Note from Wiki: In an object module compiled from C, the bss section contains
+      the local variables (but not functions) that were declared with the static keyword,
+      except for those with non-zero initial values. (In C, static variables are initialized
+      to zero by default.) It also contains the non-local (both extern and static) variables
+      that are also initialized to zero (either explicitly or by default).
+      */
+  // move to symbol table
+  /* COFF symbol table:
+      offset      field
+      0           Name(*)
+      8           Value
+      12          SectionNumber
+      14          Type
+      16          StorageClass
+      17          NumberOfAuxSymbols
+      */
+  ptr = buf + symtab_ptr;
 
-    ptr = buf + 20;     //section header
+  for (i = 0; i < symtab_sz; i++) {
+    int16_t section = get_le16(ptr + 12); // section number
 
-    for (i = 0; i < nsections; i++)
-    {
-        char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-        strncpy(sectionname, ptr, 8);
-        //log_msg("COFF: Parsing section %s\n",sectionname);
-
-        sectionlist[i] = malloc(strlen(sectionname) + 1);
+    if (section > 0 && ptr[16] == 2) {
+      // if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
 
-        if (sectionlist[i] == NULL)
-        {
-            log_msg("Allocating storage for %s failed\n", sectionname);
-            goto bail;
-        }
-        strcpy(sectionlist[i], sectionname);
+      if (get_le32(ptr)) {
+        char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+        strncpy(name, ptr, 8);
+        // log_msg("COFF: Parsing symbol %s\n",name);
+        /* The 64bit Windows compiler doesn't prefix with an _.
+         * Check what's there, and bump if necessary
+         */
+        if (name[0] == '_')
+          printf("%-40s EQU ", name + 1);
+        else
+          printf("%-40s EQU ", name);
+      } else {
+        // log_msg("COFF: Parsing symbol %s\n",
+        //        buf + strtab_ptr + get_le32(ptr+4));
+        if ((buf + strtab_ptr + get_le32(ptr + 4))[0] == '_')
+          printf("%-40s EQU ",
+                 buf + strtab_ptr + get_le32(ptr + 4) + 1);
+        else
+          printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
+      }
 
-        if (!strcmp(sectionname, ".rdata")) sectionrawdata_ptr = get_le32(ptr + 20);
+      if (!(strcmp(sectionlist[section - 1], ".bss"))) {
+        symoffset = 0;
+      } else {
+        symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
+      }
 
-        ptr += 40;
+      // log_msg("      Section: %d\n",section);
+      // log_msg("      Class:   %d\n",ptr[16]);
+      // log_msg("      Address: %u\n",get_le32(ptr+8));
+      // log_msg("      Offset: %u\n", symoffset);
+
+      printf("%5d\n", symoffset);
     }
 
-    //log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
-    //log_msg("COFF: raw data pointer ofset for section .rdata is %u\n", sectionrawdata_ptr);
+    ptr += 18;
+  }
 
-    /*  The compiler puts the data with non-zero offset in .rdata section, but puts the data with
-        zero offset in .bss section. So, if the data in in .bss section, set offset=0.
-        Note from Wiki: In an object module compiled from C, the bss section contains
-        the local variables (but not functions) that were declared with the static keyword,
-        except for those with non-zero initial values. (In C, static variables are initialized
-        to zero by default.) It also contains the non-local (both extern and static) variables
-        that are also initialized to zero (either explicitly or by default).
-        */
-    //move to symbol table
-    /* COFF symbol table:
-        offset      field
-        0           Name(*)
-        8           Value
-        12          SectionNumber
-        14          Type
-        16          StorageClass
-        17          NumberOfAuxSymbols
-        */
-    ptr = buf + symtab_ptr;
-
-    for (i = 0; i < symtab_sz; i++)
-    {
-        int16_t section = get_le16(ptr + 12); //section number
-
-        if (section > 0 && ptr[16] == 2)
-        {
-            //if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
+  printf("    END\n");
 
-            if (get_le32(ptr))
-            {
-                char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-                strncpy(name, ptr, 8);
-                //log_msg("COFF: Parsing symbol %s\n",name);
-                /* The 64bit Windows compiler doesn't prefix with an _.
-                 * Check what's there, and bump if necessary
-                 */
-                if (name[0] == '_')
-                    printf("%-40s EQU ", name + 1);
-                else
-                    printf("%-40s EQU ", name);
-            }
-            else
-            {
-                //log_msg("COFF: Parsing symbol %s\n",
-                //        buf + strtab_ptr + get_le32(ptr+4));
-                if ((buf + strtab_ptr + get_le32(ptr + 4))[0] == '_')
-                    printf("%-40s EQU ",
-                           buf + strtab_ptr + get_le32(ptr + 4) + 1);
-                else
-                    printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
-            }
+  for (i = 0; i < nsections; i++) {
+    free(sectionlist[i]);
+  }
 
-            if (!(strcmp(sectionlist[section-1], ".bss")))
-            {
-                symoffset = 0;
-            }
-            else
-            {
-                symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
-            }
-
-            //log_msg("      Section: %d\n",section);
-            //log_msg("      Class:   %d\n",ptr[16]);
-            //log_msg("      Address: %u\n",get_le32(ptr+8));
-            //log_msg("      Offset: %u\n", symoffset);
+  free(sectionlist);
 
-            printf("%5d\n", symoffset);
-        }
-
-        ptr += 18;
-    }
-
-    printf("    END\n");
-
-    for (i = 0; i < nsections; i++)
-    {
-        free(sectionlist[i]);
-    }
-
-    free(sectionlist);
-
-    return 0;
+  return 0;
 bail:
 
-    for (i = 0; i < nsections; i++)
-    {
-        free(sectionlist[i]);
-    }
+  for (i = 0; i < nsections; i++) {
+    free(sectionlist[i]);
+  }
 
-    free(sectionlist);
+  free(sectionlist);
 
-    return 1;
+  return 1;
 }
 #endif /* defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) */
 
-int main(int argc, char **argv)
-{
-    output_fmt_t mode = OUTPUT_FMT_PLAIN;
-    const char *f;
-    uint8_t *file_buf;
-    int res;
-    FILE *fp;
-    long int file_size;
+int main(int argc, char **argv) {
+  output_fmt_t mode = OUTPUT_FMT_PLAIN;
+  const char *f;
+  uint8_t *file_buf;
+  int res;
+  FILE *fp;
+  long int file_size;
 
-    if (argc < 2 || argc > 3)
-    {
-        fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
-        fprintf(stderr, "  <obj file>\tobject file to parse\n");
-        fprintf(stderr, "Output Formats:\n");
-        fprintf(stderr, "  gas  - compatible with GNU assembler\n");
-        fprintf(stderr, "  rvds - compatible with armasm\n");
-        goto bail;
-    }
+  if (argc < 2 || argc > 3) {
+    fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
+    fprintf(stderr, "  <obj file>\tobject file to parse\n");
+    fprintf(stderr, "Output Formats:\n");
+    fprintf(stderr, "  gas  - compatible with GNU assembler\n");
+    fprintf(stderr, "  rvds - compatible with armasm\n");
+    goto bail;
+  }
 
-    f = argv[2];
+  f = argv[2];
 
-    if (!strcmp(argv[1], "rvds"))
-        mode = OUTPUT_FMT_RVDS;
-    else if (!strcmp(argv[1], "gas"))
-        mode = OUTPUT_FMT_GAS;
-    else
-        f = argv[1];
+  if (!strcmp(argv[1], "rvds"))
+    mode = OUTPUT_FMT_RVDS;
+  else if (!strcmp(argv[1], "gas"))
+    mode = OUTPUT_FMT_GAS;
+  else
+    f = argv[1];
 
-    fp = fopen(f, "rb");
+  fp = fopen(f, "rb");
 
-    if (!fp)
-    {
-        perror("Unable to open file");
-        goto bail;
-    }
+  if (!fp) {
+    perror("Unable to open file");
+    goto bail;
+  }
 
-    if (fseek(fp, 0, SEEK_END))
-    {
-        perror("stat");
-        goto bail;
-    }
+  if (fseek(fp, 0, SEEK_END)) {
+    perror("stat");
+    goto bail;
+  }
 
-    file_size = ftell(fp);
-    file_buf = malloc(file_size);
+  file_size = ftell(fp);
+  file_buf = malloc(file_size);
 
-    if (!file_buf)
-    {
-        perror("malloc");
-        goto bail;
-    }
+  if (!file_buf) {
+    perror("malloc");
+    goto bail;
+  }
 
-    rewind(fp);
+  rewind(fp);
 
-    if (fread(file_buf, sizeof(char), file_size, fp) != file_size)
-    {
-        perror("read");
-        goto bail;
-    }
+  if (fread(file_buf, sizeof(char), file_size, fp) != file_size) {
+    perror("read");
+    goto bail;
+  }
 
-    if (fclose(fp))
-    {
-        perror("close");
-        goto bail;
-    }
+  if (fclose(fp)) {
+    perror("close");
+    goto bail;
+  }
 
 #if defined(__GNUC__) && __GNUC__
 #if defined(__MACH__)
-    res = parse_macho(file_buf, file_size);
+  res = parse_macho(file_buf, file_size, mode);
 #elif defined(__ELF__)
-    res = parse_elf(file_buf, file_size, mode);
+  res = parse_elf(file_buf, file_size, mode);
 #endif
 #endif
 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
-    res = parse_coff(file_buf, file_size);
+  res = parse_coff(file_buf, file_size);
 #endif
 
-    free(file_buf);
+  free(file_buf);
 
-    if (!res)
-        return EXIT_SUCCESS;
+  if (!res)
+    return EXIT_SUCCESS;
 
 bail:
-    return EXIT_FAILURE;
+  return EXIT_FAILURE;
 }
new file mode 100644
--- /dev/null
+++ b/media/libvpx/build/make/thumb.pm
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+##
+##  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+package thumb;
+
+sub FixThumbInstructions($$)
+{
+    my $short_branches = $_[1];
+    my $branch_shift_offset = $short_branches ? 1 : 0;
+
+    # Write additions with shifts, such as "add r10, r11, lsl #8",
+    # in three operand form, "add r10, r10, r11, lsl #8".
+    s/(add\s+)(r\d+),\s*(r\d+),\s*(lsl #\d+)/$1$2, $2, $3, $4/g;
+
+    # Convert additions with a non-constant shift into a sequence
+    # with left shift, addition and a right shift (to restore the
+    # register to the original value). Currently the right shift
+    # isn't necessary in the code base since the values in these
+    # registers aren't used, but doing the shift for consitency.
+    # This converts instructions such as "add r12, r12, r5, lsl r4"
+    # into the sequence "lsl r5, r4", "add r12, r12, r5", "lsr r5, r4".
+    s/^(\s*)(add)(\s+)(r\d+),\s*(r\d+),\s*(r\d+),\s*lsl (r\d+)/$1lsl$3$6, $7\n$1$2$3$4, $5, $6\n$1lsr$3$6, $7/g;
+
+    # Convert loads with right shifts in the indexing into a
+    # sequence of an add, load and sub. This converts
+    # "ldrb r4, [r9, lr, asr #1]" into "add r9, r9, lr, asr #1",
+    # "ldrb r9, [r9]", "sub r9, r9, lr, asr #1".
+    s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+),\s*(asr #\d+)\]/$1add $3$5, $5, $6, $7\n$1$2$3$4, [$5]\n$1sub $3$5, $5, $6, $7/g;
+
+    # Convert register indexing with writeback into a separate add
+    # instruction. This converts "ldrb r12, [r1, r2]!" into
+    # "ldrb r12, [r1, r2]", "add r1, r1, r2".
+    s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+)\]!/$1$2$3$4, [$5, $6]\n$1add $3$5, $6/g;
+
+    # Convert negative register indexing into separate sub/add instructions.
+    # This converts "ldrne r4, [src, -pstep, lsl #1]" into
+    # "subne src, src, pstep, lsl #1", "ldrne r4, [src]",
+    # "addne src, src, pstep, lsl #1". In a couple of cases where
+    # this is used, it's used for two subsequent load instructions,
+    # where a hand-written version of it could merge two subsequent
+    # add and sub instructions.
+    s/^(\s*)((ldr|str|pld)(ne)?)(\s+)(r\d+,\s*)?\[(\w+), -([^\]]+)\]/$1sub$4$5$7, $7, $8\n$1$2$5$6\[$7\]\n$1add$4$5$7, $7, $8/g;
+
+    # Convert register post indexing to a separate add instruction.
+    # This converts "ldrneb r9, [r0], r2" into "ldrneb r9, [r0]",
+    # "add r0, r2".
+    s/^(\s*)((ldr|str)(ne)?[bhd]?)(\s+)(\w+),(\s*\w+,)?\s*\[(\w+)\],\s*(\w+)/$1$2$5$6,$7 [$8]\n$1add$4$5$8, $8, $9/g;
+
+    # Convert a conditional addition to the pc register into a series of
+    # instructions. This converts "addlt pc, pc, r3, lsl #2" into
+    # "itttt lt", "movlt.n r12, pc", "addlt.w r12, #12",
+    # "addlt.w r12, r12, r3, lsl #2", "movlt.n pc, r12".
+    # This assumes that r12 is free at this point.
+    s/^(\s*)addlt(\s+)pc,\s*pc,\s*(\w+),\s*lsl\s*#(\d+)/$1itttt$2lt\n$1movlt.n$2r12, pc\n$1addlt.w$2r12, #12\n$1addlt.w$2r12, r12, $3, lsl #($4-$branch_shift_offset)\n$1movlt.n$2pc, r12/g;
+
+    # Convert "mov pc, lr" into "bx lr", since the former only works
+    # for switching from arm to thumb (and only in armv7), but not
+    # from thumb to arm.
+    s/mov(\s*)pc\s*,\s*lr/bx$1lr/g;
+}
+
+1;
--- a/media/libvpx/moz.build
+++ b/media/libvpx/moz.build
@@ -1,315 +1,75 @@
 # -*- 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.vpx += [
-    'vpx/vp8.h',
-    'vpx/vp8cx.h',
-    'vpx/vp8dx.h',
-    'vpx/vpx_codec.h',
-    'vpx/vpx_codec_impl_bottom.h',
-    'vpx/vpx_codec_impl_top.h',
-    'vpx/vpx_decoder.h',
-    'vpx/vpx_encoder.h',
-    'vpx/vpx_image.h',
-    'vpx/vpx_integer.h',
-    'vpx_mem/include/vpx_mem_intrnl.h',
-    'vpx_mem/vpx_mem.h',
-    'vpx_ports/arm.h',
-    'vpx_ports/mem.h',
-    'vpx_ports/vpx_timer.h',
-    'vpx_ports/x86.h',
-    'vpx_scale/scale_mode.h',
-    'vpx_scale/vpxscale.h',
-    'vpx_scale/yv12config.h',
-]
+include('sources.mozbuild')
+
+EXPORTS.vpx += files['EXPORTS']
 
 if CONFIG['VPX_NEED_OBJ_INT_EXTRACT']:
     HOST_SOURCES += [
         'build/make/obj_int_extract.c',
     ]
 
     HOST_PROGRAM = 'host_obj_int_extract'
 
-SOURCES += [
-    'vp8/common/alloccommon.c',
-    'vp8/common/blockd.c',
-    'vp8/common/debugmodes.c',
-    'vp8/common/dequantize.c',
-    'vp8/common/entropy.c',
-    'vp8/common/entropymode.c',
-    'vp8/common/entropymv.c',
-    'vp8/common/extend.c',
-    'vp8/common/filter.c',
-    'vp8/common/findnearmv.c',
-    'vp8/common/generic/systemdependent.c',
-    'vp8/common/idct_blk.c',
-    'vp8/common/idctllm.c',
-    'vp8/common/loopfilter.c',
-    'vp8/common/loopfilter_filters.c',
-    'vp8/common/mbpitch.c',
-    'vp8/common/modecont.c',
-    'vp8/common/quant_common.c',
-    'vp8/common/reconinter.c',
-    'vp8/common/reconintra.c',
-    'vp8/common/reconintra4x4.c',
-    'vp8/common/rtcd.c',
-    'vp8/common/sad_c.c',
-    'vp8/common/setupintrarecon.c',
-    'vp8/common/swapyv12buffer.c',
-    'vp8/common/treecoder.c',
-    'vp8/common/variance_c.c',
-    'vp8/decoder/asm_dec_offsets.c',
-    'vp8/decoder/dboolhuff.c',
-    'vp8/decoder/decodemv.c',
-    'vp8/decoder/decodframe.c',
-    'vp8/decoder/detokenize.c',
-    'vp8/decoder/onyxd_if.c',
-    'vp8/decoder/threading.c',
-    'vp8/vp8_dx_iface.c',
-    'vpx/src/vpx_codec.c',
-    'vpx/src/vpx_decoder.c',
-    'vpx/src/vpx_encoder.c',
-    'vpx/src/vpx_image.c',
-    'vpx_mem/vpx_mem.c',
-    'vpx_scale/generic/gen_scalers.c',
-    'vpx_scale/generic/vpxscale.c',
-    'vpx_scale/generic/yv12config.c',
-    'vpx_scale/generic/yv12extend.c',
-]
+SOURCES += files['COMMON']
 
 if CONFIG['MOZ_VP8_ERROR_CONCEALMENT']:
-    SOURCES += [
-        'vp8/decoder/error_concealment.c'
-    ]
+    SOURCES += files['ERROR_CONCEALMENT']
 
 if CONFIG['MOZ_VP8_ENCODER']:
-    SOURCES += [
-        'vp8/encoder/bitstream.c',
-        'vp8/encoder/dct.c',
-        'vp8/encoder/encodeframe.c',
-        'vp8/encoder/encodeintra.c',
-        'vp8/encoder/encodemb.c',
-        'vp8/encoder/encodemv.c',
-        'vp8/encoder/ethreading.c',
-        'vp8/encoder/firstpass.c',
-        'vp8/encoder/lookahead.c',
-        'vp8/encoder/mcomp.c',
-        'vp8/encoder/modecosts.c',
-        'vp8/encoder/mr_dissim.c',
-        'vp8/encoder/onyx_if.c',
-        'vp8/encoder/pickinter.c',
-        'vp8/encoder/picklpf.c',
-        'vp8/encoder/psnr.c',
-        'vp8/encoder/quantize.c',
-        'vp8/encoder/ratectrl.c',
-        'vp8/encoder/rdopt.c',
-        'vp8/encoder/segmentation.c',
-        'vp8/encoder/tokenize.c',
-        'vp8/encoder/treewriter.c',
-        'vp8/vp8_cx_iface.c',
-    ]
+    SOURCES += files['ENCODER']
 
 #postproc is only enabled on x86 with asm
 if CONFIG['VPX_X86_ASM']:
-    SOURCES += [
-        'vp8/common/mfqe.c',
-        'vp8/common/postproc.c',
-        'vp8/encoder/temporal_filter.c',
-    ]
+    SOURCES += files['VP8_POSTPROC']
 
 if CONFIG['VPX_X86_ASM'] and CONFIG['OS_TARGET'] == 'WINNT':
     SOURCES += [
-        'vp8/common/asm_com_offsets.c',
+        'vpx_scale/vpx_scale_asm_offsets.c',
     ]
     if CONFIG['MOZ_VP8_ENCODER']:
         SOURCES += [
-            'vp8/encoder/asm_enc_offsets.c',
+            'vp8/encoder/vp8_asm_enc_offsets.c',
         ]
 
 if CONFIG['VPX_X86_ASM']:
-    SOURCES += [
-        'vp8/common/x86/filter_x86.c',
-        'vp8/common/x86/idct_blk_mmx.c',
-        'vp8/common/x86/idct_blk_sse2.c',
-        'vp8/common/x86/loopfilter_x86.c',
-        'vp8/common/x86/postproc_x86.c',
-        'vp8/common/x86/recon_wrapper_sse2.c',
-        'vp8/common/x86/variance_mmx.c',
-        'vp8/common/x86/variance_sse2.c',
-        'vp8/common/x86/variance_ssse3.c',
-        'vp8/common/x86/vp8_asm_stubs.c',
-        'vpx_ports/x86_cpuid.c',
-    ]
-    SOURCES += [
-        'vp8/common/x86/dequantize_mmx.asm',
-        'vp8/common/x86/idctllm_mmx.asm',
-        'vp8/common/x86/idctllm_sse2.asm',
-        'vp8/common/x86/iwalsh_mmx.asm',
-        'vp8/common/x86/iwalsh_sse2.asm',
-        'vp8/common/x86/loopfilter_mmx.asm',
-        'vp8/common/x86/loopfilter_sse2.asm',
-        'vp8/common/x86/mfqe_sse2.asm',
-        'vp8/common/x86/postproc_mmx.asm',
-        'vp8/common/x86/postproc_sse2.asm',
-        'vp8/common/x86/recon_mmx.asm',
-        'vp8/common/x86/recon_sse2.asm',
-        'vp8/common/x86/sad_mmx.asm',
-        'vp8/common/x86/sad_sse2.asm',
-        'vp8/common/x86/sad_sse3.asm',
-        'vp8/common/x86/sad_sse4.asm',
-        'vp8/common/x86/sad_ssse3.asm',
-        'vp8/common/x86/subpixel_mmx.asm',
-        'vp8/common/x86/subpixel_sse2.asm',
-        'vp8/common/x86/subpixel_ssse3.asm',
-        'vp8/common/x86/variance_impl_mmx.asm',
-        'vp8/common/x86/variance_impl_sse2.asm',
-        'vp8/common/x86/variance_impl_ssse3.asm',
-        'vpx_ports/emms.asm',
-    ]
+    SOURCES += files['X86_ASM']
 
     if '64' in CONFIG['OS_TEST']:
-        SOURCES += [
-            'vp8/common/x86/loopfilter_block_sse2.asm',
-        ]
+        SOURCES += files['X86-64_ASM']
+
+    # AVX2 only supported on
+    # Darwin toolchain right now
+    if CONFIG['OS_TARGET'] == 'Darwin':
+        SOURCES += files['AVX2']
 
 if CONFIG['VPX_X86_ASM'] and CONFIG['MOZ_VP8_ENCODER']:
-    SOURCES += [
-        'vp8/encoder/x86/vp8_enc_stubs_mmx.c',
-        'vp8/encoder/x86/vp8_enc_stubs_sse2.c',
-    ]
-    SOURCES += [
-        'vp8/encoder/x86/dct_mmx.asm',
-        'vp8/encoder/x86/dct_sse2.asm',
-        'vp8/encoder/x86/encodeopt.asm',
-        'vp8/encoder/x86/fwalsh_sse2.asm',
-        'vp8/encoder/x86/quantize_mmx.asm',
-        'vp8/encoder/x86/quantize_sse2.asm',
-        'vp8/encoder/x86/quantize_sse4.asm',
-        'vp8/encoder/x86/quantize_ssse3.asm',
-        'vp8/encoder/x86/subtract_mmx.asm',
-        'vp8/encoder/x86/subtract_sse2.asm',
-        'vp8/encoder/x86/temporal_filter_apply_sse2.asm',
-
-    ]
-
-if CONFIG['MOZ_VP8_ENCODER']:
-    SOURCES += [
-        'vp8/encoder/denoising.c',
-    ]
-    if CONFIG['VPX_X86_ASM']:
-        SOURCES += [
-            'vp8/encoder/x86/denoising_sse2.c',
-        ]
+    SOURCES += files['X86_ASM_ENCODER']
+    if '64' in CONFIG['OS_TEST']:
+        SOURCES += files['X86-64_ASM_ENCODER']
 
 arm_asm_files = []
+if CONFIG['VPX_ARM_ASM']:
+    arm_asm_files += files['ARM_ASM']
+    if CONFIG['MOZ_VP8_ENCODER']:
+        arm_asm_files += files['ARM_ASM_ENCODER']
 
-if CONFIG['VPX_ARM_ASM']:
-    SOURCES += [
-        'vp8/common/arm/armv6/idct_blk_v6.c',
-        'vp8/common/arm/bilinearfilter_arm.c',
-        'vp8/common/arm/dequantize_arm.c',
-        'vp8/common/arm/filter_arm.c',
-        'vp8/common/arm/loopfilter_arm.c',
-        'vp8/common/arm/neon/idct_blk_neon.c',
-        'vp8/common/arm/reconintra_arm.c',
-        'vp8/common/arm/variance_arm.c',
-        'vpx_ports/arm_cpudetect.c',
-        'vpx_scale/arm/neon/yv12extend_arm.c',
-    ]
-    arm_asm_files += [
-        'vp8/common/arm/armv6/bilinearfilter_v6.asm',
-        'vp8/common/arm/armv6/copymem16x16_v6.asm',
-        'vp8/common/arm/armv6/copymem8x4_v6.asm',
-        'vp8/common/arm/armv6/copymem8x8_v6.asm',
-        'vp8/common/arm/armv6/dc_only_idct_add_v6.asm',
-        'vp8/common/arm/armv6/dequant_idct_v6.asm',
-        'vp8/common/arm/armv6/dequantize_v6.asm',
-        'vp8/common/arm/armv6/filter_v6.asm',
-        'vp8/common/arm/armv6/idct_v6.asm',
-        'vp8/common/arm/armv6/intra4x4_predict_v6.asm',
-        'vp8/common/arm/armv6/iwalsh_v6.asm',
-        'vp8/common/arm/armv6/loopfilter_v6.asm',
-        'vp8/common/arm/armv6/simpleloopfilter_v6.asm',
-        'vp8/common/arm/armv6/sixtappredict8x4_v6.asm',
-        'vp8/common/arm/armv6/vp8_sad16x16_armv6.asm',
-        'vp8/common/arm/armv6/vp8_variance16x16_armv6.asm',
-        'vp8/common/arm/armv6/vp8_variance8x8_armv6.asm',
-        'vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_h_armv6.asm',
-        'vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_hv_armv6.asm',
-        'vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_v_armv6.asm',
-        'vp8/common/arm/neon/bilinearpredict16x16_neon.asm',
-        'vp8/common/arm/neon/bilinearpredict4x4_neon.asm',
-        'vp8/common/arm/neon/bilinearpredict8x4_neon.asm',
-        'vp8/common/arm/neon/bilinearpredict8x8_neon.asm',
-        'vp8/common/arm/neon/buildintrapredictorsmby_neon.asm',
-        'vp8/common/arm/neon/copymem16x16_neon.asm',
-        'vp8/common/arm/neon/copymem8x4_neon.asm',
-        'vp8/common/arm/neon/copymem8x8_neon.asm',
-        'vp8/common/arm/neon/dc_only_idct_add_neon.asm',
-        'vp8/common/arm/neon/dequant_idct_neon.asm',
-        'vp8/common/arm/neon/dequantizeb_neon.asm',
-        'vp8/common/arm/neon/idct_dequant_0_2x_neon.asm',
-        'vp8/common/arm/neon/idct_dequant_full_2x_neon.asm',
-        'vp8/common/arm/neon/iwalsh_neon.asm',
-        'vp8/common/arm/neon/loopfilter_neon.asm',
-        'vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm',
-        'vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm',
-        'vp8/common/arm/neon/mbloopfilter_neon.asm',
-        'vp8/common/arm/neon/sad16_neon.asm',
-        'vp8/common/arm/neon/sad8_neon.asm',
-        'vp8/common/arm/neon/save_reg_neon.asm',
-        'vp8/common/arm/neon/shortidct4x4llm_neon.asm',
-        'vp8/common/arm/neon/sixtappredict16x16_neon.asm',
-        'vp8/common/arm/neon/sixtappredict4x4_neon.asm',
-        'vp8/common/arm/neon/sixtappredict8x4_neon.asm',
-        'vp8/common/arm/neon/sixtappredict8x8_neon.asm',
-        'vp8/common/arm/neon/variance_neon.asm',
-        'vp8/common/arm/neon/vp8_subpixelvariance16x16_neon.asm',
-        'vp8/common/arm/neon/vp8_subpixelvariance16x16s_neon.asm',
-        'vp8/common/arm/neon/vp8_subpixelvariance8x8_neon.asm',
-        'vp8/encoder/arm/armv6/vp8_mse16x16_armv6.asm',
-        'vp8/encoder/arm/neon/vp8_mse16x16_neon.asm',
-        'vpx_scale/arm/neon/vp8_vpxyv12_copy_y_neon.asm',
-        'vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm',
-        'vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm',
-        'vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm',
-    ]
-
-if CONFIG['VPX_ARM_ASM'] and CONFIG['MOZ_VP8_ENCODER']:
-    SOURCES += [
-        'vp8/encoder/arm/boolhuff_arm.c',
-        'vp8/encoder/arm/dct_arm.c',
-        'vp8/encoder/arm/neon/picklpf_arm.c',
-        'vp8/encoder/arm/quantize_arm.c',
-    ]
-    arm_asm_files += [
-        'vp8/encoder/arm/armv5te/boolhuff_armv5te.asm',
-        'vp8/encoder/arm/armv5te/vp8_packtokens_armv5.asm',
-        'vp8/encoder/arm/armv5te/vp8_packtokens_mbrow_armv5.asm',
-        'vp8/encoder/arm/armv5te/vp8_packtokens_partitions_armv5.asm',
-        'vp8/encoder/arm/armv6/vp8_fast_quantize_b_armv6.asm',
-        'vp8/encoder/arm/armv6/vp8_short_fdct4x4_armv6.asm',
-        'vp8/encoder/arm/armv6/vp8_subtract_armv6.asm',
-        'vp8/encoder/arm/armv6/walsh_v6.asm',
-        'vp8/encoder/arm/neon/fastquantizeb_neon.asm',
-        'vp8/encoder/arm/neon/shortfdct_neon.asm',
-        'vp8/encoder/arm/neon/subtract_neon.asm',
-        'vp8/encoder/arm/neon/vp8_memcpy_neon.asm',
-        'vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm',
-    ]
-
-if arm_asm_files:
     if CONFIG['VPX_AS_CONVERSION']:
         GENERATED_SOURCES += [ "%s.%s" % (f, CONFIG['VPX_ASM_SUFFIX'])
-            for f in sorted(arm_asm_files)]
+            for f in sorted(arm_asm_files) if f.endswith('.asm')
+        ]
+        SOURCES += [
+            f for f in sorted(arm_asm_files) if not f.endswith('.asm')
+        ]
     else:
         SOURCES += sorted(arm_asm_files)
 
 # boolhuff_armv5te.asm defines the same functions as boolhuff.c instead of
 # using RTCD, so we have to make sure we only add one of the two.
 if CONFIG['MOZ_VP8_ENCODER'] \
     and 'vp8/encoder/arm/armv5te/boolhuff_armv5te.asm' not in arm_asm_files:
     SOURCES += [
new file mode 100644
--- /dev/null
+++ b/media/libvpx/sources.mozbuild
@@ -0,0 +1,333 @@
+files = {
+ 'ARM_ASM': ['vp8/common/arm/armv6/bilinearfilter_v6.asm',
+             'vp8/common/arm/armv6/copymem16x16_v6.asm',
+             'vp8/common/arm/armv6/copymem8x4_v6.asm',
+             'vp8/common/arm/armv6/copymem8x8_v6.asm',
+             'vp8/common/arm/armv6/dc_only_idct_add_v6.asm',
+             'vp8/common/arm/armv6/dequant_idct_v6.asm',
+             'vp8/common/arm/armv6/dequantize_v6.asm',
+             'vp8/common/arm/armv6/filter_v6.asm',
+             'vp8/common/arm/armv6/idct_blk_v6.c',
+             'vp8/common/arm/armv6/idct_v6.asm',
+             'vp8/common/arm/armv6/intra4x4_predict_v6.asm',
+             'vp8/common/arm/armv6/iwalsh_v6.asm',
+             'vp8/common/arm/armv6/loopfilter_v6.asm',
+             'vp8/common/arm/armv6/simpleloopfilter_v6.asm',
+             'vp8/common/arm/armv6/sixtappredict8x4_v6.asm',
+             'vp8/common/arm/armv6/vp8_sad16x16_armv6.asm',
+             'vp8/common/arm/armv6/vp8_variance16x16_armv6.asm',
+             'vp8/common/arm/armv6/vp8_variance8x8_armv6.asm',
+             'vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_h_armv6.asm',
+             'vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_hv_armv6.asm',
+             'vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_v_armv6.asm',
+             'vp8/common/arm/bilinearfilter_arm.c',
+             'vp8/common/arm/dequantize_arm.c',
+             'vp8/common/arm/filter_arm.c',
+             'vp8/common/arm/loopfilter_arm.c',
+             'vp8/common/arm/neon/bilinearpredict16x16_neon.asm',
+             'vp8/common/arm/neon/bilinearpredict4x4_neon.asm',
+             'vp8/common/arm/neon/bilinearpredict8x4_neon.asm',
+             'vp8/common/arm/neon/bilinearpredict8x8_neon.asm',
+             'vp8/common/arm/neon/buildintrapredictorsmby_neon.asm',
+             'vp8/common/arm/neon/copymem16x16_neon.asm',
+             'vp8/common/arm/neon/copymem8x4_neon.asm',
+             'vp8/common/arm/neon/copymem8x8_neon.asm',
+             'vp8/common/arm/neon/dc_only_idct_add_neon.asm',
+             'vp8/common/arm/neon/dequant_idct_neon.asm',
+             'vp8/common/arm/neon/dequantizeb_neon.asm',
+             'vp8/common/arm/neon/idct_blk_neon.c',
+             'vp8/common/arm/neon/idct_dequant_0_2x_neon.asm',
+             'vp8/common/arm/neon/idct_dequant_full_2x_neon.asm',
+             'vp8/common/arm/neon/iwalsh_neon.asm',
+             'vp8/common/arm/neon/loopfilter_neon.asm',
+             'vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm',
+             'vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm',
+             'vp8/common/arm/neon/mbloopfilter_neon.asm',
+             'vp8/common/arm/neon/sad16_neon.asm',
+             'vp8/common/arm/neon/sad8_neon.asm',
+             'vp8/common/arm/neon/save_reg_neon.asm',
+             'vp8/common/arm/neon/shortidct4x4llm_neon.asm',
+             'vp8/common/arm/neon/sixtappredict16x16_neon.asm',
+             'vp8/common/arm/neon/sixtappredict4x4_neon.asm',
+             'vp8/common/arm/neon/sixtappredict8x4_neon.asm',
+             'vp8/common/arm/neon/sixtappredict8x8_neon.asm',
+             'vp8/common/arm/neon/variance_neon.asm',
+             'vp8/common/arm/neon/vp8_subpixelvariance16x16_neon.asm',
+             'vp8/common/arm/neon/vp8_subpixelvariance16x16s_neon.asm',
+             'vp8/common/arm/neon/vp8_subpixelvariance8x8_neon.asm',
+             'vp8/common/arm/reconintra_arm.c',
+             'vp8/common/arm/variance_arm.c',
+             'vp9/common/arm/neon/vp9_avg_neon.asm',
+             'vp9/common/arm/neon/vp9_convolve8_avg_neon.asm',
+             'vp9/common/arm/neon/vp9_convolve8_neon.asm',
+             'vp9/common/arm/neon/vp9_convolve_neon.c',
+             'vp9/common/arm/neon/vp9_copy_neon.asm',
+             'vp9/common/arm/neon/vp9_dc_only_idct_add_neon.asm',
+             'vp9/common/arm/neon/vp9_idct16x16_neon.c',
+             'vp9/common/arm/neon/vp9_loopfilter_neon.asm',
+             'vp9/common/arm/neon/vp9_mb_lpf_neon.asm',
+             'vp9/common/arm/neon/vp9_save_reg_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct16x16_1_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct16x16_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct32x32_1_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct32x32_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct4x4_1_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct4x4_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct8x8_1_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_idct8x8_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_iht4x4_add_neon.asm',
+             'vp9/common/arm/neon/vp9_short_iht8x8_add_neon.asm',
+             'vpx_ports/arm_cpudetect.c',
+             'vpx_scale/arm/neon/vp8_vpxyv12_copy_y_neon.asm',
+             'vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm',
+             'vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm',
+             'vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm',
+             'vpx_scale/arm/neon/yv12extend_arm.c'],
+ 'ARM_ASM_ENCODER': ['vp8/encoder/arm/armv5te/boolhuff_armv5te.asm',
+                     'vp8/encoder/arm/armv5te/vp8_packtokens_armv5.asm',
+                     'vp8/encoder/arm/armv5te/vp8_packtokens_mbrow_armv5.asm',
+                     'vp8/encoder/arm/armv5te/vp8_packtokens_partitions_armv5.asm',
+                     'vp8/encoder/arm/armv6/vp8_fast_quantize_b_armv6.asm',
+                     'vp8/encoder/arm/armv6/vp8_mse16x16_armv6.asm',
+                     'vp8/encoder/arm/armv6/vp8_short_fdct4x4_armv6.asm',
+                     'vp8/encoder/arm/armv6/vp8_subtract_armv6.asm',
+                     'vp8/encoder/arm/armv6/walsh_v6.asm',
+                     'vp8/encoder/arm/boolhuff_arm.c',
+                     'vp8/encoder/arm/dct_arm.c',
+                     'vp8/encoder/arm/neon/fastquantizeb_neon.asm',
+                     'vp8/encoder/arm/neon/picklpf_arm.c',
+                     'vp8/encoder/arm/neon/shortfdct_neon.asm',
+                     'vp8/encoder/arm/neon/subtract_neon.asm',
+                     'vp8/encoder/arm/neon/vp8_memcpy_neon.asm',
+                     'vp8/encoder/arm/neon/vp8_mse16x16_neon.asm',
+                     'vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm',
+                     'vp8/encoder/arm/quantize_arm.c'],
+ 'AVX2': ['vp9/common/x86/vp9_loopfilter_intrin_avx2.c'],
+ 'COMMON': ['vp8/common/alloccommon.c',
+            'vp8/common/blockd.c',
+            'vp8/common/debugmodes.c',
+            'vp8/common/dequantize.c',
+            'vp8/common/entropy.c',
+            'vp8/common/entropymode.c',
+            'vp8/common/entropymv.c',
+            'vp8/common/extend.c',
+            'vp8/common/filter.c',
+            'vp8/common/findnearmv.c',
+            'vp8/common/generic/systemdependent.c',
+            'vp8/common/idct_blk.c',
+            'vp8/common/idctllm.c',
+            'vp8/common/loopfilter.c',
+            'vp8/common/loopfilter_filters.c',
+            'vp8/common/mbpitch.c',
+            'vp8/common/modecont.c',
+            'vp8/common/quant_common.c',
+            'vp8/common/reconinter.c',
+            'vp8/common/reconintra.c',
+            'vp8/common/reconintra4x4.c',
+            'vp8/common/rtcd.c',
+            'vp8/common/sad_c.c',
+            'vp8/common/setupintrarecon.c',
+            'vp8/common/swapyv12buffer.c',
+            'vp8/common/treecoder.c',
+            'vp8/common/variance_c.c',
+            'vp8/decoder/dboolhuff.c',
+            'vp8/decoder/decodemv.c',
+            'vp8/decoder/decodframe.c',
+            'vp8/decoder/detokenize.c',
+            'vp8/decoder/onyxd_if.c',
+            'vp8/decoder/threading.c',
+            'vp8/vp8_dx_iface.c',
+            'vp9/common/generic/vp9_systemdependent.c',
+            'vp9/common/vp9_alloccommon.c',
+            'vp9/common/vp9_common_data.c',
+            'vp9/common/vp9_convolve.c',
+            'vp9/common/vp9_debugmodes.c',
+            'vp9/common/vp9_entropy.c',
+            'vp9/common/vp9_entropymode.c',
+            'vp9/common/vp9_entropymv.c',
+            'vp9/common/vp9_extend.c',
+            'vp9/common/vp9_filter.c',
+            'vp9/common/vp9_findnearmv.c',
+            'vp9/common/vp9_idct.c',
+            'vp9/common/vp9_loopfilter.c',
+            'vp9/common/vp9_loopfilter_filters.c',
+            'vp9/common/vp9_mvref_common.c',
+            'vp9/common/vp9_pred_common.c',
+            'vp9/common/vp9_quant_common.c',
+            'vp9/common/vp9_reconinter.c',
+            'vp9/common/vp9_reconintra.c',
+            'vp9/common/vp9_rtcd.c',
+            'vp9/common/vp9_scale.c',
+            'vp9/common/vp9_scan.c',
+            'vp9/common/vp9_seg_common.c',
+            'vp9/common/vp9_tile_common.c',
+            'vp9/common/vp9_treecoder.c',
+            'vp9/decoder/vp9_dboolhuff.c',
+            'vp9/decoder/vp9_decodemv.c',
+            'vp9/decoder/vp9_decodframe.c',
+            'vp9/decoder/vp9_detokenize.c',
+            'vp9/decoder/vp9_dsubexp.c',
+            'vp9/decoder/vp9_onyxd_if.c',
+            'vp9/decoder/vp9_thread.c',
+            'vp9/vp9_dx_iface.c',
+            'vpx/src/vpx_codec.c',
+            'vpx/src/vpx_decoder.c',
+            'vpx/src/vpx_encoder.c',
+            'vpx/src/vpx_image.c',
+            'vpx_mem/vpx_mem.c',
+            'vpx_scale/generic/gen_scalers.c',
+            'vpx_scale/generic/vpx_scale.c',
+            'vpx_scale/generic/yv12config.c',
+            'vpx_scale/generic/yv12extend.c',
+            'vpx_scale/vpx_scale_rtcd.c'],
+ 'ENCODER': ['vp8/encoder/bitstream.c',
+             'vp8/encoder/dct.c',
+             'vp8/encoder/denoising.c',
+             'vp8/encoder/encodeframe.c',
+             'vp8/encoder/encodeintra.c',
+             'vp8/encoder/encodemb.c',
+             'vp8/encoder/encodemv.c',
+             'vp8/encoder/ethreading.c',
+             'vp8/encoder/firstpass.c',
+             'vp8/encoder/lookahead.c',
+             'vp8/encoder/mcomp.c',
+             'vp8/encoder/modecosts.c',
+             'vp8/encoder/mr_dissim.c',
+             'vp8/encoder/onyx_if.c',
+             'vp8/encoder/pickinter.c',
+             'vp8/encoder/picklpf.c',
+             'vp8/encoder/psnr.c',
+             'vp8/encoder/quantize.c',
+             'vp8/encoder/ratectrl.c',
+             'vp8/encoder/rdopt.c',
+             'vp8/encoder/segmentation.c',
+             'vp8/encoder/temporal_filter.c',
+             'vp8/encoder/tokenize.c',
+             'vp8/encoder/treewriter.c',
+             'vp8/vp8_cx_iface.c',
+             'vp9/encoder/vp9_bitstream.c',
+             'vp9/encoder/vp9_boolhuff.c',
+             'vp9/encoder/vp9_dct.c',
+             'vp9/encoder/vp9_encodeframe.c',
+             'vp9/encoder/vp9_encodeintra.c',
+             'vp9/encoder/vp9_encodemb.c',
+             'vp9/encoder/vp9_encodemv.c',
+             'vp9/encoder/vp9_firstpass.c',
+             'vp9/encoder/vp9_lookahead.c',
+             'vp9/encoder/vp9_mbgraph.c',
+             'vp9/encoder/vp9_mcomp.c',
+             'vp9/encoder/vp9_modecosts.c',
+             'vp9/encoder/vp9_onyx_if.c',
+             'vp9/encoder/vp9_picklpf.c',
+             'vp9/encoder/vp9_psnr.c',
+             'vp9/encoder/vp9_quantize.c',
+             'vp9/encoder/vp9_ratectrl.c',
+             'vp9/encoder/vp9_rdopt.c',
+             'vp9/encoder/vp9_sad_c.c',
+             'vp9/encoder/vp9_segmentation.c',
+             'vp9/encoder/vp9_subexp.c',
+             'vp9/encoder/vp9_temporal_filter.c',
+             'vp9/encoder/vp9_tokenize.c',
+             'vp9/encoder/vp9_treewriter.c',
+             'vp9/encoder/vp9_vaq.c',
+             'vp9/encoder/vp9_variance_c.c',
+             'vp9/vp9_cx_iface.c',
+             'vpx/src/svc_encodeframe.c'],
+ 'ERROR_CONCEALMENT': ['vp8/decoder/error_concealment.c'],
+ 'EXPORTS': ['vpx/vp8.h',
+             'vpx/vp8cx.h',
+             'vpx/vp8dx.h',
+             'vpx/vpx_codec.h',
+             'vpx/vpx_decoder.h',
+             'vpx/vpx_encoder.h',
+             'vpx/vpx_image.h',
+             'vpx/vpx_integer.h',
+             'vpx_mem/include/vpx_mem_intrnl.h',
+             'vpx_mem/vpx_mem.h',
+             'vpx_ports/arm.h',
+             'vpx_ports/mem.h',
+             'vpx_ports/vpx_timer.h',
+             'vpx_ports/x86.h',
+             'vpx_scale/vpx_scale.h',
+             'vpx_scale/yv12config.h'],
+ 'VP8_POSTPROC': ['vp8/common/mfqe.c', 'vp8/common/postproc.c'],
+ 'VP9_POSTPROC': ['vp9/common/vp9_postproc.c'],
+ 'X86-64_ASM': ['third_party/x86inc/x86inc.asm',
+                'vp8/common/x86/loopfilter_block_sse2.asm'],
+ 'X86-64_ASM_ENCODER': ['vp9/encoder/x86/vp9_quantize_ssse3.asm'],
+ 'X86_ASM': ['vp8/common/x86/dequantize_mmx.asm',
+             'vp8/common/x86/filter_x86.c',
+             'vp8/common/x86/idct_blk_mmx.c',
+             'vp8/common/x86/idct_blk_sse2.c',
+             'vp8/common/x86/idctllm_mmx.asm',
+             'vp8/common/x86/idctllm_sse2.asm',
+             'vp8/common/x86/iwalsh_mmx.asm',
+             'vp8/common/x86/iwalsh_sse2.asm',
+             'vp8/common/x86/loopfilter_mmx.asm',
+             'vp8/common/x86/loopfilter_sse2.asm',
+             'vp8/common/x86/loopfilter_x86.c',
+             'vp8/common/x86/mfqe_sse2.asm',
+             'vp8/common/x86/postproc_mmx.asm',
+             'vp8/common/x86/postproc_sse2.asm',
+             'vp8/common/x86/postproc_x86.c',
+             'vp8/common/x86/recon_mmx.asm',
+             'vp8/common/x86/recon_sse2.asm',
+             'vp8/common/x86/recon_wrapper_sse2.c',
+             'vp8/common/x86/sad_mmx.asm',
+             'vp8/common/x86/sad_sse2.asm',
+             'vp8/common/x86/sad_sse3.asm',
+             'vp8/common/x86/sad_sse4.asm',
+             'vp8/common/x86/sad_ssse3.asm',
+             'vp8/common/x86/subpixel_mmx.asm',
+             'vp8/common/x86/subpixel_sse2.asm',
+             'vp8/common/x86/subpixel_ssse3.asm',
+             'vp8/common/x86/variance_impl_mmx.asm',
+             'vp8/common/x86/variance_impl_sse2.asm',
+             'vp8/common/x86/variance_impl_ssse3.asm',
+             'vp8/common/x86/variance_mmx.c',
+             'vp8/common/x86/variance_sse2.c',
+             'vp8/common/x86/variance_ssse3.c',
+             'vp8/common/x86/vp8_asm_stubs.c',
+             'vp9/common/x86/vp9_asm_stubs.c',
+             'vp9/common/x86/vp9_copy_sse2.asm',
+             'vp9/common/x86/vp9_idct_intrin_sse2.c',
+             'vp9/common/x86/vp9_intrapred_sse2.asm',
+             'vp9/common/x86/vp9_intrapred_ssse3.asm',
+             'vp9/common/x86/vp9_loopfilter_intrin_sse2.c',
+             'vp9/common/x86/vp9_loopfilter_mmx.asm',
+             'vp9/common/x86/vp9_subpixel_8t_sse2.asm',
+             'vp9/common/x86/vp9_subpixel_8t_ssse3.asm',
+             'vpx_ports/emms.asm',
+             'vpx_ports/x86_cpuid.c'],
+ 'X86_ASM_ENCODER': ['vp8/encoder/x86/dct_mmx.asm',
+                     'vp8/encoder/x86/dct_sse2.asm',
+                     'vp8/encoder/x86/denoising_sse2.c',
+                     'vp8/encoder/x86/encodeopt.asm',
+                     'vp8/encoder/x86/fwalsh_sse2.asm',
+                     'vp8/encoder/x86/quantize_mmx.asm',
+                     'vp8/encoder/x86/quantize_sse2.c',
+                     'vp8/encoder/x86/quantize_sse4.asm',
+                     'vp8/encoder/x86/quantize_ssse3.asm',
+                     'vp8/encoder/x86/subtract_mmx.asm',
+                     'vp8/encoder/x86/subtract_sse2.asm',
+                     'vp8/encoder/x86/temporal_filter_apply_sse2.asm',
+                     'vp8/encoder/x86/vp8_enc_stubs_mmx.c',
+                     'vp8/encoder/x86/vp8_enc_stubs_sse2.c',
+                     'vp9/encoder/x86/vp9_dct32x32_sse2.c',
+                     'vp9/encoder/x86/vp9_dct_sse2.c',
+                     'vp9/encoder/x86/vp9_error_sse2.asm',
+                     'vp9/encoder/x86/vp9_sad4d_sse2.asm',
+                     'vp9/encoder/x86/vp9_sad_mmx.asm',
+                     'vp9/encoder/x86/vp9_sad_sse2.asm',
+                     'vp9/encoder/x86/vp9_sad_sse3.asm',
+                     'vp9/encoder/x86/vp9_sad_sse4.asm',
+                     'vp9/encoder/x86/vp9_sad_ssse3.asm',
+                     'vp9/encoder/x86/vp9_subpel_variance.asm',
+                     'vp9/encoder/x86/vp9_subpel_variance_impl_sse2.asm',
+                     'vp9/encoder/x86/vp9_subtract_sse2.asm',
+                     'vp9/encoder/x86/vp9_temporal_filter_apply_sse2.asm',
+                     'vp9/encoder/x86/vp9_variance_impl_mmx.asm',
+                     'vp9/encoder/x86/vp9_variance_impl_sse2.asm',
+                     'vp9/encoder/x86/vp9_variance_mmx.c',
+                     'vp9/encoder/x86/vp9_variance_sse2.c']
+}
new file mode 100644
--- /dev/null
+++ b/media/libvpx/third_party/x86inc/x86inc.asm
@@ -0,0 +1,1199 @@
+;*****************************************************************************
+;* x86inc.asm: x264asm abstraction layer
+;*****************************************************************************
+;* Copyright (C) 2005-2012 x264 project
+;*
+;* Authors: Loren Merritt <lorenm@u.washington.edu>
+;*          Anton Mitrofanov <BugMaster@narod.ru>
+;*          Jason Garrett-Glaser <darkshikari@gmail.com>
+;*          Henrik Gramner <hengar-6@student.ltu.se>
+;*
+;* Permission to use, copy, modify, and/or distribute this software for any
+;* purpose with or without fee is hereby granted, provided that the above
+;* copyright notice and this permission notice appear in all copies.
+;*
+;* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+;* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+;* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+;* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+;* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+;* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+;*****************************************************************************
+
+; This is a header file for the x264ASM assembly language, which uses
+; NASM/YASM syntax combined with a large number of macros to provide easy
+; abstraction between different calling conventions (x86_32, win64, linux64).
+; It also has various other useful features to simplify writing the kind of
+; DSP functions that are most often used in x264.
+
+; Unlike the rest of x264, this file is available under an ISC license, as it
+; has significant usefulness outside of x264 and we want it to be available
+; to the largest audience possible.  Of course, if you modify it for your own
+; purposes to add a new feature, we strongly encourage contributing a patch
+; as this feature might be useful for others as well.  Send patches or ideas
+; to x264-devel@videolan.org .
+
+%include "vpx_config.asm"
+
+%define program_name vp9
+
+
+%define UNIX64 0
+%define WIN64  0
+%if ARCH_X86_64
+    %ifidn __OUTPUT_FORMAT__,win32
+        %define WIN64  1
+    %elifidn __OUTPUT_FORMAT__,win64
+        %define WIN64  1
+    %elifidn __OUTPUT_FORMAT__,x64
+        %define WIN64  1
+    %else
+        %define UNIX64 1
+    %endif
+%endif
+
+%ifidn   __OUTPUT_FORMAT__,elf32
+    %define mangle(x) x
+%elifidn __OUTPUT_FORMAT__,elf64
+    %define mangle(x) x
+%elifidn __OUTPUT_FORMAT__,elf
+    %define mangle(x) x
+%elifidn __OUTPUT_FORMAT__,x64
+    %define mangle(x) x
+%elifidn __OUTPUT_FORMAT__,win64
+    %define mangle(x) x
+%else
+    %define mangle(x) _ %+ x
+%endif
+
+; FIXME: All of the 64bit asm functions that take a stride as an argument
+; via register, assume that the high dword of that register is filled with 0.
+; This is true in practice (since we never do any 64bit arithmetic on strides,
+; and x264's strides are all positive), but is not guaranteed by the ABI.
+
+; Name of the .rodata section.
+; Kludge: Something on OS X fails to align .rodata even given an align attribute,
+; so use a different read-only section.
+%macro SECTION_RODATA 0-1 16
+    %ifidn __OUTPUT_FORMAT__,macho64
+        SECTION .text align=%1
+    %elifidn __OUTPUT_FORMAT__,macho
+        SECTION .text align=%1
+        fakegot:
+    %elifidn __OUTPUT_FORMAT__,aout
+        section .text
+    %else
+        SECTION .rodata align=%1
+    %endif
+%endmacro
+
+; aout does not support align=
+%macro SECTION_TEXT 0-1 16
+    %ifidn __OUTPUT_FORMAT__,aout
+        SECTION .text
+    %else
+        SECTION .text align=%1
+    %endif
+%endmacro
+
+; PIC macros are copied from vpx_ports/x86_abi_support.asm. The "define PIC"
+; from original code is added in for 64bit.
+%ifidn __OUTPUT_FORMAT__,elf32
+%define ABI_IS_32BIT 1
+%elifidn __OUTPUT_FORMAT__,macho32
+%define ABI_IS_32BIT 1
+%elifidn __OUTPUT_FORMAT__,win32
+%define ABI_IS_32BIT 1
+%elifidn __OUTPUT_FORMAT__,aout
+%define ABI_IS_32BIT 1
+%else
+%define ABI_IS_32BIT 0
+%endif
+
+%if ABI_IS_32BIT
+  %if CONFIG_PIC=1
+  %ifidn __OUTPUT_FORMAT__,elf32
+    %define GET_GOT_SAVE_ARG 1
+    %define WRT_PLT wrt ..plt
+    %macro GET_GOT 1
+      extern _GLOBAL_OFFSET_TABLE_
+      push %1
+      call %%get_got
+      %%sub_offset:
+      jmp %%exitGG
+      %%get_got:
+      mov %1, [esp]
+      add %1, _GLOBAL_OFFSET_TABLE_ + $$ - %%sub_offset wrt ..gotpc
+      ret
+      %%exitGG:
+      %undef GLOBAL
+      %define GLOBAL(x) x + %1 wrt ..gotoff
+      %undef RESTORE_GOT
+      %define RESTORE_GOT pop %1
+    %endmacro
+  %elifidn __OUTPUT_FORMAT__,macho32
+    %define GET_GOT_SAVE_ARG 1
+    %macro GET_GOT 1
+      push %1
+      call %%get_got
+      %%get_got:
+      pop  %1
+      %undef GLOBAL
+      %define GLOBAL(x) x + %1 - %%get_got
+      %undef RESTORE_GOT
+      %define RESTORE_GOT pop %1
+    %endmacro
+  %endif
+  %endif
+
+  %if ARCH_X86_64 == 0
+    %undef PIC
+  %endif
+
+%else
+  %macro GET_GOT 1
+  %endmacro
+  %define GLOBAL(x) rel x
+  %define WRT_PLT wrt ..plt
+
+  %if WIN64
+    %define PIC
+  %elifidn __OUTPUT_FORMAT__,macho64
+    %define PIC
+  %elif CONFIG_PIC
+    %define PIC
+  %endif
+%endif
+
+%ifnmacro GET_GOT
+    %macro GET_GOT 1
+    %endmacro
+    %define GLOBAL(x) x
+%endif
+%ifndef RESTORE_GOT
+%define RESTORE_GOT
+%endif
+%ifndef WRT_PLT
+%define WRT_PLT
+%endif
+
+%ifdef PIC
+    default rel
+%endif
+; Done with PIC macros
+
+; Always use long nops (reduces 0x90 spam in disassembly on x86_32)
+%ifndef __NASM_VER__
+CPU amdnop
+%else
+%use smartalign
+ALIGNMODE k7
+%endif
+
+; Macros to eliminate most code duplication between x86_32 and x86_64:
+; Currently this works only for leaf functions which load all their arguments
+; into registers at the start, and make no other use of the stack. Luckily that
+; covers most of x264's asm.
+
+; PROLOGUE:
+; %1 = number of arguments. loads them from stack if needed.
+; %2 = number of registers used. pushes callee-saved regs if needed.
+; %3 = number of xmm registers used. pushes callee-saved xmm regs if needed.
+; %4 = list of names to define to registers
+; PROLOGUE can also be invoked by adding the same options to cglobal
+
+; e.g.
+; cglobal foo, 2,3,0, dst, src, tmp
+; declares a function (foo), taking two args (dst and src) and one local variable (tmp)
+
+; TODO Some functions can use some args directly from the stack. If they're the
+; last args then you can just not declare them, but if they're in the middle
+; we need more flexible macro.
+
+; RET:
+; Pops anything that was pushed by PROLOGUE, and returns.
+
+; REP_RET:
+; Same, but if it doesn't pop anything it becomes a 2-byte ret, for athlons
+; which are slow when a normal ret follows a branch.
+
+; registers:
+; rN and rNq are the native-size register holding function argument N
+; rNd, rNw, rNb are dword, word, and byte size
+; rNm is the original location of arg N (a register or on the stack), dword
+; rNmp is native size
+
+%macro DECLARE_REG 5-6
+    %define r%1q %2
+    %define r%1d %3
+    %define r%1w %4
+    %define r%1b %5
+    %if %0 == 5
+        %define r%1m  %3
+        %define r%1mp %2
+    %elif ARCH_X86_64 ; memory
+        %define r%1m [rsp + stack_offset + %6]
+        %define r%1mp qword r %+ %1m
+    %else
+        %define r%1m [esp + stack_offset + %6]
+        %define r%1mp dword r %+ %1m
+    %endif
+    %define r%1  %2
+%endmacro
+
+%macro DECLARE_REG_SIZE 2
+    %define r%1q r%1
+    %define e%1q r%1
+    %define r%1d e%1
+    %define e%1d e%1
+    %define r%1w %1
+    %define e%1w %1
+    %define r%1b %2
+    %define e%1b %2
+%if ARCH_X86_64 == 0
+    %define r%1  e%1
+%endif
+%endmacro
+
+DECLARE_REG_SIZE ax, al
+DECLARE_REG_SIZE bx, bl
+DECLARE_REG_SIZE cx, cl
+DECLARE_REG_SIZE dx, dl
+DECLARE_REG_SIZE si, sil
+DECLARE_REG_SIZE di, dil
+DECLARE_REG_SIZE bp, bpl
+
+; t# defines for when per-arch register allocation is more complex than just function arguments
+
+%macro DECLARE_REG_TMP 1-*
+    %assign %%i 0
+    %rep %0
+        CAT_XDEFINE t, %%i, r%1
+        %assign %%i %%i+1
+        %rotate 1
+    %endrep
+%endmacro
+
+%macro DECLARE_REG_TMP_SIZE 0-*
+    %rep %0
+        %define t%1q t%1 %+ q
+        %define t%1d t%1 %+ d
+        %define t%1w t%1 %+ w
+        %define t%1b t%1 %+ b
+        %rotate 1
+    %endrep
+%endmacro
+
+DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
+
+%if ARCH_X86_64
+    %define gprsize 8
+%else
+    %define gprsize 4
+%endif
+
+%macro PUSH 1
+    push %1
+    %assign stack_offset stack_offset+gprsize
+%endmacro
+
+%macro POP 1
+    pop %1
+    %assign stack_offset stack_offset-gprsize
+%endmacro
+
+%macro PUSH_IF_USED 1-*
+    %rep %0
+        %if %1 < regs_used
+            PUSH r%1
+        %endif
+        %rotate 1
+    %endrep
+%endmacro
+
+%macro POP_IF_USED 1-*
+    %rep %0
+        %if %1 < regs_used
+            pop r%1
+        %endif
+        %rotate 1
+    %endrep
+%endmacro
+
+%macro LOAD_IF_USED 1-*
+    %rep %0
+        %if %1 < num_args
+            mov r%1, r %+ %1 %+ mp
+        %endif
+        %rotate 1
+    %endrep
+%endmacro
+
+%macro SUB 2
+    sub %1, %2
+    %ifidn %1, rsp
+        %assign stack_offset stack_offset+(%2)
+    %endif
+%endmacro
+
+%macro ADD 2
+    add %1, %2
+    %ifidn %1, rsp
+        %assign stack_offset stack_offset-(%2)
+    %endif
+%endmacro
+
+%macro movifnidn 2
+    %ifnidn %1, %2
+        mov %1, %2
+    %endif
+%endmacro
+
+%macro movsxdifnidn 2
+    %ifnidn %1, %2
+        movsxd %1, %2
+    %endif
+%endmacro
+
+%macro ASSERT 1
+    %if (%1) == 0
+        %error assert failed
+    %endif
+%endmacro
+
+%macro DEFINE_ARGS 0-*
+    %ifdef n_arg_names
+        %assign %%i 0
+        %rep n_arg_names
+            CAT_UNDEF arg_name %+ %%i, q
+            CAT_UNDEF arg_name %+ %%i, d
+            CAT_UNDEF arg_name %+ %%i, w
+            CAT_UNDEF arg_name %+ %%i, b
+            CAT_UNDEF arg_name %+ %%i, m
+            CAT_UNDEF arg_name %+ %%i, mp
+            CAT_UNDEF arg_name, %%i
+            %assign %%i %%i+1
+        %endrep
+    %endif
+
+    %xdefine %%stack_offset stack_offset
+    %undef stack_offset ; so that the current value of stack_offset doesn't get baked in by xdefine
+    %assign %%i 0
+    %rep %0
+        %xdefine %1q r %+ %%i %+ q
+        %xdefine %1d r %+ %%i %+ d
+        %xdefine %1w r %+ %%i %+ w
+        %xdefine %1b r %+ %%i %+ b
+        %xdefine %1m r %+ %%i %+ m
+        %xdefine %1mp r %+ %%i %+ mp
+        CAT_XDEFINE arg_name, %%i, %1
+        %assign %%i %%i+1
+        %rotate 1
+    %endrep
+    %xdefine stack_offset %%stack_offset
+    %assign n_arg_names %0
+%endmacro
+
+%if WIN64 ; Windows x64 ;=================================================
+
+DECLARE_REG 0,  rcx, ecx,  cx,   cl
+DECLARE_REG 1,  rdx, edx,  dx,   dl
+DECLARE_REG 2,  R8,  R8D,  R8W,  R8B
+DECLARE_REG 3,  R9,  R9D,  R9W,  R9B
+DECLARE_REG 4,  R10, R10D, R10W, R10B, 40
+DECLARE_REG 5,  R11, R11D, R11W, R11B, 48
+DECLARE_REG 6,  rax, eax,  ax,   al,   56
+DECLARE_REG 7,  rdi, edi,  di,   dil,  64
+DECLARE_REG 8,  rsi, esi,  si,   sil,  72
+DECLARE_REG 9,  rbx, ebx,  bx,   bl,   80
+DECLARE_REG 10, rbp, ebp,  bp,   bpl,  88
+DECLARE_REG 11, R12, R12D, R12W, R12B, 96
+DECLARE_REG 12, R13, R13D, R13W, R13B, 104
+DECLARE_REG 13, R14, R14D, R14W, R14B, 112
+DECLARE_REG 14, R15, R15D, R15W, R15B, 120
+
+%macro PROLOGUE 2-4+ 0 ; #args, #regs, #xmm_regs, arg_names...
+    %assign num_args %1
+    %assign regs_used %2
+    ASSERT regs_used >= num_args
+    ASSERT regs_used <= 15
+    PUSH_IF_USED 7, 8, 9, 10, 11, 12, 13, 14
+    %if mmsize == 8
+        %assign xmm_regs_used 0
+    %else
+        WIN64_SPILL_XMM %3
+    %endif
+    LOAD_IF_USED 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+    DEFINE_ARGS %4
+%endmacro
+
+%macro WIN64_SPILL_XMM 1
+    %assign xmm_regs_used %1
+    ASSERT xmm_regs_used <= 16
+    %if xmm_regs_used > 6
+        SUB rsp, (xmm_regs_used-6)*16+16
+        %assign %%i xmm_regs_used
+        %rep (xmm_regs_used-6)
+            %assign %%i %%i-1
+            movdqa [rsp + (%%i-6)*16+(~stack_offset&8)], xmm %+ %%i
+        %endrep
+    %endif
+%endmacro
+
+%macro WIN64_RESTORE_XMM_INTERNAL 1
+    %if xmm_regs_used > 6
+        %assign %%i xmm_regs_used
+        %rep (xmm_regs_used-6)
+            %assign %%i %%i-1
+            movdqa xmm %+ %%i, [%1 + (%%i-6)*16+(~stack_offset&8)]
+        %endrep
+        add %1, (xmm_regs_used-6)*16+16
+    %endif
+%endmacro
+
+%macro WIN64_RESTORE_XMM 1
+    WIN64_RESTORE_XMM_INTERNAL %1
+    %assign stack_offset stack_offset-(xmm_regs_used-6)*16+16
+    %assign xmm_regs_used 0
+%endmacro
+
+%macro RET 0
+    WIN64_RESTORE_XMM_INTERNAL rsp
+    POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7
+    ret
+%endmacro
+
+%macro REP_RET 0
+    %if regs_used > 7 || xmm_regs_used > 6
+        RET
+    %else
+        rep ret
+    %endif
+%endmacro
+
+%elif ARCH_X86_64 ; *nix x64 ;=============================================
+
+DECLARE_REG 0,  rdi, edi,  di,   dil
+DECLARE_REG 1,  rsi, esi,  si,   sil
+DECLARE_REG 2,  rdx, edx,  dx,   dl
+DECLARE_REG 3,  rcx, ecx,  cx,   cl
+DECLARE_REG 4,  R8,  R8D,  R8W,  R8B
+DECLARE_REG 5,  R9,  R9D,  R9W,  R9B
+DECLARE_REG 6,  rax, eax,  ax,   al,   8
+DECLARE_REG 7,  R10, R10D, R10W, R10B, 16
+DECLARE_REG 8,  R11, R11D, R11W, R11B, 24
+DECLARE_REG 9,  rbx, ebx,  bx,   bl,   32
+DECLARE_REG 10, rbp, ebp,  bp,   bpl,  40
+DECLARE_REG 11, R12, R12D, R12W, R12B, 48
+DECLARE_REG 12, R13, R13D, R13W, R13B, 56
+DECLARE_REG 13, R14, R14D, R14W, R14B, 64
+DECLARE_REG 14, R15, R15D, R15W, R15B, 72
+
+%macro PROLOGUE 2-4+ ; #args, #regs, #xmm_regs, arg_names...
+    %assign num_args %1
+    %assign regs_used %2
+    ASSERT regs_used >= num_args
+    ASSERT regs_used <= 15
+    PUSH_IF_USED 9, 10, 11, 12, 13, 14
+    LOAD_IF_USED 6, 7, 8, 9, 10, 11, 12, 13, 14
+    DEFINE_ARGS %4
+%endmacro
+
+%macro RET 0
+    POP_IF_USED 14, 13, 12, 11, 10, 9
+    ret
+%endmacro
+
+%macro REP_RET 0
+    %if regs_used > 9
+        RET
+    %else
+        rep ret
+    %endif
+%endmacro
+
+%else ; X86_32 ;==============================================================
+
+DECLARE_REG 0, eax, eax, ax, al,   4
+DECLARE_REG 1, ecx, ecx, cx, cl,   8
+DECLARE_REG 2, edx, edx, dx, dl,   12
+DECLARE_REG 3, ebx, ebx, bx, bl,   16
+DECLARE_REG 4, esi, esi, si, null, 20
+DECLARE_REG 5, edi, edi, di, null, 24
+DECLARE_REG 6, ebp, ebp, bp, null, 28
+%define rsp esp
+
+%macro DECLARE_ARG 1-*
+    %rep %0
+        %define r%1m [esp + stack_offset + 4*%1 + 4]
+        %define r%1mp dword r%1m
+        %rotate 1
+    %endrep
+%endmacro
+
+DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14
+
+%macro PROLOGUE 2-4+ ; #args, #regs, #xmm_regs, arg_names...
+    %assign num_args %1
+    %assign regs_used %2
+    %if regs_used > 7
+        %assign regs_used 7
+    %endif
+    ASSERT regs_used >= num_args
+    PUSH_IF_USED 3, 4, 5, 6
+    LOAD_IF_USED 0, 1, 2, 3, 4, 5, 6
+    DEFINE_ARGS %4
+%endmacro
+
+%macro RET 0
+    POP_IF_USED 6, 5, 4, 3
+    ret
+%endmacro
+
+%macro REP_RET 0
+    %if regs_used > 3
+        RET
+    %else
+        rep ret
+    %endif
+%endmacro
+
+%endif ;======================================================================
+
+%if WIN64 == 0
+%macro WIN64_SPILL_XMM 1
+%endmacro
+%macro WIN64_RESTORE_XMM 1
+%endmacro
+%endif
+
+;=============================================================================
+; arch-independent part
+;=============================================================================
+
+%assign function_align 16
+
+; Begin a function.
+; Applies any symbol mangling needed for C linkage, and sets up a define such that
+; subsequent uses of the function name automatically refer to the mangled version.
+; Appends cpuflags to the function name if cpuflags has been specified.
+%macro cglobal 1-2+ ; name, [PROLOGUE args]
+%if %0 == 1
+    cglobal_internal %1 %+ SUFFIX
+%else
+    cglobal_internal %1 %+ SUFFIX, %2
+%endif
+%endmacro
+%macro cglobal_internal 1-2+
+    %ifndef cglobaled_%1
+        %xdefine %1 mangle(program_name %+ _ %+ %1)
+        %xdefine %1.skip_prologue %1 %+ .skip_prologue
+        CAT_XDEFINE cglobaled_, %1, 1
+    %endif
+    %xdefine current_function %1
+    %ifidn __OUTPUT_FORMAT__,elf
+        global %1:function hidden
+    %elifidn __OUTPUT_FORMAT__,elf32
+        global %1:function hidden
+    %elifidn __OUTPUT_FORMAT__,elf64
+        global %1:function hidden
+    %elifidn __OUTPUT_FORMAT__,macho32
+        global %1:private_extern
+    %elifidn __OUTPUT_FORMAT__,macho64
+        global %1:private_extern
+    %else
+        global %1
+    %endif
+    align function_align
+    %1:
+    RESET_MM_PERMUTATION ; not really needed, but makes disassembly somewhat nicer
+    %assign stack_offset 0
+    %if %0 > 1
+        PROLOGUE %2
+    %endif
+%endmacro
+
+%macro cextern 1
+    %xdefine %1 mangle(program_name %+ _ %+ %1)
+    CAT_XDEFINE cglobaled_, %1, 1
+    extern %1
+%endmacro
+
+; like cextern, but without the prefix
+%macro cextern_naked 1
+    %xdefine %1 mangle(%1)
+    CAT_XDEFINE cglobaled_, %1, 1
+    extern %1
+%endmacro
+
+%macro const 2+
+    %xdefine %1 mangle(program_name %+ _ %+ %1)
+    global %1
+    %1: %2
+%endmacro
+
+; This is needed for ELF, otherwise the GNU linker assumes the stack is
+; executable by default.
+%ifidn __OUTPUT_FORMAT__,elf
+SECTION .note.GNU-stack noalloc noexec nowrite progbits
+%elifidn __OUTPUT_FORMAT__,elf32
+SECTION .note.GNU-stack noalloc noexec nowrite progbits
+%elifidn __OUTPUT_FORMAT__,elf64
+SECTION .note.GNU-stack noalloc noexec nowrite progbits
+%endif
+
+; cpuflags
+
+%assign cpuflags_mmx      (1<<0)
+%assign cpuflags_mmx2     (1<<1) | cpuflags_mmx
+%assign cpuflags_3dnow    (1<<2) | cpuflags_mmx
+%assign cpuflags_3dnow2   (1<<3) | cpuflags_3dnow
+%assign cpuflags_sse      (1<<4) | cpuflags_mmx2
+%assign cpuflags_sse2     (1<<5) | cpuflags_sse
+%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2
+%assign cpuflags_sse3     (1<<7) | cpuflags_sse2
+%assign cpuflags_ssse3    (1<<8) | cpuflags_sse3
+%assign cpuflags_sse4     (1<<9) | cpuflags_ssse3
+%assign cpuflags_sse42    (1<<10)| cpuflags_sse4
+%assign cpuflags_avx      (1<<11)| cpuflags_sse42
+%assign cpuflags_xop      (1<<12)| cpuflags_avx
+%assign cpuflags_fma4     (1<<13)| cpuflags_avx
+
+%assign cpuflags_cache32  (1<<16)
+%assign cpuflags_cache64  (1<<17)
+%assign cpuflags_slowctz  (1<<18)
+%assign cpuflags_lzcnt    (1<<19)
+%assign cpuflags_misalign (1<<20)
+%assign cpuflags_aligned  (1<<21) ; not a cpu feature, but a function variant
+%assign cpuflags_atom     (1<<22)
+
+%define    cpuflag(x) ((cpuflags & (cpuflags_ %+ x)) == (cpuflags_ %+ x))
+%define notcpuflag(x) ((cpuflags & (cpuflags_ %+ x)) != (cpuflags_ %+ x))
+
+; Takes up to 2 cpuflags from the above list.
+; All subsequent functions (up to the next INIT_CPUFLAGS) is built for the specified cpu.
+; You shouldn't need to invoke this macro directly, it's a subroutine for INIT_MMX &co.
+%macro INIT_CPUFLAGS 0-2
+    %if %0 >= 1
+        %xdefine cpuname %1
+        %assign cpuflags cpuflags_%1
+        %if %0 >= 2
+            %xdefine cpuname %1_%2
+            %assign cpuflags cpuflags | cpuflags_%2
+        %endif
+        %xdefine SUFFIX _ %+ cpuname
+        %if cpuflag(avx)
+            %assign avx_enabled 1
+        %endif
+        %if mmsize == 16 && notcpuflag(sse2)
+            %define mova movaps
+            %define movu movups
+            %define movnta movntps
+        %endif
+        %if cpuflag(aligned)
+            %define movu mova
+        %elifidn %1, sse3
+            %define movu lddqu
+        %endif
+    %else
+        %xdefine SUFFIX
+        %undef cpuname
+        %undef cpuflags
+    %endif
+%endmacro
+
+; merge mmx and sse*
+
+%macro CAT_XDEFINE 3
+    %xdefine %1%2 %3
+%endmacro
+
+%macro CAT_UNDEF 2
+    %undef %1%2
+%endmacro
+
+%macro INIT_MMX 0-1+
+    %assign avx_enabled 0
+    %define RESET_MM_PERMUTATION INIT_MMX %1
+    %define mmsize 8
+    %define num_mmregs 8
+    %define mova movq
+    %define movu movq
+    %define movh movd
+    %define movnta movntq
+    %assign %%i 0
+    %rep 8
+    CAT_XDEFINE m, %%i, mm %+ %%i
+    CAT_XDEFINE nmm, %%i, %%i
+    %assign %%i %%i+1
+    %endrep
+    %rep 8
+    CAT_UNDEF m, %%i
+    CAT_UNDEF nmm, %%i
+    %assign %%i %%i+1
+    %endrep
+    INIT_CPUFLAGS %1
+%endmacro
+
+%macro INIT_XMM 0-1+
+    %assign avx_enabled 0
+    %define RESET_MM_PERMUTATION INIT_XMM %1
+    %define mmsize 16
+    %define num_mmregs 8
+    %if ARCH_X86_64
+    %define num_mmregs 16
+    %endif
+    %define mova movdqa
+    %define movu movdqu
+    %define movh movq
+    %define movnta movntdq
+    %assign %%i 0
+    %rep num_mmregs
+    CAT_XDEFINE m, %%i, xmm %+ %%i
+    CAT_XDEFINE nxmm, %%i, %%i
+    %assign %%i %%i+1
+    %endrep
+    INIT_CPUFLAGS %1
+%endmacro
+
+; FIXME: INIT_AVX can be replaced by INIT_XMM avx
+%macro INIT_AVX 0
+    INIT_XMM
+    %assign avx_enabled 1
+    %define PALIGNR PALIGNR_SSSE3
+    %define RESET_MM_PERMUTATION INIT_AVX
+%endmacro
+
+%macro INIT_YMM 0-1+
+    %assign avx_enabled 1
+    %define RESET_MM_PERMUTATION INIT_YMM %1
+    %define mmsize 32
+    %define num_mmregs 8
+    %if ARCH_X86_64
+    %define num_mmregs 16
+    %endif
+    %define mova vmovaps
+    %define movu vmovups
+    %undef movh
+    %define movnta vmovntps
+    %assign %%i 0
+    %rep num_mmregs
+    CAT_XDEFINE m, %%i, ymm %+ %%i
+    CAT_XDEFINE nymm, %%i, %%i
+    %assign %%i %%i+1
+    %endrep
+    INIT_CPUFLAGS %1
+%endmacro
+
+INIT_XMM
+
+; I often want to use macros that permute their arguments. e.g. there's no
+; efficient way to implement butterfly or transpose or dct without swapping some
+; arguments.
+;
+; I would like to not have to manually keep track of the permutations:
+; If I insert a permutation in the middle of a function, it should automatically
+; change everything that follows. For more complex macros I may also have multiple
+; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations.
+;
+; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that
+; permutes its arguments. It's equivalent to exchanging the contents of the
+; registers, except that this way you exchange the register names instead, so it
+; doesn't cost any cycles.
+
+%macro PERMUTE 2-* ; takes a list of pairs to swap
+%rep %0/2
+    %xdefine tmp%2 m%2
+    %xdefine ntmp%2 nm%2
+    %rotate 2
+%endrep
+%rep %0/2
+    %xdefine m%1 tmp%2
+    %xdefine nm%1 ntmp%2
+    %undef tmp%2
+    %undef ntmp%2
+    %rotate 2
+%endrep
+%endmacro
+
+%macro SWAP 2-* ; swaps a single chain (sometimes more concise than pairs)
+%rep %0-1
+%ifdef m%1
+    %xdefine tmp m%1
+    %xdefine m%1 m%2
+    %xdefine m%2 tmp
+    CAT_XDEFINE n, m%1, %1
+    CAT_XDEFINE n, m%2, %2
+%else
+    ; If we were called as "SWAP m0,m1" rather than "SWAP 0,1" infer the original numbers here.
+    ; Be careful using this mode in nested macros though, as in some cases there may be
+    ; other copies of m# that have already been dereferenced and don't get updated correctly.
+    %xdefine %%n1 n %+ %1
+    %xdefine %%n2 n %+ %2
+    %xdefine tmp m %+ %%n1
+    CAT_XDEFINE m, %%n1, m %+ %%n2
+    CAT_XDEFINE m, %%n2, tmp
+    CAT_XDEFINE n, m %+ %%n1, %%n1
+    CAT_XDEFINE n, m %+ %%n2, %%n2
+%endif
+    %undef tmp
+    %rotate 1
+%endrep
+%endmacro
+
+; If SAVE_MM_PERMUTATION is placed at the end of a function, then any later
+; calls to that function will automatically load the permutation, so values can
+; be returned in mmregs.
+%macro SAVE_MM_PERMUTATION 0-1
+    %if %0
+        %xdefine %%f %1_m
+    %else
+        %xdefine %%f current_function %+ _m
+    %endif
+    %assign %%i 0
+    %rep num_mmregs
+        CAT_XDEFINE %%f, %%i, m %+ %%i
+    %assign %%i %%i+1
+    %endrep
+%endmacro
+
+%macro LOAD_MM_PERMUTATION 1 ; name to load from
+    %ifdef %1_m0
+        %assign %%i 0
+        %rep num_mmregs
+            CAT_XDEFINE m, %%i, %1_m %+ %%i
+            CAT_XDEFINE n, m %+ %%i, %%i
+        %assign %%i %%i+1
+        %endrep
+    %endif
+%endmacro
+
+; Append cpuflags to the callee's name iff the appended name is known and the plain name isn't
+%macro call 1
+    call_internal %1, %1 %+ SUFFIX
+%endmacro
+%macro call_internal 2
+    %xdefine %%i %1
+    %ifndef cglobaled_%1
+        %ifdef cglobaled_%2
+            %xdefine %%i %2
+        %endif
+    %endif
+    call %%i
+    LOAD_MM_PERMUTATION %%i
+%endmacro
+
+; Substitutions that reduce instruction size but are functionally equivalent
+%macro add 2
+    %ifnum %2
+        %if %2==128
+            sub %1, -128
+        %else
+            add %1, %2
+        %endif
+    %else
+        add %1, %2
+    %endif
+%endmacro
+
+%macro sub 2
+    %ifnum %2
+        %if %2==128
+            add %1, -128
+        %else
+            sub %1, %2
+        %endif
+    %else
+        sub %1, %2
+    %endif
+%endmacro
+
+;=============================================================================
+; AVX abstraction layer
+;=============================================================================
+
+%assign i 0
+%rep 16