Merge m-c to fx-team. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 26 Nov 2014 21:44:26 -0500
changeset 242139 679466398b30c66fc38b12d031ea184ee42c3db6
parent 242138 6e82407a7c65ddc7f464cf83f4c4ef845a193a87 (current diff)
parent 242059 cef590a6f94681064fa954890bae6014db819158 (diff)
child 242140 7dfad34d265b2cf21bd2c470ba6f6f526af3b663
child 242159 67ad36ab89c184b9bebc65994f3ba1289d4fb41b
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team. a=merge
dom/icc/tests/marionette/test_icc_card_lock.js
js/src/jit/IonAllocPolicy.h
js/src/jit/IonFrames-inl.h
js/src/jit/IonFrames.cpp
js/src/jit/IonFrames.h
js/src/jit/IonLinker.h
js/src/jit/IonMacroAssembler.cpp
js/src/jit/IonMacroAssembler.h
layout/style/test/test_flexbox_flex_basis_values.html
security/sandbox/chromium/base/platform_file.h
security/sandbox/chromium/base/strings/string_util_stripped.cc
security/sandbox/chromium/base/win/event_trace_provider.cc
security/sandbox/chromium/base/win/event_trace_provider.h
security/sandbox/chromium/base/win/registry.cc
security/sandbox/chromium/base/win/registry.h
security/sandbox/chromium/sandbox/linux/sandbox_export.h
testing/web-platform/meta/DOMEvents/tests/approved/addEventListener.optional.useCapture.html.ini
testing/web-platform/meta/DOMEvents/tests/approved/dispatchEvent.return.value.html.ini
testing/web-platform/meta/DOMEvents/tests/submissions/Microsoft/converted/addEventListener.optional.useCapture.html.ini
testing/web-platform/meta/DOMEvents/tests/submissions/Microsoft/converted/dispatchEvent.return.value.html.ini
testing/web-platform/meta/selectors-api/tests/submissions/Opera/level2-baseline.html.ini
toolkit/components/places/tests/unit/test_PlacesUtils_promiseHrefAndPostDataForKeyword.js
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -155,41 +155,48 @@ this.Utils = { // jshint ignore:line
   },
 
   get CurrentContentDoc() {
     let browser = this.CurrentBrowser;
     return browser ? browser.contentDocument : null;
   },
 
   get AllMessageManagers() {
-    let messageManagers = [];
+    let messageManagers = new Set();
 
     function collectLeafMessageManagers(mm) {
       for (let i = 0; i < mm.childCount; i++) {
         let childMM = mm.getChildAt(i);
 
         if ('sendAsyncMessage' in childMM) {
-          messageManagers.push(childMM);
+          messageManagers.add(childMM);
         } else {
           collectLeafMessageManagers(childMM);
         }
       }
     }
 
     collectLeafMessageManagers(this.win.messageManager);
 
     let document = this.CurrentContentDoc;
 
     if (document) {
+      if (document.location.host === 'b2g') {
+        // The document is a b2g app chrome (ie. Mulet).
+        let contentBrowser = this.win.content.shell.contentBrowser;
+        messageManagers.add(this.getMessageManager(contentBrowser));
+        document = contentBrowser.contentDocument;
+      }
+
       let remoteframes = document.querySelectorAll('iframe');
 
       for (let i = 0; i < remoteframes.length; ++i) {
         let mm = this.getMessageManager(remoteframes[i]);
         if (mm) {
-          messageManagers.push(mm);
+          messageManagers.add(mm);
         }
       }
 
     }
 
     return messageManagers;
   },
 
--- a/accessible/jsat/content-script.js
+++ b/accessible/jsat/content-script.js
@@ -18,17 +18,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   'resource://gre/modules/accessibility/EventManager.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'ContentControl',
   'resource://gre/modules/accessibility/ContentControl.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
   'resource://gre/modules/accessibility/Constants.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'States',
   'resource://gre/modules/accessibility/Constants.jsm');
 
-Logger.debug('content-script.js');
+Logger.info('content-script.js', content.document.location);
 
 let eventManager = null;
 let contentControl = null;
 
 function forwardToParent(aMessage) {
   // XXX: This is a silly way to make a deep copy
   let newJSON = JSON.parse(JSON.stringify(aMessage.json));
   newJSON.origin = 'child';
--- a/addon-sdk/Makefile.in
+++ b/addon-sdk/Makefile.in
@@ -7,16 +7,17 @@ ADDONSRC = $(srcdir)/$(TESTADDONS)
 TESTROOT = $(CURDIR)/$(DEPTH)/_tests/testing/mochitest/jetpack-addon/$(relativesrcdir)/$(TESTADDONS)
 
 # Build a list of the test add-ons
 ADDONS = $(patsubst $(ADDONSRC)/%/package.json,$(TESTADDONS)/%.xpi,$(wildcard $(ADDONSRC)/*/package.json))
 
 INSTALL_TARGETS += test_addons
 test_addons_FILES = $(ADDONS)
 test_addons_DEST = $(TESTROOT)
+test_addons_TARGET := misc
 
 sinclude $(topsrcdir)/config/rules.mk
 
 # This can switch to just zipping the files when native jetpacks land
 $(TESTADDONS)/%.xpi: FORCE $(call mkdir_deps,$(CURDIR)/$(TESTADDONS)) $(ADDONSRC)/%
 	$(PYTHON) $(srcdir)/source/bin/cfx xpi --pkgdir=$(lastword $^) --output-file=$@
 
 #libs:: $(ADDONS)
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -4,16 +4,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # -*- 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/.
 
+HAS_MISC_RULE = True
+
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 JETPACK_PACKAGE_MANIFESTS += ['source/test/jetpack-package.ini']
 JETPACK_ADDON_MANIFESTS += ['source/test/addons/jetpack-addon.ini']
 
 EXTRA_JS_MODULES.sdk += [
     'source/app-extension/bootstrap.js',
 ]
 
--- a/b2g/components/SystemAppProxy.jsm
+++ b/b2g/components/SystemAppProxy.jsm
@@ -84,20 +84,26 @@ let SystemAppProxy = {
 
     event.initCustomEvent(type, true, false, payload);
     (target || content).dispatchEvent(event);
 
     return event;
   },
 
   // Now deprecated, use sendCustomEvent with a custom event name
-  dispatchEvent: function systemApp_sendChromeEvent(details, target) {
+  dispatchEvent: function systemApp_dispatchEvent(details, target) {
     return this._sendCustomEvent('mozChromeEvent', details, false, target);
   },
 
+  dispatchKeyboardEvent: function systemApp_dispatchKeyboardEvent(type, details) {
+    let content = this._frame ? this._frame.contentWindow : null;
+    let e = new content.KeyboardEvent(type, details);
+    content.dispatchEvent(e);
+  },
+
   // Listen for dom events on the system app
   addEventListener: function systemApp_addEventListener() {
     let content = this._frame ? this._frame.contentWindow : null;
     if (!content) {
       this._pendingListeners.push(arguments);
       return false;
     }
 
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,21 +14,21 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8b13bfc1d7d25cee4de55f332654fdba25b8460b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,21 +14,21 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8b13bfc1d7d25cee4de55f332654fdba25b8460b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "2a664cbb4d735d9c55fc5b6cf3e39a24bcfbe551", 
+    "revision": "05f40074f94c58315e6c353089d31e8e20ea3c1a", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/tooltool-manifests/linux32/releng.manifest
+++ b/b2g/config/tooltool-manifests/linux32/releng.manifest
@@ -8,18 +8,18 @@
 {
 "size": 80458572,
 "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
 "algorithm": "sha512",
 "filename": "gcc.tar.xz",
 "unpack": "True"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 },
 {
 "size": 31057326,
 "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
 "algorithm": "sha512",
 "filename": "moztt.tar.bz2",
--- a/b2g/config/tooltool-manifests/linux64/releng.manifest
+++ b/b2g/config/tooltool-manifests/linux64/releng.manifest
@@ -8,18 +8,18 @@
 {
 "size": 80458572,
 "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
 "algorithm": "sha512",
 "filename": "gcc.tar.xz",
 "unpack": "True"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 },
 {
 "size": 31057326,
 "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
 "algorithm": "sha512",
 "filename": "moztt.tar.bz2",
--- a/b2g/config/tooltool-manifests/macosx64/releng.manifest
+++ b/b2g/config/tooltool-manifests/macosx64/releng.manifest
@@ -10,18 +10,18 @@
 },
 {
 "size": 56126352,
 "digest": "e156e2a39abd5bf272ee30748a6825f22ddd27565b097c66662a2a6f2e9892bc5b4bf30a3552dffbe867dbfc39e7ee086e0b2cd7935f6ea216c0cf936178a88f",
 "algorithm": "sha512",
 "filename": "clang.tar.bz2"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 },
 {
 "size": 31057326,
 "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
 "algorithm": "sha512",
 "filename": "moztt.tar.bz2",
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0f7bb156969c5c838ff90ebc88d7691fc4d94310"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/dev/config/tooltool-manifests/linux64/releng.manifest
+++ b/b2g/dev/config/tooltool-manifests/linux64/releng.manifest
@@ -7,18 +7,18 @@
 },
 {
 "size": 80458572,
 "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
 "algorithm": "sha512",
 "filename": "gcc.tar.xz"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 },
 {
 "size": 31057326,
 "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
 "algorithm": "sha512",
 "filename": "moztt.tar.bz2",
--- a/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest
+++ b/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest
@@ -10,18 +10,18 @@
 },
 {
 "size": 59602619,
 "digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b",
 "algorithm": "sha512",
 "filename": "clang.tar.bz2"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 },
 {
 "size": 31057326,
 "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
 "algorithm": "sha512",
 "filename": "moztt.tar.bz2",
--- a/b2g/dev/config/tooltool-manifests/win32/releng.manifest
+++ b/b2g/dev/config/tooltool-manifests/win32/releng.manifest
@@ -7,18 +7,18 @@
 },
 {
 "size": 51,
 "digest": "c8e40edb314eeabfb92c77cf5ff9a7857033f15dd65a00349bcf9e3e5b75624afc71f733b2ff7e029c20a78313038409c2bd022bf7e5a7e0c487fc2c2d640986",
 "algorithm": "sha512",
 "filename": "setup.sh"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 },
 {
 "size": 31057326,
 "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
 "algorithm": "sha512",
 "filename": "moztt.tar.bz2",
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -318,17 +318,17 @@ pref("browser.urlbar.doubleClickSelectsA
 pref("browser.urlbar.doubleClickSelectsAll", false);
 #endif
 
 // Control autoFill behavior
 pref("browser.urlbar.autoFill", true);
 pref("browser.urlbar.autoFill.typed", true);
 
 // Use the new unifiedComplete component
-pref("browser.urlbar.unifiedcomplete", true);
+pref("browser.urlbar.unifiedcomplete", false);
 
 // 0: Match anywhere (e.g., middle of words)
 // 1: Match on word boundaries and then try matching anywhere
 // 2: Match only on word boundaries (e.g., after / or .)
 // 3: Match at the beginning of the url or title
 pref("browser.urlbar.matchBehavior", 1);
 pref("browser.urlbar.filter.javascript", true);
 
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -1103,24 +1103,24 @@ toolbarpaletteitem[dragover] {
 
 #customization-palette-container {
   display: flex;
   flex-direction: column;
 }
 
 #customization-palette:not([hidden]) {
   display: block;
-  flex: 1 1 main-size;
+  flex: 1 1 auto;
   overflow: auto;
   min-height: 3em;
 }
 
 #customization-footer-spacer,
 #customization-spacer {
-  flex: 1 1 main-size;
+  flex: 1 1 auto;
 }
 
 #customization-footer {
   display: flex;
   flex-shrink: 0;
   flex-wrap: wrap;
 }
 
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -408,17 +408,17 @@ support-files =
 [browser_selectTabAtIndex.js]
 [browser_star_hsts.js]
 [browser_subframe_favicons_not_used.js]
 [browser_tabDrop.js]
 skip-if = buildapp == 'mulet' || e10s
 [browser_tabMatchesInAwesomebar.js]
 skip-if = e10s # Bug 1093206 - need to re-enable tests relying on swapFrameLoaders et al for e10s (test calls gBrowser.swapBrowsersAndCloseOther)
 [browser_tabMatchesInAwesomebar_perwindowpb.js]
-skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory
+skip-if = e10s || true # Bug 1093373, Bug 1104755
 [browser_tab_drag_drop_perwindow.js]
 skip-if = buildapp == 'mulet'
 [browser_tab_dragdrop.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1093206 - need to re-enable tests relying on swapFrameLoaders et al for e10s (test calls gBrowser.swapBrowsersAndCloseOther)
 [browser_tab_dragdrop2.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1093206 - need to re-enable tests relying on swapFrameLoaders et al for e10s (test calls gBrowser.swapBrowsersAndCloseOther)
 [browser_tabbar_big_widgets.js]
 skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
--- a/browser/base/content/test/general/browser_action_keyword.js
+++ b/browser/base/content/test/general/browser_action_keyword.js
@@ -11,18 +11,20 @@ function* promise_first_result(inputText
 
   let firstResult = gURLBar.popup.richlistbox.firstChild;
   return firstResult;
 }
 
 
 add_task(function*() {
   // This test is only relevant if UnifiedComplete is enabled.
-  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
+  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) {
+    todo(false, "Stop supporting old autocomplete components.");
     return;
+  }
 
   let tab = gBrowser.selectedTab = gBrowser.addTab("about:mozilla");
   let tabs = [tab];
   registerCleanupFunction(() => {
     for (let tab of tabs)
       gBrowser.removeTab(tab);
     PlacesUtils.bookmarks.removeItem(itemId);
   });
--- a/browser/base/content/test/general/browser_action_searchengine.js
+++ b/browser/base/content/test/general/browser_action_searchengine.js
@@ -13,18 +13,20 @@ function* promise_first_result(inputText
   yield promisePopupShown(gURLBar.popup);
 
   let firstResult = gURLBar.popup.richlistbox.firstChild;
   return firstResult;
 }
 
 add_task(function* () {
   // This test is only relevant if UnifiedComplete is enabled.
-  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
+  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) {
+    todo(false, "Stop supporting old autocomplete components.");
     return;
+  }
 
   Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
                                        "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
   gOriginalEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
 
   let tab = gBrowser.selectedTab = gBrowser.addTab();
--- a/browser/base/content/test/general/browser_autocomplete_a11y_label.js
+++ b/browser/base/content/test/general/browser_autocomplete_a11y_label.js
@@ -10,18 +10,20 @@ function* check_a11y_label(inputText, ex
   ok(gURLBar.popup.richlistbox.children.length > 1, "Should get at least 2 results");
   let result = gURLBar.popup.richlistbox.children[1];
   is(result.getAttribute("type"), "action switchtab", "Expect right type attribute");
   is(result.label, expectedLabel, "Result a11y label should be as expected");
 }
 
 add_task(function*() {
   // This test is only relevant if UnifiedComplete is enabled.
-  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
+  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) {
+    todo(false, "Stop supporting old autocomplete components.");
     return;
+  }
 
   let tab = gBrowser.addTab("about:about");
   yield promiseTabLoaded(tab);
 
   let actionURL = makeActionURI("switchtab", {url: "about:about"}).spec;
   yield check_a11y_label("% about", "about:about " + actionURL + " Tab");
 
   gURLBar.popup.hidePopup();
--- a/browser/base/content/test/general/browser_autocomplete_autoselect.js
+++ b/browser/base/content/test/general/browser_autocomplete_autoselect.js
@@ -11,16 +11,22 @@ function* promiseAutoComplete(inputText)
   yield promiseSearchComplete();
 }
 
 function is_selected(index) {
   is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`);
 }
 
 add_task(function*() {
+  // This test is only relevant if UnifiedComplete is enabled.
+  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) {
+    todo(false, "Stop supporting old autocomplete components.");
+    return;
+  }
+
   registerCleanupFunction(promiseClearHistory);
 
   let visits = [];
   repeat(10, i => {
     visits.push({
       uri: makeURI("http://example.com/autocomplete/?" + i),
     });
   });
--- a/browser/base/content/test/general/browser_autocomplete_no_title.js
+++ b/browser/base/content/test/general/browser_autocomplete_no_title.js
@@ -9,18 +9,20 @@ function* check_title(inputText, expecte
 
   ok(gURLBar.popup.richlistbox.children.length > 1, "Should get at least 2 results");
   let result = gURLBar.popup.richlistbox.children[1];
   is(result._title.textContent, expectedTitle, "Result title should be as expected");
 }
 
 add_task(function*() {
   // This test is only relevant if UnifiedComplete is enabled.
-  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
+  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) {
+    todo(false, "Stop supporting old autocomplete components.");
     return;
+  }
 
   let uri = NetUtil.newURI("http://bug1060642.example.com/beards/are/pretty/great");
   yield PlacesTestUtils.addVisits([{uri: uri, title: ""}]);
 
   yield check_title("bug1060642", "bug1060642.example.com");
 
   gURLBar.popup.hidePopup();
   yield promisePopupHidden(gURLBar.popup);
--- a/browser/base/content/test/general/browser_bug1003461-switchtab-override.js
+++ b/browser/base/content/test/general/browser_bug1003461-switchtab-override.js
@@ -1,16 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(function* test_switchtab_override() {
   // This test is only relevant if UnifiedComplete is enabled.
-  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
+  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) {
+    todo(false, "Stop supporting old autocomplete components.");
     return;
+  }
 
   let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
 
   info("Opening first tab");
   let tab = gBrowser.addTab(testURL);
   let deferred = Promise.defer();
   whenTabLoaded(tab, deferred.resolve);
   yield deferred.promise;
--- a/browser/base/content/test/general/browser_bug1070778.js
+++ b/browser/base/content/test/general/browser_bug1070778.js
@@ -9,18 +9,20 @@ function* promiseAutoComplete(inputText)
 }
 
 function is_selected(index) {
   is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`);
 }
 
 add_task(function*() {
   // This test is only relevant if UnifiedComplete is enabled.
-  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
+  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) {
+    todo(false, "Stop supporting old autocomplete components.");
     return;
+  }
 
   registerCleanupFunction(() => {
     PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
   });
 
   let itemId =
     PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                          NetUtil.newURI("http://example.com/?q=%s"),
--- a/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js
+++ b/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js
@@ -49,17 +49,20 @@ function continue_test() {
       aCallback();
     });
   }
 
   test_autoFill("http://", "http://", function () {
     test_autoFill("http://au", "http://autofilltrimurl.com/", function () {
       test_autoFill("http://www.autofilltrimurl.com", "http://www.autofilltrimurl.com/", function () {
         // Now ensure selecting from the popup correctly trims.
-        is(gURLBar.controller.matchCount, 2, "Found the expected number of matches");
+        if (Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
+          is(gURLBar.controller.matchCount, 2, "Found the expected number of matches");
+        else
+          is(gURLBar.controller.matchCount, 1, "Found the expected number of matches");
         EventUtils.synthesizeKey("VK_DOWN", {});
         is(gURLBar.textValue, "www.autofilltrimurl.com/whatever", "trim was applied correctly");
         gURLBar.closePopup();
         waitForClearHistory(finish);
       });
     });
   });
 }
--- a/browser/config/tooltool-manifests/linux32/releng.manifest
+++ b/browser/config/tooltool-manifests/linux32/releng.manifest
@@ -7,14 +7,14 @@
 }, 
 {
 "size": 80458572,
 "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
 "algorithm": "sha512", 
 "filename": "gcc.tar.xz"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/linux64/releng.manifest
+++ b/browser/config/tooltool-manifests/linux64/releng.manifest
@@ -7,14 +7,14 @@
 }, 
 {
 "size": 80458572,
 "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
 "algorithm": "sha512", 
 "filename": "gcc.tar.xz"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/macosx64/releng.manifest
+++ b/browser/config/tooltool-manifests/macosx64/releng.manifest
@@ -10,14 +10,14 @@
 }, 
 {
 "size": 59602619, 
 "digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b", 
 "algorithm": "sha512", 
 "filename": "clang.tar.bz2"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/win32/releng.manifest
+++ b/browser/config/tooltool-manifests/win32/releng.manifest
@@ -7,14 +7,14 @@
 },
 {
 "size": 176,
 "digest": "2809058907ac5eefdc394113d2e4fe76ba559ac61c2eca2f88e7a12a74bdf44a15d9039fa8aa229f7362a14b67d67395063f68147ae098beac5dfcc78aff98da",
 "algorithm": "sha512",
 "filename": "setup.sh"
 },
 {
-"size": 168320,
-"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"size": 166506,
+"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2"
 }
 ]
--- a/browser/devtools/markupview/markup-view.css
+++ b/browser/devtools/markupview/markup-view.css
@@ -30,17 +30,17 @@
    * the editor covers up any content to the left (including expander arrows
    * and hover effects). */
   margin-left: -1000em;
   padding-left: 1000em;
 }
 
 .html-editor-inner {
   border: solid .1px;
-  flex: 1 1 main-size;
+  flex: 1 1 auto;
 
   /* Keep the editor away from the markup view floating scrollbars */
   -moz-margin-end: 12px;
 }
 
 .html-editor iframe {
   height: 100%;
   width: 100%;
--- a/browser/devtools/responsivedesign/responsivedesign.jsm
+++ b/browser/devtools/responsivedesign/responsivedesign.jsm
@@ -477,63 +477,63 @@ ResponsiveUI.prototype = {
   // FxOS custom controls
   buildPhoneUI: function () {
     this.stack.classList.add("fxos-mode");
 
     let sleepButton = this.chromeDoc.createElement("button");
     sleepButton.className = "devtools-responsiveui-sleep-button";
     sleepButton.setAttribute("top", 0);
     sleepButton.setAttribute("right", 0);
-    sleepButton.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "sleep-button-press"});
+    sleepButton.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "Power"});
     });
-    sleepButton.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "sleep-button-release"});
+    sleepButton.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "Power"});
     });
     this.stack.appendChild(sleepButton);
 
     let volumeButtons = this.chromeDoc.createElement("vbox");
     volumeButtons.className = "devtools-responsiveui-volume-buttons";
     volumeButtons.setAttribute("top", 0);
     volumeButtons.setAttribute("left", 0);
 
     let volumeUp = this.chromeDoc.createElement("button");
     volumeUp.className = "devtools-responsiveui-volume-up-button";
-    volumeUp.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-up-button-press"});
+    volumeUp.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "VolumeUp"});
     });
-    volumeUp.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-up-button-release"});
+    volumeUp.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "VolumeUp"});
     });
 
     let volumeDown = this.chromeDoc.createElement("button");
     volumeDown.className = "devtools-responsiveui-volume-down-button";
-    volumeDown.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-down-button-press"});
+    volumeDown.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "VolumeDown"});
     });
-    volumeDown.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-down-button-release"});
+    volumeDown.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "VolumeDown"});
     });
 
     volumeButtons.appendChild(volumeUp);
     volumeButtons.appendChild(volumeDown);
     this.stack.appendChild(volumeButtons);
 
     let bottomToolbar = this.chromeDoc.createElement("toolbar");
     bottomToolbar.className = "devtools-responsiveui-hardware-buttons";
     bottomToolbar.setAttribute("align", "center");
     bottomToolbar.setAttribute("pack", "center");
 
     let homeButton = this.chromeDoc.createElement("toolbarbutton");
     homeButton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-home-button";
-    homeButton.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "home-button-press"});
+    homeButton.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "Home"});
     });
-    homeButton.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "home-button-release"});
+    homeButton.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "Home"});
     });
     bottomToolbar.appendChild(homeButton);
     this.bottomToolbar = bottomToolbar;
     this.container.appendChild(bottomToolbar);
   },
 
   /**
    * Validate and apply any user input on the editable menulist
--- a/browser/metro/theme/config.css
+++ b/browser/metro/theme/config.css
@@ -52,17 +52,17 @@ body {
     border: none;
     background-image: none;
     background-color: transparent;
     display: inline-block;
     width: 12em;
     min-width: 0;
     color: #000000;
     opacity: 1;
-    flex: 1 1 main-size;
+    flex: 1 1 auto;
 }
 
 #filter-input:-moz-placeholder {
     color: rgba(255,255,255,0.5);
 }
 
 .toolbar input {
     display: inline-block;
@@ -188,17 +188,17 @@ li {
     text-align: left;
     text-overflow: ellipsis;
     overflow: hidden;
     background-image: none;
 }
 
 .pref-value {
     color: rgba(0,0,0,0.5);
-    flex: 1 1 main-size;
+    flex: 1 1 auto;
     border: none;
     -moz-appearance: none;
     background-image: none;
     background-color: transparent;
 }
 
 .pref-name[locked] {
     padding-right: 20px;
@@ -222,37 +222,37 @@ li {
 .pref-item-line {
     border-top: 1px solid rgba(0,0,0,0.05);
     color: rgba(0,0,0,0.5);
     display: flex;
     flex-direction: row;
 }
 
 #new-pref-value-boolean {
-    flex: 1 1 main-size;
+    flex: 1 1 auto;
 }
 
 /* Disable newPref dialog spinbuttons, use custom version from Android */
 /* Filed Bug 962359 to enhance the default spinbutton style to be touch-friendly */
 #new-pref-value-int {
     -moz-appearance: textfield;
 }
 
 #new-pref-container .pref-button.toggle {
     display: inline-block;
     opacity: 1;
-    flex: 0 1 main-size;
+    flex: 0 1 auto;
     float: right;
 }
 
 #new-pref-container .pref-button.cancel,
 #new-pref-container .pref-button.create {
     display: inline-block;
     opacity: 1;
-    flex: 1 1 main-size;
+    flex: 1 1 auto;
 }
 
 .pref-item-line {
     pointer-events: none;
 }
 
 #new-pref-container .pref-item-line,
 .pref-item.selected .pref-item-line,
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -250,17 +250,17 @@ panelview:not([mainview]) .toolbarbutton
 }
 
 .cui-widget-panel.cui-widget-panelWithFooter > .panel-arrowcontainer > .panel-arrowcontent {
   padding-bottom: 0;
 }
 
 #PanelUI-contents {
   display: block;
-  flex: 1 0 main-size;
+  flex: 1 0 auto;
   margin-left: auto;
   margin-right: auto;
   padding: .5em 0;
   max-width: @menuPanelWidth@;
 }
 
 #PanelUI-contents-scroller {
   overflow-y: auto;
--- a/browser/themes/shared/devtools/webconsole.inc.css
+++ b/browser/themes/shared/devtools/webconsole.inc.css
@@ -119,17 +119,17 @@ a {
 
 .message-body {
   white-space: pre-wrap;
   word-wrap: break-word;
 }
 
 .message-flex-body > .message-body {
   display: block;
-  flex: 1 1 main-size;
+  flex: 1 1 auto;
   vertical-align: middle;
 }
 
 .message-flex-body > .message-location {
   margin-top: 0;
 }
 
 .jsterm-input-container {
@@ -234,17 +234,17 @@ a {
   display: flex;
 }
 
 .message[category=network] .method {
   flex: none;
 }
 
 .message[category=network]:not(.navigation-marker) .url {
-  flex: 1 1 main-size;
+  flex: 1 1 auto;
   /* Make sure the URL is very small initially, let flex change width as needed. */
   width: 100px;
   min-width: 5em;
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
 }
 
@@ -452,17 +452,17 @@ a {
 
 .stacktrace li {
   display: flex;
   margin: 0;
 }
 
 .stacktrace .function {
   display: block;
-  flex: 1 1 main-size;
+  flex: 1 1 auto;
 }
 
 .cm-s-mozilla a[class] {
   font-style: italic;
   text-decoration: none;
 }
 
 .cm-s-mozilla a[class]:hover,
--- a/build/autoconf/toolchain.m4
+++ b/build/autoconf/toolchain.m4
@@ -156,16 +156,17 @@ unset ac_cv_prog_CXX
 AC_PROG_CXX
 
 AC_CHECK_PROGS(RANLIB, "${target_alias}-ranlib" "${target}-ranlib", :)
 AC_CHECK_PROGS(AR, "${target_alias}-ar" "${target}-ar", :)
 MOZ_PATH_PROGS(AS, "${target_alias}-as" "${target}-as", :)
 AC_CHECK_PROGS(LD, "${target_alias}-ld" "${target}-ld", :)
 AC_CHECK_PROGS(STRIP, "${target_alias}-strip" "${target}-strip", :)
 AC_CHECK_PROGS(WINDRES, "${target_alias}-windres" "${target}-windres", :)
+AC_CHECK_PROGS(OTOOL, "${target_alias}-otool" "${target}-otool", :)
 AC_DEFINE(CROSS_COMPILE)
 CROSS_COMPILE=1
 
 dnl If we cross compile for ppc on Mac OS X x86, cross_compiling will
 dnl dnl have erroneously been set to "no", because the x86 build host is
 dnl dnl able to run ppc code in a translated environment, making a cross
 dnl dnl compiler appear native.  So we override that here.
 cross_compiling=yes
--- a/build/macosx/universal/mozconfig.common
+++ b/build/macosx/universal/mozconfig.common
@@ -37,17 +37,18 @@ if test "$MOZ_BUILD_APP" = "i386" -o "$M
   CXX="$CXX -arch $TARGET_CPU"
 
   # These must be set for cross builds, and don't hurt straight builds.
   RANLIB=ranlib
   AR=ar
   AS=$CC
   LD=ld
   STRIP="strip"
+  OTOOL="otool"
 
   # Each per-CPU build should be entirely oblivious to the fact that a
   # universal binary will be produced.  The exception is packager.mk, which
   # needs to know to look for universal bits when building the .dmg.
   UNIVERSAL_BINARY=1
 
-  export CC CXX HOST_CC HOST_CXX RANLIB AR AS LD STRIP
+  export CC CXX HOST_CC HOST_CXX RANLIB AR AS LD STRIP OTOOL
 fi
 fi
--- a/build/unix/rewrite_asan_dylib.py
+++ b/build/unix/rewrite_asan_dylib.py
@@ -1,16 +1,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import sys
 import os
 import subprocess
 import shutil
+from buildconfig import substs
 
 '''
 Scans the given directories for binaries referencing the AddressSanitizer
 runtime library, copies it to the main directory and rewrites binaries to not
 reference it with absolute paths but with @executable_path instead.
 '''
 
 # This is the dylib we're looking for
@@ -23,17 +24,17 @@ def scan_directory(path):
         for filename in files:
             filename = os.path.join(root, filename)
 
             # Skip all files that aren't either dylibs or executable
             if not (filename.endswith('.dylib') or os.access(filename, os.X_OK)):
                 continue
 
             try:
-                otoolOut = subprocess.check_output(['otool', '-L', filename])
+                otoolOut = subprocess.check_output([substs['OTOOL'], '-L', filename])
             except:
                 # Errors are expected on non-mach executables, ignore them and continue
                 continue
 
             for line in otoolOut.splitlines():
                 if line.find(DYLIB_NAME) != -1:
                     absDylibPath = line.split()[0]
 
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -43,25 +43,27 @@ HEADERS_TARGET := export
 INSTALL_TARGETS += HEADERS
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 HOST_CFLAGS += -DUNICODE -D_UNICODE
 
 ifndef JS_STANDALONE
+ifndef MOZ_PROFILE_USE
 # Generate a new buildid every time we "export" in config... that's only
 # supposed to be once per-build!
 export::
 ifdef MOZ_BUILD_DATE
 	printf '%s' $(MOZ_BUILD_DATE) > buildid
 else
 	$(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-buildid > buildid
 endif
 endif
+endif
 
 ifdef WRAP_SYSTEM_INCLUDES
 export-preqs = \
   $(call mkdir_deps,system_wrappers) \
   $(NULL)
 
 export:: $(export-preqs)
 	$(PYTHON) -m mozbuild.action.preprocessor $(DEFINES) $(ACDEFINES) \
@@ -101,17 +103,17 @@ STL_WRAPPERS_SENTINEL = $(DIST)/stl_wrap
 
 export:: $(STL_WRAPPERS_SENTINEL)
 
 GARBAGE += $(STL_WRAPPERS_SENTINEL)
 GARBAGE_DIRS += stl_wrappers
 endif
 
 GARBAGE += \
-  $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES) buildid $(srcdir)/*.pyc *.pyc
+  $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES) $(srcdir)/*.pyc *.pyc
 
 FORCE:
 
 ifndef JS_STANDALONE
 check-preqs += check-jar-mn
 endif
 check-preqs += check-makefiles
 
--- a/configure.in
+++ b/configure.in
@@ -365,16 +365,17 @@ else
     esac
     AC_PROG_CXX
     AC_PROG_RANLIB
     MOZ_PATH_PROGS(AS, $AS as, $CC)
     AC_CHECK_PROGS(AR, ar, :)
     AC_CHECK_PROGS(LD, ld, :)
     AC_CHECK_PROGS(STRIP, strip, :)
     AC_CHECK_PROGS(WINDRES, windres, :)
+    AC_CHECK_PROGS(OTOOL, otool, :)
     if test -z "$HOST_CC"; then
         HOST_CC="$CC"
     fi
     if test -z "$HOST_CFLAGS"; then
         HOST_CFLAGS="$CFLAGS"
     fi
     if test -z "$HOST_CXX"; then
         HOST_CXX="$CXX"
@@ -7168,22 +7169,22 @@ elif test -n "$MOZ_REPLACE_MALLOC"; then
             ac_cv_weak_dynamic_linking,
             [echo 'extern void foo() __attribute__((weak_import));int bar() { if (foo) foo(); return 0; }' > conftest.c
              if AC_TRY_COMMAND([${CC-cc} -o conftest${DLL_SUFFIX} $CFLAGS -dynamiclib $LDFLAGS -Wl,-U,_foo conftest.c $LIBS 1>&5]) &&
                 test -s conftest${DLL_SUFFIX}; then
                  dnl There are several ways the linker can put link edit rules in a binary:
                  dnl - classic info only (for OSX < 10.6)
                  dnl - dyld info only
                  dnl - both
-                 if otool -l conftest${DLL_SUFFIX} 2> /dev/null | grep "LC_DYLD_INFO_ONLY" > /dev/null; then
+                 if "$OTOOL" -l conftest${DLL_SUFFIX} 2> /dev/null | grep "LC_DYLD_INFO_ONLY" > /dev/null; then
                      _CLASSIC_INFO=
                  else
                      _CLASSIC_INFO=1
                  fi
-                 if otool -l conftest${DLL_SUFFIX} 2> /dev/null | grep "LC_DYLD_INFO" > /dev/null; then
+                 if "$OTOOL" -l conftest${DLL_SUFFIX} 2> /dev/null | grep "LC_DYLD_INFO" > /dev/null; then
                      _DYLD_INFO=1
                  else
                      _DYLD_INFO=
                  fi
                  dnl With classic info, we need to build with -flat_namespace.
                  dnl With dyld info, Xcode 4.5 does the right thing without additional flags,
                  dnl but Xcode < 4.5 requires a dummy library and -flat_namespace because it
                  dnl forgets to set the weak flag in the dyld info.
--- a/dom/base/MessagePort.cpp
+++ b/dom/base/MessagePort.cpp
@@ -120,17 +120,17 @@ PostMessageReadStructuredClone(JSContext
       // called because the static analysis thinks dereferencing XPCOM objects
       // can GC (because in some cases it can!), and a return statement with a
       // JSObject* type means that JSObject* is on the stack as a raw pointer
       // while destructors are running.
       JS::Rooted<JS::Value> val(cx);
       {
         nsRefPtr<File> blob = new File(scInfo->mPort->GetParentObject(),
                                              blobImpl);
-        if (!WrapNewBindingObject(cx, blob, &val)) {
+        if (!GetOrCreateDOMReflector(cx, blob, &val)) {
           return nullptr;
         }
       }
 
       return &val.toObject();
     }
   }
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -2051,17 +2051,17 @@ Navigator::DoResolve(JSContext* aCx, JS:
           FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false);
           return true;
         }
       }
 
       nsISupports* existingObject = mCachedResolveResults.GetWeak(name);
       if (existingObject) {
         // We know all of our WebIDL objects here are wrappercached, so just go
-        // ahead and WrapObject() them.  We can't use WrapNewBindingObject,
+        // ahead and WrapObject() them.  We can't use GetOrCreateDOMReflector,
         // because we don't have the concrete type.
         JS::Rooted<JS::Value> wrapped(aCx);
         if (!dom::WrapObject(aCx, existingObject, &wrapped)) {
           return false;
         }
         domObject = &wrapped.toObject();
       } else {
         domObject = construct(aCx, naviObj);
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6036,17 +6036,17 @@ nsContentUtils::CreateBlobBuffer(JSConte
   if (blobData) {
     memcpy(blobData, aData.BeginReading(), blobLen);
     blob = mozilla::dom::File::CreateMemoryFile(aParent, blobData, blobLen,
                                                 EmptyString());
   } else {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  if (!WrapNewBindingObject(aCx, blob, aBlob)) {
+  if (!GetOrCreateDOMReflector(aCx, blob, aBlob)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 void
 nsContentUtils::StripNullChars(const nsAString& aInStr, nsAString& aOutStr)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7907,17 +7907,17 @@ PostMessageReadStructuredClone(JSContext
       // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
       // called because the static analysis thinks dereferencing XPCOM objects
       // can GC (because in some cases it can!), and a return statement with a
       // JSObject* type means that JSObject* is on the stack as a raw pointer
       // while destructors are running.
       JS::Rooted<JS::Value> val(cx);
       {
         nsRefPtr<File> blob = new File(scInfo->window, blobImpl);
-        if (!WrapNewBindingObject(cx, blob, &val)) {
+        if (!GetOrCreateDOMReflector(cx, blob, &val)) {
           return nullptr;
         }
       }
 
       return &val.toObject();
     }
   }
 
@@ -11066,16 +11066,20 @@ nsGlobalWindow::HandleIdleActiveEvent()
 nsGlobalWindow::SlowScriptResponse
 nsGlobalWindow::ShowSlowScriptDialog()
 {
   MOZ_ASSERT(IsInnerWindow());
 
   nsresult rv;
   AutoJSContext cx;
 
+  if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
+    return KillSlowScript;
+  }
+
   // If it isn't safe to run script, then it isn't safe to bring up the prompt
   // (since that spins the event loop). In that (rare) case, we just kill the
   // script and report a warning.
   if (!nsContentUtils::IsSafeToRunScript()) {
     JS_ReportWarning(cx, "A long running script was terminated");
     return KillSlowScript;
   }
 
@@ -14025,17 +14029,17 @@ nsGlobalWindow::GetConsole(JSContext* aC
                            JS::MutableHandle<JS::Value> aConsole)
 {
   ErrorResult rv;
   nsRefPtr<Console> console = GetConsole(rv);
   if (rv.Failed()) {
     return rv.ErrorCode();
   }
 
-  if (!WrapNewBindingObject(aCx, console, aConsole)) {
+  if (!GetOrCreateDOMReflector(aCx, console, aConsole)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::SetConsole(JSContext* aCx, JS::Handle<JS::Value> aValue)
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -332,17 +332,17 @@ nsJSUtils::EvaluateString(JSContext* aCx
 /* static */
 bool
 nsJSUtils::GetScopeChainForElement(JSContext* aCx,
                                    mozilla::dom::Element* aElement,
                                    JS::AutoObjectVector& aScopeChain)
 {
   for (nsINode* cur = aElement; cur; cur = cur->GetScopeChainParent()) {
     JS::RootedValue val(aCx);
-    if (!WrapNewBindingObject(aCx, cur, &val)) {
+    if (!GetOrCreateDOMReflector(aCx, cur, &val)) {
       return false;
     }
 
     if (!aScopeChain.append(&val.toObject())) {
       return false;
     }
   }
 
--- a/dom/base/nsXMLHttpRequest.cpp
+++ b/dom/base/nsXMLHttpRequest.cpp
@@ -1009,17 +1009,17 @@ nsXMLHttpRequest::GetResponse(JSContext*
       }
     }
 
     if (!mResponseBlob) {
       aResponse.setNull();
       return;
     }
 
-    WrapNewBindingObject(aCx, mResponseBlob, aResponse);
+    GetOrCreateDOMReflector(aCx, mResponseBlob, aResponse);
     return;
   }
   case XML_HTTP_RESPONSE_TYPE_DOCUMENT:
   {
     if (!(mState & XML_HTTP_REQUEST_DONE) || !mResponseXML) {
       aResponse.setNull();
       return;
     }
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2528,17 +2528,17 @@ ConvertExceptionToPromise(JSContext* cx,
   if (rv.Failed()) {
     // We just give up.  Make sure to not leak memory on the
     // ErrorResult, but then just put the original exception back.
     ThrowMethodFailedWithDetails(cx, rv, "", "");
     JS_SetPendingException(cx, exn);
     return false;
   }
 
-  return WrapNewBindingObject(cx, promise, rval);
+  return GetOrCreateDOMReflector(cx, promise, rval);
 }
 
 /* static */
 void
 CreateGlobalOptions<nsGlobalWindow>::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
 {
   xpc::TraceXPCGlobal(aTrc, aObj);
 }
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -850,28 +850,35 @@ MaybeWrapValue(JSContext* cx, JS::Mutabl
 
   if (!rval.isObject()) {
     return true;
   }
 
   return MaybeWrapObjectValue(cx, rval);
 }
 
-// Create a JSObject wrapping "value", if there isn't one already, and store it
-// in rval.  "value" must be a concrete class that implements a
-// GetWrapperPreserveColor() which can return its existing wrapper, if any, and
-// a WrapObject() which will try to create a wrapper. Typically, this is done by
-// having "value" inherit from nsWrapperCache.
-//
-// The value stored in rval will be ready to be exposed to whatever JS
-// is running on cx right now.  In particular, it will be in the
-// compartment of cx, and outerized as needed.
+namespace binding_detail {
+enum GetOrCreateReflectorWrapBehavior {
+  eWrapIntoContextCompartment,
+  eDontWrapIntoContextCompartment
+};
+
 template <class T>
+struct TypeNeedsOuterization
+{
+  // We only need to outerize Window objects, so anything inheriting from
+  // nsGlobalWindow (which inherits from EventTarget itself).
+  static const bool value =
+    IsBaseOf<nsGlobalWindow, T>::value || IsSame<EventTarget, T>::value;
+};
+
+template <class T, GetOrCreateReflectorWrapBehavior wrapBehavior>
 MOZ_ALWAYS_INLINE bool
-WrapNewBindingObject(JSContext* cx, T* value, JS::MutableHandle<JS::Value> rval)
+DoGetOrCreateDOMReflector(JSContext* cx, T* value,
+                          JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(value);
   JSObject* obj = value->GetWrapperPreserveColor();
   // We can get rid of this when we remove support for hasXPConnectImpls.
   bool couldBeDOMBinding = CouldBeDOMBinding(value);
   if (obj) {
     JS::ExposeObjectToActiveJS(obj);
   } else {
@@ -905,24 +912,63 @@ WrapNewBindingObject(JSContext* cx, T* v
   }
 #endif
 
   rval.set(JS::ObjectValue(*obj));
 
   bool sameCompartment =
     js::GetObjectCompartment(obj) == js::GetContextCompartment(cx);
   if (sameCompartment && couldBeDOMBinding) {
-    // We only need to outerize Window objects, so anything inheriting from
-    // nsGlobalWindow (which inherits from EventTarget itself).
-    return IsBaseOf<nsGlobalWindow, T>::value || IsSame<EventTarget, T>::value ?
-           TryToOuterize(cx, rval) : true;
+    return TypeNeedsOuterization<T>::value ? TryToOuterize(cx, rval) : true;
+  }
+
+  if (wrapBehavior == eDontWrapIntoContextCompartment) {
+    if (TypeNeedsOuterization<T>::value) {
+      JSAutoCompartment ac(cx, obj);
+      return TryToOuterize(cx, rval);
+    }
+
+    return true;
   }
 
   return JS_WrapValue(cx, rval);
 }
+} // namespace binding_detail
+
+// Create a JSObject wrapping "value", if there isn't one already, and store it
+// in rval.  "value" must be a concrete class that implements a
+// GetWrapperPreserveColor() which can return its existing wrapper, if any, and
+// a WrapObject() which will try to create a wrapper. Typically, this is done by
+// having "value" inherit from nsWrapperCache.
+//
+// The value stored in rval will be ready to be exposed to whatever JS
+// is running on cx right now.  In particular, it will be in the
+// compartment of cx, and outerized as needed.
+template <class T>
+MOZ_ALWAYS_INLINE bool
+GetOrCreateDOMReflector(JSContext* cx, T* value,
+                        JS::MutableHandle<JS::Value> rval)
+{
+  using namespace binding_detail;
+  return DoGetOrCreateDOMReflector<T, eWrapIntoContextCompartment>(cx, value,
+                                                                   rval);
+}
+
+// Like GetOrCreateDOMReflector but doesn't wrap into the context compartment,
+// and hence does not actually require cx to be in a compartment.
+template <class T>
+MOZ_ALWAYS_INLINE bool
+GetOrCreateDOMReflectorNoWrap(JSContext* cx, T* value,
+                              JS::MutableHandle<JS::Value> rval)
+{
+  using namespace binding_detail;
+  return DoGetOrCreateDOMReflector<T, eDontWrapIntoContextCompartment>(cx,
+                                                                       value,
+                                                                       rval);
+}
 
 // Create a JSObject wrapping "value", for cases when "value" is a
 // non-wrapper-cached object using WebIDL bindings.  "value" must implement a
 // WrapObject() method taking a JSContext and a scope.
 template <class T>
 inline bool
 WrapNewBindingNonWrapperCachedObject(JSContext* cx,
                                      JS::Handle<JSObject*> scopeArg,
@@ -1274,18 +1320,18 @@ XPCOMObjectToJsval(JSContext* cx, JS::Ha
 
 // Special-cased wrapping for variants
 bool
 VariantToJsval(JSContext* aCx, nsIVariant* aVariant,
                JS::MutableHandle<JS::Value> aRetval);
 
 // Wrap an object "p" which is not using WebIDL bindings yet.  This _will_
 // actually work on WebIDL binding objects that are wrappercached, but will be
-// much slower than WrapNewBindingObject.  "cache" must either be null or be the
-// nsWrapperCache for "p".
+// much slower than GetOrCreateDOMReflector.  "cache" must either be null or be
+// the nsWrapperCache for "p".
 template<class T>
 inline bool
 WrapObject(JSContext* cx, T* p, nsWrapperCache* cache, const nsIID* iid,
            JS::MutableHandle<JS::Value> rval)
 {
   if (xpc_FastGetCachedWrapper(cx, cache, rval))
     return true;
   qsObjectHelper helper(p, cache);
@@ -1578,54 +1624,86 @@ WrapCallThisObject<JS::Rooted<JSObject*>
 
   if (!JS_WrapObject(cx, &obj)) {
     return nullptr;
   }
 
   return obj;
 }
 
-// Helper for calling WrapNewBindingObject with smart pointers
+// Helper for calling GetOrCreateDOMReflector with smart pointers
 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
 template <class T, bool isSmartPtr=HasgetMember<T>::Value>
-struct WrapNewBindingObjectHelper
+struct GetOrCreateDOMReflectorHelper
 {
-  static inline bool Wrap(JSContext* cx, const T& value,
-                          JS::MutableHandle<JS::Value> rval)
+  static inline bool GetOrCreate(JSContext* cx, const T& value,
+                                 JS::MutableHandle<JS::Value> rval)
   {
-    return WrapNewBindingObject(cx, value.get(), rval);
+    return GetOrCreateDOMReflector(cx, value.get(), rval);
   }
 };
 
 template <class T>
-struct WrapNewBindingObjectHelper<T, false>
+struct GetOrCreateDOMReflectorHelper<T, false>
 {
-  static inline bool Wrap(JSContext* cx, T& value,
-                          JS::MutableHandle<JS::Value> rval)
+  static inline bool GetOrCreate(JSContext* cx, T& value,
+                                 JS::MutableHandle<JS::Value> rval)
   {
-    return WrapNewBindingObject(cx, &value, rval);
+    return GetOrCreateDOMReflector(cx, &value, rval);
   }
 };
 
 template<class T>
 inline bool
-WrapNewBindingObject(JSContext* cx, T& value, JS::MutableHandle<JS::Value> rval)
+GetOrCreateDOMReflector(JSContext* cx, T& value,
+                        JS::MutableHandle<JS::Value> rval)
 {
-  return WrapNewBindingObjectHelper<T>::Wrap(cx, value, rval);
+  return GetOrCreateDOMReflectorHelper<T>::GetOrCreate(cx, value, rval);
 }
 
-// We need this version of WrapNewBindingObject for codegen, so it'll have the
-// same signature as WrapNewBindingNonWrapperCachedObject and
+// We need this version of GetOrCreateDOMReflector for codegen, so it'll have
+// the same signature as WrapNewBindingNonWrapperCachedObject and
 // WrapNewBindingNonWrapperCachedOwnedObject, which still need the scope.
 template<class T>
 inline bool
-WrapNewBindingObject(JSContext* cx, JS::Handle<JSObject*> scope, T& value,
-                     JS::MutableHandle<JS::Value> rval)
+GetOrCreateDOMReflector(JSContext* cx, JS::Handle<JSObject*> scope, T& value,
+                        JS::MutableHandle<JS::Value> rval)
+{
+  return GetOrCreateDOMReflector(cx, value, rval);
+}
+
+// Helper for calling GetOrCreateDOMReflectorNoWrap with smart pointers
+// (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
+template <class T, bool isSmartPtr=HasgetMember<T>::Value>
+struct GetOrCreateDOMReflectorNoWrapHelper
 {
-  return WrapNewBindingObject(cx, value, rval);
+  static inline bool GetOrCreate(JSContext* cx, const T& value,
+                                 JS::MutableHandle<JS::Value> rval)
+  {
+    return GetOrCreateDOMReflectorNoWrap(cx, value.get(), rval);
+  }
+};
+
+template <class T>
+struct GetOrCreateDOMReflectorNoWrapHelper<T, false>
+{
+  static inline bool GetOrCreate(JSContext* cx, T& value,
+                                 JS::MutableHandle<JS::Value> rval)
+  {
+    return GetOrCreateDOMReflectorNoWrap(cx, &value, rval);
+  }
+};
+
+template<class T>
+inline bool
+GetOrCreateDOMReflectorNoWrap(JSContext* cx, T& value,
+                              JS::MutableHandle<JS::Value> rval)
+{
+  return
+    GetOrCreateDOMReflectorNoWrapHelper<T>::GetOrCreate(cx, value, rval);
 }
 
 template <class T>
 inline JSObject*
 GetCallbackFromCallbackObject(T* aObj)
 {
   return aObj->Callback();
 }
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -412,17 +412,17 @@ DOMInterfaces = {
 },
 
 'Event': {
     'implicitJSContext': [ 'defaultPrevented', 'preventDefault' ],
 },
 
 'EventTarget': {
     # When we get rid of hasXPConnectImpls, we can get rid of the
-    # couldBeDOMBinding stuff in WrapNewBindingObject.
+    # couldBeDOMBinding stuff in GetOrCreateDOMReflector.
     #
     # We can also get rid of the UnwrapArg bits in
     # the dom QueryInterface (in BindingUtils.cpp) at that point.
     'hasXPConnectImpls': True,
     'concrete': False,
     'jsImplParent': 'mozilla::DOMEventTargetHelper'
 },
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1730,17 +1730,17 @@ class CGConstructNavigatorObject(CGAbstr
             JS::Rooted<JS::Value> v(aCx);
             {  // Scope to make sure |result| goes out of scope while |v| is rooted
               nsRefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
               rv.WouldReportJSException();
               if (rv.Failed()) {
                 ThrowMethodFailedWithDetails(aCx, rv, "${descriptorName}", "navigatorConstructor");
                 return nullptr;
               }
-              if (!WrapNewBindingObject(aCx, result, &v)) {
+              if (!GetOrCreateDOMReflector(aCx, result, &v)) {
                 //XXX Assertion disabled for now, see bug 991271.
                 MOZ_ASSERT(true || JS_IsExceptionPending(aCx));
                 return nullptr;
               }
             }
             return &v.toObject();
             """,
             descriptorName=self.descriptor.name)
@@ -5759,17 +5759,17 @@ def getWrapTemplateForType(type, descrip
                             indent(setNull()) +
                             "}\n")
         else:
             wrappingCode = ""
 
         if not descriptor.interface.isExternal() and not descriptor.skipGen:
             if descriptor.wrapperCache:
                 assert descriptor.nativeOwnership != 'owned'
-                wrapMethod = "WrapNewBindingObject"
+                wrapMethod = "GetOrCreateDOMReflector"
             else:
                 if not returnsNewObject:
                     raise MethodNotNewObjectError(descriptor.interface.identifier.name)
                 if descriptor.nativeOwnership == 'owned':
                     wrapMethod = "WrapNewBindingNonWrapperCachedOwnedObject"
                 else:
                     wrapMethod = "WrapNewBindingNonWrapperCachedObject"
             wrap = "%s(cx, ${obj}, %s, ${jsvalHandle})" % (wrapMethod, result)
@@ -5849,25 +5849,25 @@ def getWrapTemplateForType(type, descrip
                 indent(wrapCode) +
                 "} else {\n" +
                 indent(setNull()) +
                 "}\n")
         wrapCode = wrapCode % {"result": result}
         return wrapCode, False
 
     if type.isAny():
-        # See comments in WrapNewBindingObject explaining why we need
+        # See comments in GetOrCreateDOMReflector explaining why we need
         # to wrap here.
         # NB: _setValue(..., type-that-is-any) calls JS_WrapValue(), so is fallible
         head = "JS::ExposeValueToActiveJS(%s);\n" % result
         return (head + _setValue(result, wrapAsType=type), False)
 
     if (type.isObject() or (type.isSpiderMonkeyInterface() and
                             not typedArraysAreStructs)):
-        # See comments in WrapNewBindingObject explaining why we need
+        # See comments in GetOrCreateDOMReflector explaining why we need
         # to wrap here.
         if type.nullable():
             toValue = "%s"
             setter = setObjectOrNull
             head = """if (%s) {
               JS::ExposeObjectToActiveJS(%s);
             }
             """ % (result, result)
@@ -5890,17 +5890,17 @@ def getWrapTemplateForType(type, descrip
                                                        typedArraysAreStructs)
         return ("if (%s.IsNull()) {\n" % result +
                 indent(setNull()) +
                 "}\n" +
                 recTemplate, recInfal)
 
     if type.isSpiderMonkeyInterface():
         assert typedArraysAreStructs
-        # See comments in WrapNewBindingObject explaining why we need
+        # See comments in GetOrCreateDOMReflector explaining why we need
         # to wrap here.
         # NB: setObject(..., some-object-type) calls JS_WrapValue(), so is fallible
         return (setObject("*%s.Obj()" % result,
                           wrapAsType=type), False)
 
     if type.isUnion():
         return (wrapAndSetPtr("%s.ToJSVal(cx, ${obj}, ${jsvalHandle})" % result),
                 False)
@@ -13250,17 +13250,17 @@ class CGJSImplMethod(CGJSImplMember):
             constructorArgs.append("js::GetObjectCompartment(scopeObj)")
             initCall = fill(
                 """
                 // Wrap the object before calling __Init so that __DOM_IMPL__ is available.
                 nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(window);
                 JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
                 MOZ_ASSERT(js::IsObjectInContextCompartment(scopeObj, cx));
                 JS::Rooted<JS::Value> wrappedVal(cx);
-                if (!WrapNewBindingObject(cx, impl, &wrappedVal)) {
+                if (!GetOrCreateDOMReflector(cx, impl, &wrappedVal)) {
                   //XXX Assertion disabled for now, see bug 991271.
                   MOZ_ASSERT(true || JS_IsExceptionPending(cx));
                   aRv.Throw(NS_ERROR_UNEXPECTED);
                   return nullptr;
                 }
                 // Initialize the object with the constructor arguments.
                 impl->mImpl->__Init(${args});
                 if (aRv.Failed()) {
@@ -13540,17 +13540,17 @@ class CGJSImplClass(CGBindingImplClass):
             }
             nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global.GetAsSupports());
             if (!window) {
               return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of ${ifaceName}._create", "Window");
             }
             JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
             nsRefPtr<${implName}> impl = new ${implName}(arg, window);
             MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
-            return WrapNewBindingObject(cx, impl, args.rval());
+            return GetOrCreateDOMReflector(cx, impl, args.rval());
             """,
             ifaceName=self.descriptor.interface.identifier.name,
             implName=self.descriptor.name)
 
 
 def isJSImplementedDescriptor(descriptorProvider):
     return (isinstance(descriptorProvider, Descriptor) and
             descriptorProvider.interface.isJSImplemented())
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -71,17 +71,17 @@ ThrowExceptionObject(JSContext* aCx, Exc
   }
 
   JS::Rooted<JSObject*> glob(aCx, JS::CurrentGlobalOrNull(aCx));
   if (!glob) {
     // XXXbz Can this actually be null here?
     return false;
   }
 
-  if (!WrapNewBindingObject(aCx, aException, &thrown)) {
+  if (!GetOrCreateDOMReflector(aCx, aException, &thrown)) {
     return false;
   }
 
   JS_SetPendingException(aCx, thrown);
   return true;
 }
 
 bool
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -146,17 +146,17 @@ ToJSValue(JSContext* aCx,
           T& aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   // Make sure we're called in a compartment
   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
   // Make sure non-webidl objects don't sneak in here
   MOZ_ASSERT(aArgument.IsDOMBinding());
 
-  return WrapNewBindingObject(aCx, aArgument, aValue);
+  return GetOrCreateDOMReflector(aCx, aArgument, aValue);
 }
 
 // Accept typed arrays built from appropriate nsTArray values
 template<typename T>
 typename EnableIf<IsBaseOf<AllTypedArraysBase, T>::value, bool>::Type
 ToJSValue(JSContext* aCx,
           const TypedArrayCreator<T>& aArgument,
           JS::MutableHandle<JS::Value> aValue)
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -17,16 +17,17 @@ using namespace mozilla;
 
 nsWeakPtr CameraControlImpl::sCameraThread;
 
 CameraControlImpl::CameraControlImpl(uint32_t aCameraId)
   : mListenerLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "CameraControlImpl.Listeners.Lock"))
   , mCameraId(aCameraId)
   , mPreviewState(CameraControlListener::kPreviewStopped)
   , mHardwareState(CameraControlListener::kHardwareClosed)
+  , mHardwareStateChangeReason(NS_OK)
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
 
   // reuse the same camera thread to conserve resources
   nsCOMPtr<nsIThread> ct = do_QueryReferent(sCameraThread);
   if (ct) {
     mCameraThread = ct.forget();
   } else {
@@ -66,43 +67,46 @@ CameraControlImpl::~CameraControlImpl()
 
 void
 CameraControlImpl::Shutdown()
 {
   DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 }
 
 void
-CameraControlImpl::OnHardwareStateChange(CameraControlListener::HardwareState aNewState)
+CameraControlImpl::OnHardwareStateChange(CameraControlListener::HardwareState aNewState,
+                                         nsresult aReason)
 {
   // This callback can run on threads other than the Main Thread and
   //  the Camera Thread. On Gonk, it may be called from the camera's
   //  local binder thread, should the mediaserver process die.
   RwLockAutoEnterRead lock(mListenerLock);
 
   if (aNewState == mHardwareState) {
     DOM_CAMERA_LOGI("OnHardwareStateChange: state did not change from %d\n", mHardwareState);
     return;
   }
 
 #ifdef PR_LOGGING
   const char* state[] = { "closed", "open", "failed" };
   MOZ_ASSERT(aNewState >= 0);
   if (static_cast<unsigned int>(aNewState) < sizeof(state) / sizeof(state[0])) {
-    DOM_CAMERA_LOGI("New hardware state is '%s'\n", state[aNewState]);
+    DOM_CAMERA_LOGI("New hardware state is '%s' (reason=0x%x)\n",
+      state[aNewState], aReason);
   } else {
     DOM_CAMERA_LOGE("OnHardwareStateChange: got invalid HardwareState value %d\n", aNewState);
   }
 #endif
 
   mHardwareState = aNewState;
+  mHardwareStateChangeReason = aReason;
 
   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
     CameraControlListener* l = mListeners[i];
-    l->OnHardwareStateChange(mHardwareState);
+    l->OnHardwareStateChange(mHardwareState, mHardwareStateChangeReason);
   }
 }
 
 void
 CameraControlImpl::OnConfigurationChange()
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread);
   RwLockAutoEnterRead lock(mListenerLock);
@@ -178,29 +182,16 @@ CameraControlImpl::OnShutter()
 
   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
     CameraControlListener* l = mListeners[i];
     l->OnShutter();
   }
 }
 
 void
-CameraControlImpl::OnClosed()
-{
-  // This callback can run on threads other than the Main Thread and
-  //  the Camera Thread.
-  RwLockAutoEnterRead lock(mListenerLock);
-
-  for (uint32_t i = 0; i < mListeners.Length(); ++i) {
-    CameraControlListener* l = mListeners[i];
-    l->OnHardwareStateChange(CameraControlListener::kHardwareClosed);
-  }
-}
-
-void
 CameraControlImpl::OnRecorderStateChange(CameraControlListener::RecorderState aState,
                                          int32_t aStatus, int32_t aTrackNumber)
 {
   // This callback can run on threads other than the Main Thread and
   //  the Camera Thread. On Gonk, it is called from the media encoder
   //  thread.
   RwLockAutoEnterRead lock(mListenerLock);
 
@@ -701,17 +692,17 @@ CameraControlImpl::AddListenerImpl(alrea
 {
   RwLockAutoEnterWrite lock(mListenerLock);
 
   CameraControlListener* l = *mListeners.AppendElement() = aListener;
   DOM_CAMERA_LOGI("Added camera control listener %p\n", l);
 
   // Update the newly-added listener's state
   l->OnConfigurationChange(mCurrentConfiguration);
-  l->OnHardwareStateChange(mHardwareState);
+  l->OnHardwareStateChange(mHardwareState, mHardwareStateChangeReason);
   l->OnPreviewStateChange(mPreviewState);
 }
 
 void
 CameraControlImpl::AddListener(CameraControlListener* aListener)
  {
   class Message : public ListenerMessage
   {
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -48,33 +48,33 @@ public:
   virtual nsresult ResumeContinuousFocus() MOZ_OVERRIDE;
 
   uint32_t GetCameraId() { return mCameraId; }
 
   virtual void Shutdown() MOZ_OVERRIDE;
 
   // Event handlers called directly from outside this class.
   void OnShutter();
-  void OnClosed();
   void OnUserError(CameraControlListener::UserContext aContext, nsresult aError);
   void OnSystemError(CameraControlListener::SystemContext aContext, nsresult aError);
   void OnAutoFocusMoving(bool aIsMoving);
 
 protected:
   // Event handlers.
   void OnAutoFocusComplete(bool aAutoFocusSucceeded);
   void OnFacesDetected(const nsTArray<Face>& aFaces);
   void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType);
 
   void OnRateLimitPreview(bool aLimit);
   bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
   void OnRecorderStateChange(CameraControlListener::RecorderState aState,
                              int32_t aStatus = -1, int32_t aTrackNumber = -1);
   void OnPreviewStateChange(CameraControlListener::PreviewState aState);
-  void OnHardwareStateChange(CameraControlListener::HardwareState aState);
+  void OnHardwareStateChange(CameraControlListener::HardwareState aState,
+                             nsresult aReason);
   void OnConfigurationChange();
 
   // When we create a new CameraThread, we keep a static reference to it so
   // that multiple CameraControl instances can find and reuse it; but we
   // don't want that reference to keep the thread object around unnecessarily,
   // so we make it a weak reference. The strong dynamic references will keep
   // the thread object alive as needed.
   static nsWeakPtr sCameraThread;
@@ -129,16 +129,17 @@ protected:
   void OnClosedInternal();
 
   uint32_t mCameraId;
 
   CameraControlListener::CameraListenerConfiguration mCurrentConfiguration;
 
   CameraControlListener::PreviewState   mPreviewState;
   CameraControlListener::HardwareState  mHardwareState;
+  nsresult                              mHardwareStateChangeReason;
 
 private:
   CameraControlImpl(const CameraControlImpl&) MOZ_DELETE;
   CameraControlImpl& operator=(const CameraControlImpl&) MOZ_DELETE;
 };
 
 } // namespace mozilla
 
--- a/dom/camera/CameraControlListener.h
+++ b/dom/camera/CameraControlListener.h
@@ -33,17 +33,24 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CameraControlListener);
 
   enum HardwareState
   {
     kHardwareClosed,
     kHardwareOpen,
     kHardwareOpenFailed
   };
-  virtual void OnHardwareStateChange(HardwareState aState) { }
+  // aReason:
+  //    NS_OK : state change was expected and normal;
+  //    NS_ERROR_FAILURE : one or more system-level components failed and
+  //                       the camera was closed;
+  //    NS_ERROR_NOT_AVAILABLE : the hardware is in use by another process
+  //                             and cannot be acquired, or another process
+  //                             was given access to the camera hardware.
+  virtual void OnHardwareStateChange(HardwareState aState, nsresult aReason) { }
 
   enum PreviewState
   {
     kPreviewStopped,
     kPreviewPaused,
     kPreviewStarted
   };
   virtual void OnPreviewStateChange(PreviewState aState) { }
--- a/dom/camera/CameraPreviewMediaStream.cpp
+++ b/dom/camera/CameraPreviewMediaStream.cpp
@@ -14,29 +14,32 @@
  */
 #define MAX_INVALIDATE_PENDING 4
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 
 namespace mozilla {
 
+static const TrackID TRACK_VIDEO = 2;
+
 void
 FakeMediaStreamGraph::DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable)
 {
   nsRefPtr<nsIRunnable> task = aRunnable;
   NS_DispatchToMainThread(task);
 }
 
 CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
   : MediaStream(aWrapper)
   , mMutex("mozilla::camera::CameraPreviewMediaStream")
   , mInvalidatePending(0)
   , mDiscardedFrames(0)
   , mRateLimit(false)
+  , mTrackCreated(false)
 {
   SetGraphImpl(MediaStreamGraph::GetInstance());
   mFakeMediaStreamGraph = new FakeMediaStreamGraph();
   mIsConsumed = false;
 }
 
 void
 CameraPreviewMediaStream::AddAudioOutput(void* aKey)
@@ -107,16 +110,34 @@ CameraPreviewMediaStream::RemoveListener
   MutexAutoLock lock(mMutex);
 
   nsRefPtr<MediaStreamListener> listener(aListener);
   mListeners.RemoveElement(aListener);
   listener->NotifyEvent(mFakeMediaStreamGraph, MediaStreamListener::EVENT_REMOVED);
 }
 
 void
+CameraPreviewMediaStream::OnPreviewStateChange(bool aActive)
+{
+  if (aActive) {
+    MutexAutoLock lock(mMutex);
+    if (!mTrackCreated) {
+      mTrackCreated = true;
+      VideoSegment tmpSegment;
+      for (uint32_t j = 0; j < mListeners.Length(); ++j) {
+        MediaStreamListener* l = mListeners[j];
+        l->NotifyQueuedTrackChanges(mFakeMediaStreamGraph, TRACK_VIDEO, 0,
+                                    MediaStreamListener::TRACK_EVENT_CREATED,
+                                    tmpSegment);
+      }
+    }
+  }
+}
+
+void
 CameraPreviewMediaStream::Destroy()
 {
   MutexAutoLock lock(mMutex);
   DestroyImpl();
 }
 
 void
 CameraPreviewMediaStream::Invalidate()
--- a/dom/camera/CameraPreviewMediaStream.h
+++ b/dom/camera/CameraPreviewMediaStream.h
@@ -46,30 +46,32 @@ public:
   virtual void SetAudioOutputVolume(void* aKey, float aVolume) MOZ_OVERRIDE;
   virtual void RemoveAudioOutput(void* aKey) MOZ_OVERRIDE;
   virtual void AddVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void RemoveVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void ChangeExplicitBlockerCount(int32_t aDelta) MOZ_OVERRIDE;
   virtual void AddListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void RemoveListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void Destroy();
+  void OnPreviewStateChange(bool aActive);
 
   void Invalidate();
 
   // Call these on any thread.
   void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage);
   void ClearCurrentFrame();
   void RateLimit(bool aLimit);
 
 protected:
   // mMutex protects all the class' fields.
   // This class is not registered to MediaStreamGraph.
   // It needs to protect all the fields.
   Mutex mMutex;
   int32_t mInvalidatePending;
   uint32_t mDiscardedFrames;
   bool mRateLimit;
+  bool mTrackCreated;
   nsRefPtr<FakeMediaStreamGraph> mFakeMediaStreamGraph;
 };
 
 }
 
 #endif // DOM_CAMERA_CAMERAPREVIEWMEDIASTREAM_H
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -32,16 +32,17 @@
 #include "mozilla/dom/CameraControlBinding.h"
 #include "mozilla/dom/CameraManagerBinding.h"
 #include "mozilla/dom/CameraCapabilitiesBinding.h"
 #include "mozilla/dom/CameraConfigurationEvent.h"
 #include "mozilla/dom/CameraConfigurationEventBinding.h"
 #include "mozilla/dom/CameraFacesDetectedEvent.h"
 #include "mozilla/dom/CameraFacesDetectedEventBinding.h"
 #include "mozilla/dom/CameraStateChangeEvent.h"
+#include "mozilla/dom/CameraClosedEvent.h"
 #include "mozilla/dom/BlobEvent.h"
 #include "DOMCameraDetectedFace.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "nsPrintfCString.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
@@ -285,17 +286,18 @@ nsDOMCameraControl::nsDOMCameraControl(u
 #endif
     mCameraControl = ICameraControl::Create(aCameraId);
 #ifdef MOZ_WIDGET_GONK
   }
 #endif
   mCurrentConfiguration = initialConfig.forget();
 
   // Attach our DOM-facing media stream to our viewfinder stream.
-  mStream = mInput;
+  SetHintContents(HINT_CONTENTS_VIDEO);
+  InitStreamCommon(mInput);
   MOZ_ASSERT(mWindow, "Shouldn't be created with a null window!");
   if (mWindow->GetExtantDoc()) {
     CombineWithPrincipal(mWindow->GetExtantDoc()->NodePrincipal());
   }
 
   // Register a listener for camera events.
   mListener = new DOMCameraControlListener(this, mInput);
   mCameraControl->AddListener(mListener);
@@ -1209,24 +1211,26 @@ nsDOMCameraControl::DispatchStateEvent(c
   nsRefPtr<CameraStateChangeEvent> event =
     CameraStateChangeEvent::Constructor(this, aType, eventInit);
 
   DispatchTrustedEvent(event);
 }
 
 // Camera Control event handlers--must only be called from the Main Thread!
 void
-nsDOMCameraControl::OnHardwareStateChange(CameraControlListener::HardwareState aState)
+nsDOMCameraControl::OnHardwareStateChange(CameraControlListener::HardwareState aState,
+                                          nsresult aReason)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ErrorResult ignored;
 
   switch (aState) {
     case CameraControlListener::kHardwareOpen:
       DOM_CAMERA_LOGI("DOM OnHardwareStateChange: open\n");
+      MOZ_ASSERT(aReason == NS_OK);
       {
         // The hardware is open, so we can return a camera to JS, even if
         // the preview hasn't started yet.
         nsRefPtr<Promise> promise = mGetCameraPromise.forget();
         if (promise) {
           CameraGetPromiseData data;
           data.mCamera = this;
           data.mConfiguration = *mCurrentConfiguration;
@@ -1240,39 +1244,63 @@ nsDOMCameraControl::OnHardwareStateChang
         }
       }
       break;
 
     case CameraControlListener::kHardwareClosed:
       DOM_CAMERA_LOGI("DOM OnHardwareStateChange: closed\n");
       {
         nsRefPtr<Promise> promise = mReleasePromise.forget();
-        if (promise || mReleaseOnSuccessCb) {
-          // If we have this event handler, this was a solicited hardware close.
-          if (promise) {
-            promise->MaybeResolve(JS::UndefinedHandleValue);
-          }
-          nsRefPtr<CameraReleaseCallback> cb = mReleaseOnSuccessCb.forget();
-          mReleaseOnErrorCb = nullptr;
-          if (cb) {
-            cb->Call(ignored);
-          }
-        } else {
-          // If not, something else closed the hardware.
-          nsRefPtr<CameraClosedCallback> cb = mOnClosedCb;
-          if (cb) {
-            cb->Call(ignored);
-          }
+        if (promise) {
+          promise->MaybeResolve(JS::UndefinedHandleValue);
+        }
+
+        nsRefPtr<CameraReleaseCallback> rcb = mReleaseOnSuccessCb.forget();
+        mReleaseOnErrorCb = nullptr;
+        if (rcb) {
+          ErrorResult ignored;
+          rcb->Call(ignored);
         }
-        DispatchTrustedEvent(NS_LITERAL_STRING("close"));
+
+        CameraClosedEventInit eventInit;
+        switch (aReason) {
+          case NS_OK:
+            eventInit.mReason = NS_LITERAL_STRING("HardwareReleased");
+            break;
+
+          case NS_ERROR_FAILURE:
+            eventInit.mReason = NS_LITERAL_STRING("SystemFailure");
+            break;
+
+          case NS_ERROR_NOT_AVAILABLE:
+            eventInit.mReason = NS_LITERAL_STRING("NotAvailable");
+            break;
+
+          default:
+            DOM_CAMERA_LOGE("Unhandled hardware close reason, 0x%x\n", aReason);
+            MOZ_ASSERT_UNREACHABLE("Unanticipated reason for hardware close");
+            eventInit.mReason = NS_LITERAL_STRING("SystemFailure");
+            break;
+        }
+
+        nsRefPtr<CameraClosedCallback> cb = mOnClosedCb;
+        if (cb) {
+          cb->Call(eventInit.mReason, ignored);
+        }
+        nsRefPtr<CameraClosedEvent> event =
+          CameraClosedEvent::Constructor(this,
+                                         NS_LITERAL_STRING("close"),
+                                         eventInit);
+        DispatchTrustedEvent(event);
       }
       break;
 
     case CameraControlListener::kHardwareOpenFailed:
       DOM_CAMERA_LOGI("DOM OnHardwareStateChange: open failed\n");
+      MOZ_ASSERT(aReason == NS_ERROR_NOT_AVAILABLE);
       OnUserError(DOMCameraControlListener::kInStartCamera, NS_ERROR_NOT_AVAILABLE);
       break;
 
     default:
       DOM_CAMERA_LOGE("DOM OnHardwareStateChange: UNKNOWN=%d\n", aState);
       MOZ_ASSERT_UNREACHABLE("Unanticipated camera hardware state");
   }
 }
@@ -1561,18 +1589,34 @@ nsDOMCameraControl::OnUserError(CameraCo
     case CameraControlListener::kInStartCamera:
       promise = mGetCameraPromise.forget();
       mGetCameraOnSuccessCb = nullptr;
       errorCb = mGetCameraOnErrorCb.forget();
       break;
 
     case CameraControlListener::kInStopCamera:
       promise = mReleasePromise.forget();
+      errorCb = mReleaseOnErrorCb.forget();
+      if (aError == NS_ERROR_NOT_INITIALIZED) {
+        // This value indicates that the hardware is already closed; which for
+        // kInStopCamera, is not actually an error.
+        if (promise) {
+          promise->MaybeResolve(JS::UndefinedHandleValue);
+        }
+
+        nsRefPtr<CameraReleaseCallback> cb = mReleaseOnSuccessCb.forget();
+        mReleaseOnErrorCb = nullptr;
+        if (cb) {
+          ErrorResult ignored;
+          cb->Call(ignored);
+        }
+
+        return;
+      }
       mReleaseOnSuccessCb = nullptr;
-      errorCb = mReleaseOnErrorCb.forget();
       break;
 
     case CameraControlListener::kInSetConfiguration:
       promise = mSetConfigurationPromise.forget();
       mSetConfigurationOnSuccessCb = nullptr;
       errorCb = mSetConfigurationOnErrorCb.forget();
       break;
 
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -182,17 +182,17 @@ protected:
 
   void OnCreatedFileDescriptor(bool aSucceeded);
 
   void OnAutoFocusComplete(bool aAutoFocusSucceeded);
   void OnAutoFocusMoving(bool aIsMoving);
   void OnTakePictureComplete(nsIDOMBlob* aPicture);
   void OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces);
 
-  void OnHardwareStateChange(DOMCameraControlListener::HardwareState aState);
+  void OnHardwareStateChange(DOMCameraControlListener::HardwareState aState, nsresult aReason);
   void OnPreviewStateChange(DOMCameraControlListener::PreviewState aState);
   void OnRecorderStateChange(CameraControlListener::RecorderState aState, int32_t aStatus, int32_t aTrackNum);
   void OnConfigurationChange(DOMCameraConfiguration* aConfiguration);
   void OnShutter();
   void OnUserError(CameraControlListener::UserContext aContext, nsresult aError);
 
   bool IsWindowStillActive();
 
--- a/dom/camera/DOMCameraControlListener.cpp
+++ b/dom/camera/DOMCameraControlListener.cpp
@@ -59,38 +59,41 @@ public:
   }
 
 protected:
   nsMainThreadPtrHandle<nsDOMCameraControl> mDOMCameraControl;
 };
 
 // Specific callback handlers
 void
-DOMCameraControlListener::OnHardwareStateChange(HardwareState aState)
+DOMCameraControlListener::OnHardwareStateChange(HardwareState aState,
+                                                nsresult aReason)
 {
   class Callback : public DOMCallback
   {
   public:
     Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
-             HardwareState aState)
+             HardwareState aState, nsresult aReason)
       : DOMCallback(aDOMCameraControl)
       , mState(aState)
+      , mReason(aReason)
     { }
 
     void
     RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
     {
-      aDOMCameraControl->OnHardwareStateChange(mState);
+      aDOMCameraControl->OnHardwareStateChange(mState, mReason);
     }
 
   protected:
     HardwareState mState;
+    nsresult mReason;
   };
 
-  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
+  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState, aReason));
 }
 
 void
 DOMCameraControlListener::OnPreviewStateChange(PreviewState aState)
 {
   class Callback : public DOMCallback
   {
   public:
@@ -132,16 +135,17 @@ DOMCameraControlListener::OnPreviewState
       DOM_CAMERA_LOGI("Preview started\n");
       break;
 
     default:
       DOM_CAMERA_LOGE("Unknown preview state %d\n", aState);
       MOZ_ASSERT_UNREACHABLE("Invalid preview state");
       return;
   }
+  mStream->OnPreviewStateChange(aState == kPreviewStarted);
   NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
 }
 
 void
 DOMCameraControlListener::OnRecorderStateChange(RecorderState aState,
                                                 int32_t aStatus, int32_t aTrackNum)
 {
   class Callback : public DOMCallback
--- a/dom/camera/DOMCameraControlListener.h
+++ b/dom/camera/DOMCameraControlListener.h
@@ -18,17 +18,17 @@ class DOMCameraControlListener : public 
 public:
   DOMCameraControlListener(nsDOMCameraControl* aDOMCameraControl, CameraPreviewMediaStream* aStream);
 
   virtual void OnAutoFocusComplete(bool aAutoFocusSucceeded) MOZ_OVERRIDE;
   virtual void OnAutoFocusMoving(bool aIsMoving) MOZ_OVERRIDE;
   virtual void OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces) MOZ_OVERRIDE;
   virtual void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType) MOZ_OVERRIDE;
 
-  virtual void OnHardwareStateChange(HardwareState aState) MOZ_OVERRIDE;
+  virtual void OnHardwareStateChange(HardwareState aState, nsresult aReason) MOZ_OVERRIDE;
   virtual void OnPreviewStateChange(PreviewState aState) MOZ_OVERRIDE;
   virtual void OnRecorderStateChange(RecorderState aState, int32_t aStatus, int32_t aTrackNum) MOZ_OVERRIDE;
   virtual void OnConfigurationChange(const CameraListenerConfiguration& aConfiguration) MOZ_OVERRIDE;
   virtual void OnShutter() MOZ_OVERRIDE;
   virtual void OnRateLimitPreview(bool aLimit) MOZ_OVERRIDE;
   virtual bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) MOZ_OVERRIDE;
   virtual void OnUserError(UserContext aContext, nsresult aError) MOZ_OVERRIDE;
 
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -83,17 +83,18 @@ nsGonkCameraControl::nsGonkCameraControl
 
 nsresult
 nsGonkCameraControl::StartImpl(const Configuration* aInitialConfig)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread);
 
   nsresult rv = StartInternal(aInitialConfig);
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    OnHardwareStateChange(CameraControlListener::kHardwareOpenFailed);
+    OnHardwareStateChange(CameraControlListener::kHardwareOpenFailed,
+                          NS_ERROR_NOT_AVAILABLE);
   }
   return rv;
 }
 
 nsresult
 nsGonkCameraControl::StartInternal(const Configuration* aInitialConfig)
 {
   /**
@@ -124,22 +125,22 @@ nsGonkCameraControl::StartInternal(const
     default:
       return rv;
   }
 
   if (aInitialConfig) {
     rv = SetConfigurationInternal(*aInitialConfig);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       // The initial configuration failed, close up the hardware
-      StopImpl();
+      StopInternal();
       return rv;
     }
   }
 
-  OnHardwareStateChange(CameraControlListener::kHardwareOpen);
+  OnHardwareStateChange(CameraControlListener::kHardwareOpen, NS_OK);
   if (aInitialConfig) {
     return StartPreviewImpl();
   }
 
   return NS_OK;
 }
 
 nsresult
@@ -1148,17 +1149,19 @@ nsGonkCameraControl::StopRecordingImpl()
 
   private:
     nsRefPtr<DeviceStorageFile> mFile;
   };
 
   ReentrantMonitorAutoEnter mon(mRecorderMonitor);
 
   // nothing to do if we have no mRecorder
-  NS_ENSURE_TRUE(mRecorder, NS_OK);
+  if (!mRecorder) {
+    return NS_OK;
+  }
 
   mRecorder->stop();
   mRecorder = nullptr;
   OnRecorderStateChange(CameraControlListener::kRecorderStopped);
 
   {
     ICameraControlParameterSetAutoEnter set(this);
 
@@ -1486,18 +1489,18 @@ nsGonkCameraControl::SelectVideoAndPrevi
     return SetVideoAndPreviewSize(preview, video);
   }
 
   // Otherwise, if the requested preview size is larger than the preferred
   // size, or there is an aspect ratio mismatch, then we need to set the
   // preview size to the closest size smaller than the preferred size,
   // preferably with the same aspect ratio as the requested video size.
 
-  SizeIndex bestSizeMatch;
-  SizeIndex bestSizeMatchWithAspectRatio;
+  SizeIndex bestSizeMatch = 0; // initializers to keep warnings away
+  SizeIndex bestSizeMatchWithAspectRatio = 0;
   bool foundSizeMatch = false;
   bool foundSizeMatchWithAspectRatio = false;
 
   uint32_t bestAreaDelta = UINT32_MAX;
   uint32_t bestAreaDeltaWithAspect = UINT32_MAX;
 
   for (SizeIndex i = 0; i < sizes.Length(); ++i) {
     const Size& s = sizes[i];
@@ -1821,34 +1824,48 @@ nsGonkCameraControl::SetupRecording(int 
   // recording API needs file descriptor of output file
   CHECK_SETARG_RETURN(mRecorder->setOutputFile(aFd, 0, 0), NS_ERROR_FAILURE);
   CHECK_SETARG_RETURN(mRecorder->prepare(), NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 nsresult
-nsGonkCameraControl::StopImpl()
+nsGonkCameraControl::StopInternal()
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
 
   // if we're recording, stop recording
   StopRecordingImpl();
 
   // stop the preview
-  StopPreviewImpl();
+  nsresult rv = StopPreviewImpl();
 
   // release the hardware handle
   if (mCameraHw.get()){
      mCameraHw->Close();
      mCameraHw.clear();
   }
 
-  OnHardwareStateChange(CameraControlListener::kHardwareClosed);
-  return NS_OK;
+  return rv;
+}
+
+nsresult
+nsGonkCameraControl::StopImpl()
+{
+  DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+
+  nsresult rv = StopInternal();
+  if (rv != NS_ERROR_NOT_INITIALIZED) {
+    rv = NS_OK;
+  }
+  if (NS_SUCCEEDED(rv)) {
+    OnHardwareStateChange(CameraControlListener::kHardwareClosed, NS_OK);
+  }
+  return rv;
 }
 
 nsresult
 nsGonkCameraControl::LoadRecorderProfiles()
 {
   if (mRecorderProfiles.Count() == 0) {
     nsTArray<nsRefPtr<RecorderProfile>> profiles;
     nsresult rv = GonkRecorderProfile::GetAll(mCameraId, profiles);
@@ -1941,18 +1958,18 @@ nsGonkCameraControl::OnNewPreviewFrame(l
                     mCurrentConfiguration.mPreviewSize.height);
 }
 
 void
 nsGonkCameraControl::OnSystemError(CameraControlListener::SystemContext aWhere,
                                    nsresult aError)
 {
   if (aWhere == CameraControlListener::kSystemService) {
-    OnPreviewStateChange(CameraControlListener::kPreviewStopped);
-    OnHardwareStateChange(CameraControlListener::kHardwareClosed);
+    StopInternal();
+    OnHardwareStateChange(CameraControlListener::kHardwareClosed, NS_ERROR_FAILURE);
   }
 
   CameraControlImpl::OnSystemError(aWhere, aError);
 }
 
 // Gonk callback handlers.
 namespace mozilla {
 
@@ -2000,22 +2017,16 @@ OnNewPreviewFrame(nsGonkCameraControl* g
 
 void
 OnShutter(nsGonkCameraControl* gc)
 {
   gc->OnShutter();
 }
 
 void
-OnClosed(nsGonkCameraControl* gc)
-{
-  gc->OnClosed();
-}
-
-void
 OnSystemError(nsGonkCameraControl* gc,
               CameraControlListener::SystemContext aWhere,
               int32_t aArg1, int32_t aArg2)
 {
 #ifdef PR_LOGGING
   DOM_CAMERA_LOGE("OnSystemError : aWhere=%d, aArg1=%d, aArg2=%d\n", aWhere, aArg1, aArg2);
 #else
   unused << aArg1;
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -104,16 +104,17 @@ protected:
   virtual void EndBatchParameterSet() MOZ_OVERRIDE;
 
   nsresult Initialize();
 
   nsresult SetConfigurationInternal(const Configuration& aConfig);
   nsresult SetPictureConfiguration(const Configuration& aConfig);
   nsresult SetVideoConfiguration(const Configuration& aConfig);
   nsresult StartInternal(const Configuration* aInitialConfig);
+  nsresult StopInternal();
 
   template<class T> nsresult SetAndPush(uint32_t aKey, const T& aValue);
 
   // See CameraControlImpl.h for these methods' return values.
   virtual nsresult StartImpl(const Configuration* aInitialConfig = nullptr) MOZ_OVERRIDE;
   virtual nsresult SetConfigurationImpl(const Configuration& aConfig) MOZ_OVERRIDE;
   virtual nsresult StopImpl() MOZ_OVERRIDE;
   virtual nsresult StartPreviewImpl() MOZ_OVERRIDE;
@@ -193,16 +194,15 @@ private:
 void OnRateLimitPreview(nsGonkCameraControl* gc, bool aLimit);
 void OnTakePictureComplete(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength);
 void OnTakePictureError(nsGonkCameraControl* gc);
 void OnAutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess);
 void OnAutoFocusMoving(nsGonkCameraControl* gc, bool aIsMoving);
 void OnFacesDetected(nsGonkCameraControl* gc, camera_frame_metadata_t* aMetaData);
 void OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer);
 void OnShutter(nsGonkCameraControl* gc);
-void OnClosed(nsGonkCameraControl* gc);
 void OnSystemError(nsGonkCameraControl* gc,
                    CameraControlListener::SystemContext aWhere,
                    int32_t aArg1, int32_t aArg2);
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_GONKCAMERACONTROL_H
--- a/dom/camera/GonkCameraHwMgr.cpp
+++ b/dom/camera/GonkCameraHwMgr.cpp
@@ -263,28 +263,16 @@ GonkCameraHardware::Close()
   IPCThreadState::self()->flushCommands();
 }
 
 GonkCameraHardware::~GonkCameraHardware()
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, (void*)this);
   mCamera.clear();
   mNativeWindow.clear();
-
-  if (mClosing) {
-    return;
-  }
-
-  /**
-   * Trigger the OnClosed event; the upper layers can't do anything
-   * with the hardware layer once they receive this event.
-   */
-  if (mTarget) {
-    OnClosed(mTarget);
-  }
 }
 
 int
 GonkCameraHardware::GetSensorOrientation(uint32_t aType)
 {
   DOM_CAMERA_LOGI("%s\n", __func__);
 
   switch (aType) {
--- a/dom/camera/TestGonkCameraHardware.cpp
+++ b/dom/camera/TestGonkCameraHardware.cpp
@@ -34,22 +34,55 @@ TestGonkCameraHardware::TestGonkCameraHa
 }
 
 TestGonkCameraHardware::~TestGonkCameraHardware()
 {
   MOZ_COUNT_DTOR(TestGonkCameraHardware);
   DOM_CAMERA_LOGA("^===== Destroyed TestGonkCameraHardware =====^\n");
 }
 
+void
+TestGonkCameraHardware::InjectFakeSystemFailure()
+{
+  DOM_CAMERA_LOGA("====== Fake Camera Hardware Failure ======\n");
+  // The values '100' and '0' below seem to be what the AOSP layer
+  // throws back when the mediaserver process fails.
+  OnSystemError(mTarget, CameraControlListener::kSystemService, 100, 0);
+}
+
 nsresult
 TestGonkCameraHardware::Init()
 {
+  class DeferredSystemFailure : public nsRunnable
+  {
+  public:
+    DeferredSystemFailure(TestGonkCameraHardware* aCameraHw)
+      : mCameraHw(aCameraHw)
+    { }
+
+    NS_IMETHODIMP
+    Run()
+    {
+      mCameraHw->InjectFakeSystemFailure();
+      return NS_OK;
+    }
+
+  protected:
+    android::sp<TestGonkCameraHardware> mCameraHw;
+  };
+
   if (IsTestCase("init-failure")) {
     return NS_ERROR_NOT_INITIALIZED;
   }
+  if (IsTestCase("post-init-system-failure")) {
+    nsCOMPtr<nsIThread> me = NS_GetCurrentThread();
+    if (me) {
+      me->Dispatch(new DeferredSystemFailure(this), NS_DISPATCH_NORMAL);
+    }
+  }
 
   return GonkCameraHardware::Init();
 }
 
 const nsCString
 TestGonkCameraHardware::TestCase()
 {
   nsCString test;
--- a/dom/camera/TestGonkCameraHardware.h
+++ b/dom/camera/TestGonkCameraHardware.h
@@ -57,16 +57,17 @@ public:
 
 protected:
   const nsCString TestCase();
   const nsCString GetExtraParameters();
   bool IsTestCaseInternal(const char* aTest, const char* aFile, int aLine);
   int TestCaseError(int aDefaultError);
 
   int StartAutoFocusMoving(bool aIsMoving);
+  void InjectFakeSystemFailure();
 
 private:
   TestGonkCameraHardware(const TestGonkCameraHardware&) MOZ_DELETE;
   TestGonkCameraHardware& operator=(const TestGonkCameraHardware&) MOZ_DELETE;
 };
 
 #define IsTestCase(test)  IsTestCaseInternal((test), __FILE__, __LINE__)
 
new file mode 100644
--- /dev/null
+++ b/dom/camera/test/callback/test_bug1099390.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for bug 1099390</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="camera_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<video id="viewfinder" width="200" height="200" autoplay></video>
+<img src="#" alt="This image is going to load" id="testimage"/>
+<script class="testbody" type="text/javascript;version=1.7">
+
+var whichCamera = navigator.mozCameras.getListOfCameras()[0];
+var config = {
+  mode: 'picture',
+  recorderProfile: 'cif',
+  previewSize: {
+    width: 352,
+    height: 288
+  }
+};
+
+function onError(e) {
+  ok(false, "Error " + e);
+}
+
+var Camera = {
+  _cameraObj: null,
+
+  get viewfinder() {
+    return document.getElementById('viewfinder');
+  },
+
+  release: function release() {
+    viewfinder.mozSrcObject = null;
+    if (Camera._cameraObj) {
+      Camera._cameraObj.release();
+      Camera._cameraObj = null;
+    }
+  },
+
+  test: function test(cam) {
+    var gotCloseEvent = false;
+    var gotReleaseCallback = false;
+
+    function gotAll() {
+      var all = gotCloseEvent && gotReleaseCallback;
+      if (all) {
+        info("Got all expected notifications");
+      }
+      return all;
+    };
+
+    cam.onClosed = function(reason) {
+      cam.onClosed = null;
+      ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent);
+      ok(reason === "HardwareReleased", "onClosed reason is: " + reason);
+      gotCloseEvent = true;
+      if (gotAll()) {
+        SimpleTest.finish();
+      }
+    };
+
+    var onSuccess = function() {
+      ok(!gotReleaseCallback, "gotReleaseCallback was " + gotReleaseCallback);
+      gotReleaseCallback = true;
+      if (gotAll()) {
+        SimpleTest.finish();
+      }
+    };
+
+    cam.release(onSuccess, onError);
+  }, // test()
+
+  start: function start() {
+    function onSuccess(cam) {
+      Camera._cameraObj = cam;
+      Camera.viewfinder.mozSrcObject = cam;
+      Camera.viewfinder.play();
+
+      var onPreviewStateChange = function(e) {
+        if (e.newState === 'started') {
+          cam.removeEventListener('previewstatechange', onPreviewStateChange);
+          Camera.test(cam);
+        }
+      }; // onPreviewStateChange
+      cam.addEventListener('previewstatechange', onPreviewStateChange);
+    }; // onSuccess()
+
+    navigator.mozCameras.getCamera(whichCamera, config, onSuccess, onError);
+  }, // start()
+}
+
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener('beforeunload', function() {
+  Camera.release();
+});
+
+Camera.start();
+
+</script>
+</body>
+
+</html>
--- a/dom/camera/test/callback/test_camera_hardware_init_failure.html
+++ b/dom/camera/test/callback/test_camera_hardware_init_failure.html
@@ -60,21 +60,74 @@ var tests = [
       }
       function onError(error) {
         ok(false, "onError called incorrectly: " + error);
         test.next();
       }
       info("Running test: init-success");
       navigator.mozCameras.getCamera(whichCamera, initialConfig, onSuccess, onError)
     }
-  }
+  },
+  /* Test for bug 1099390 to make sure events related to the underlying
+     platform failing are generated and handled properly. */
+  {
+    name: "post-init-system-failure",
+    key: "post-init-system-failure",
+    func: function(test) {
+      var gotReleaseCallback = false;
+      var gotCloseCallback = false;
+
+      function gotAll() {
+        var all = gotReleaseCallback && gotCloseCallback;
+        if (all) {
+          info("Got all expected notifications");
+        }
+        return all;
+      }
+
+      function onSuccess(camera, config) {
+        camera.onClosed = function(reason) {
+          camera.onClosed = null;
+          ok(reason === "SystemFailure", "reason is: " + reason);
+          ok(!gotCloseCallback, "gotCloseCallback was " + gotCloseCallback);
+          gotCloseCallback = true;
+          if (gotAll()) {
+            test.next();
+          }
+
+          camera.release(
+            function success() {
+              ok(true, "Got release() success callback");
+              ok(!gotReleaseCallback, "gotReleaseCallback was " + gotReleaseCallback);
+              gotReleaseCallback = true;
+              if (gotAll()) {
+                test.next();
+              }
+            },
+            function error(e) {
+              ok(false, "Unexpected release() onError callback: " + e);
+              test.next();
+            }
+          ); // release()
+        } // onClosed
+      } // onSuccess
+
+      function onError(error) {
+        ok(false, "onError called incorrectly: " + error);
+        test.next();
+      }
+
+      info("Running test: post-init-system-failure");
+      navigator.mozCameras.getCamera(whichCamera, initialConfig, onSuccess, onError);
+    }
+  },
 ];
 
 var testGenerator = function() {
-  for (var i = 0; i < tests.length; ++i ) {
+  for (var i = 0; i < tests.length; ++i) {
     yield tests[i];
   }
 }();
 
 CameraTest.begin("hardware", function(test) {
   CameraTest.next = function() {
     try {
       var t = testGenerator.next();
--- a/dom/camera/test/mochitest.ini
+++ b/dom/camera/test/mochitest.ini
@@ -5,19 +5,21 @@ support-files = camera_common.js
 [callback/test_camera_2.html]
 [callback/test_camera_3.html]
 [callback/test_camera_hardware_init_failure.html]
 [callback/test_camera_hardware_failures.html]
 [callback/test_bug975472.html]
 [callback/test_camera_hardware_face_detection.html]
 [callback/test_camera_hardware_auto_focus_moving_cb.html]
 [callback/test_bug1022766.html]
+[callback/test_bug1099390.html]
 [test_camera.html]
 [test_camera_2.html]
 [test_camera_3.html]
 [test_camera_hardware_init_failure.html]
 [test_camera_hardware_failures.html]
 [test_bug975472.html]
 [test_camera_fake_parameters.html]
 [test_camera_hardware_face_detection.html]
 [test_camera_hardware_auto_focus_moving_cb.html]
 [test_bug1022766.html]
 [test_bug1037322.html]
+[test_bug1099390.html]
new file mode 100644
--- /dev/null
+++ b/dom/camera/test/test_bug1099390.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for bug 1099390</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="camera_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<video id="viewfinder" width="200" height="200" autoplay></video>
+<img src="#" alt="This image is going to load" id="testimage"/>
+<script class="testbody" type="text/javascript;version=1.7">
+
+var whichCamera = navigator.mozCameras.getListOfCameras()[0];
+var config = {
+  mode: 'picture',
+  recorderProfile: 'cif',
+  previewSize: {
+    width: 352,
+    height: 288
+  }
+};
+
+function onError(e) {
+  ok(false, "Error " + e);
+}
+
+var Camera = {
+  _cameraObj: null,
+
+  get viewfinder() {
+    return document.getElementById('viewfinder');
+  },
+
+  release: function release() {
+    viewfinder.mozSrcObject = null;
+    if (Camera._cameraObj) {
+      Camera._cameraObj.release();
+      Camera._cameraObj = null;
+    }
+  },
+
+  test: function test(cam) {
+    var gotCloseEvent = false;
+    var gotReleasePromise = false;
+
+    function gotAll() {
+      var all = gotCloseEvent && gotReleasePromise;
+      if (all) {
+        info("Got all expected notifications");
+      }
+      return all;
+    };
+
+    var onClosed = function(e) {
+      cam.removeEventListener('close', onClosed);
+      ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent);
+      ok(e.reason === "HardwareReleased", "'close' event reason is: " + e.reason);
+      gotCloseEvent = true;
+      if (gotAll()) {
+        SimpleTest.finish();
+      }
+    };
+
+    cam.addEventListener('close', onClosed);
+
+    var onResolve = function() {
+      ok(!gotReleasePromise, "gotReleasePromise was " + gotReleasePromise);
+      gotReleasePromise = true;
+      if (gotAll()) {
+        SimpleTest.finish();
+      }
+    };
+
+    cam.release().then(onResolve, onError);
+  }, // test()
+
+  start: function start() {
+    function onSuccess(d) {
+      Camera._cameraObj = d.camera;
+      var cam = d.camera;
+
+      var onPreviewStateChange = function(e) {
+        if (e.newState === 'started') {
+          cam.removeEventListener('previewstatechange', onPreviewStateChange);
+          Camera.test(cam);
+        }
+      }; // onPreviewStateChange
+      cam.addEventListener('previewstatechange', onPreviewStateChange);
+    }; // onSuccess()
+
+    navigator.mozCameras.getCamera(whichCamera, config).then(onSuccess, onError);
+  }, // start()
+}
+
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener('beforeunload', function() {
+  Camera.release();
+});
+
+Camera.start();
+
+</script>
+</body>
+
+</html>
--- a/dom/camera/test/test_camera.html
+++ b/dom/camera/test/test_camera.html
@@ -104,28 +104,36 @@ var Camera = {
   takePictureSuccess: function taken_foto(blob) {
     ok(blob.size > 100 , "Blob Size Gathered = " + blob.size);
     ok("image/" + test.fileFormat ==  blob.type, "Blob Type = " + blob.type);
   },
   takePictureEvent: function taken_foto_evt(e) {
     var blob = e.data;
     var img = new Image();
     var test = this._currentTest;
+    var onPreviewStateChange = function(e) {
+      if (e.newState === 'started') {
+        ok(true, "viewfinder is ready and playing after resume");
+        Camera.cameraObj.removeEventListener('previewstatechange', onPreviewStateChange);
+        Camera._testsCompleted++;
+        if(Camera._testsCompleted == Camera._tests.length) {
+          ok(true, "test finishing");
+          SimpleTest.finish();
+        } else {
+          Camera.runTests();
+        }
+      }
+    }
+    Camera.cameraObj.addEventListener('previewstatechange', onPreviewStateChange);
     img.onload = function Imgsize() {
       ok(this.width == test.pictureSize.width, "The image taken has the width " +
                                               this.width + " pictureSize width = " + test.pictureSize.width);
       ok(this.height == test.pictureSize.height, "The image taken has the height " +
                                               this.height + " picturesize height = " + test.pictureSize.height);
-      Camera._testsCompleted++;
-      if(Camera._testsCompleted == Camera._tests.length) {
-        ok(true, "test finishing");
-        SimpleTest.finish();
-      } else {
-        Camera.runTests();
-      }
+      Camera.cameraObj.resumePreview();
     }
     ok(blob.size > 100 , "Blob Size Gathered = " + blob.size);
     ok("image/" + test.fileFormat ==  blob.type, "Blob Type = " + blob.type);
     img.src = window.URL.createObjectURL(blob);
   },
   shutter: function onShutter () {
     Camera._shutter++;
     
--- a/dom/camera/test/test_camera_hardware_init_failure.html
+++ b/dom/camera/test/test_camera_hardware_init_failure.html
@@ -50,31 +50,85 @@ var tests = [
   /* This test case (init-success) *must* follow the preceeding test case
      (init-failure) in order for the desired condition to be verified */
   {
     name: "init-success",
     key: "",
     func: function(test) {
       function onSuccess(d) {
         ok(true, "onSuccess called correctly");
-        d.camera.release();
-        test.next();
+        d.camera.release().then(test.next);
       }
       function onError(error) {
         ok(false, "onError called incorrectly: " + error);
         test.next();
       }
       info("Running test: init-success");
       navigator.mozCameras.getCamera(whichCamera, initialConfig).then(onSuccess, onError)
     }
-  }
+  },
+  /* Test for bug 1099390 to make sure events related to the underlying
+     platform failing are generated and handled properly. */
+  {
+    name: "post-init-system-failure",
+    key: "post-init-system-failure",
+    func: function(test) {
+      var gotReleasePromise = false;
+      var gotCloseEvent = false;
+
+      function gotAll() {
+        var all = gotReleasePromise && gotCloseEvent;
+        if (all) {
+          info("Got all expected notifications");
+        }
+        return all;
+      }
+
+      function onSuccess(d) {
+        var onClosedEvent = function(e) {
+          d.camera.removeEventListener('close', onClosedEvent);
+
+          ok(e.reason === "SystemFailure", "reason is: " + e.reason);
+          ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent);
+          gotCloseEvent = true;
+          if (gotAll()) {
+            test.next();
+          }
+
+          d.camera.release().then(
+            function resolve(e) {
+              ok(true, "release() promise resolved");
+              ok(!gotReleasePromise, "gotReleasePromise was " + gotReleasePromise);
+              gotReleasePromise = true;
+              if (gotAll()) {
+                test.next();
+              }
+            },
+            function reject(e) {
+              ok(false, "release() promise unexpected rejected: " + e);
+            }
+          );
+        };
+
+        d.camera.addEventListener('close', onClosedEvent);
+      }
+
+      function onError(error) {
+        ok(false, "onError called incorrectly: " + error);
+        test.next();
+      }
+
+      info("Running test: post-init-system-failure");
+      navigator.mozCameras.getCamera(whichCamera, initialConfig).then(onSuccess, onError)
+    }
+  },
 ];
 
 var testGenerator = function() {
-  for (var i = 0; i < tests.length; ++i ) {
+  for (var i = 0; i < tests.length; ++i) {
     yield tests[i];
   }
 }();
 
 CameraTest.begin("hardware", function(test) {
   CameraTest.next = function() {
     try {
       var t = testGenerator.next();
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -83,17 +83,18 @@ WebGLContext::WebGLObjectAsJSValue(JSCon
 {
     if (!object) {
         return JS::NullValue();
     }
     MOZ_ASSERT(this == object->Context());
     JS::Rooted<JS::Value> v(cx);
     JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
     JSAutoCompartment ac(cx, wrapper);
-    if (!dom::WrapNewBindingObject(cx, const_cast<WebGLObjectType*>(object), &v)) {
+    if (!dom::GetOrCreateDOMReflector(cx, const_cast<WebGLObjectType*>(object),
+                                      &v)) {
         rv.Throw(NS_ERROR_FAILURE);
         return JS::NullValue();
     }
     return v;
 }
 
 template <typename WebGLObjectType>
 JSObject*
--- a/dom/canvas/test/_webgl-conformance.ini
+++ b/dom/canvas/test/_webgl-conformance.ini
@@ -494,16 +494,17 @@ support-files = webgl-conformance/../web
 [webgl-conformance/_wrappers/test_conformance__buffers__buffer-bind-test.html]
 [webgl-conformance/_wrappers/test_conformance__buffers__buffer-data-array-buffer.html]
 [webgl-conformance/_wrappers/test_conformance__buffers__index-validation-copies-indices.html]
 [webgl-conformance/_wrappers/test_conformance__buffers__index-validation-crash-with-buffer-sub-data.html]
 [webgl-conformance/_wrappers/test_conformance__buffers__index-validation-verifies-too-many-indices.html]
 [webgl-conformance/_wrappers/test_conformance__buffers__index-validation-with-resized-buffer.html]
 [webgl-conformance/_wrappers/test_conformance__buffers__index-validation.html]
 [webgl-conformance/_wrappers/test_conformance__canvas__buffer-offscreen-test.html]
+skip-if = os == 'android' # Bug 1102402 - It fails intermittently and causes a lot of retried jobs
 [webgl-conformance/_wrappers/test_conformance__canvas__buffer-preserve-test.html]
 [webgl-conformance/_wrappers/test_conformance__canvas__canvas-test.html]
 [webgl-conformance/_wrappers/test_conformance__canvas__canvas-zero-size.html]
 [webgl-conformance/_wrappers/test_conformance__canvas__drawingbuffer-static-canvas-test.html]
 skip-if = os == 'mac'
 [webgl-conformance/_wrappers/test_conformance__canvas__drawingbuffer-test.html]
 [webgl-conformance/_wrappers/test_conformance__canvas__viewport-unchanged-upon-resize.html]
 [webgl-conformance/_wrappers/test_conformance__context__constants.html]
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -895,17 +895,17 @@ EventListenerManager::CompileEventHandle
   // the JS string stuff, so don't worry about playing games with
   // refcounting XPCOM stringbuffers.
   JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
                                                       str.BeginReading(),
                                                       str.Length()));
   NS_ENSURE_TRUE(jsStr, NS_ERROR_OUT_OF_MEMORY);
 
   // Get the reflector for |aElement|, so that we can pass to setElement.
-  if (NS_WARN_IF(!WrapNewBindingObject(cx, target, aElement, &v))) {
+  if (NS_WARN_IF(!GetOrCreateDOMReflector(cx, target, aElement, &v))) {
     return NS_ERROR_FAILURE;
   }
   JS::CompileOptions options(cx);
   options.setIntroductionType("eventHandler")
          .setFileAndLine(url.get(), lineNo)
          .setVersion(JSVERSION_DEFAULT)
          .setElement(&v.toObject())
          .setElementAttributeName(jsStr);
--- a/dom/events/test/test_all_synthetic_events.html
+++ b/dom/events/test/test_all_synthetic_events.html
@@ -75,16 +75,20 @@ const kEventConstructors = {
   CallEvent:                                 { create: function (aName, aProps) {
                                                           return new CallEvent(aName, aProps);
                                                        },
                                              },
   CallGroupErrorEvent:                       { create: function (aName, aProps) {
                                                           return new CallGroupErrorEvent(aName, aProps);
                                                        },
                                              },
+  CameraClosedEvent:                        { create: function (aName, aProps) {
+                                                          return new CameraClosedEvent(aName, aProps);
+                                                       },
+                                             },
   CameraConfigurationEvent:                  { create: function (aName, aProps) {
                                                           return new CameraConfigurationEvent(aName, aProps);
                                                        },
                                              },
   CameraFacesDetectedEvent:                  { create: function (aName, aProps) {
                                                           return new CameraFacesDetectedEvent(aName, aProps);
                                                        },
                                              },
--- a/dom/events/test/test_dom_before_after_keyboard_event_remote.html
+++ b/dom/events/test/test_dom_before_after_keyboard_event_remote.html
@@ -30,56 +30,87 @@ var testsForEventOrder = [
                         kParent | kKeyUpEvent,
                         kChild | kKeyUpEvent,
                         kParent | kAfterEvent | kKeyUpEvent ] ],
     resultEvents: [],
     classifiedEvents: [ [], [] ],
     doPreventDefaultAt: kUnknownEvent
   },
   {
-    description: "Testing the order of the events (OOP), calling preventDefault() at \"mozbrowserbeforekeydown\" event",
+    description: "Testing the order of the events (OOP), calling " +
+                 "preventDefault() at \"mozbrowserbeforekeydown\" event",
     expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                         kParent | kAfterEvent | kKeyDownEvent ],
                       [ kParent | kBeforeEvent | kKeyUpEvent,
                         kParent | kKeyUpEvent,
                         kChild | kKeyUpEvent,
                         kParent | kAfterEvent | kKeyUpEvent ] ],
     resultEvents: [],
     classifiedEvents: [ [], [] ],
     doPreventDefaultAt: kParent | kBeforeEvent | kKeyDownEvent
   },
   {
-    description: "Testing the order of the events (OOP), calling preventDefault() at \"mozbrowserbeforekeyup\" event",
+    description: "Testing the order of the events (OOP), calling " +
+                 "preventDefault() at \"mozbrowserbeforekeyup\" event",
     expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                         kParent | kKeyDownEvent,
                         kChild | kKeyDownEvent,
                         kParent | kAfterEvent | kKeyDownEvent ],
                       [ kParent | kBeforeEvent | kKeyUpEvent,
                         kParent | kAfterEvent | kKeyUpEvent ] ],
     resultEvents: [],
     classifiedEvents: [ [], [] ],
     doPreventDefaultAt: kParent | kBeforeEvent | kKeyUpEvent
   },
-
   {
-    description: "Testing the order of the events (OOP), calling preventDefault() at \"keydown\" event",
+    description: "Testing the order of the events (OOP), calling " +
+                 "preventDefault() at \"keydown\" event in parent process",
+    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
+                        kParent | kKeyDownEvent,
+                        kParent | kAfterEvent | kKeyDownEvent ],
+                      [ kParent | kBeforeEvent | kKeyUpEvent,
+                        kParent | kKeyUpEvent,
+                        kChild | kKeyUpEvent,
+                        kParent | kAfterEvent | kKeyUpEvent ] ],
+    resultEvents: [],
+    classifiedEvents: [ [], [] ],
+    doPreventDefaultAt: kParent | kKeyDownEvent
+  },
+  {
+    description: "Testing the order of the events (OOP), calling " +
+                 "preventDefault() at \"keydown\" event in child process",
     expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                         kParent | kKeyDownEvent,
                         kChild | kKeyDownEvent,
                         kParent | kAfterEvent | kKeyDownEvent ],
                       [ kParent | kBeforeEvent | kKeyUpEvent,
                         kParent | kKeyUpEvent,
                         kChild | kKeyUpEvent,
                         kParent | kAfterEvent | kKeyUpEvent ] ],
     resultEvents: [],
     classifiedEvents: [ [], [] ],
     doPreventDefaultAt: kChild | kKeyDownEvent
   },
   {
-    description: "Testing the order of the events (OOP), calling preventDefault() at \"keyup\" event",
+    description: "Testing the order of the events (OOP), calling " +
+                 "preventDefault() at \"keyup\" event in parent process",
+    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
+                        kParent | kKeyDownEvent,
+                        kChild | kKeyDownEvent,
+                        kParent | kAfterEvent | kKeyDownEvent ],
+                      [ kParent | kBeforeEvent | kKeyUpEvent,
+                        kParent | kKeyUpEvent,
+                        kParent | kAfterEvent | kKeyUpEvent ] ],
+    resultEvents: [],
+    classifiedEvents: [ [], [] ],
+    doPreventDefaultAt: kParent | kKeyUpEvent
+  },
+  {
+    description: "Testing the order of the events (OOP), calling " +
+                 "preventDefault() at \"keyup\" event in child process",
     expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                         kParent | kKeyDownEvent,
                         kChild | kKeyDownEvent,
                         kParent | kAfterEvent | kKeyDownEvent ],
                       [ kParent | kBeforeEvent | kKeyUpEvent,
                         kParent | kKeyUpEvent,
                         kChild | kKeyUpEvent,
                         kParent | kAfterEvent | kKeyUpEvent ] ],
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLCanvasElement.h"
 
 #include "ImageEncoder.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "Layers.h"
+#include "mozilla/Assertions.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/HTMLCanvasElementBinding.h"
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/gfx/Rect.h"
@@ -154,16 +155,20 @@ HTMLCanvasElement::GetWidthHeight()
   }
 
   if ((value = GetParsedAttr(nsGkAtoms::height)) &&
       value->Type() == nsAttrValue::eInteger)
   {
       size.height = value->GetIntegerValue();
   }
 
+  MOZ_ASSERT(size.width >= 0 && size.height >= 0,
+             "we should've required <canvas> width/height attrs to be "
+             "unsigned (non-negative) values");
+
   return size;
 }
 
 NS_IMPL_UINT_ATTR_DEFAULT_VALUE(HTMLCanvasElement, Width, width, DEFAULT_CANVAS_WIDTH)
 NS_IMPL_UINT_ATTR_DEFAULT_VALUE(HTMLCanvasElement, Height, height, DEFAULT_CANVAS_HEIGHT)
 NS_IMPL_BOOL_ATTR(HTMLCanvasElement, MozOpaque, moz_opaque)
 
 nsresult
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -2146,66 +2146,64 @@ nsresult
 HTMLInputElement::GetValueIfStepped(int32_t aStep,
                                     StepCallerType aCallerType,
                                     Decimal* aNextStep)
 {
   if (!DoStepDownStepUpApply()) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
+  Decimal stepBase = GetStepBase();
   Decimal step = GetStep();
   if (step == kStepAny) {
     if (aCallerType != CALLED_FOR_USER_EVENT) {
       return NS_ERROR_DOM_INVALID_STATE_ERR;
     }
     // Allow the spin buttons and up/down arrow keys to do something sensible:
     step = GetDefaultStep();
   }
 
-  Decimal value = GetValueAsDecimal();
-  if (value.isNaN()) {
-    value = Decimal(0);
-  }
-
   Decimal minimum = GetMinimum();
-
   Decimal maximum = GetMaximum();
+
   if (!maximum.isNaN()) {
     // "max - (max - stepBase) % step" is the nearest valid value to max.
-    maximum = maximum - NS_floorModulo(maximum - GetStepBase(), step);
-  }
-
-  // Cases where we are clearly going in the wrong way.
-  // We don't use ValidityState because we can be higher than the maximal
-  // allowed value and still not suffer from range overflow in the case of
-  // of the value specified in @max isn't in the step.
-  if ((value <= minimum && aStep < 0) ||
-      (value >= maximum && aStep > 0)) {
-    return NS_OK;
-  }
-
-  // If the current value isn't aligned on a step, then shift the value to the
-  // nearest step that will cause the addition of aStep steps (further below)
-  // to |value| to hit the required value.
-  // (Instead of using GetValidityState(VALIDITY_STATE_STEP_MISMATCH) we have
-  // to check HasStepMismatch and pass true as its aUseZeroIfValueNaN argument
-  // since we need to treat the value "" as zero for stepping purposes even
-  // though we don't suffer from a step mismatch when our value is the empty
-  // string.)
-  if (HasStepMismatch(true) &&
-      value != minimum && value != maximum) {
+    maximum = maximum - NS_floorModulo(maximum - stepBase, step);
+    if (!minimum.isNaN()) {
+      if (minimum > maximum) {
+        // Either the minimum was greater than the maximum prior to our
+        // adjustment to align maximum on a step, or else (if we adjusted
+        // maximum) there is no valid step between minimum and the unadjusted
+        // maximum.
+        return NS_OK;
+      }
+    }
+  }
+
+  Decimal value = GetValueAsDecimal();
+  bool valueWasNaN = false;
+  if (value.isNaN()) {
+    value = Decimal(0);
+    valueWasNaN = true;
+  }
+  Decimal valueBeforeStepping = value;
+
+  Decimal deltaFromStep = NS_floorModulo(value - stepBase, step);
+
+  if (deltaFromStep != Decimal(0)) {
     if (aStep > 0) {
-      value -= NS_floorModulo(value - GetStepBase(), step);
+      value += step - deltaFromStep;      // partial step
+      value += step * Decimal(aStep - 1); // then remaining steps
     } else if (aStep < 0) {
-      value -= NS_floorModulo(value - GetStepBase(), step);
-      value += step;
-    }
-  }
-
-  value += step * Decimal(aStep);
+      value -= deltaFromStep;             // partial step
+      value += step * Decimal(aStep + 1); // then remaining steps
+    }
+  } else {
+    value += step * Decimal(aStep);
+  }
 
   // For date inputs, the value can hold a string that is not a day. We do not
   // want to round it, as it might result in a step mismatch. Instead we want to
   // clamp to the next valid value.
   if (mType == NS_FORM_INPUT_DATE &&
       NS_floorModulo(Decimal(value - GetStepBase()), GetStepScaleFactor()) != Decimal(0)) {
     MOZ_ASSERT(GetStep() > Decimal(0));
     Decimal validStep = EuclidLCM<Decimal>(GetStep().floor(),
@@ -2213,37 +2211,40 @@ HTMLInputElement::GetValueIfStepped(int3
     if (aStep > 0) {
       value -= NS_floorModulo(value - GetStepBase(), validStep);
       value += validStep;
     } else if (aStep < 0) {
       value -= NS_floorModulo(value - GetStepBase(), validStep);
     }
   }
 
-  // When stepUp() is called and the value is below minimum, we should clamp on
-  // minimum unless stepUp() moves us higher than minimum.
-  if (GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW) && aStep > 0 &&
-      value <= minimum) {
-    MOZ_ASSERT(!minimum.isNaN(), "Can't be NaN if we are here");
+  if (value < minimum) {
     value = minimum;
-  // Same goes for stepDown() and maximum.
-  } else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) && aStep < 0 &&
-             value >= maximum) {
-    MOZ_ASSERT(!maximum.isNaN(), "Can't be NaN if we are here");
+    deltaFromStep = NS_floorModulo(value - stepBase, step);
+    if (deltaFromStep != Decimal(0)) {
+      value += step - deltaFromStep;
+    }
+  }
+  if (value > maximum) {
     value = maximum;
-  // If we go down, we want to clamp on min.
-  } else if (aStep < 0 && minimum == minimum) {
-    value = std::max(value, minimum);
-  // If we go up, we want to clamp on max.
-  } else if (aStep > 0 && maximum == maximum) {
-    value = std::min(value, maximum);
+    deltaFromStep = NS_floorModulo(value - stepBase, step);
+    if (deltaFromStep != Decimal(0)) {
+      value -= deltaFromStep;
+    }
+  }
+
+  if (!valueWasNaN && // value="", resulting in us using "0"
+      ((aStep > 0 && value < valueBeforeStepping) ||
+       (aStep < 0 && value > valueBeforeStepping))) {
+    // We don't want step-up to effectively step down, or step-down to
+    // effectively step up, so return;
+    return NS_OK;
   }
 
   *aNextStep = value;
-
   return NS_OK;
 }
 
 nsresult
 HTMLInputElement::ApplyStep(int32_t aStep)
 {
   Decimal nextStep = Decimal::nan(); // unchanged if value will not change
 
@@ -3696,17 +3697,20 @@ HTMLInputElement::StopNumberControlSpinn
       numberControlFrame->SpinnerStateChanged();
     }
   }
 }
 
 void
 HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection)
 {
-  if (!IsValid()) {
+  // We can't use GetValidityState here because the validity state is not set
+  // if the user hasn't previously taken an action to set or change the value,
+  // according to the specs.
+  if (HasBadInput()) {
     // If the user has typed a value into the control and inadvertently made a
     // mistake (e.g. put a thousand separator at the wrong point) we do not
     // want to wipe out what they typed if they try to increment/decrement the
     // value. Better is to highlight the value as being invalid so that they
     // can correct what they typed.
     // We only do this if there actually is a value typed in by/displayed to
     // the user. (IsValid() can return false if the 'required' attribute is
     // set and the value is the empty string.)
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -900,17 +900,17 @@ nsHTMLDocument::GetDomain(nsAString& aDo
 }
 
 void
 nsHTMLDocument::GetDomain(nsAString& aDomain, ErrorResult& rv)
 {
   nsCOMPtr<nsIURI> uri = GetDomainURI();
 
   if (!uri) {
-    rv.Throw(NS_ERROR_FAILURE);
+    SetDOMStringToNull(aDomain);
     return;
   }
 
   nsAutoCString hostName;
 
   if (NS_SUCCEEDED(uri->GetHost(hostName))) {
     CopyUTF8toUTF16(hostName, aDomain);
   } else {
--- a/dom/html/test/forms/test_stepup_stepdown.html
+++ b/dom/html/test/forms/test_stepup_stepdown.html
@@ -164,17 +164,23 @@ function checkStepDown()
     [ '9',  '2',   '-10',  null,  null, '8',    false ],
     [ '7',  '3',   '-10',  null,  null, '5',    false ],
     [ '-2', '3',   '-10',  null,  null, '-4',   false ],
     // Clamping.
     [ '0',  '2',    '-1',  null,  null, '-1',   false ],
     [ '10', '2',    '0',   '4',   '10', '0',    false ],
     [ '10', '2',    '0',   '4',   '5',  '0',    false ],
     // value = "" (NaN).
-    [ '',   null,   null,  null,  null, '-1',     false ],
+    [ '',   null,   null,  null,  null, '-1',   false ],
+    [ '',    '2',   null,  null,  null, '-2',   false ],
+    [ '',    '2',    '3',  null,  null,  '3',   false ],
+    [ '',   null,    '3',  null,  null,  '3',   false ],
+    [ '',    '2',    '3',   '8',  null,  '3',   false ],
+    [ '',   null,  '-10',  '10',  null, '-1',   false ],
+    [ '',    '3',  '-10',  '10',  null, '-1',   false ],
     // With step = 'any'.
     [ '0',  'any',  null,  null,  1,    null,   true ],
     [ '0',  'ANY',  null,  null,  1,    null,   true ],
     [ '0',  'AnY',  null,  null,  1,    null,   true ],
     [ '0',  'aNy',  null,  null,  1,    null,   true ],
     // With @value = step base.
     [ '1',  '2',    null,  null,  null, '-1',   false ],
   ]},
@@ -479,17 +485,24 @@ function checkStepUp()
     [ '1',  '2',    '0',  '3',   null,  '2',   false ],
     [ '0',  '5',    '1',  '8',   '10',  '6',   false ],
     [ '-9', '3',    '-8', '-1',  '5',   '-2',  false ],
     [ '-9', '3',    '8',  '15',  '15',  '14',  false ],
     [ '-1', '3',    '-1', '4',   '3',   '2',   false ],
     [ '-3', '2',    '-6',  '-2',  null, '-2',  false ],
     [ '-3', '2',    '-6',  '-1',  null, '-2',  false ],
     // value = "" (NaN).
-    [ '',   null,   null,  null,  null, '1',    false ],
+    [ '',   null,   null,  null,  null,  '1',  false ],
+    [ '',   null,   null,  null,  null,  '1',  false ],
+    [ '',    '2',   null,  null,  null,  '2',  false ],
+    [ '',    '2',    '3',  null,  null,  '3',  false ],
+    [ '',   null,    '3',  null,  null,  '3',  false ],
+    [ '',    '2',    '3',   '8',  null,  '3',  false ],
+    [ '',   null,  '-10',  '10',  null,  '1',  false ],
+    [ '',    '3',  '-10',  '10',  null,  '2',  false ],
     // With step = 'any'.
     [ '0',  'any',  null,  null,  1,    null,  true ],
     [ '0',  'ANY',  null,  null,  1,    null,  true ],
     [ '0',  'AnY',  null,  null,  1,    null,  true ],
     [ '0',  'aNy',  null,  null,  1,    null,  true ],
     // With @value = step base.
     [ '1',  '2',    null,  null,  null, '3',   false ],
   ]},
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/head.js
@@ -0,0 +1,348 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
+
+const PREF_KEY_RIL_DEBUGGING_ENABLED = "ril.debugging.enabled";
+
+// The pin code hard coded in emulator is "0000".
+const DEFAULT_PIN = "0000";
+// The puk code hard coded in emulator is "12345678".
+const DEFAULT_PUK = "12345678";
+
+// Emulate Promise.jsm semantics.
+Promise.defer = function() { return new Deferred(); }
+function Deferred() {
+  this.promise = new Promise(function(resolve, reject) {
+    this.resolve = resolve;
+    this.reject = reject;
+  }.bind(this));
+  Object.freeze(this);
+}
+
+let _pendingEmulatorCmdCount = 0;
+
+/**
+ * Send emulator command with safe guard.
+ *
+ * We should only call |finish()| after all emulator command transactions
+ * end, so here comes with the pending counter.  Resolve when the emulator
+ * gives positive response, and reject otherwise.
+ *
+ * Fulfill params:
+ *   result -- an array of emulator response lines.
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @param aCommand
+ *        A string command to be passed to emulator through its telnet console.
+ *
+ * @return A deferred promise.
+ */
+function runEmulatorCmdSafe(aCommand) {
+  let deferred = Promise.defer();
+
+  ++_pendingEmulatorCmdCount;
+  runEmulatorCmd(aCommand, function(aResult) {
+    --_pendingEmulatorCmdCount;
+
+    ok(true, "Emulator response: " + JSON.stringify(aResult));
+    if (Array.isArray(aResult) &&
+        aResult[aResult.length - 1] === "OK") {
+      deferred.resolve(aResult);
+    } else {
+      deferred.reject(aResult);
+    }
+  });
+
+  return deferred.promise;
+}
+
+let workingFrame;
+let iccManager;
+
+/**
+ * Push required permissions and test if
+ * |navigator.mozIccManager| exists. Resolve if it does,
+ * reject otherwise.
+ *
+ * Fulfill params:
+ *   iccManager -- an reference to navigator.mozIccManager.
+ *
+ * Reject params: (none)
+ *
+ * @param aAdditonalPermissions [optional]
+ *        An array of permission strings other than "mobileconnection" to be
+ *        pushed. Default: empty string.
+ *
+ * @return A deferred promise.
+ */
+function ensureIccManager(aAdditionalPermissions) {
+  let deferred = Promise.defer();
+
+  aAdditionalPermissions = aAdditionalPermissions || [];
+
+  if (aAdditionalPermissions.indexOf("mobileconnection") < 0) {
+    aAdditionalPermissions.push("mobileconnection");
+  }
+  let permissions = [];
+  for (let perm of aAdditionalPermissions) {
+    permissions.push({ "type": perm, "allow": 1, "context": document });
+  }
+
+  SpecialPowers.pushPermissions(permissions, function() {
+    ok(true, "permissions pushed: " + JSON.stringify(permissions));
+
+    // Permission changes can't change existing Navigator.prototype
+    // objects, so grab our objects from a new Navigator.
+    workingFrame = document.createElement("iframe");
+    workingFrame.addEventListener("load", function load() {
+      workingFrame.removeEventListener("load", load);
+
+      iccManager = workingFrame.contentWindow.navigator.mozIccManager;
+
+      if (iccManager) {
+        ok(true, "navigator.mozIccManager is instance of " + iccManager.constructor);
+      } else {
+        ok(true, "navigator.mozIccManager is undefined");
+      }
+
+      if (iccManager instanceof MozIccManager) {
+        deferred.resolve(iccManager);
+      } else {
+        deferred.reject();
+      }
+    });
+
+    document.body.appendChild(workingFrame);
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Get MozIcc by IccId
+ *
+ * @param aIccId [optional]
+ *        Default: The first item of |aIccManager.iccIds|.
+ *
+ * @return A MozIcc.
+ */
+function getMozIcc(aIccId) {
+  aIccId = aIccId || iccManager.iccIds[0];
+
+  if (!aIccId) {
+    ok(true, "iccManager.iccIds[0] is undefined");
+    return null;
+  }
+
+  return iccManager.getIccById(aIccId);
+}
+
+/**
+ * Get MozMobileConnection by ServiceId
+ *
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id. Default: 0 if not indicated.
+ *
+ * @return A MozMobileConnection.
+ */
+function getMozMobileConnectionByServiceId(aServiceId) {
+  aServiceId = aServiceId || 0;
+  return workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId];
+}
+
+/**
+ * Set radio enabling state.
+ *
+ * Resolve no matter the request succeeds or fails. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aEnabled
+ *        A boolean state.
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id.
+ *
+ * @return A deferred promise.
+ */
+function setRadioEnabled(aEnabled, aServiceId) {
+  return getMozMobileConnectionByServiceId(aServiceId).setRadioEnabled(aEnabled)
+    .then(() => {
+      ok(true, "setRadioEnabled " + aEnabled + " on " + aServiceId + " success.");
+    }, (aError) => {
+      ok(false, "setRadioEnabled " + aEnabled + " on " + aServiceId + " " +
+         aError.name);
+    });
+}
+
+/**
+ * Wait for one named event.
+ *
+ * Resolve if that named event occurs.  Never reject.
+ *
+ * Fulfill params: the DOMEvent passed.
+ *
+ * @param aEventTarget
+ *        An EventTarget object.
+ * @param aEventName
+ *        A string event name.
+ * @param aMatchFun [optional]
+ *        A matching function returns true or false to filter the event.
+ *
+ * @return A deferred promise.
+ */
+function waitForTargetEvent(aEventTarget, aEventName, aMatchFun) {
+  let deferred = Promise.defer();
+
+  aEventTarget.addEventListener(aEventName, function onevent(aEvent) {
+    if (!aMatchFun || aMatchFun(aEvent)) {
+      aEventTarget.removeEventListener(aEventName, onevent);
+      ok(true, "Event '" + aEventName + "' got.");
+      deferred.resolve(aEvent);
+    }
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Set radio enabling state and wait for "radiostatechange" event.
+ *
+ * Resolve if radio state changed to the expected one. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aEnabled
+ *        A boolean state.
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id. Default: the one indicated in
+ *        start*TestCommon() or 0 if not indicated.
+ *
+ * @return A deferred promise.
+ */
+function setRadioEnabledAndWait(aEnabled, aServiceId) {
+  let mobileConn = getMozMobileConnectionByServiceId(aServiceId);
+  let promises = [];
+
+  promises.push(waitForTargetEvent(mobileConn, "radiostatechange", function() {
+    // To ignore some transient states, we only resolve that deferred promise
+    // when |radioState| equals to the expected one.
+    return mobileConn.radioState === (aEnabled ? "enabled" : "disabled");
+  }));
+  promises.push(setRadioEnabled(aEnabled, aServiceId));
+
+  return Promise.all(promises);
+}
+
+/**
+ * Restart radio and wait card state changes to expected one.
+ *
+ * Resolve if card state changed to the expected one. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aCardState
+ *        Expected card state.
+ *
+ * @return A deferred promise.
+ */
+function restartRadioAndWait(aCardState) {
+  return setRadioEnabledAndWait(false).then(() => {
+    let promises = [];
+
+    promises.push(waitForTargetEvent(iccManager, "iccdetected")
+      .then((aEvent) => {
+        let icc = getMozIcc(aEvent.iccId);
+        if (icc.cardState !== aCardState) {
+          return waitForTargetEvent(icc, "cardstatechange", function() {
+            return icc.cardState === aCardState;
+          });
+        }
+      }));
+    promises.push(setRadioEnabledAndWait(true));
+
+    return Promise.all(promises);
+  });
+}
+
+/**
+ * Enable/Disable PIN-lock.
+ *
+ * Fulfill params: (none)
+ * Reject params:
+ *   An object contains error name and remaining retry count.
+ *   @see IccCardLockError
+ *
+ * @param aIcc
+ *        A MozIcc object.
+ * @param aEnabled
+ *        A boolean state.
+ *
+ * @return A deferred promise.
+ */
+function setPinLockEnabled(aIcc, aEnabled) {
+  let options = {
+    lockType: "pin",
+    enabled: aEnabled,
+    pin: DEFAULT_PIN
+  };
+
+  return aIcc.setCardLock(options);
+}
+
+/**
+ * Wait for pending emulator transactions and call |finish()|.
+ */
+function cleanUp() {
+  // Use ok here so that we have at least one test run.
+  ok(true, ":: CLEANING UP ::");
+
+  waitFor(finish, function() {
+    return _pendingEmulatorCmdCount === 0;
+  });
+}
+
+/**
+ * Basic test routine helper for icc tests.
+ *
+ * This helper does nothing but clean-ups.
+ *
+ * @param aTestCaseMain
+ *        A function that takes no parameter.
+ */
+function startTestBase(aTestCaseMain) {
+  // Turn on debugging pref.
+  let debugPref = SpecialPowers.getBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED);
+  SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, true);
+
+  Promise.resolve()
+    .then(aTestCaseMain)
+    .catch((aError) => {
+      ok(false, "promise rejects during test: " + aError);
+    })
+    .then(() => {
+      // Restore debugging pref.
+      SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, debugPref);
+      cleanUp();
+    });
+}
+
+/**
+ * Common test routine helper for icc tests.
+ *
+ * This function ensures global variable |iccManager| and |icc| is available
+ * during the process and performs clean-ups as well.
+ *
+ * @param aTestCaseMain
+ *        A function that takes one parameter -- icc.
+ * @param aAdditonalPermissions [optional]
+ *        An array of permission strings other than "mobileconnection" to be
+ *        pushed. Default: empty string..
+ */
+function startTestCommon(aTestCaseMain, aAdditionalPermissions) {
+  startTestBase(function() {
+    return ensureIccManager(aAdditionalPermissions)
+      .then(aTestCaseMain);
+  });
+}
--- a/dom/icc/tests/marionette/manifest.ini
+++ b/dom/icc/tests/marionette/manifest.ini
@@ -1,16 +1,20 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
 [test_stk_proactive_command.js]
 [test_icc_contact.js]
-[test_icc_card_lock.js]
+[test_icc_card_lock_get_retry_count.js]
+[test_icc_card_lock_change_pin.js]
+[test_icc_card_lock_enable_pin.js]
+[test_icc_card_lock_unlock_pin.js]
+[test_icc_card_lock_unlock_puk.js]
 [test_icc_card_state.js]
 [test_icc_info.js]
 [test_stk_refresh.js]
 [test_stk_poll_off.js]
 [test_stk_setup_event_list.js]
 [test_stk_setup_call.js]
 [test_stk_send_ss.js]
 [test_stk_send_ussd.js]
rename from dom/icc/tests/marionette/test_icc_card_lock.js
rename to dom/icc/tests/marionette/test_icc_card_lock_change_pin.js
--- a/dom/icc/tests/marionette/test_icc_card_lock.js
+++ b/dom/icc/tests/marionette/test_icc_card_lock_change_pin.js
@@ -1,126 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 30000;
-MARIONETTE_HEAD_JS = "icc_header.js";
-
-/* Test PIN code changes fail */
-taskHelper.push(function testPinChangeFailed() {
-  // The default pin is '0000' in emulator
-  let request = icc.setCardLock(
-    {lockType: "pin",
-     pin: "1111",
-     newPin: "0000"});
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-  ok(request instanceof DOMRequest,
-     "request instanceof " + request.constructor);
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
 
-  request.onerror = function onerror() {
-    is(request.error.name, "IncorrectPassword");
-    // The default pin retries is 3, failed once becomes to 2
-    is(request.error.retryCount, 2);
-
-    // Reset pin retries by passing correct pin code.
-    let resetRequest = icc.setCardLock(
-      {lockType: "pin",
-       pin: "0000",
-       newPin: "0000"});
+const LOCK_TYPE = "pin";
 
-    resetRequest.onsuccess = function onsuccess() {
-      taskHelper.runNext();
-    };
-
-    resetRequest.onerror = function onerror() {
-      ok(false, "Reset pin retries got error: " + request.error.name);
-      taskHelper.runNext();
-    };
-  };
-});
-
-/* Test PIN code changes success */
-taskHelper.push(function testPinChangeSuccess() {
-  // The default pin is '0000' in emulator
-  let request = icc.setCardLock(
-    {lockType: "pin",
-     pin: "0000",
-     newPin: "0000"});
-
-  ok(request instanceof DOMRequest,
-     "request instanceof " + request.constructor);
-
-  request.onerror = function onerror() {
-    ok(false, "Should not fail, got error: " + request.error.name);
-
-    taskHelper.runNext();
-  };
-
-  request.onsuccess = function onsuccess() {
-    taskHelper.runNext();
-  };
-});
+function testChangePin(aIcc, aPin, aNewPin, aErrorName, aRetryCount) {
+  log("testChangePin for pin=" + aPin + " and newPin=" + aNewPin);
+  return aIcc.setCardLock({ lockType: LOCK_TYPE, pin: aPin, newPin: aNewPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "changing pin should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "changing pin should not fail");
+        return;
+      }
 
-/* Read PIN-lock retry count */
-taskHelper.push(function testPinCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('pin');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
+      // check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
 
-  request.onsuccess = function onsuccess() {
-    ok(request.result.retryCount >= 0,
-        'retryCount is ' + request.result.retryCount);
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    // The operation is optional any might not be supported for all
-    // all locks. In this case, we generate 'NotSupportedError' for
-    // the valid lock types.
-    is(request.error.name, 'RequestNotSupported',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
-});
-
-/* Read PUK-lock retry count */
-taskHelper.push(function testPukCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('puk');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
 
-  request.onsuccess = function onsuccess() {
-    ok(request.result.retryCount >= 0,
-        'retryCount is ' + request.result.retryCount);
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    // The operation is optional any might not be supported for all
-    // all locks. In this case, we generate 'NotSupportedError' for
-    // the valid lock types.
-    is(request.error.name, 'RequestNotSupported',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
+  return icc.getCardLockRetryCount(LOCK_TYPE)
+    // Get current PIN-lock retry count.
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, LOCK_TYPE + " retryCount is " + retryCount);
+    })
+    // Test PIN code changes fail.
+    // The retry count should be decreased by 1.
+    .then(() => testChangePin(icc, "1111", DEFAULT_PIN, "IncorrectPassword",
+                              retryCount - 1))
+    // Test PIN code changes success. This will reset the retry count.
+    .then(() => testChangePin(icc, DEFAULT_PIN, DEFAULT_PIN));
 });
-
-/* Read lock retry count for an invalid entries  */
-taskHelper.push(function testInvalidCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('invalid-lock-type');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
-
-  request.onsuccess = function onsuccess() {
-    ok(false,
-        'request should never return success for an invalid lock type');
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    is(request.error.name, 'GenericFailure',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
-});
-
-// Start test
-taskHelper.runNext();
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_enable_pin.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function setCardLockAndCheck(aIcc, aLockType, aPin, aEnabled, aErrorName,
+                             aRetryCount) {
+  let options = {
+    lockType: aLockType,
+    enabled: aEnabled,
+    pin: aPin
+  };
+
+  return aIcc.setCardLock(options)
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "setting pin should not success");
+        return;
+      }
+
+      // Check lock state.
+      return aIcc.getCardLock(aLockType)
+        .then((aResult) => {
+          is(aResult.enabled, aEnabled, "result.enabled");
+        });
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "setting pin should not fail");
+        return;
+      }
+
+      // Check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let lockType = "pin";
+  let retryCount;
+
+  return icc.getCardLockRetryCount(lockType)
+    // Get current PIN-lock retry count.
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, lockType + " retryCount is " + retryCount);
+    })
+    // Test fail to enable PIN-lock by passing wrong pin.
+    // The retry count should be decreased by 1.
+    .then(() => setCardLockAndCheck(icc, lockType, "1111", true,
+                                    "IncorrectPassword", retryCount -1))
+    // Test enabling PIN-lock.
+    .then(() => setCardLockAndCheck(icc, lockType, DEFAULT_PIN, true))
+    // Restore pin state.
+    .then(() => setCardLockAndCheck(icc, lockType, DEFAULT_PIN, false));
+});
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_get_retry_count.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function testGetCardLockRetryCount(aIcc, aLockType, aRetryCount) {
+  log("testGetCardLockRetryCount for " + aLockType);
+  return aIcc.getCardLockRetryCount(aLockType)
+    .then((aResult) => {
+      if (!aRetryCount) {
+        ok(false, "getCardLockRetryCount(" + aLockType + ") should not success");
+        return;
+      }
+
+      // Check the request result.
+      is(aResult.retryCount, aRetryCount, "result.retryCount");
+    }, (aError) => {
+      if (aRetryCount) {
+        ok(false, "getCardLockRetryCount(" + aLockType + ") should not fail");
+        return;
+      }
+
+      // Check the error.
+      is(aError.name, "GenericFailure", "error.name");
+    });
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+
+  // Read PIN-lock retry count.
+  // The default PIN-lock retry count hard coded in emulator is 3.
+  return testGetCardLockRetryCount(icc, "pin", 3)
+    // Read PUK-lock retry count.
+    // The default PUK-lock retry count hard coded in emulator is 6.
+    .then(() => testGetCardLockRetryCount(icc, "puk", 6))
+    // Read lock retry count for an invalid entries.
+    .then(() => testGetCardLockRetryCount(icc, "invalid-lock-type"));
+});
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_unlock_pin.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function testUnlockPin(aIcc, aPin, aErrorName, aRetryCount) {
+  log("testUnlockPin with pin=" + aPin);
+
+  return aIcc.unlockCardLock({ lockType: "pin", pin: aPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "unlocking pin should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "unlocking pin should not fail");
+        return;
+      }
+
+      // Check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
+
+function testUnlockPinAndWait(aIcc, aPin, aCardState) {
+  log("testUnlockPin with pin=" + aPin + ", and wait cardState changes to '" +
+      aCardState + "'");
+
+  let promises = [];
+
+  promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() {
+    return aIcc.cardState === aCardState;
+  }));
+  promises.push(testUnlockPin(aIcc, aPin));
+
+  return Promise.all(promises);
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
+
+  // Enable PIN-lock.
+  return setPinLockEnabled(icc, true)
+    // Reset card state to "pinRequired" by restarting radio
+    .then(() => restartRadioAndWait("pinRequired"))
+    .then(() => { icc = getMozIcc(); })
+
+    // Get current PIN-lock retry count.
+    .then(() => icc.getCardLockRetryCount("pin"))
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, "pin retryCount is " + retryCount);
+    })
+
+    // Test fail to unlock PIN-lock.
+    // The retry count should be decreased by 1.
+    .then(() => testUnlockPin(icc, "1111", "IncorrectPassword", retryCount - 1))
+
+    // Test success to unlock PIN-lock.
+    .then(() => testUnlockPinAndWait(icc, DEFAULT_PIN, "ready"))
+
+    // Restore pin state.
+    .then(() => setPinLockEnabled(icc, false));
+});
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_unlock_puk.js
@@ -0,0 +1,97 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function passingWrongPinAndWait(aIcc) {
+  return aIcc.getCardLockRetryCount("pin").then((aResult) => {
+    let promises = [];
+    let retryCount = aResult.retryCount;
+
+    ok(true, "pin retryCount is " + retryCount);
+
+    promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() {
+      return aIcc.cardState === "pukRequired";
+    }));
+
+    for (let i = 0; i < retryCount; i++) {
+      promises.push(aIcc.unlockCardLock({ lockType: "pin", pin: "1111" })
+        .then(() => {
+          ok(false, "unlocking pin should not success");
+        }, function reject(aRetryCount, aError) {
+          // check the request error.
+          is(aError.name, "IncorrectPassword", "error.name");
+          is(aError.retryCount, aRetryCount, "error.retryCount");
+        }.bind(null, retryCount - i - 1)));
+    }
+
+    return Promise.all(promises);
+  });
+}
+
+function testUnlockPuk(aIcc, aPuk, aNewPin, aErrorName, aRetryCount) {
+  log("testUnlockPuk with puk=" + aPuk + " and newPin=" + aNewPin);
+
+  return aIcc.unlockCardLock({ lockType: "puk", puk: aPuk, newPin: aNewPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "unlocking puk should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "unlocking puk should not fail");
+        return;
+      }
+
+      // Check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
+
+function testUnlockPukAndWait(aIcc, aPuk, aNewPin, aCardState) {
+  log("testUnlockPuk with puk=" + aPuk + "/newPin=" + aNewPin +
+      ", and wait card state changes to '" + aCardState + "'");
+
+  let promises = [];
+
+  promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() {
+    return aIcc.cardState === aCardState;
+  }));
+  promises.push(testUnlockPuk(aIcc, aPuk, aNewPin));
+
+  return Promise.all(promises);
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
+
+  // Enable pin lock.
+  return setPinLockEnabled(icc, true)
+    // Reset card state to "pinRequired" by restarting radio
+    .then(() => restartRadioAndWait("pinRequired"))
+    .then(() => { icc = getMozIcc() })
+    // Switch cardState to "pukRequired" by entering wrong pin code.
+    .then(() => passingWrongPinAndWait(icc))
+
+    // Get current PUK-lock retry count.
+    .then(() => icc.getCardLockRetryCount("puk"))
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, "puk retryCount is " + retryCount);
+    })
+
+    // Test unlock PUK code fail.
+    // The retry count should be decreased by 1.
+    .then(() => testUnlockPuk(icc, "11111111", DEFAULT_PIN, "IncorrectPassword",
+                              retryCount - 1))
+
+    // Test unlock PUK code success.
+    .then(() => testUnlockPukAndWait(icc, DEFAULT_PUK, DEFAULT_PIN, "ready"))
+
+    // Restore pin state.
+    .then(() => setPinLockEnabled(icc, false));
+});
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -623,17 +623,17 @@ public:
     if (aData.tag == SCTAG_DOM_BLOB) {
       if (NS_WARN_IF(!ResolveMysteryBlob(aFile.mFile,
                                          aData.type,
                                          aData.size))) {
         return false;
       }
 
       JS::Rooted<JS::Value> wrappedBlob(aCx);
-      if (!WrapNewBindingObject(aCx, aFile.mFile, &wrappedBlob)) {
+      if (!GetOrCreateDOMReflector(aCx, aFile.mFile, &wrappedBlob)) {
         return false;
       }
 
       aResult.set(&wrappedBlob.toObject());
       return true;
     }
 
     MOZ_ASSERT(aFile.mFile->IsFile());
@@ -642,17 +642,17 @@ public:
                                        aData.name,
                                        aData.type,
                                        aData.size,
                                        aData.lastModifiedDate))) {
       return false;
     }
 
     JS::Rooted<JS::Value> wrappedFile(aCx);
-    if (!WrapNewBindingObject(aCx, aFile.mFile, &wrappedFile)) {
+    if (!GetOrCreateDOMReflector(aCx, aFile.mFile, &wrappedFile)) {
       return false;
     }
 
     aResult.set(&wrappedFile.toObject());
     return true;
   }
 };
 
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -459,17 +459,17 @@ IndexedDatabaseManager::DefineIndexedDB(
                                               getter_AddRefs(factory)))) {
     return false;
   }
 
   MOZ_ASSERT(factory, "This should never fail for chrome!");
 
   JS::Rooted<JS::Value> indexedDB(aCx);
   js::AssertSameCompartment(aCx, aGlobal);
-  if (!WrapNewBindingObject(aCx, factory, &indexedDB)) {
+  if (!GetOrCreateDOMReflector(aCx, factory, &indexedDB)) {
     return false;
   }
 
   return JS_DefineProperty(aCx, aGlobal, IDB_STR, indexedDB, JSPROP_ENUMERATE);
 }
 
 // static
 bool
--- a/dom/ipc/StructuredCloneUtils.cpp
+++ b/dom/ipc/StructuredCloneUtils.cpp
@@ -60,17 +60,17 @@ Read(JSContext* aCx, JSStructuredCloneRe
       }
 #endif
 
       // Let's create a new blob with the correct parent.
       nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
       MOZ_ASSERT(global);
 
       nsRefPtr<File> newBlob = new File(global, blob->Impl());
-      if (!WrapNewBindingObject(aCx, newBlob, &val)) {
+      if (!GetOrCreateDOMReflector(aCx, newBlob, &val)) {
         return nullptr;
       }
     }
 
     return &val.toObject();
   }
 
   return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr);
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2121,16 +2121,17 @@ MediaDecoderStateMachine::DecodeFirstFra
     nsresult res = FinishDecodeFirstFrame();
     NS_ENSURE_SUCCESS(res, res);
   } else {
     if (HasAudio()) {
       ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor());
       mReader->RequestAudioData();
     }
     if (HasVideo()) {
+      mVideoDecodeStartTime = TimeStamp::Now();
       ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor());
       mReader->RequestVideoData(false, 0);
     }
   }
 
   return NS_OK;
 }
 
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -451,16 +451,17 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo
   if (duration != -1) {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mDecoder->SetMediaDuration(duration);
   }
 
   *aInfo = mInfo;
   *aTags = nullptr;
 
+  MonitorAutoLock mon(mIndexMonitor);
   UpdateIndex();
 
   return NS_OK;
 }
 
 void
 MP4Reader::ReadUpdatedMetadata(MediaInfo* aInfo)
 {
@@ -847,26 +848,18 @@ MP4Reader::Seek(int64_t aTime,
     mDemuxer->SeekAudio(
       mQueuedVideoSample ? mQueuedVideoSample->composition_timestamp : aTime);
   }
   LOG("MP4Reader::Seek(%lld) exit", aTime);
   GetCallback()->OnSeekCompleted(NS_OK);
 }
 
 void
-MP4Reader::NotifyDataArrived(const char* aBuffer, uint32_t aLength,
-                             int64_t aOffset)
-{
-  UpdateIndex();
-}
-
-void
 MP4Reader::UpdateIndex()
 {
-  MonitorAutoLock mon(mIndexMonitor);
   if (!mIndexReady) {
     return;
   }
 
   AutoPinned<MediaResource> resource(mDecoder->GetResource());
   nsTArray<MediaByteRange> ranges;
   if (NS_SUCCEEDED(resource->GetCachedRanges(ranges))) {
     mDemuxer->UpdateIndex(ranges);
@@ -886,16 +879,17 @@ MP4Reader::GetEvictionOffset(double aTim
 
 nsresult
 MP4Reader::GetBuffered(dom::TimeRanges* aBuffered)
 {
   MonitorAutoLock mon(mIndexMonitor);
   if (!mIndexReady) {
     return NS_OK;
   }
+  UpdateIndex();
   MOZ_ASSERT(mStartTime != -1, "Need to finish metadata decode first");
 
   AutoPinned<MediaResource> resource(mDecoder->GetResource());
   nsTArray<MediaByteRange> ranges;
   nsresult rv = resource->GetCachedRanges(ranges);
 
   if (NS_SUCCEEDED(rv)) {
     nsTArray<Interval<Microseconds>> timeRanges;
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -52,19 +52,16 @@ public:
 
   virtual void Seek(int64_t aTime,
                     int64_t aStartTime,
                     int64_t aEndTime,
                     int64_t aCurrentTime) MOZ_OVERRIDE;
 
   virtual bool IsMediaSeekable() MOZ_OVERRIDE;
 
-  virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength,
-                                 int64_t aOffset) MOZ_OVERRIDE;
-
   virtual int64_t GetEvictionOffset(double aTime) MOZ_OVERRIDE;
 
   virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE;
 
   // For Media Resource Management
   virtual void SetIdle() MOZ_OVERRIDE;
   virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
   virtual bool IsDormantNeeded() MOZ_OVERRIDE;
--- a/dom/media/fmp4/gonk/GonkAudioDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkAudioDecoderManager.cpp
@@ -199,16 +199,22 @@ GonkAudioDecoderManager::Output(int64_t 
       ALOG("Decoder failed, err=%d", err);
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   return NS_OK;
 }
 
+nsresult
+GonkAudioDecoderManager::Flush()
+{
+  return NS_OK;
+}
+
 void GonkAudioDecoderManager::ReleaseAudioBuffer() {
   if (mAudioBuffer) {
     mDecoder->ReleaseMediaBuffer(mAudioBuffer);
     mAudioBuffer = nullptr;
   }
 }
 
 nsresult
--- a/dom/media/fmp4/gonk/GonkAudioDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkAudioDecoderManager.h
@@ -27,16 +27,18 @@ public:
   ~GonkAudioDecoderManager();
 
   virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+
+  virtual nsresult Flush() MOZ_OVERRIDE;
 private:
 
   nsresult CreateAudioData(int64_t aStreamOffset,
                               AudioData** aOutData);
 
   void ReleaseAudioBuffer();
   // MediaCodedc's wrapper that performs the decoding.
   android::sp<MediaCodecProxy> mDecoder;
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
@@ -130,18 +130,17 @@ nsresult
 GonkMediaDataDecoder::Flush()
 {
   // Flush the input task queue. This cancels all pending Decode() calls.
   // Note this blocks until the task queue finishes its current job, if
   // it's executing at all. Note the MP4Reader ignores all output while
   // flushing.
   mTaskQueue->Flush();
 
-  status_t err = mDecoder->flush();
-  return err == OK ? NS_OK : NS_ERROR_FAILURE;
+  return mManager->Flush();
 }
 
 void
 GonkMediaDataDecoder::ProcessDrain()
 {
   // Notify decoder input EOS by sending a null data.
   ProcessDecode(nullptr);
   mSignaledEOS = true;
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
@@ -28,16 +28,17 @@ public:
   // Produces decoded output, it blocks until output can be produced or a timeout
   // is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
   // if there's not enough data to produce more output. If this returns a failure
   // code other than NS_ERROR_NOT_AVAILABLE, an error will be reported to the
   // MP4Reader.
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) = 0;
+  virtual nsresult Flush() = 0;
 
   virtual void ReleaseMediaResources() {};
 };
 
 // Samples are decoded using the GonkDecoder (MediaCodec)
 // created by the GonkDecoderManager. This class implements
 // the higher-level logic that drives mapping the Gonk to the async
 // MediaDataDecoder interface. The specifics of decoding the exact stream
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -49,16 +49,17 @@ enum {
   kNotifyCodecCanceled = 'coca',
 };
 
 GonkVideoDecoderManager::GonkVideoDecoderManager(
                            mozilla::layers::ImageContainer* aImageContainer,
 		           const mp4_demuxer::VideoDecoderConfig& aConfig)
   : mImageContainer(aImageContainer)
   , mReaderCallback(nullptr)
+  , mMonitor("GonkVideoDecoderManager")
   , mColorConverterBufferSize(0)
   , mNativeWindow(nullptr)
   , mPendingVideoBuffersLock("GonkVideoDecoderManager::mPendingVideoBuffersLock")
 {
   NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
   MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(GonkVideoDecoderManager);
   mVideoWidth  = aConfig.display_width;
@@ -116,16 +117,60 @@ GonkVideoDecoderManager::Init(MediaDataD
   if (mDecoder->getCapability(&capability) == OK && (capability &
       MediaCodecProxy::kCanExposeGraphicBuffer)) {
     mNativeWindow = new GonkNativeWindow();
   }
 
   return mDecoder;
 }
 
+void
+GonkVideoDecoderManager::QueueFrameTimeIn(int64_t aPTS, int64_t aDuration)
+{
+  MonitorAutoLock mon(mMonitor);
+  FrameTimeInfo timeInfo = {aPTS, aDuration};
+  mFrameTimeInfo.AppendElement(timeInfo);
+}
+
+nsresult
+GonkVideoDecoderManager::QueueFrameTimeOut(int64_t aPTS, int64_t& aDuration)
+{
+  MonitorAutoLock mon(mMonitor);
+
+  // Set default to 1 here.
+  // During seeking, frames could still in MediaCodec and the mFrameTimeInfo could
+  // be cleared before these frames are out from MediaCodec. This is ok because
+  // these frames are old frame before seeking.
+  aDuration = 1;
+  for (uint32_t i = 0; i < mFrameTimeInfo.Length(); i++) {
+    const FrameTimeInfo& entry = mFrameTimeInfo.ElementAt(i);
+    if (i == 0) {
+      if (entry.pts > aPTS) {
+        // Codec sent a frame with rollbacked PTS time. It could
+        // be codec's problem.
+        ReleaseVideoBuffer();
+        return NS_ERROR_NOT_AVAILABLE;
+      }
+    }
+
+    // Ideally, the first entry in mFrameTimeInfo should be the one we are looking
+    // for. However, MediaCodec could dropped frame and the first entry doesn't
+    // match current decoded frame's PTS.
+    if (entry.pts == aPTS) {
+      aDuration = entry.duration;
+      if (i > 0) {
+        LOG("Frame could be dropped by MediaCodec, %d dropped frames.", i);
+      }
+      mFrameTimeInfo.RemoveElementsAt(0, i+1);
+      break;
+    }
+  }
+  return NS_OK;
+}
+
 nsresult
 GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
 {
   *v = nullptr;
   nsRefPtr<VideoData> data;
   int64_t timeUs;
   int32_t keyFrame;
 
@@ -134,16 +179,20 @@ GonkVideoDecoderManager::CreateVideoData
     return NS_ERROR_UNEXPECTED;
   }
 
   if (!mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
     ALOG("Decoder did not return frame time");
     return NS_ERROR_UNEXPECTED;
   }
 
+  int64_t duration;
+  nsresult rv = QueueFrameTimeOut(timeUs, duration);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   if (mVideoBuffer->range_length() == 0) {
     // Some decoders may return spurious empty buffers that we just want to ignore
     // quoted from Android's AwesomePlayer.cpp
     ReleaseVideoBuffer();
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (!mVideoBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
@@ -173,17 +222,17 @@ GonkVideoDecoderManager::CreateVideoData
     GrallocTextureClientOGL* grallocClient = static_cast<GrallocTextureClientOGL*>(textureClient.get());
     grallocClient->SetMediaBuffer(mVideoBuffer);
     textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this);
 
     data = VideoData::Create(mInfo.mVideo,
                              mImageContainer,
                              aStreamOffset,
                              timeUs,
-                             1, // We don't know the duration.
+                             duration,
                              textureClient,
                              keyFrame,
                              -1,
                              picture);
   } else {
     if (!mVideoBuffer->data()) {
       ALOG("No data in Video Buffer!");
       return NS_ERROR_UNEXPECTED;
@@ -395,27 +444,42 @@ GonkVideoDecoderManager::Input(mp4_demux
     return NS_ERROR_UNEXPECTED;
   }
   status_t rv;
   if (aSample != nullptr) {
     // We must prepare samples in AVC Annex B.
     mp4_demuxer::AnnexB::ConvertSample(aSample);
     // Forward sample data to the decoder.
 
+    QueueFrameTimeIn(aSample->composition_timestamp, aSample->duration);
+
     const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
     uint32_t length = aSample->size;
     rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0);
   }
   else {
     // Inputted data is null, so it is going to notify decoder EOS
     rv = mDecoder->Input(nullptr, 0, 0ll, 0);
   }
   return (rv == OK) ? NS_OK : NS_ERROR_FAILURE;
 }
 
+nsresult
+GonkVideoDecoderManager::Flush()
+{
+  status_t err = mDecoder->flush();
+  if (err != OK) {
+    return NS_ERROR_FAILURE;
+  }
+
+  MonitorAutoLock mon(mMonitor);
+  mFrameTimeInfo.Clear();
+  return NS_OK;
+}
+
 void
 GonkVideoDecoderManager::codecReserved()
 {
   sp<AMessage> format = new AMessage;
   sp<Surface> surface;
 
   // Fixed values
   format->setString("mime", "video/avc");
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
@@ -45,16 +45,18 @@ public:
 
   virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
+  virtual nsresult Flush() MOZ_OVERRIDE;
+
   virtual void ReleaseMediaResources();
 
   static void RecycleCallback(TextureClient* aClient, void* aClosure);
 
 private:
   struct FrameInfo
   {
     int32_t mWidth = 0;
@@ -99,30 +101,42 @@ private:
     VideoResourceListener() MOZ_DELETE;
     VideoResourceListener(const VideoResourceListener &rhs) MOZ_DELETE;
     const VideoResourceListener &operator=(const VideoResourceListener &rhs) MOZ_DELETE;
 
     GonkVideoDecoderManager *mManager;
   };
   friend class VideoResourceListener;
 
+  // FrameTimeInfo keeps the presentation time stamp (pts) and its duration.
+  // On MediaDecoderStateMachine, it needs pts and duration to display decoded
+  // frame correctly. But OMX can carry one field of time info (kKeyTime) so
+  // we use FrameTimeInfo to keep pts and duration.
+  struct FrameTimeInfo {
+    int64_t pts;       // presentation time stamp of this frame.
+    int64_t duration;  // the playback duration.
+  };
+
   bool SetVideoFormat();
 
   nsresult CreateVideoData(int64_t aStreamOffset, VideoData** aOutData);
   void ReleaseVideoBuffer();
   uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
 
   // For codec resource management
   void codecReserved();
   void codecCanceled();
   void onMessageReceived(const sp<AMessage> &aMessage);
 
   void ReleaseAllPendingVideoBuffers();
   void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer);
 
+  void QueueFrameTimeIn(int64_t aPTS, int64_t aDuration);
+  nsresult QueueFrameTimeOut(int64_t aPTS, int64_t& aDuration);
+
   uint32_t mVideoWidth;
   uint32_t mVideoHeight;
   uint32_t mDisplayWidth;
   uint32_t mDisplayHeight;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
 
   android::sp<MediaCodecProxy> mDecoder;
@@ -134,16 +148,24 @@ private:
   MediaDataDecoderCallback*  mReaderCallback;
   MediaInfo mInfo;
   android::sp<VideoResourceListener> mVideoListener;
   android::sp<MessageHandler> mHandler;
   android::sp<ALooper> mLooper;
   android::sp<ALooper> mManagerLooper;
   FrameInfo mFrameInfo;
 
+  // It protects mFrameTimeInfo.
+  Monitor mMonitor;
+  // Array of FrameTimeInfo whose corresponding frames are sent to OMX.
+  // Ideally, it is a FIFO. Input() adds the entry to the end element and
+  // CreateVideoData() takes the first entry. However, there are exceptions
+  // due to MediaCodec error or seeking.
+  nsTArray<FrameTimeInfo> mFrameTimeInfo;
+
   // color converter
   android::I420ColorConverterHelper mColorConverter;
   nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
   size_t mColorConverterBufferSize;
 
   android::sp<android::GonkNativeWindow> mNativeWindow;
   enum {
     kNotifyPostReleaseBuffer = 'nprb',
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -271,16 +271,21 @@ public:
     }
     aStart = compositionRange.start;
     aEnd = compositionRange.end;
     MSE_DEBUG("MP4ContainerParser(%p)::ParseStartAndEndTimestamps: [%lld, %lld]",
               this, aStart, aEnd);
     return true;
   }
 
+  bool TimestampsFuzzyEqual(int64_t aLhs, int64_t aRhs)
+  {
+    return llabs(aLhs - aRhs) <= 1000;
+  }
+
 private:
   nsRefPtr<mp4_demuxer::BufferStream> mStream;
   nsAutoPtr<mp4_demuxer::MoofParser> mParser;
 };
 
 /*static*/ ContainerParser*
 ContainerParser::CreateForMIMEType(const nsACString& aType)
 {
--- a/dom/media/webaudio/AudioNodeExternalInputStream.cpp
+++ b/dom/media/webaudio/AudioNodeExternalInputStream.cpp
@@ -103,17 +103,17 @@ static void ConvertSegmentToAudioBlock(A
   }
 }
 
 void
 AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
                                            uint32_t aFlags)
 {
   // According to spec, number of outputs is always 1.
-  mLastChunks.SetLength(1);
+  MOZ_ASSERT(mLastChunks.Length() == 1);
 
   // GC stuff can result in our input stream being destroyed before this stream.
   // Handle that.
   if (!IsEnabled() || mInputs.IsEmpty() || mPassThrough) {
     mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
     AdvanceOutputSegment();
     return;
   }
--- a/dom/media/webaudio/AudioNodeStream.cpp
+++ b/dom/media/webaudio/AudioNodeStream.cpp
@@ -20,16 +20,37 @@ namespace mozilla {
  * An AudioNodeStream produces a single audio track with ID
  * AUDIO_TRACK. This track has rate AudioContext::sIdealAudioRate
  * for regular audio contexts, and the rate requested by the web content
  * for offline audio contexts.
  * Each chunk in the track is a single block of WEBAUDIO_BLOCK_SIZE samples.
  * Note: This must be a different value than MEDIA_STREAM_DEST_TRACK_ID
  */
 
+AudioNodeStream::AudioNodeStream(AudioNodeEngine* aEngine,
+                                 MediaStreamGraph::AudioNodeStreamKind aKind,
+                                 TrackRate aSampleRate)
+  : ProcessedMediaStream(nullptr),
+    mEngine(aEngine),
+    mSampleRate(aSampleRate),
+    mKind(aKind),
+    mNumberOfInputChannels(2),
+    mMarkAsFinishedAfterThisBlock(false),
+    mAudioParamStream(false),
+    mPassThrough(false)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mChannelCountMode = ChannelCountMode::Max;
+  mChannelInterpretation = ChannelInterpretation::Speakers;
+  // AudioNodes are always producing data
+  mHasCurrentData = true;
+  mLastChunks.SetLength(std::max(uint16_t(1), mEngine->OutputCount()));
+  MOZ_COUNT_CTOR(AudioNodeStream);
+}
+
 AudioNodeStream::~AudioNodeStream()
 {
   MOZ_COUNT_DTOR(AudioNodeStream);
 }
 
 size_t
 AudioNodeStream::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
@@ -445,18 +466,18 @@ void
 AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
 {
   if (!mFinished) {
     EnsureTrack(AUDIO_TRACK);
   }
   // No more tracks will be coming
   mBuffer.AdvanceKnownTracksTime(STREAM_TIME_MAX);
 
-  uint16_t outputCount = std::max(uint16_t(1), mEngine->OutputCount());
-  mLastChunks.SetLength(outputCount);
+  uint16_t outputCount = mLastChunks.Length();
+  MOZ_ASSERT(outputCount == std::max(uint16_t(1), mEngine->OutputCount()));
 
   // Consider this stream blocked if it has already finished output. Normally
   // mBlocked would reflect this, but due to rounding errors our audio track may
   // appear to extend slightly beyond aFrom, so we might not be blocked yet.
   bool blocked = mFinished || mBlocked.GetAt(aFrom);
   // If the stream has finished at this time, it will be blocked.
   if (blocked || InMutedCycle()) {
     for (uint16_t i = 0; i < outputCount; ++i) {
@@ -470,17 +491,17 @@ AudioNodeStream::ProcessInput(GraphTime 
     for (uint16_t i = 0; i < maxInputs; ++i) {
       ObtainInputBlock(inputChunks[i], i);
     }
     bool finished = false;
     if (mPassThrough) {
       MOZ_ASSERT(outputCount == 1, "For now, we only support nodes that have one output port");
       mLastChunks[0] = inputChunks[0];
     } else {
-      if (maxInputs <= 1 && mEngine->OutputCount() <= 1) {
+      if (maxInputs <= 1 && outputCount <= 1) {
         mEngine->ProcessBlock(this, inputChunks[0], &mLastChunks[0], &finished);
       } else {
         mEngine->ProcessBlocksOnPorts(this, inputChunks, mLastChunks, &finished);
       }
     }
     for (uint16_t i = 0; i < outputCount; ++i) {
       NS_ASSERTION(mLastChunks[i].GetDuration() == WEBAUDIO_BLOCK_SIZE,
                    "Invalid WebAudio chunk size");
@@ -510,17 +531,17 @@ AudioNodeStream::ProcessInput(GraphTime 
 
 void
 AudioNodeStream::ProduceOutputBeforeInput(GraphTime aFrom)
 {
   MOZ_ASSERT(mEngine->AsDelayNodeEngine());
   MOZ_ASSERT(mEngine->OutputCount() == 1,
              "DelayNodeEngine output count should be 1");
   MOZ_ASSERT(!InMutedCycle(), "DelayNodes should break cycles");
-  mLastChunks.SetLength(1);
+  MOZ_ASSERT(mLastChunks.Length() == 1);
 
   // Consider this stream blocked if it has already finished output. Normally
   // mBlocked would reflect this, but due to rounding errors our audio track may
   // appear to extend slightly beyond aFrom, so we might not be blocked yet.
   bool blocked = mFinished || mBlocked.GetAt(aFrom);
   // If the stream has finished at this time, it will be blocked.
   if (blocked) {
     mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
--- a/dom/media/webaudio/AudioNodeStream.h
+++ b/dom/media/webaudio/AudioNodeStream.h
@@ -42,33 +42,17 @@ public:
 
   typedef nsAutoTArray<AudioChunk, 1> OutputChunks;
 
   /**
    * Transfers ownership of aEngine to the new AudioNodeStream.
    */
   AudioNodeStream(AudioNodeEngine* aEngine,
                   MediaStreamGraph::AudioNodeStreamKind aKind,
-                  TrackRate aSampleRate)
-    : ProcessedMediaStream(nullptr),
-      mEngine(aEngine),
-      mSampleRate(aSampleRate),
-      mKind(aKind),
-      mNumberOfInputChannels(2),
-      mMarkAsFinishedAfterThisBlock(false),
-      mAudioParamStream(false),
-      mPassThrough(false)
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    mChannelCountMode = ChannelCountMode::Max;
-    mChannelInterpretation = ChannelInterpretation::Speakers;
-    // AudioNodes are always producing data
-    mHasCurrentData = true;
-    MOZ_COUNT_CTOR(AudioNodeStream);
-  }
+                  TrackRate aSampleRate);
 
 protected:
   ~AudioNodeStream();
 
 public:
   // Control API
   /**
    * Sets a parameter that's a time relative to some stream's played time.
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
@@ -336,17 +336,18 @@ void
 MediaEngineGonkVideoSource::StopImpl() {
   MOZ_ASSERT(NS_IsMainThread());
 
   hal::UnregisterScreenConfigurationObserver(this);
   mCameraControl->Stop();
 }
 
 void
-MediaEngineGonkVideoSource::OnHardwareStateChange(HardwareState aState)
+MediaEngineGonkVideoSource::OnHardwareStateChange(HardwareState aState,
+                                                  nsresult aReason)
 {
   ReentrantMonitorAutoEnter sync(mCallbackMonitor);
   if (aState == CameraControlListener::kHardwareClosed) {
     // When the first CameraControl listener is added, it gets pushed
     // the current state of the camera--normally 'closed'. We only
     // pay attention to that state if we've progressed out of the
     // allocated state.
     if (mState != kAllocated) {
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.h
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.h
@@ -40,18 +40,18 @@ class MediaEngineGonkVideoSource : publi
                                  , public mozilla::hal::ScreenConfigurationObserver
                                  , public CameraControlListener
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   MediaEngineGonkVideoSource(int aIndex)
     : MediaEngineCameraVideoSource(aIndex, "GonkCamera.Monitor")
+    , mCallbackMonitor("GonkCamera.CallbackMonitor")
     , mCameraControl(nullptr)
-    , mCallbackMonitor("GonkCamera.CallbackMonitor")
     , mRotation(0)
     , mBackCamera(false)
     , mOrientationChanged(true) // Correct the orientation at first time takePhoto.
     {
       Init();
     }
 
   virtual nsresult Allocate(const VideoTrackConstraintsN &aConstraints,
@@ -65,21 +65,21 @@ public:
                           StreamTime aDesiredTime,
                           StreamTime &aLastEndTime) MOZ_OVERRIDE;
   virtual bool SatisfiesConstraintSets(
       const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
   {
     return true;
   }
 
-  void OnHardwareStateChange(HardwareState aState);
+  void OnHardwareStateChange(HardwareState aState, nsresult aReason) MOZ_OVERRIDE;
   void GetRotation();
-  bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
-  void OnUserError(UserContext aContext, nsresult aError);
-  void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType);
+  bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) MOZ_OVERRIDE;
+  void OnUserError(UserContext aContext, nsresult aError) MOZ_OVERRIDE;
+  void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType) MOZ_OVERRIDE;
 
   void AllocImpl();
   void DeallocImpl();
   void StartImpl(webrtc::CaptureCapability aCapability);
   void StopImpl();
   uint32_t ConvertPixelFormatToFOURCC(int aFormat);
   void RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
   void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration);
--- a/dom/mobilemessage/MmsMessage.cpp
+++ b/dom/mobilemessage/MmsMessage.cpp
@@ -575,17 +575,17 @@ MmsMessage::GetAttachments(JSContext* aC
     // Get |attachment.mContent|.
 
     // Duplicating the File with the correct parent object.
     nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
     MOZ_ASSERT(global);
     nsRefPtr<File> newBlob = new File(global, attachment.content->Impl());
 
     JS::Rooted<JS::Value> val(aCx);
-    if (!WrapNewBindingObject(aCx, newBlob, &val)) {
+    if (!GetOrCreateDOMReflector(aCx, newBlob, &val)) {
       return NS_ERROR_FAILURE;
     }
 
     if (!JS_DefineProperty(aCx, attachmentObj, "content", val, JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
 
     if (!JS_SetElement(aCx, attachments, i, attachmentObj)) {
--- a/dom/mobilemessage/ipc/SmsParent.cpp
+++ b/dom/mobilemessage/ipc/SmsParent.cpp
@@ -61,17 +61,17 @@ MmsAttachmentDataToJSObject(JSContext* a
   // JSObject* type means that JSObject* is on the stack as a raw pointer
   // while destructors are running.
   JS::Rooted<JS::Value> content(aContext);
   {
     nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aContext));
     MOZ_ASSERT(global);
 
     nsRefPtr<File> blob = new File(global, blobImpl);
-    if (!WrapNewBindingObject(aContext, blob, &content)) {
+    if (!GetOrCreateDOMReflector(aContext, blob, &content)) {
       return nullptr;
     }
   }
 
   if (!JS_DefineProperty(aContext, obj, "content", content, 0)) {
     return nullptr;
   }
 
--- a/dom/network/NetUtils.cpp
+++ b/dom/network/NetUtils.cpp
@@ -23,18 +23,16 @@ InitNetUtilsLib()
 
 static void*
 GetNetUtilsLibHandle()
 {
   PR_CallOnce(&sInitNetUtilsLib, InitNetUtilsLib);
   return sNetUtilsLib;
 }
 
-mozilla::Mutex NetUtils::sIfcMutex("NetUtils::sIfcMutex");
-
 // static
 void*
 NetUtils::GetSharedLibrary()
 {
   void* netLib = GetNetUtilsLibHandle();
   if (!netLib) {
     NS_WARNING("No /system/lib/libnetutils.so");
   }
@@ -65,87 +63,78 @@ DEFINE_DLFUNC(dhcp_stop, int32_t, const 
 
 NetUtils::NetUtils()
 {
 }
 
 int32_t NetUtils::do_ifc_enable(const char *ifname)
 {
   USE_DLFUNC(ifc_enable)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_enable(ifname);
 }
 
 int32_t NetUtils::do_ifc_disable(const char *ifname)
 {
   USE_DLFUNC(ifc_disable)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_disable(ifname);
 }
 
 int32_t NetUtils::do_ifc_configure(const char *ifname,
                                        in_addr_t address,
                                        uint32_t prefixLength,
                                        in_addr_t gateway,
                                        in_addr_t dns1,
                                        in_addr_t dns2)
 {
   USE_DLFUNC(ifc_configure)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   int32_t ret = ifc_configure(ifname, address, prefixLength, gateway, dns1, dns2);
   return ret;
 }
 
 int32_t NetUtils::do_ifc_reset_connections(const char *ifname,
                                                const int32_t resetMask)
 {
   USE_DLFUNC(ifc_reset_connections)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_reset_connections(ifname, resetMask);
 }
 
 int32_t NetUtils::do_ifc_set_default_route(const char *ifname,
                                            in_addr_t gateway)
 {
   USE_DLFUNC(ifc_set_default_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_set_default_route(ifname, gateway);
 }
 
 int32_t NetUtils::do_ifc_add_route(const char *ifname,
                                    const char *dst,
                                    uint32_t prefixLength,
                                    const char *gateway)
 {
   USE_DLFUNC(ifc_add_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_add_route(ifname, dst, prefixLength, gateway);
 }
 
 int32_t NetUtils::do_ifc_remove_route(const char *ifname,
                                       const char *dst,
                                       uint32_t prefixLength,
                                       const char *gateway)
 {
   USE_DLFUNC(ifc_remove_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_remove_route(ifname, dst, prefixLength, gateway);
 }
 
 int32_t NetUtils::do_ifc_remove_host_routes(const char *ifname)
 {
   USE_DLFUNC(ifc_remove_host_routes)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_remove_host_routes(ifname);
 }
 
 int32_t NetUtils::do_ifc_remove_default_route(const char *ifname)
 {
   USE_DLFUNC(ifc_remove_default_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_remove_default_route(ifname);
 }
 
 int32_t NetUtils::do_dhcp_stop(const char *ifname)
 {
   USE_DLFUNC(dhcp_stop)
   return dhcp_stop(ifname);
 }
--- a/dom/network/NetUtils.h
+++ b/dom/network/NetUtils.h
@@ -6,17 +6,16 @@
  * Abstraction on top of the network support from libnetutils that we
  * use to set up network connections.
  */
 
 #ifndef NetUtils_h
 #define NetUtils_h
 
 #include "arpa/inet.h"
-#include "mozilla/Mutex.h"
 
 // Copied from ifc.h
 #define RESET_IPV4_ADDRESSES 0x01
 #define RESET_IPV6_ADDRESSES 0x02
 #define RESET_ALL_ADDRESSES  (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES)
 
 // Implements netutils functions. No need for an abstract class here since we
 // only have a one sdk specific method (dhcp_do_request)
@@ -54,19 +53,16 @@ public:
                              uint32_t *prefixLength,
                              char *dns1,
                              char *dns2,
                              char *server,
                              uint32_t  *lease,
                              char* vendorinfo);
 
   static int32_t SdkVersion();
-
-private:
-  static mozilla::Mutex sIfcMutex;
 };
 
 // Defines a function type with the right arguments and return type.
 #define DEFINE_DLFUNC(name, ret, args...) typedef ret (*FUNC##name)(args);
 
 // Set up a dlsymed function ready to use.
 #define USE_DLFUNC(name)                                                      \
   FUNC##name name = (FUNC##name) dlsym(GetSharedLibrary(), #name);            \
--- a/dom/nfc/NfcContentHelper.js
+++ b/dom/nfc/NfcContentHelper.js
@@ -84,16 +84,17 @@ NfcContentHelper.prototype = {
   classInfo: XPCOMUtils.generateCI({
     classID:          NFCCONTENTHELPER_CID,
     classDescription: "NfcContentHelper",
     interfaces:       [Ci.nsINfcContentHelper]
   }),
 
   _window: null,
   _requestMap: null,
+  _rfState: null,
   eventListener: null,
 
   init: function init(aWindow) {
     if (aWindow == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     this._window = aWindow;
@@ -102,16 +103,23 @@ NfcContentHelper.prototype = {
     if (!NFC.DEBUG_CONTENT_HELPER && this._window.navigator.mozSettings) {
       let lock = this._window.navigator.mozSettings.createLock();
       var nfcDebug = lock.get(NFC.SETTING_NFC_DEBUG);
       nfcDebug.onsuccess = function _nfcDebug() {
         DEBUG = nfcDebug.result[NFC.SETTING_NFC_DEBUG];
         updateDebug();
       };
     }
+
+    let info = cpmm.sendSyncMessage("NFC:QueryInfo")[0];
+    this._rfState = info.rfState;
+  },
+
+  queryRFState: function queryRFState() {
+    return this._rfState;
   },
 
   encodeNDEFRecords: function encodeNDEFRecords(records) {
     let encodedRecords = [];
     for (let i = 0; i < records.length; i++) {
       let record = records[i];
       encodedRecords.push({
         tnf: record.tnf,
@@ -314,16 +322,20 @@ NfcContentHelper.prototype = {
                                         result.isReadOnly,
                                         result.isFormatable);
 
             this.eventListener.notifyTagFound(result.sessionToken, event, result.records);
             break;
           case NFC.TAG_EVENT_LOST:
             this.eventListener.notifyTagLost(result.sessionToken);
             break;
+          case NFC.RF_EVENT_STATE_CHANGE:
+            this._rfState = result.rfState;
+            this.eventListener.notifyRFStateChange(this._rfState);
+            break;
         }
         break;
     }
   },
 
   handle: function handle(name, result) {
     switch (name) {
       case NFC.SETTING_NFC_DEBUG:
--- a/dom/nfc/gonk/Nfc.js
+++ b/dom/nfc/gonk/Nfc.js
@@ -54,17 +54,18 @@ const NFC_CONTRACTID = "@mozilla.org/nfc
 const NFC_CID =
   Components.ID("{2ff24790-5e74-11e1-b86c-0800200c9a66}");
 
 const NFC_IPC_ADD_EVENT_TARGET_MSG_NAMES = [
   "NFC:AddEventListener"
 ];
 
 const NFC_IPC_MSG_NAMES = [
-  "NFC:CheckSessionToken"
+  "NFC:CheckSessionToken",
+  "NFC:QueryInfo"
 ];
 
 const NFC_IPC_READ_PERM_MSG_NAMES = [
   "NFC:ReadNDEF",
   "NFC:Connect",
   "NFC:Close",
 ];
 
@@ -263,16 +264,23 @@ XPCOMUtils.defineLazyGetter(this, "gMess
 
     onPeerEvent: function onPeerEvent(eventType, sessionToken) {
       for (let target of this.eventListeners) {
         this.notifyDOMEvent(target, { event: eventType,
                                       sessionToken: sessionToken });
       }
     },
 
+    onRFStateChange: function onRFStateChange(rfState) {
+      for (let target of this.eventListeners) {
+        this.notifyDOMEvent(target, { event: NFC.RF_EVENT_STATE_CHANGE,
+                                      rfState: rfState});
+      }
+    },
+
     /**
      * nsIMessageListener interface methods.
      */
 
     receiveMessage: function receiveMessage(message) {
       DEBUG && debug("Received message from content process: " + JSON.stringify(message));
 
       if (message.name == "child-process-shutdown") {
@@ -552,21 +560,22 @@ Nfc.prototype = {
         delete message.sessionId;
 
         gSystemMessenger.broadcastMessage("nfc-manager-tech-lost", message);
         break;
      case "HCIEventTransactionNotification":
         this.notifyHCIEventTransaction(message);
         break;
      case "ChangeRFStateResponse":
+        this.sendNfcResponse(message);
+
         if (!message.errorMsg) {
           this.rfState = message.rfState;
+          gMessageManager.onRFStateChange(this.rfState);
         }
-
-        this.sendNfcResponse(message);
         break;
       case "ConnectResponse": // Fall through.
       case "CloseResponse":
       case "ReadNDEFResponse":
       case "MakeReadOnlyResponse":
       case "FormatResponse":
       case "WriteNDEFResponse":
         this.sendNfcResponse(message);
@@ -597,23 +606,25 @@ Nfc.prototype = {
   },
 
   /**
    * Process a message from the gMessageManager.
    */
   receiveMessage: function receiveMessage(message) {
     let isRFAPI = message.name == "NFC:ChangeRFState";
     let isSendFile = message.name == "NFC:SendFile";
-    if (!isRFAPI && (this.rfState != NFC.NFC_RF_STATE_DISCOVERY)) {
+    let isInfoAPI = message.name == "NFC:QueryInfo";
+
+    if (!isRFAPI && !isInfoAPI && (this.rfState != NFC.NFC_RF_STATE_DISCOVERY)) {
       debug("NFC is not enabled. current rfState:" + this.rfState);
       this.sendNfcErrorResponse(message, NFC.NFC_GECKO_ERROR_NOT_ENABLED);
       return null;
     }
 
-    if (!isRFAPI && !isSendFile) {
+    if (!isRFAPI && !isSendFile && !isInfoAPI) {
       // Update the current sessionId before sending to the NFC service.
       message.data.sessionId = SessionHelper.getId(message.data.sessionToken);
     }
 
     switch (message.name) {
       case "NFC:ChangeRFState":
         this.sendToNfcService("changeRFState", message.data);
         break;
@@ -642,16 +653,18 @@ Nfc.prototype = {
         // and system app that handles the system message :
         // 'nfc-manager-send-file'. System app subsequently handover's
         // the data to alternate carrier's (BT / WiFi) 'sendFile' interface.
 
         // Notify system app to initiate BT send file operation
         gSystemMessenger.broadcastMessage("nfc-manager-send-file",
                                            message.data);
         break;
+      case "NFC:QueryInfo":
+        return {rfState: this.rfState};
       default:
         debug("UnSupported : Message Name " + message.name);
         return null;
     }
     this.targetsByRequestId[message.data.requestId] = message.target;
 
     return null;
   },
--- a/dom/nfc/gonk/nfc_consts.js
+++ b/dom/nfc/gonk/nfc_consts.js
@@ -46,11 +46,12 @@ this.TOPIC_XPCOM_SHUTDOWN           = "x
 
 this.SETTING_NFC_DEBUG = "nfc.debugging.enabled";
 
 this.PEER_EVENT_READY = 0x01;
 this.PEER_EVENT_LOST  = 0x02;
 this.TAG_EVENT_FOUND = 0x03;
 this.TAG_EVENT_LOST  = 0x04;
 this.PEER_EVENT_FOUND = 0x05;
+this.RF_EVENT_STATE_CHANGE = 0x06;
 
 // Allow this file to be imported via Components.utils.import().
 this.EXPORTED_SYMBOLS = Object.keys(this);
--- a/dom/nfc/nsINfcContentHelper.idl
+++ b/dom/nfc/nsINfcContentHelper.idl
@@ -17,17 +17,17 @@ interface nsINfcTagEvent : nsISupports
 
   readonly attribute long maxNDEFSize;
 
   readonly attribute boolean isReadOnly;
 
   readonly attribute boolean isFormatable;
 };
 
-[scriptable, uuid(42c7a85f-59ae-4bde-b961-e1f1436476c3)]
+[scriptable, uuid(fcbd98d6-3d04-4657-bd64-1164e311b399)]
 interface nsINfcEventListener : nsISupports
 {
   /**
    * Callback function used to notify tagfound.
    *
    * @param sessionToken
    *        SessionToken received from parent process
    * @param event
@@ -58,33 +58,41 @@ interface nsINfcEventListener : nsISuppo
 
   /**
    * Callback function used to notify peerlost.
    *
    * @param sessionToken
    *        SessionToken received from parent process
    */
   void notifyPeerLost(in DOMString sessionToken);
+
+  /**
+   * Callback function used to notify RF state change.
+   *
+   * @param rfState
+   *        RF state received from parent process
+   */
+  void notifyRFStateChange(in DOMString rfState);
 };
 
 [scriptable, uuid(a8ef3590-d853-4766-b54a-a4547da4dde4)]
 interface nsINfcRequestCallback : nsISupports
 {
   DOMString getCallbackId();
 
   void notifySuccess();
 
   void notifySuccessWithBoolean(in boolean result);
 
   void notifySuccessWithNDEFRecords(in nsIVariant records);
 
   void notifyError(in DOMString errorMsg);
 };
 
-[scriptable, uuid(9da02537-c4d0-4b2d-b294-d3250ff1720e)]
+[scriptable, uuid(bcf214de-885b-43e6-9e53-9b7d880e1633)]
 interface nsINfcContentHelper : nsISupports
 {
   void init(in nsIDOMWindow window);
 
   boolean checkSessionToken(in DOMString sessionToken, in boolean isP2P);
 
   /**
    * Read current NDEF data on the tag.
@@ -162,16 +170,21 @@ interface nsINfcContentHelper : nsISuppo
    *
    * @param callback
    *        Called when request is finished
    */
   void close(in DOMString sessionToken,
              in nsINfcRequestCallback callback);
 
   /**
+   * Get current RF state.
+   */
+  DOMString queryRFState();
+
+  /**
    * Initiate send file operation.
    *
    * @param blob
    *        Raw data of the file to be sent. This object represents a file-like
    *        (nsIDOMFile) object of immutable, raw data. The blob data needs
    *        to be 'object wrapped' before calling this interface.
    *
    * @param sessionToken
--- a/dom/nfc/nsNfc.js
+++ b/dom/nfc/nsNfc.js
@@ -260,16 +260,17 @@ function MozNFCImpl() {
 
   this.eventService = Cc["@mozilla.org/eventlistenerservice;1"]
                         .getService(Ci.nsIEventListenerService);
   this._nfcContentHelper.addEventListener(this);
 }
 MozNFCImpl.prototype = {
   _nfcContentHelper: null,
   _window: null,
+  _rfState: null,
   nfcPeer: null,
   nfcTag: null,
   eventService: null,
 
   // Should be mapped to the RFState defined in WebIDL.
   rfState: {
     IDLE: "idle",
     LISTEN: "listen",
@@ -282,16 +283,17 @@ MozNFCImpl.prototype = {
     this.defineEventHandlerGetterSetter("ontagfound");
     this.defineEventHandlerGetterSetter("ontaglost");
     this.defineEventHandlerGetterSetter("onpeerready");
     this.defineEventHandlerGetterSetter("onpeerfound");
     this.defineEventHandlerGetterSetter("onpeerlost");
 
     if (this._nfcContentHelper) {
       this._nfcContentHelper.init(aWindow);
+      this._rfState = this._nfcContentHelper.queryRFState();
     }
   },
 
   // Only apps which have nfc-manager permission can call the following interfaces
   // 'checkP2PRegistration' , 'notifyUserAcceptedP2P' , 'notifySendFileStatus',
   // 'startPoll', 'stopPoll', and 'powerOff'.
   checkP2PRegistration: function checkP2PRegistration(manifestUrl) {
     // Get the AppID and pass it to ContentHelper
@@ -515,16 +517,20 @@ MozNFCImpl.prototype = {
     }
 
     if (this.nfcPeer) {
       debug("handleEvent notifyPeerLost");
       this.notifyPeerLost(this.nfcPeer.session);
     }
   },
 
+  notifyRFStateChange: function notifyRFStateChange(rfState) {
+    this._rfState = rfState;
+  },
+
   checkPermissions: function checkPermissions(perms) {
     let principal = this._window.document.nodePrincipal;
     for (let perm of perms) {
       let permValue =
         Services.perms.testExactPermissionFromPrincipal(principal, perm);
       if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
         return true;
       } else {
@@ -542,10 +548,50 @@ MozNFCImpl.prototype = {
   classID: Components.ID("{6ff2b290-2573-11e3-8224-0800200c9a66}"),
   contractID: "@mozilla.org/navigatorNfc;1",
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
                                          Ci.nsIDOMGlobalPropertyInitializer,
                                          Ci.nsINfcEventListener,
                                          Ci.nsIDOMEventListener]),
 };
 
+function NFCSendFileWrapper() {
+}
+NFCSendFileWrapper.prototype = {
+  // nsISystemMessagesWrapper implementation.
+  wrapMessage: function wrapMessage(aMessage, aWindow) {
+    let peerImpl = new MozNFCPeerImpl(aWindow, aMessage.sessionToken);
+    let peer = aWindow.MozNFCPeer._create(aWindow, peerImpl);
+
+    delete aMessage.sessionToken;
+    aMessage = Cu.cloneInto(aMessage, aWindow);
+    aMessage.peer = peer;
+    return aMessage;
+  },
+
+  classDescription: "NFCSendFileWrapper",
+  classID: Components.ID("{c5063a5c-8cb9-41d2-baf5-56062a2e30e9}"),
+  contractID: "@mozilla.org/dom/system-messages/wrapper/nfc-manager-send-file;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesWrapper])
+};
+
+function NFCTechDiscoveredWrapper() {
+}
+NFCTechDiscoveredWrapper.prototype = {
+  // nsISystemMessagesWrapper implementation.
+  wrapMessage: function wrapMessage(aMessage, aWindow) {
+    aMessage = Cu.cloneInto(aMessage, aWindow);
+    if (aMessage.techList.indexOf("P2P") != -1) {
+      let peerImpl = new MozNFCPeerImpl(aWindow, aMessage.sessionToken);
+      let peer = aWindow.MozNFCPeer._create(aWindow, peerImpl);
+      aMessage.peer = peer;
+    }
+    return aMessage;
+  },
+
+  classDescription: "NFCTechDiscoveredWrapper",
+  classID: Components.ID("{2e7f9285-3c72-4e1f-b985-141a00a23a75}"),
+  contractID: "@mozilla.org/dom/system-messages/wrapper/nfc-manager-tech-discovered;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesWrapper])
+};
+
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozNFCTagImpl,
-  MozNFCPeerImpl, MozNFCImpl]);
+  MozNFCPeerImpl, MozNFCImpl, NFCSendFileWrapper, NFCTechDiscoveredWrapper]);
--- a/dom/nfc/nsNfc.manifest
+++ b/dom/nfc/nsNfc.manifest
@@ -1,8 +1,14 @@
 component {6ff2b290-2573-11e3-8224-0800200c9a66} nsNfc.js
 contract @mozilla.org/navigatorNfc;1 {6ff2b290-2573-11e3-8224-0800200c9a66}
 
 component {4e1e2e90-3137-11e3-aa6e-0800200c9a66} nsNfc.js
 contract @mozilla.org/nfc/NFCTag;1 {4e1e2e90-3137-11e3-aa6e-0800200c9a66}
 
 component {c1b2bcf0-35eb-11e3-aa6e-0800200c9a66} nsNfc.js
 contract @mozilla.org/nfc/NFCPeer;1 {c1b2bcf0-35eb-11e3-aa6e-0800200c9a66}
+
+component {c5063a5c-8cb9-41d2-baf5-56062a2e30e9} nsNfc.js
+contract @mozilla.org/dom/system-messages/wrapper/nfc-manager-send-file;1 {c5063a5c-8cb9-41d2-baf5-56062a2e30e9}
+
+component {2e7f9285-3c72-4e1f-b985-141a00a23a75} nsNfc.js
+contract @mozilla.org/dom/system-messages/wrapper/nfc-manager-tech-discovered;1 {2e7f9285-3c72-4e1f-b985-141a00a23a75}
--- a/dom/notification/ChromeNotifications.js
+++ b/dom/notification/ChromeNotifications.js
@@ -49,16 +49,21 @@ ChromeNotifications.prototype = {
 
     notifications.forEach(function(notification) {
       let behavior;
       try {
         behavior = JSON.parse(notification.mozbehavior);
       } catch(e) {
         behavior = undefined;
       }
+
+      if (behavior && behavior.showOnlyOnce === true) {
+        return;
+      }
+
       appNotifier.showAppNotification(
         notification.icon,
         notification.title,
         notification.body,
         null,
         {
           manifestURL: notification.origin,
           id: notification.alertName,
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -321,17 +321,17 @@ Promise::CreateWrapper(ErrorResult& aRv)
   AutoJSAPI jsapi;
   if (!jsapi.Init(mGlobal)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
   JSContext* cx = jsapi.cx();
 
   JS::Rooted<JS::Value> wrapper(cx);
-  if (!WrapNewBindingObject(cx, this, &wrapper)) {
+  if (!GetOrCreateDOMReflector(cx, this, &wrapper)) {
     JS_ClearPendingException(cx);
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   dom::PreserveWrapper(this);
 
   // Now grab our allocation stack
@@ -470,17 +470,17 @@ Promise::CreateFunction(JSContext* aCx, 
                                                  aParent, nullptr);
   if (!func) {
     return nullptr;
   }
 
   JS::Rooted<JSObject*> obj(aCx, JS_GetFunctionObject(func));
 
   JS::Rooted<JS::Value> promiseObj(aCx);
-  if (!dom::WrapNewBindingObject(aCx, aPromise, &promiseObj)) {
+  if (!dom::GetOrCreateDOMReflector(aCx, aPromise, &promiseObj)) {
     return nullptr;
   }
 
   js::SetFunctionNativeReserved(obj, SLOT_PROMISE, promiseObj);
   js::SetFunctionNativeReserved(obj, SLOT_DATA, JS::Int32Value(aTask));
 
   return obj;
 }
@@ -497,17 +497,17 @@ Promise::CreateThenableFunction(JSContex
                                                  nullptr, nullptr);
   if (!func) {
     return nullptr;
   }
 
   JS::Rooted<JSObject*> obj(aCx, JS_GetFunctionObject(func));
 
   JS::Rooted<JS::Value> promiseObj(aCx);
-  if (!dom::WrapNewBindingObject(aCx, aPromise, &promiseObj)) {
+  if (!dom::GetOrCreateDOMReflector(aCx, aPromise, &promiseObj)) {
     return nullptr;
   }
 
   js::SetFunctionNativeReserved(obj, SLOT_PROMISE, promiseObj);
 
   return obj;
 }
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -201,16 +201,18 @@ var interfaceNamesInGlobalScope =
     {name: "BoxObject", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CallEvent", b2g: true, pref: "dom.telephony.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CallGroupErrorEvent", b2g: true, pref: "dom.telephony.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CameraCapabilities", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "CameraClosedEvent", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CameraConfigurationEvent", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CameraControl", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CameraDetectedFace", b2g: true, pref: "camera.control.face_detection.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CameraFacesDetectedEvent", b2g: true, pref: "camera.control.face_detection.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/tests/mochitest/notification/test_notification_resend.html
+++ b/dom/tests/mochitest/notification/test_notification_resend.html
@@ -82,16 +82,45 @@
 
       navigator.mozChromeNotifications.mozResendAllNotifications(function(number) {
         is(number, 1, "One notification resent");
         notif.close();
       });
     },
 
     function (done) {
+      info("Sending one non-resendable notification");
+      var behavior = {
+        showOnlyOnce: true
+      };
+      var notif = new Notification("title", { mozbehavior: behavior });
+      ok(notif, "Notification object is valid");
+      notifications.push(notif);
+
+      var promise = Notification.get();
+      promise.then(function (notifications) {
+        is(notifications.length, 1, "one notification has been sent");
+        done();
+      });
+    },
+
+    function (done) {
+      info("Trying to resend non-resendable notification");
+      var notif = notifications.pop();
+      notif.onclose = function() {
+        done();
+      };
+
+      navigator.mozChromeNotifications.mozResendAllNotifications(function(number) {
+        is(number, 0, "One notification not resent");
+        notif.close();
+      });
+    },
+
+    function (done) {
       info("Sending two notifications, closing one");
       var notif1 = new Notification("title1");
       ok(notif1, "Notification object is valid");
       notif1.onclose = function() {
         done();
       };
 
       var payload = NotificationTest.payload;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CameraClosedEvent.webidl
@@ -0,0 +1,16 @@
+/* -*- 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/. */
+
+[Func="Navigator::HasCameraSupport",
+ Constructor(DOMString type, optional CameraClosedEventInit eventInitDict)]
+interface CameraClosedEvent : Event
+{
+  readonly attribute DOMString reason;
+};
+
+dictionary CameraClosedEventInit : EventInit
+{
+  DOMString reason = "HardwareReleased";
+};
--- a/dom/webidl/CameraControl.webidl
+++ b/dom/webidl/CameraControl.webidl
@@ -111,17 +111,17 @@ dictionary CameraStartRecordingOptions
   boolean autoEnableLowLightTorch = false;
 };
 
 callback CameraSetConfigurationCallback = void (CameraConfiguration configuration);
 callback CameraAutoFocusCallback = void (boolean focused);
 callback CameraTakePictureCallback = void (Blob picture);
 callback CameraStartRecordingCallback = void ();
 callback CameraShutterCallback = void ();
-callback CameraClosedCallback = void ();
+callback CameraClosedCallback = void (DOMString reason);
 callback CameraReleaseCallback = void ();
 callback CameraRecorderStateChange = void (DOMString newState);
 callback CameraPreviewStateChange = void (DOMString newState);
 callback CameraAutoFocusMovingCallback = void (boolean isMoving);
 
 /*
     attributes here affect the preview, any pictures taken, and/or
     any video recorded by the camera.
@@ -236,26 +236,37 @@ interface CameraControl : MediaStream
   attribute CameraShutterCallback? onShutter;
 
   /* the event dispatched on the camera's shutter event, to trigger
      a shutter sound and/or a visual shutter indicator.
 
      contains no event-specific data. */
   attribute EventHandler onshutter;
 
-  /* the function to call when the camera hardware is closed
-     by the underlying framework, e.g. when another app makes a more
-     recent call to get the camera. */
+  /* the function to call when the camera hardware is closed; this may
+     be due to a system failure, another process taking over the camera,
+     or a call to release().
+
+     The 'reason' will be one of the following string values:
+       - SystemFailure    : the camera subsystem failed and was closed;
+       - HardwareReleased : a call to release() was successful;
+       - NotAvailable     : the camera hardware is in use by another process.
+  */
   attribute CameraClosedCallback? onClosed;
 
-  /* the event dispatched when the camera hardware is closed
-     by the underlying framework, e.g. when another app makes a more
-     recent call to get the camera.
+  /* the event dispatched when the camera hardware is closed; this may
+     be due to a system failure, another process taking over the camera,
+     or a call to release().
 
-     contains no event-specific data. */
+     The event has a 'reason' attribute that will be one of the following
+     string values:
+       - SystemFailure    : the camera subsystem failed and was closed;
+       - HardwareReleased : a call to release() was successful;
+       - NotAvailable     : the camera hardware is in use by another process.
+  */
   attribute EventHandler onclose;
 
   /* the function to call when the recorder changes state, either because
      the recording process encountered an error, or because one of the
      recording limits (see CameraStartRecordingOptions) was reached. */
   attribute CameraRecorderStateChange? onRecorderStateChange;
 
   /* the event dispatched when the recorder changes state, either because
--- a/dom/webidl/Notification.webidl
+++ b/dom/webidl/Notification.webidl
@@ -67,16 +67,17 @@ dictionary NotificationOptions {
 
 dictionary GetNotificationOptions {
   DOMString tag;
 };
 
 dictionary NotificationBehavior {
   boolean noscreen = false;
   boolean noclear = false;
+  boolean showOnlyOnce = false;
   DOMString soundFile = "";
   sequence<unsigned long> vibrationPattern;
 };
 
 enum NotificationPermission {
   "default",
   "denied",
   "granted"
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -676,16 +676,17 @@ if CONFIG['MOZ_B2G_FM']:
         'FMRadio.webidl',
     ]
 
 GENERATED_EVENTS_WEBIDL_FILES = [
     'AutocompleteErrorEvent.webidl',
     'BlobEvent.webidl',
     'CallEvent.webidl',
     'CallGroupErrorEvent.webidl',
+    'CameraClosedEvent.webidl',
     'CameraConfigurationEvent.webidl',
     'CameraFacesDetectedEvent.webidl',
     'CameraStateChangeEvent.webidl',
     'CFStateChangeEvent.webidl',
     'CloseEvent.webidl',
     'CSSFontFaceLoadEvent.webidl',
     'DataErrorEvent.webidl',
     'DataStoreChangeEvent.webidl',
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -146,21 +146,27 @@ UpdatePromise::RejectAllPromises(const E
       AutoJSAPI jsapi;
       jsapi.Init(go);
 
       JSContext* cx = jsapi.cx();
 
       JS::Rooted<JSString*> stack(cx, JS_GetEmptyString(JS_GetRuntime(cx)));
 
       JS::Rooted<JS::Value> fnval(cx);
-      ToJSValue(cx, aErrorDesc.mFilename, &fnval);
+      if (!ToJSValue(cx, aErrorDesc.mFilename, &fnval)) {
+        pendingPromise->MaybeReject(NS_ERROR_FAILURE);
+        continue;
+      }
       JS::Rooted<JSString*> fn(cx, fnval.toString());
 
       JS::Rooted<JS::Value> msgval(cx);
-      ToJSValue(cx, aErrorDesc.mMessage, &msgval);
+      if (!ToJSValue(cx, aErrorDesc.mMessage, &msgval)) {
+        pendingPromise->MaybeReject(NS_ERROR_FAILURE);
+        continue;
+      }
       JS::Rooted<JSString*> msg(cx, msgval.toString());
 
       JS::Rooted<JS::Value> error(cx);
       if (!JS::CreateError(cx, JSEXN_ERR, stack, fn, aErrorDesc.mLineno,
                            aErrorDesc.mColno, nullptr, msg, &error)) {
         pendingPromise->MaybeReject(NS_ERROR_FAILURE);
         continue;
       }
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -317,17 +317,17 @@ struct WorkerStructuredCloneCallbacks
                        "Only immutable blob should be passed to worker");
         }
 #endif
 
         {
           // New scope to protect |result| from a moving GC during ~nsRefPtr.
           nsRefPtr<File> blob = new File(nullptr, blobImpl);
           JS::Rooted<JS::Value> val(aCx);
-          if (WrapNewBindingObject(aCx, blob, &val)) {
+          if (GetOrCreateDOMReflector(aCx, blob, &val)) {
             result = val.toObjectOrNull();
           }
         }
 
         return result;
       }
     }
     // See if the object is an ImageData.
@@ -421,17 +421,17 @@ struct MainThreadWorkerStructuredCloneCa
         // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
         // called because the static analysis thinks dereferencing XPCOM objects
         // can GC (because in some cases it can!), and a return statement with a
         // JSObject* type means that JSObject* is on the stack as a raw pointer
         // while destructors are running.
         JS::Rooted<JS::Value> val(aCx);
         {
           nsRefPtr<File> blob = new File(nullptr, blobImpl);
-          if (!WrapNewBindingObject(aCx, blob, &val)) {
+          if (!GetOrCreateDOMReflector(aCx, blob, &val)) {
             return nullptr;
           }
         }
 
         return &val.toObject();
       }
     }
 
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -1067,26 +1067,23 @@ Proxy::HandleEvent(nsIDOMEvent* aEvent)
   else {
     runnable = new EventRunnable(this, !!uploadTarget, type);
   }
 
   {
     AutoSafeJSContext cx;
     JSAutoRequest ar(cx);
 
-    JS::Rooted<JSObject*> scope(cx, xpc::UnprivilegedJunkScope());
-    JSAutoCompartment ac(cx, scope);
-
     JS::Rooted<JS::Value> value(cx);
-    if (!WrapNewBindingObject(cx, mXHR, &value)) {
+    if (!GetOrCreateDOMReflectorNoWrap(cx, mXHR, &value)) {
       return NS_ERROR_FAILURE;
     }
 
-    scope = js::UncheckedUnwrap(&value.toObject());
-    JSAutoCompartment ac2(cx, scope);
+    JS::Rooted<JSObject*> scope(cx, &value.toObject());
+    JSAutoCompartment ac(cx, scope);
 
     runnable->Dispatch(cx);
   }
 
   if (!uploadTarget) {
     if (type.EqualsASCII(sEventStrings[STRING_loadstart])) {
       NS_ASSERTION(!mMainThreadSeenLoadStart, "Huh?!");
       mMainThreadSeenLoadStart = true;
@@ -2170,17 +2167,17 @@ XMLHttpRequest::Send(File& aBody, ErrorR
   }
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   JS::Rooted<JS::Value> value(cx);
-  if (!WrapNewBindingObject(cx, &aBody, &value)) {
+  if (!GetOrCreateDOMReflector(cx, &aBody, &value)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   JSStructuredCloneCallbacks* callbacks =
     mWorkerPrivate->IsChromeWorker() ?
     ChromeWorkerStructuredCloneCallbacks(false) :
     WorkerStructuredCloneCallbacks(false);
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -4938,17 +4938,17 @@ nsHTMLEditRules::AlignInnerBlocks(nsIDOM
 ///////////////////////////////////////////////////////////////////////////
 // AlignBlockContents: align contents of a block element
 //                  
 nsresult
 nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType)
 {
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   NS_ENSURE_TRUE(node && alignType, NS_ERROR_NULL_POINTER);
-  nsresult res;
+  nsresult res = NS_OK;
   nsCOMPtr<nsIContent> firstChild, lastChild;
   nsCOMPtr<Element> divNode;
   
   bool useCSS = mHTMLEditor->IsCSSEnabled();
 
   NS_ENSURE_STATE(mHTMLEditor);
   firstChild = mHTMLEditor->GetFirstEditableChild(*node);
   NS_ENSURE_STATE(mHTMLEditor);
--- a/editor/libeditor/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/nsHTMLEditorStyle.cpp
@@ -1098,17 +1098,17 @@ nsHTMLEditor::GetInlinePropertyBase(nsIA
                                     bool *aFirst, 
                                     bool *aAny, 
                                     bool *aAll,
                                     nsAString *outValue,
                                     bool aCheckDefaults)
 {
   NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
 
-  nsresult result;
+  nsresult result = NS_OK;
   *aAny = false;
   *aAll = true;
   *aFirst = false;
   bool first = true;
 
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
--- a/editor/reftests/reftest.list
+++ b/editor/reftests/reftest.list
@@ -93,22 +93,22 @@ skip-if(Android||B2G) needs-focus == 462
 == readonly-editable.html readonly-editable-ref.html
 == dynamic-overflow-change.html dynamic-overflow-change-ref.html
 == 694880-1.html 694880-ref.html
 == 694880-2.html 694880-ref.html
 == 694880-3.html 694880-ref.html
 == 388980-1.html 388980-1-ref.html
 needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html
 skip-if(B2G) fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658
-needs-focus pref(selectioncaret.enabled,false) == 824080-1.html 824080-1-ref.html
+needs-focus == 824080-1.html 824080-1-ref.html
 needs-focus == 824080-2.html 824080-2-ref.html
-needs-focus pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html
+needs-focus test-pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html
 needs-focus != 824080-2.html 824080-3.html
-needs-focus pref(selectioncaret.enabled,false) == 824080-4.html 824080-4-ref.html
-needs-focus pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html
+needs-focus == 824080-4.html 824080-4-ref.html
+needs-focus test-pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html
 needs-focus != 824080-4.html 824080-5.html
 needs-focus == 824080-6.html 824080-6-ref.html
 needs-focus pref(selectioncaret.enabled,false) == 824080-7.html 824080-7-ref.html
 needs-focus != 824080-6.html 824080-7.html
 # Bug 674927: copy spellcheck-textarea tests to contenteditable
 == spellcheck-contenteditable-attr.html spellcheck-contenteditable-nofocus-ref.html
 fails-if(Android||B2G) needs-focus != spellcheck-contenteditable-attr.html spellcheck-contenteditable-ref.html # B2G no spellcheck underline
 needs-focus == spellcheck-contenteditable-focused.html spellcheck-contenteditable-ref.html
--- a/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
+++ b/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
@@ -10170,1237 +10170,1238 @@ 28105a33818
 28227c33940
 < immerse/XDSGN
 ---
 > immerse/XDSGNV
 28513c34226
 < inbound
 ---
 > inbound/s
-28531,28532c34244
+28531,28532c34244,34245
 < incentive's
 < incentive/ES
 ---
 > incentive/ESM
-28560,28561c34272
+> incentivize/SDG
+28560,28561c34273
 < incline's
 < incline/EGDS
 ---
 > incline/EGDSM
-28590,28591c34301
+28590,28591c34302
 < incorrigibility/M
 < incorrigible
 ---
 > incorrigibleness
-28593d34302
+28593d34303
 < incorruptibly
-28650a34360
+28650a34361
 > indices
-28812d34521
+28812d34522
 < inflexion/SM
-28981,28982c34690
+28981,28982c34691
 < insert's
 < insert/AGSD
 ---
 > insert/AGSDM
-29204a34913
+29204a34914
 > intermediacy/S
-29206c34915,34917
+29206c34916,34918
 < intermediate/SMY
 ---
 > intermediate/SMYPGD
 > intermediation/SE
 > intermediator/SM
-29216a34928
+29216a34929
 > intern/GDL
-29266a34979
+29266a34980
 > interruptible/U
-29272a34986,34989
+29272a34987,34990
 > intersex
 > intersexual/MS
 > intersexualism
 > intersexuality
-29446c35163
+29446c35164
 < ironic
 ---
 > ironic/U
-29447a35165
+29447a35166
 > ironically/U
-29724c35442
+29724c35443
 < jewellery's
 ---
 > jewellery/M
-29733,29734c35451
+29733,29734c35452
 < jig's
 < jig/AS
 ---
 > jig/ASM
-29736,29737c35453
+29736,29737c35454
 < jigger's
 < jigger/ASDG
 ---
 > jigger/ASDGM
-29799,29800c35515
+29799,29800c35516
 < join's
 < join/AFDSG
 ---
 > join/AFDSGM
-29803,29804c35518
+29803,29804c35519
 < joint's
 < joint/EGSD
 ---
 > joint/EGSDM
-29869,29870c35583,35584
+29869,29870c35584,35585
 < judge's
 < judge/ADSG
 ---
 > judge/ADSGM
 > judgement/MS
-30035a35750,35751
+30035a35751,35752
 > keylogger/MS
 > keylogging/MS
-30066c35782
+30066c35783
 < kiddie/M
 ---
 > kiddie/SM
-30102,30103c35818
+30102,30103c35819
 < kind's
 < kind/UPRYT
 ---
 > kind/UPRYTM
-30262,30263c35977
+30262,30263c35978
 < kraut's
 < kraut/S!
 ---
 > kraut/MS!
-30283,30284c35997
+30283,30284c35998
 < label's
 < label/ASDG
 ---
 > label/ASDGM
-30302,30303c36015
+30302,30303c36016
 < lace's
 < lace/UGDS
 ---
 > lace/UGDSM
-30497,30498c36209
+30497,30498c36210
 < latch's
 < latch/UDSG
 ---
 > latch/UDSGM
-30637c36348
+30637c36349
 < learning's
 ---
 > learning/M
-30643,30644c36354
+30643,30644c36355
 < leash's
 < leash/UDSG
 ---
 > leash/UDSGM
-30665a36376
+30665a36377
 > lector/MS
-30700c36411
+30700c36412
 < legation's/AC
 ---
 > legation/ACM
-30927,30928c36638
+30927,30928c36639
 < light's/C
 < light/CASTGD
 ---
 > light/CASTGDM
-30938c36648
+30938c36649
 < lighting's
 ---
 > lighting/M
-30981,30982c36691
+30981,30982c36692
 < limit's
 < limit/CSZGDR
 ---
 > limit/CSZGDRM
-30986c36695
+30986c36696
 < limiter's
 ---
 > limiter/M
-30990a36700,36702
+30990a36701,36703
 > limnological
 > limnologist/MS
 > limnology/M
-31031c36743
+31031c36744
 < linguini's
 ---
 > linguini/M
-31034c36746
+31034c36747
 < linguistically
 ---
 > linguistical/Y
-31047,31048c36759
+31047,31048c36760
 < lint's
 < lint/CDSG
 ---
 > lint/CDSGM
-31058a36770
+31058a36771
 > lepidopterist/SM
-31151,31152c36863
+31151,31152c36864
 < liver's
 < liver/S
 ---
 > liver/MS
-31170,31171c36881
+31170,31171c36882
 < load's
 < load/AUGSD
 ---
 > load/AUGSDM
-31211,31212c36921
+31211,31212c36922
 < location's/A
 < location/ESM
 ---
 > location/ESMA
-31291,31292c37000
+31291,31292c37001
 < long's
 < long/KDSTG
 ---
 > long/KDSTGM
-31379,31380c37087
+31379,31380c37088
 < louse's
 < louse/CDSG
 ---
 > louse/CDSGM
-31639a37347
+31639a37348
 > mage/SM
-31741,31742c37449
+31741,31742c37450
 < make's/A
 < make/UAGS
 ---
 > make/UAGSM
-31806a37514
+31806a37515
 > malware/MS
-31822,31823c37530
+31822,31823c37531
 < man's/F
 < man/USY
 ---
 > man/USYMF
-31924,31925c37631
+31924,31925c37632
 < mantle's
 < mantle/EGDS
 ---
 > mantle/EGDSM
-31940,31941c37646
+31940,31941c37647
 < map's
 < map/AS
 ---
 > map/ASM
-32061,32062c37766
+32061,32062c37767
 < mask's
 < mask/UDSG
 ---
 > mask/UDSGM
-32084,32085c37788
+32084,32085c37789
 < master's
 < master/ADGS
 ---
 > master/ADGSM
-32230c37933
+32230c37934
 < meanie/M
 ---
 > meanie/MS
-32246,32247c37949
+32246,32247c37950
 < measure's
 < measure/ADSG
 ---
 > measure/ADSGM
-32317,32318c38019
+32317,32318c38020
 < megadeath/M
 < megadeaths
 ---
 > megadeath/SM
-32320c38021
+32320c38022
 < megajoules
 ---
 > megajoule/SM
-32329c38030
+32329c38031
 < megapixel/S
 ---
 > megapixel/MS
-32361,32362c38062
+32361,32362c38063
 < melt's
 < melt/ADSG
 ---
 > melt/ADSGM
-32365,32366c38065
+32365,32366c38066
 < member's
 < member/EAS
 ---
 > member/EASM
-32708a38408
+32708a38409
 > might've
-32717a38418
+32717a38419
 > migrator/SM
-32760a38462
+32760a38463
 > millennia
-32777d38478
+32777d38479
 < millionnaire/M
-32806,32807c38507
+32806,32807c38508
 < mind's
 < mind/ADRSZG
 ---
 > mind/ADRSZGM
-32934a38635
+32934a38636
 > miscommunication/S
-32991a38693
+32991a38694
 > misjudgement/MS
-33027,33028c38729
+33027,33028c38730
 < miss's
 < miss/EDSGV
 ---
 > miss/EDSGVM
-33051,33052c38752
+33051,33052c38753
 < mist's
 < mist/CDRSZG
 ---
 > mist/CDRSZGM
-33056c38756
+33056c38757
 < mister's
 ---
 > mister/M
-33107,33108c38807
+33107,33108c38808
 < mob's
 < mob/CS
 ---
 > mob/CSM
-33448,33449c39147
+33448,33449c39148
 < mortgage's
 < mortgage/AGDS
 ---
 > mortgage/AGDSM
-33471,33472c39169
+33471,33472c39170
 < mote's
 < mote/KCXSVN
 ---
 > mote/KCXSVNM
-33539,33540c39236
+33539,33540c39237
 < mounting's
 < mountings
 ---
 > mounting/MS
-33784a39481
+33784a39482
 > must've
-33887,33888c39584
+33887,33888c39585
 < name's
 < name/AGDS
 ---
 > name/AGDSM
-33963c39659
+33963c39660
 < native/MS
 ---
 > native/MSY
-33970,33971c39666
+33970,33971c39667
 < natural's
 < natural/UPY
 ---
 > natural/UPYM
-33979,33980c39674
+33979,33980c39675
 < nature's
 < nature/CS
 ---
 > nature/CSM
-34133,34134c39827
+34133,34134c39828
 < nerve's
 < nerve/UDSG
 ---
 > nerve/UDSGM
-34169,34171c39862,39864
+34169,34171c39863,39865
 < neurone/S
 < neurophysiology
 < neuroscience
 ---
 > neurophysiology/M
 > neuroscience/MS
 > neuroscientist/MS
-34175a39869
+34175a39870
 > neurosurgical
-34275c39969
+34275c39970
 < nightie/M
 ---
 > nightie/SM
-34388,34389c40082
+34388,34389c40083
 < nomination's/A
 < nomination/CSM
 ---
 > nomination/CSMA
-34755,34756c40448
+34755,34756c40449
 < note's
 < note/FCSDG
 ---
 > note/FCSDGM
-34840,34841c40532
+34840,34841c40533
 < number's
 < number/ASDG
 ---
 > number/ASDGM
-35104a40796
+35104a40797
 > octopi
-35137,35138c40829
+35137,35138c40830
 < offensive's
 < offensive/IYP
 ---
 > offensive/IYPM
-35219d40909
+35219d40910
 < oleomargarin/M
-35226a40917
+35226a40918
 > oligo
-35345c41036
+35345c41037
 < oppose/DSG
 ---
 > oppose/DSGRB
-35452,35453c41143
+35452,35453c41144
 < orient's
 < orient/AEDGS
 ---
 > orient/AEDGSM
-35913c41603
+35913c41604
 < oversize/D
 ---
 > oversize
-36031,36032c41721
+36031,36032c41722
 < pack's
 < pack/UADSG
 ---
 > pack/UADSGM
-36034,36035c41723
+36034,36035c41724
 < package's
 < package/AGDS
 ---
 > package/AGDSM
-36041c41729
+36041c41730
 < packing's
 ---
 > packing/M
-36056,36059d41743
+36056,36059d41744
 < paederast/S
 < paediatrician's
 < paediatricians
 < paediatrics/M
-36290a41975,41976
+36290a41976,41977
 > parallelization/SM
 > parallelize/SGD
-36291a41978
+36291a41979
 > paralyses
-36377a42065
+36377a42066
 > parkour
-36403d42090
+36403d42091
 < parrakeet/MS
-36418,36419c42105
+36418,36419c42106
 < part's
 < part/CDSG
 ---
 > part/CDSGM
-36445,36447c42131
+36445,36447c42132
 < partition's
 < partition/ADG
 < partitions
 ---
 > partition/ADGMS
-36449d42132
+36449d42133
 < partizan/SM
-36621,36622c42304
+36621,36622c42305
 < pay's
 < pay/ASGBL
 ---
 > pay/ASGBLM
-37093a42776
+37093a42777
 > petabyte/MS
-37102c42785
+37102c42786
 < petitioner/M
 ---
 > petitioner/MS
-37221a42905,42906
+37221a42906,42907
 > phlebotomist/SM
 > phlebotomize/SGD
-37228a42914
+37228a42915
 > pho
-37264a42951
+37264a42952
 > phosphorylate/DSGN
-37310,37311c42997
+37310,37311c42998
 < phrase's
 < phrase/AGDS
 ---
 > phrase/AGDSM
-37316d43001
+37316d43002
 < phrenetic
-37469,37470c43154
+37469,37470c43155
 < pine's
 < pine/AGDS
 ---
 > pine/AGDSM
-37596,37597c43280
+37596,37597c43281
 < place's
 < place/EAGLDS
 ---
 > place/EAGLDSM
-37630a43314
+37630a43315
 > plaintext
-37636,37637c43320
+37636,37637c43321
 < plane's
 < plane/CGDS
 ---
 > plane/CGDSM
-37786,37787c43469
+37786,37787c43470
 < ploy's
 < ploy/S
 ---
 > ploy/SM
-37792,37793c43474
+37792,37793c43475
 < plug's
 < plug/US
 ---
 > plug/USM
-37796a43478
+37796a43479
 > plugin/MS
-37987c43669
+37987c43670
 < polypeptide/S
 ---
 > polypeptide/MS
-38106,38107c43788
+38106,38107c43789
 < port's
 < port/CAEGDS
 ---
 > port/CAEGDSM
-38134,38135c43815
+38134,38135c43816
 < pose's/A
 < pose/CAKEGDS
 ---
 > pose/CAKEGDSM
-38140,38141c43820
+38140,38141c43821
 < position's/KC
 < position/ACKES
 ---
 > position/ACKESM
-38260,38261c43939
+38260,38261c43940
 < pound's
 < pound/KDSG
 ---
 > pound/KDSGM
-38266a43945
+38266a43946
 > poutine/S
-38291d43969
+38291d43970
 < practise's
-38451a44130
+38451a44131
 > prejudgement/MS
-38568,38569c44247
+38568,38569c44248
 < press's
 < press/ACGSD
 ---
 > press/ACGSDM
-38638,38639c44316
+38638,38639c44317
 < price's
 < price/AGDS
 ---
 > price/AGDSM
-38756,38757c44433
+38756,38757c44434
 < process's
 < process/AGDS
 ---
 > process/AGDSM
-38780,38781c44456
+38780,38781c44457
 < produce's
 < produce/AZGDRS
 ---
 > produce/AZGDRSM
-38805a44481
+38805a44482
 > profiler/SM
-38835a44512
+38835a44513
 > programmatically
-38891a44569,44570
+38891a44570,44571
 > pronate/DSGN
 > pronator/MS
-38951c44630
+38951c44631
 < proprietorship/M
 ---
 > proprietorship/MS
-39039a44719
+39039a44720
 > provender/M
-39095a44776
+39095a44777
 > pseudorandom/Y
-39564a45246
+39564a45247
 > quinoa
-39581,39582c45263
+39581,39582c45264
 < quire's
 < quire/IAS
 ---
 > quire/IASM
-39614,39615c45295
+39614,39615c45296
 < quote's
 < quote/UDSG
 ---
 > quote/UDSGM
-39653,39654c45333
+39653,39654c45334
 < racoon's
 < racoons
 ---
 > racoon/MS
-39738,39739c45417
+39738,39739c45418
 < rail's
 < rail/CGDS
 ---
 > rail/CGDSM
-39816,39817c45494
+39816,39817c45495
 < range's
 < range/CGDS
 ---
 > range/CGDSM
-39873a45551,45552
+39873a45552,45553
 > rasterization/M
 > rasterize/SGDR
-39925,39926c45604
+39925,39926c45605
 < ravel's
 < ravel/UDSG
 ---
 > ravel/UDSGM
-40036a45715
+40036a45716
 > recency
-40140a45820
+40140a45821
 > recurse/DGSV
-40141a45822
+40141a45823
 > recuse/DGS
-40204,40205c45885
+40204,40205c45886
 < reel's
 < reel/UGDS
 ---
 > reel/UGDSM
-40208a45889
+40208a45890
 > refactor/SMDG
-40244d45924
+40244d45925
 < reflexion/SM
-40659d46338
+40659d46339
 < resizing
-40829c46508
+40829c46509
 < reverie/M
 ---
 > reverie/MS
-40895a46575,46577
+40895a46576,46578
 > rheumatological
 > rheumatology/M
 > rheumatologist/SM
-40944,40945c46626
+40944,40945c46627
 < ride's
 < ride/CZGS
 ---
 > ride/CZGSM
-41104,41105c46785
+41104,41105c46786
 < robe's
 < robe/EGDS
 ---
 > robe/EGDSM
-41132,41133c46812
+41132,41133c46813
 < rogue's
 < rogue/KS
 ---
 > rogue/KSM
-41185a46865
+41185a46866
 > rootkit/MS
-41258,41259c46938
+41258,41259c46939
 < route's
 < route/ADSG
 ---
 > route/ADSGM
-41415a47095
+41415a47096
 > sabre/MS
-41447,41448c47127
+41447,41448c47128
 < saddle's
 < saddle/UDSG
 ---
 > saddle/UDSGM
-41463,41464c47142
+41463,41464c47143
 < safe's
 < safe/UYTPR
 ---
 > safe/UYTPRM
-41544,41545c47222
+41544,41545c47223
 < salt's
 < salt/CTGDS
 ---
 > salt/CTGDSM
-41765,41766c47442
+41765,41766c47443
 < say's
 < say/USG
 ---
 > say/USGM
-41787,41788c47463
+41787,41788c47464
 < scale's
 < scale/ACSDG
 ---
 > scale/ACSDGM
-41806,41807c47481
+41806,41807c47482
 < scan's
 < scan/AS
 ---
 > scan/ASM
-41880,41881c47554
+41880,41881c47555
 < schedule's
 < schedule/ADSG
 ---
 > schedule/ADSGM
-41914c47587
+41914c47588
 < schnaps's
 ---
 > schnaps/M
-41949c47622
+41949c47623
 < schrod's
 ---
 > schrod/SM
-41998a47672
+41998a47673
 > scot-free
-42016,42017c47690
+42016,42017c47691
 < scramble's
 < scramble/UGDS
 ---
 > scramble/UGDSM
-42055,42056c47728
+42055,42056c47729
 < screw's
 < screw/UDSG
 ---
 > screw/UDSGM
-42065,42066c47737
+42065,42066c47738
 < scribe's
 < scribe/IKCGSD
 ---
 > scribe/IKCGSDM
-42170,42171c47841
+42170,42171c47842
 < seal's
 < seal/AUSDG
 ---
 > seal/AUSDGM
-42204,42205c47874
+42204,42205c47875
 < seat's
 < seat/UGDS
 ---
 > seat/UGDSM
-42288,42289c47957
+42288,42289c47958
 < seed's
 < seed/AGDS
 ---
 > seed/AGDSM
-42359c48027,48028
+42359c48028,48029
 < self/M
 ---
 > self/MG
 > selfie/S
-42361a48031,48032
+42361a48032,48033
 > selfism
 > selfist/S
-42365,42367c48036,48037
+42365,42367c48037,48038
 < sell's
 < sell/AZGRS
 < seller's
 ---
 > sell/AZGRSM
 > seller/M
-42524c48194
+42524c48195
 < seraphim's
 ---
 > seraphim/M
-42558,42559c48228
+42558,42559c48229
 < serve's/AF
 < serve/FACGDS
 ---
 > serve/FACGDSM
-42574,42575c48243
+42574,42575c48244
 < serving's
 < servings
 ---
 > serving/MS
-42594,42595c48262
+42594,42595c48263
 < settle's
 < settle/AUGDS
 ---
 > settle/AUGDSM
-42647,42648c48314
+42647,42648c48315
 < shackle's
 < shackle/UGDS
 ---
 > shackle/UGDSM
-42716,42717c48382
+42716,42717c48383
 < shape's
 < shape/AGDS
 ---
 > shape/AGDSM
-42851,42852c48516
+42851,42852c48517
 < ship's
 < ship/ALS
 ---
 > ship/ALSM
-42883,42885c48547
+42883,42885c48548
 < shit's
 < shit/S!
 < shite/S!
 ---
 > shit/MS!
-42887,42888c48549,48550
+42887,42888c48550,48551
 < shithead/S!
 < shitload/!
 ---
 > shithead/MS!
 > shitload/MS!
-42891c48553
+42891c48554
 < shitty/RT!
 ---
 > shitty/TR!
-42976a48639
+42976a48640
 > should've
-43008c48671
+43008c48672
 < showtime
 ---
 > showtime/MS
-43090,43091c48753
+43090,43091c48754
 < side's
 < side/AGDS
 ---
 > side/AGDSM
-43143,43144c48805
+43143,43144c48806
 < sign's
 < sign/AFCGDS
 ---
 > sign/AFCGDSM
-43163,43164c48824
+43163,43164c48825
 < signing's/C
 < signings
 ---
 > signing/MCS
-43328c48988
+43328c48989
 < size/MGBDRS
 ---
 > size/AMGBDRS
-43368,43369c49028
+43368,43369c49029
 < skill's
 < skill/CSD
 ---
 > skill/CSDM
-43724,43726c49383
+43724,43726c49384
 < smoulder's
 < smouldered
 < smoulders
 ---
 > smoulder/GSMD
-43752,43753c49409
+43752,43753c49410
 < snap's
 < snap/US
 ---
 > snap/USM
-43767,43768c49423,49425
+43767,43768c49424,49426
 < snarl's
 < snarl/USDG
 ---
 > snarkily
 > snarky/TR
 > snarl/USDGM
-44012,44013c49669
+44012,44013c49670
 < solute's
 < solute/XN
 ---
 > solute/XNM
-44015c49671
+44015c49672
 < solution's/EA
 ---
 > solution/EAM
-44021c49677
+44021c49678
 < solver's
 ---
 > solver/M
-44041a49698
+44041a49699
 > sommelier/SM
-44062c49719
+44062c49720
 < sonofabitch
 ---
 > sonofabitch/!
-44177,44178c49834
+44177,44178c49835
 < sow's
 < sow/ASGD
 ---
 > sow/ASGDM
-44346a50003
+44346a50004
 > spelled
-44348a50006
+44348a50007
 > spelt
-44371a50030
+44371a50031
 > spick/S!
-44383c50042
+44383c50043
 < spik/S
 ---
 > spik/S!
-44413,44414c50072
+44413,44414c50073
 < spire's
 < spire/IFAS
 ---
 > spire/IFASM
-44416,44417c50074
+44416,44417c50075
 < spirit's
 < spirit/ISGD
 ---
 > spirit/ISGDM
-44475,44476c50132
+44475,44476c50133
 < spoil's
 < spoil/CSDRZG
 ---
 > spoil/CSDRZGM
-44549,44550c50205
+44549,44550c50206
 < spray's
 < spray/ASDG
 ---
 > spray/ASDGM
-44688,44689c50343
+44688,44689c50344
 < staff's
 < staff/ASDG
 ---
 > staff/ASDGM
-44729,44730c50383
+44729,44730c50384
 < stall's
 < stall/SDG
 ---
 > stall/SDGM
-44871a50525
+44871a50526
 > steampunk
-44985,44986c50639
+44985,44986c50640
 < still's
 < still/ITGSD
 ---
 > still/ITGSDM
-45024,45025c50677
+45024,45025c50678
 < stitch's
 < stitch/ADSG
 ---
 > stitch/ADSGM
-45030,45031c50682
+45030,45031c50683
 < stock's
 < stock/AGSD
 ---
 > stock/AGSDM
-45090,45091c50741
+45090,45091c50742
 < stop's
 < stop/US
 ---
 > stop/USM
-45105,45106c50755
+45105,45106c50756
 < store's
 < store/ADSG
 ---
 > store/ADSGM
-45148,45149c50797
+45148,45149c50798
 < strain's
 < strain/FADSG
 ---
 > strain/FADSGM
-45164,45165c50812
+45164,45165c50813
 < strap's
 < strap/US
 ---
 > strap/USM
-45290,45291c50937
+45290,45291c50938
 < structure's
 < structure/AGDS
 ---
 > structure/AGDSM
-45330,45331c50976
+45330,45331c50977
 < study's
 < study/AGDS
 ---
 > study/AGDSM
-45368,45369c51013
+45368,45369c51014
 < style's
 < style/ADSG
 ---
 > style/ADSGM
-45455,45456c51099
+45455,45456c51100
 < submission's
 < submission/AS
 ---
 > submission/ASM
-45872,45873c51515
+45872,45873c51516
 < surface's
 < surface/AGDS
 ---
 > surface/AGDSM
-45918,45919c51560
+45918,45919c51561
 < survey's
 < survey/ADGS
 ---
 > survey/ADGSM
-46106a51748
+46106a51749
 > syllabi
-46160c51802
+46160c51803
 < synch/GMD
 ---
 > synch/GMDS
-46167d51808
+46167d51809
 < synchs
-46178a51820,51822
+46178a51821,51823
 > synesthesia
 > synesthete/S
 > synesthetic
-46203,46204c51847,51848
+46203,46204c51848,51849
 < sysadmin/S
 < sysop/S
 ---
 > sysadmin/MS
 > sysop/MS
-46363,46364c52007
+46363,46364c52008
 < tangle's
 < tangle/UDSG
 ---
 > tangle/UDSGM
-46632a52276,52277
+46632a52277,52278
 > teleport/SGD
 > teleportation
-46675,46676c52320
+46675,46676c52321
 < template's
 < template/S
 ---
 > template/SM
-46752a52397
+46752a52398
 > terabit/MS
-46753a52399,52400
+46753a52400,52401
 > terahertz/M
 > terapixel/MS
-46806,46807c52453
+46806,46807c52454
 < test's/AFK
 < test/AKFCDGS
 ---
 > test/AKFCDGSM
-46817a52464
+46817a52465
 > testcase/MS
-46831a52479
+46831a52480
 > testsuite/MS
-46845a52494
+46845a52495
 > textbox/SM
-46925a52575
+46925a52576
 > theremin/MS
-46999c52649
+46999c52650
 < thinking's
 ---
 > thinking/M
-47095,47096c52745
+47095,47096c52746
 < throne's
 < throne/CDS
 ---
 > throne/CDSM
-47188,47189c52837
+47188,47189c52838
 < tie's
 < tie/AUSD
 ---
 > tie/AUSDM
-47213,47214c52861
+47213,47214c52862
 < till's
 < till/EDRZGS
 ---
 > till/EDRZGSM
-47303,47304c52950
+47303,47304c52951
 < tire's
 < tire/AGDS
 ---
 > tire/AGDSM
-47433,47434c53079
+47433,47434c53080
 < tone's
 < tone/IZGDRS
 ---
 > tone/IZGDRSM
-47453,47455c53098,53099
+47453,47455c53099,53100
 < tool's
 < tool/ADGS
 < toolbar
 ---
 > tool/ADGSM
 > toolbar/MS
-47540,47541c53184
+47540,47541c53185
 < tort's
 < tort/FEAS
 ---
 > tort/FEASM
-47644a53288
+47644a53289
 > traceur/SM
-47657,47658c53301
+47657,47658c53302
 < tract's
 < tract/CEKFAS
 ---
 > tract/CEKFASM
-47755a53399
+47755a53400
 > transfect/DSMG
-47774a53419,53420
+47774a53420,53421
 > transgenderism
 > transgene/MS
-47807,47808c53453
+47807,47808c53454
 < transmission's
 < transmission/AS
 ---
 > transmission/ASM
-47928,47929c53573
+47928,47929c53574
 < trench's
 < trench/AIGSD
 ---
 > trench/AIGSDM
-47951c53595
+47951c53596
 < triage/M
 ---
 > triage/MGS
-47976,47977c53620
+47976,47977c53621
 < tribute's
 < tribute/FS
 ---
 > tribute/FSM
-47997a53641
+47997a53642
 > trifecta/S
-48165,48166c53809
+48165,48166c53810
 < trust's/E
 < trust/IESGD
 ---
 > trust/IESGDM
-48180,48181c53823
+48180,48181c53824
 < try's
 < try/AGDS
 ---
 > try/AGDSM
-48271a53914
+48271a53915
 > turducken
-48334a53978
+48334a53979
 > tweep/S
-48371,48372c54015
+48371,48372c54016
 < twist's
 < twist/USDG
 ---
 > twist/USDGM
-48396,48397c54039
+48396,48397c54040
 < type's
 < type/AGDS
 ---
 > type/AGDSM
-48869a54512
+48869a54513
 > unlikeable
-49163,49164c54806
+49163,49164c54807
 < usual's
 < usual/UY
 ---
 > usual/UYM
-49211c54853
+49211c54854
 < vagina/M
 ---
 > vagina/MS
-49249,49250c54891
+49249,49250c54892
 < value's
 < value/CAGSD
 ---
 > value/CAGSDM
-49292,49293c54933
+49292,49293c54934
 < variant's
 < variant/IS
 ---
 > variant/ISM
-49356,49357c54996
+49356,49357c54997
 < veil's
 < veil/UDGS
 ---
 > veil/UDGSM
-49368,49369c55007
+49368,49369c55008
 < velour's
 < velours's
 ---
 > velour/MS
-49398,49399c55036
+49398,49399c55037
 < vent's
 < vent/DGS
 ---
 > vent/DGSM
-49435,49436c55072
+49435,49436c55073
 < verge's
 < verge/FDSG
 ---
 > verge/FDSGM
-49478a55115
+49478a55116
 > vertices
-49488,49489c55125
+49488,49489c55126
 < vest's
 < vest/ILDGS
 ---
 > vest/ILDGSM
-49681,49682c55317
+49681,49682c55318
 < visit's
 < visit/ASGD
 ---
 > visit/ASGDM
-49772a55408,55410
+49772a55409,55411
 > volcanological
 > volcanologist/MS
 > volcanology/M
-49807,49808c55445
+49807,49808c55446
 < vote's
 < vote/CGVDS
 ---
 > vote/CGVDSM
-50148a55786
+50148a55787
 > weaponize/DSG
-50215,50216c55853
+50215,50216c55854
 < weigh's
 < weigh/AGD
 ---
 > weigh/AGDM
-50260,50261d55896
+50260,50261d55897
 < werwolf/M
 < werwolves
-50555,50556c56190
+50555,50556c56191
 < wind's
 < wind/UASG
 ---
 > wind/UASGM
-50626,50627c56260
+50626,50627c56261
 < wire's
 < wire/AGDS
 ---
 > wire/AGDSM
-50728c56361
+50728c56362
 < women
 ---
 > women/M
-50794,50796c56427,56428
+50794,50796c56428,56429
 < wop/S!
 < word's
 < word/AJDSG
 ---
 > wop/MS!
 > word/AJDSGM
-50801c56433
+50801c56434
 < wording's
 ---
 > wording/M
-50808,50809c56440
+50808,50809c56441
 < work's
 < work/ADJSG
 ---
 > work/ADJSGM
-50824c56455
+50824c56456
 < working's
 ---
 > working/M
-50884,50885c56515
+50884,50885c56516
 < worthy's
 < worthy/UPRT
 ---
 > worthy/UPRTM
-50903,50904c56533
+50903,50904c56534
 < wrap's
 < wrap/US
 ---
 > wrap/USM
-50945c56574
+50945c56575
 < writing's
 ---
 > writing/M
-51118,51119c56747
+51118,51119c56748
 < yoke's
 < yoke/UGDS
 ---
 > yoke/UGDSM
-51212,51213c56840
+51212,51213c56841
 < zip's
 < zip/US
 ---
 > zip/USM
-51228,51229c56855
+51228,51229c56856
 < zone's
 < zone/AGDS
 ---
 > zone/AGDSM
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-57242
+57243
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -34528,16 +34528,17 @@ incapacitate/DSGN
 incarcerate/GNXDS
 incarceration/M
 incarnadine/GDS
 incarnate/AXGNDS
 incarnation/AM
 incendiary/SM
 incense/MGDS
 incentive/ESM
+incentivize/SDG
 inception/SM
 incessant/Y
 incest/MS
 incestuous/PY
 incestuousness/M
 inch/MDSG
 inchoate
 inchworm/SM
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -849,18 +849,18 @@ struct ParamTraits<mozilla::layers::Text
            ReadParam(aMsg, aIter, &aResult->mTextureFlags);
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::CompositableType>
   : public ContiguousTypedEnumSerializer<
              mozilla::layers::CompositableType,
-             mozilla::layers::CompositableType::BUFFER_UNKNOWN,
-             mozilla::layers::CompositableType::BUFFER_COUNT>
+             mozilla::layers::CompositableType::UNKNOWN,
+             mozilla::layers::CompositableType::COUNT>
 {};
 
 template <>
 struct ParamTraits<mozilla::gfx::SurfaceFormat>
   : public ContiguousTypedEnumSerializer<
              mozilla::gfx::SurfaceFormat,
              mozilla::gfx::SurfaceFormat::B8G8R8A8,
              mozilla::gfx::SurfaceFormat::UNKNOWN>
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -14,99 +14,74 @@
 #include "mozilla/EnumSet.h"
 
 #include "mozilla/TypedEnum.h"
 #include "mozilla/TypedEnumBits.h"
 
 namespace mozilla {
 namespace layers {
 
-typedef int32_t SurfaceDescriptorType;
-const SurfaceDescriptorType SURFACEDESCRIPTOR_UNKNOWN = 0;
-
 /**
  * Flags used by texture clients and texture hosts. These are passed from client
  * side to host side when textures and compositables are created. Usually set
  * by the compositableCient, they may be modified by either the compositable or
  * texture clients.
- *
- * XXX - switch to all caps constant names which seems to be the standard in gecko
  */
 MOZ_BEGIN_ENUM_CLASS(TextureFlags, uint32_t)
   NO_FLAGS           = 0,
   // Use nearest-neighbour texture filtering (as opposed to linear filtering).
   USE_NEAREST_FILTER = 1 << 0,
-  // The texture should be flipped around the y-axis when composited.
+  // The texture should be flipped along the y-axis when composited.
   NEEDS_Y_FLIP       = 1 << 1,
   // Force the texture to be represented using a single tile (note that this means
   // tiled textures, not tiled layers).
   DISALLOW_BIGIMAGE  = 1 << 2,
-  // Allow using 'repeat' mode for wrapping.
-  ALLOW_REPEAT       = 1 << 3,
-  // The texture represents a tile which is newly created.
-  NEW_TILE           = 1 << 4,
-  // The texture is part of a component-alpha pair
-  COMPONENT_ALPHA    = 1 << 5,
   // The buffer will be treated as if the RB bytes are swapped.
   // This is useful for rendering using Cairo/Thebes, because there is no
   // BGRX Android pixel format, and so we have to do byte swapping.
   //
   // For example, if the GraphicBuffer has an Android pixel format of
   // PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
   // (for example, with GL), a BGRA shader should be used.
-  RB_SWAPPED         = 1 << 6,
-
-  FRONT              = 1 << 7,
-  // A texture host on white for component alpha
-  ON_WHITE           = 1 << 8,
-  // A texture host on black for component alpha
-  ON_BLACK           = 1 << 9,
-  // A texture host that supports tiling
-  TILE               = 1 << 10,
-  // A texture should be recycled when no longer in used
-  RECYCLE            = 1 << 11,
-  // Texture contents should be initialized
-  // from the previous texture.
-  COPY_PREVIOUS      = 1 << 12,
-  // Who is responsible for deallocating the shared data.
-  // if DEALLOCATE_CLIENT is set, the shared data is deallocated on the
+  RB_SWAPPED         = 1 << 3,
+  // Data in this texture has not been alpha-premultiplied.
+  // XXX - Apparently only used with ImageClient/Host
+  NON_PREMULTIPLIED  = 1 << 4,
+  // The texture should be recycled when no longer in used
+  RECYCLE            = 1 << 5,
+  // If DEALLOCATE_CLIENT is set, the shared data is deallocated on the
   // client side and requires some extra synchronizaion to ensure race-free
   // deallocation.
   // The default behaviour is to deallocate on the host side.
-  DEALLOCATE_CLIENT  = 1 << 13,
+  DEALLOCATE_CLIENT  = 1 << 6,
   // After being shared ith the compositor side, an immutable texture is never
   // modified, it can only be read. It is safe to not Lock/Unlock immutable
   // textures.
-  IMMUTABLE          = 1 << 14,
+  IMMUTABLE          = 1 << 7,
   // The contents of the texture must be uploaded or copied immediately
   // during the transaction, because the producer may want to write
   // to it again.
-  IMMEDIATE_UPLOAD   = 1 << 15,
-  // The texture is going to be used as part of a double
-  // buffered pair, and so we can guarantee that the producer/consumer
-  // won't be racing to access its contents.
-  DOUBLE_BUFFERED    = 1 << 16,
-  // Data in this texture has not been alpha-premultiplied.
-  NON_PREMULTIPLIED  = 1 << 18,
+  IMMEDIATE_UPLOAD   = 1 << 8,
+  // The texture is part of a component-alpha pair
+  COMPONENT_ALPHA    = 1 << 9,
 
   // OR union of all valid bits
-  ALL_BITS           = (1 << 19) - 1,
+  ALL_BITS           = (1 << 10) - 1,
   // the default flags
-  DEFAULT = FRONT
+  DEFAULT = NO_FLAGS
 MOZ_END_ENUM_CLASS(TextureFlags)
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextureFlags)
 
 static inline bool
 TextureRequiresLocking(TextureFlags aFlags)
 {
   // If we're not double buffered, or uploading
   // within a transaction, then we need to support
   // locking correctly.
   return !(aFlags & (TextureFlags::IMMEDIATE_UPLOAD |
-                     TextureFlags::DOUBLE_BUFFERED |
                      TextureFlags::IMMUTABLE));
 }
 
 /**
  * The type of debug diagnostic to enable.
  */
 MOZ_BEGIN_ENUM_CLASS(DiagnosticTypes, uint8_t)
   NO_DIAGNOSTIC    = 0,
@@ -153,34 +128,31 @@ MOZ_BEGIN_ENUM_CLASS(EffectTypes, uint8_
   VR_DISTORTION,
   MAX  //sentinel for the count of all effect types
 MOZ_END_ENUM_CLASS(EffectTypes)
 
 /**
  * How the Compositable should manage textures.
  */
 MOZ_BEGIN_ENUM_CLASS(CompositableType, uint8_t)
-  BUFFER_UNKNOWN,
-  // the deprecated compositable types
-  BUFFER_CONTENT_INC,     // painted layer interface, only sends incremental
-                          // updates to a texture on the compositor side.
-  // somewhere in the middle
-  BUFFER_TILED,           // tiled painted layer
-  BUFFER_SIMPLE_TILED,
-  // the new compositable types
+  UNKNOWN,
+  CONTENT_INC,     // painted layer interface, only sends incremental
+                   // updates to a texture on the compositor side.
+  CONTENT_TILED,   // tiled painted layer
   IMAGE,           // image with single buffering
   IMAGE_OVERLAY,   // image without buffer
   IMAGE_BRIDGE,    // ImageBridge protocol
   CONTENT_SINGLE,  // painted layer interface, single buffering
   CONTENT_DOUBLE,  // painted layer interface, double buffering
-  BUFFER_COUNT
+  COUNT
 MOZ_END_ENUM_CLASS(CompositableType)
 
 /**
  * How the texture host is used for composition,
+ * XXX - Only used by ContentClientIncremental
  */
 MOZ_BEGIN_ENUM_CLASS(DeprecatedTextureHostFlags, uint8_t)
   DEFAULT = 0,       // The default texture host for the given SurfaceDescriptor
   TILED = 1 << 0,    // A texture host that supports tiling
   COPY_PREVIOUS = 1 << 1, // Texture contents should be initialized
                                       // from the previous texture.
   ALL_BITS = (1 << 2) - 1
 MOZ_END_ENUM_CLASS(DeprecatedTextureHostFlags)
@@ -212,18 +184,18 @@ struct TextureFactoryIdentifier
     , mSupportsTextureBlitting(aSupportsTextureBlitting)
     , mSupportsPartialUploads(aSupportsPartialUploads)
   {}
 };
 
 /**
  * Identify a texture to a compositable. Many textures can have the same id, but
  * the id is unique for any texture owned by a particular compositable.
- * XXX - This is now redundant with TextureFlags. it ill be removed along with
- * deprecated texture classes.
+ * XXX - We don't really need this, it will be removed along with the incremental
+ * ContentClient/Host.
  */
 MOZ_BEGIN_ENUM_CLASS(TextureIdentifier, uint8_t)
   Front = 1,
   Back = 2,
   OnWhiteFront = 3,
   OnWhiteBack = 4,
   HighBound
 MOZ_END_ENUM_CLASS(TextureIdentifier)
@@ -233,29 +205,31 @@ MOZ_END_ENUM_CLASS(TextureIdentifier)
  * using compositables and textures.
  * XXX - TextureInfo is a bad name: this information is useful for the compositable,
  * not the Texture. And ith new Textures, only the compositable type is really
  * useful. This may (should) be removed in the near future.
  */
 struct TextureInfo
 {
   CompositableType mCompositableType;
+  // XXX - only used by ContentClientIncremental
   DeprecatedTextureHostFlags mDeprecatedTextureHostFlags;
   TextureFlags mTextureFlags;
 
   TextureInfo()
-    : mCompositableType(CompositableType::BUFFER_UNKNOWN)
+    : mCompositableType(CompositableType::UNKNOWN)
     , mDeprecatedTextureHostFlags(DeprecatedTextureHostFlags::DEFAULT)
     , mTextureFlags(TextureFlags::NO_FLAGS)
   {}
 
-  explicit TextureInfo(CompositableType aType)
+  explicit TextureInfo(CompositableType aType,
+                       TextureFlags aTextureFlags = TextureFlags::DEFAULT)
     : mCompositableType(aType)
     , mDeprecatedTextureHostFlags(DeprecatedTextureHostFlags::DEFAULT)
-    , mTextureFlags(TextureFlags::NO_FLAGS)
+    , mTextureFlags(aTextureFlags)
   {}
 
   bool operator==(const TextureInfo& aOther) const
   {
     return mCompositableType == aOther.mCompositableType &&
            mDeprecatedTextureHostFlags == aOther.mDeprecatedTextureHostFlags &&
            mTextureFlags == aOther.mTextureFlags;
   }
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -286,18 +286,16 @@ AppendToString(std::stringstream& aStrea
     aStream << #test; \
     previous = true; \
   } \
 }
     bool previous = false;
     AppendFlag(TextureFlags::USE_NEAREST_FILTER);
     AppendFlag(TextureFlags::NEEDS_Y_FLIP);
     AppendFlag(TextureFlags::DISALLOW_BIGIMAGE);
-    AppendFlag(TextureFlags::ALLOW_REPEAT);
-    AppendFlag(TextureFlags::NEW_TILE);
 
 #undef AppendFlag
   }
   aStream << sfx;
 }
 
 void
 AppendToString(std::stringstream& aStream, mozilla::gfx::SurfaceFormat format,
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -532,17 +532,17 @@ RotatedContentBuffer::BeginPaint(Painted
     // Do not modify mBufferRect, mBufferRotation, or mDidSelfCopy,
     // or call CreateBuffer before this call.
     FinalizeFrame(result.mRegionToDraw);
   }
 
   nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
   RefPtr<DrawTarget> destDTBuffer;
   RefPtr<DrawTarget> destDTBufferOnWhite;
-  uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0;
+  uint32_t bufferFlags = 0;
   if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
     bufferFlags |= BUFFER_COMPONENT_ALPHA;
   }
   if (canReuseBuffer) {
     if (!EnsureBuffer()) {
       return result;
     }
     nsIntRect keepArea;
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -297,24 +297,22 @@ public:
    * @param aPaintState Paint state data returned by a call to BeginPaint
    * @param aIter Paint state iterator. Only required if PAINT_CAN_DRAW_ROTATED
    * was specified to BeginPaint.
    */
   gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
                                                DrawIterator* aIter = nullptr);
 
   enum {
-    ALLOW_REPEAT = 0x01,
     BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
                                   // component alpha.
   };
   /**
    * Return a new surface of |aSize| and |aType|.
-   * @param aFlags if ALLOW_REPEAT is set, then the buffer should be configured
-   * to allow repeat-mode, otherwise it should be in pad (clamp) mode
+   *
    * If the created buffer supports azure content, then the result(s) will
    * be returned in aBlackDT/aWhiteDT, otherwise aBlackSurface/aWhiteSurface
    * will be used.
    */
   virtual void
   CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
                RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) = 0;
 
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -241,16 +241,19 @@ APZCTreeManager::PrepareAPZCForLayer(con
                                      const nsIntRegion& aObscured,
                                      AsyncPanZoomController* aParent,
                                      AsyncPanZoomController* aNextSibling,
                                      TreeBuildingState& aState)
 {
   if (!aMetrics.IsScrollable()) {
     return nullptr;
   }
+  if (gfxPrefs::LayoutEventRegionsEnabled() && aLayer.IsScrollInfoLayer()) {
+    return nullptr;
+  }
 
   const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
   if (!(state && state->mController.get())) {
     return nullptr;
   }
 
   AsyncPanZoomController* apzc = nullptr;
   // If we get here, aLayer is a scrollable layer and somebody
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -138,20 +138,21 @@ public:
    * This function transforms |aEvent| to have its coordinates in DOM space.
    * This is so that the event can be passed through the DOM and content can
    * handle them. The event may need to be converted to a WidgetInputEvent
    * by the caller if it wants to do this.
    *
    * The following values may be returned by this function:
    * nsEventStatus_eConsumeNoDefault is returned to indicate the
    *   caller should discard the event with extreme prejudice.
-   *   Currently this is only returned if the APZ determines that
-   *   something is in overscroll and the event should be ignored entirely.
-   *   There may be other scenarios where this return code might be used in
-   *   the future.
+   *   Currently this is only returned if the APZ determines that something is
+   *   in overscroll and the event should be ignored entirely, or if the input
+   *   event is part of a extended gesture like flywheel scrolling, and gets
+   *   consumed within the APZ code. There may be other scenarios where this
+   *   return code might be used in the future.
    * nsEventStatus_eIgnore is returned to indicate that the APZ code didn't
    *   use this event. This might be because it was directed at a point on
    *   the screen where there was no APZ, or because the thing the user was
    *   trying to do was not allowed. (For example, attempting to pan a
    *   non-pannable document).
    * nsEventStatus_eConsumeDoDefault is returned to indicate that the APZ
    *   code may have used this event to do some user-visible thing. Note that
    *   in some cases CONSUMED is returned even if the event was NOT used. This
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -79,17 +79,17 @@ InputBlockState::IsTargetConfirmed() con
 
 TouchBlockState::TouchBlockState(const nsRefPtr<AsyncPanZoomController>& aTargetApzc,
                                  bool aTargetConfirmed)
   : InputBlockState(aTargetApzc, aTargetConfirmed)
   , mAllowedTouchBehaviorSet(false)
   , mPreventDefault(false)
   , mContentResponded(false)
   , mContentResponseTimerExpired(false)
-  , mSingleTapDisallowed(false)
+  , mDuringFastMotion(false)
   , mSingleTapOccurred(false)
 {
   TBS_LOG("Creating %p\n", this);
 }
 
 bool
 TouchBlockState::SetContentResponse(bool aPreventDefault)
 {
@@ -159,27 +159,34 @@ TouchBlockState::IsReadyForHandling() co
 bool
 TouchBlockState::IsDefaultPrevented() const
 {
   MOZ_ASSERT(mContentResponded || mContentResponseTimerExpired);
   return mPreventDefault;
 }
 
 void
-TouchBlockState::DisallowSingleTap()
+TouchBlockState::SetDuringFastMotion()
 {
-  TBS_LOG("%p disallowing single-tap\n", this);
-  mSingleTapDisallowed = true;
+  TBS_LOG("%p setting fast-motion flag\n", this);
+  mDuringFastMotion = true;
+}
+
+bool
+TouchBlockState::IsDuringFastMotion() const
+{
+  return mDuringFastMotion;
 }
 
 bool
 TouchBlockState::SetSingleTapOccurred()
 {
-  TBS_LOG("%p attempting to set single-tap occurred; disallowed=%d\n", this, mSingleTapDisallowed);
-  if (!mSingleTapDisallowed) {
+  TBS_LOG("%p attempting to set single-tap occurred; disallowed=%d\n",
+    this, mDuringFastMotion);
+  if (!mDuringFastMotion) {
     mSingleTapOccurred = true;
     return true;
   }
   return false;
 }
 
 bool
 TouchBlockState::SingleTapOccurred() const
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -111,26 +111,34 @@ public:
    */
   bool IsReadyForHandling() const;
   /**
    * @return true iff web content cancelled this block of events.
    */
   bool IsDefaultPrevented() const;
 
   /**
-   * Set a flag that disables setting the single-tap flag on this block.
+   * Sets a flag that indicates this input block occurred while the APZ was
+   * in a state of fast motion. This affects gestures that may be produced
+   * from input events in this block.
    */
-  void DisallowSingleTap();
+  void SetDuringFastMotion();
   /**
-   * Set a flag that indicates that this touch block triggered a single tap event.
-   * @return true iff DisallowSingleTap was not previously called.
+   * @return true iff SetDuringFastMotion was called on this block.
+   */
+  bool IsDuringFastMotion() const;
+  /**
+   * Set the single-tap-occurred flag that indicates that this touch block
+   * triggered a single tap event.
+   * @return true if the flag was set. This may not happen if, for example,
+   *         SetDuringFastMotion was previously called.
    */
   bool SetSingleTapOccurred();
   /**
-   * @return true iff SetSingleTapOccurred was previously called on this block.
+   * @return true iff the single-tap-occurred flag is set on this block.
    */
   bool SingleTapOccurred() const;
 
   /**
    * @return true iff there are pending events in this touch block.
    */
   bool HasEvents() const;
   /**
@@ -166,17 +174,17 @@ public:
   bool TouchActionAllowsPanningXY() const;
 
 private:
   nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
   bool mAllowedTouchBehaviorSet;
   bool mPreventDefault;
   bool mContentResponded;
   bool mContentResponseTimerExpired;
-  bool mSingleTapDisallowed;
+  bool mDuringFastMotion;
   bool mSingleTapOccurred;
   nsTArray<MultiTouchInput> mEvents;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_InputBlockState_h
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -54,25 +54,28 @@ InputQueue::ReceiveInputEvent(const nsRe
     // touch blocks still in the queue.
     if (block == CurrentTouchBlock()) {
       // XXX using the chain from |block| here may be wrong in cases where the
       // target isn't confirmed and the real target turns out to be something
       // else. For now assume this is rare enough that it's not an issue.
       if (block->GetOverscrollHandoffChain()->HasFastMovingApzc()) {
         // If we're already in a fast fling, then we want the touch event to stop the fling
         // and to disallow the touch event from being used as part of a fling.
-        block->DisallowSingleTap();
+        block->SetDuringFastMotion();
       }
       block->GetOverscrollHandoffChain()->CancelAnimations();
     }
 
     bool waitForMainThread = !aTargetConfirmed;
     if (!gfxPrefs::LayoutEventRegionsEnabled()) {
       waitForMainThread |= aTarget->NeedToWaitForContent();
     }
+    if (block->IsDuringFastMotion()) {
+      waitForMainThread = false;
+    }
     if (waitForMainThread) {
       // We either don't know for sure if aTarget is the right APZC, or we may
       // need to wait to give content the opportunity to prevent-default the
       // touch events. Either way we schedule a timeout so the main thread stuff
       // can run.
       ScheduleMainThreadTimeout(aTarget, block->GetBlockId());
     } else {
       // Content won't prevent-default this, so we can just pretend like we scheduled
@@ -101,17 +104,19 @@ InputQueue::ReceiveInputEvent(const nsRe
   // null) should take priority. This is equivalent to just always using the
   // target (confirmed or not) from the block.
   nsRefPtr<AsyncPanZoomController> target = block->GetTargetApzc();
 
   nsEventStatus result = nsEventStatus_eIgnore;
   // XXX calling ArePointerEventsConsumable on |target| may be wrong here if
   // the target isn't confirmed and the real target turns out to be something
   // else. For now assume this is rare enough that it's not an issue.
-  if (target && target->ArePointerEventsConsumable(block, aEvent.AsMultiTouchInput().mTouches.Length())) {
+  if (block->IsDuringFastMotion()) {
+    result = nsEventStatus_eConsumeNoDefault;
+  } else if (target && target->ArePointerEventsConsumable(block, aEvent.AsMultiTouchInput().mTouches.Length())) {
     result = nsEventStatus_eConsumeDoDefault;
   }
 
   if (block == CurrentTouchBlock() && block->IsReadyForHandling()) {
     INPQ_LOG("current touch block is ready with target %p preventdefault %d\n",
         target.get(), block->IsDefaultPrevented());
     if (!target || block->IsDefaultPrevented()) {
       return result;
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -122,28 +122,28 @@ CanvasClient2D::CreateTextureClientForCa
                                              ClientCanvasLayer* aLayer)
 {
   if (aLayer->IsGLLayer()) {
     // We want a cairo backend here as we don't want to be copying into
     // an accelerated backend and we like LockBits to work. This is currently
     // the most effective way to make this work.
     return TextureClient::CreateForRawBufferAccess(GetForwarder(),
                                                    aFormat, aSize, BackendType::CAIRO,
-                                                   mTextureInfo.mTextureFlags | aFlags);
+                                                   mTextureFlags | aFlags);
   }
 
   gfx::BackendType backend = gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
 #ifdef XP_WIN
   return CreateTextureClientForDrawing(aFormat, aSize, backend, aFlags);
 #else
   // XXX - We should use CreateTextureClientForDrawing, but we first need
   // to use double buffering.
   return TextureClient::CreateForRawBufferAccess(GetForwarder(),
                                                  aFormat, aSize, backend,
-                                                 mTextureInfo.mTextureFlags | aFlags);
+                                                 mTextureFlags | aFlags);
 #endif
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 CanvasClientSharedSurface::CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
                                                      TextureFlags aFlags)
   : CanvasClient(aLayerForwarder, aFlags)
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -49,56 +49,53 @@ public:
   };
   static TemporaryRef<CanvasClient> CreateCanvasClient(CanvasClientType aType,
                                                        CompositableForwarder* aFwd,
                                                        TextureFlags aFlags);
 
   CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
     : CompositableClient(aFwd, aFlags)
   {
-    mTextureInfo.mTextureFlags = aFlags;
+    mTextureFlags = aFlags;
   }
 
   virtual ~CanvasClient() {}
 
   virtual void Clear() {};
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) = 0;
 
   virtual void Updated() { }
-
-protected:
-  TextureInfo mTextureInfo;
 };
 
 // Used for 2D canvases and WebGL canvas on non-GL systems where readback is requried.
 class CanvasClient2D : public CanvasClient
 {
 public:
   CanvasClient2D(CompositableForwarder* aLayerForwarder,
                  TextureFlags aFlags)
     : CanvasClient(aLayerForwarder, aFlags)
   {
   }
 
   TextureInfo GetTextureInfo() const
   {
-    return TextureInfo(CompositableType::IMAGE);
+    return TextureInfo(CompositableType::IMAGE, mTextureFlags);
   }
 
   virtual void Clear() MOZ_OVERRIDE
   {
     mBuffer = nullptr;
   }
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
 
   virtual bool AddTextureClient(TextureClient* aTexture) MOZ_OVERRIDE
   {
-    MOZ_ASSERT((mTextureInfo.mTextureFlags & aTexture->GetFlags()) == mTextureInfo.mTextureFlags);
+    MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
     return CompositableClient::AddTextureClient(aTexture);
   }
 
   virtual void OnDetach() MOZ_OVERRIDE
   {
     mBuffer = nullptr;
   }
 
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -24,32 +24,32 @@ namespace layers {
 using namespace mozilla::gfx;
 
 class ClientImageLayer : public ImageLayer, 
                          public ClientLayer {
 public:
   explicit ClientImageLayer(ClientLayerManager* aLayerManager)
     : ImageLayer(aLayerManager,
                  static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
-    , mImageClientTypeContainer(CompositableType::BUFFER_UNKNOWN)
+    , mImageClientTypeContainer(CompositableType::UNKNOWN)
   {
     MOZ_COUNT_CTOR(ClientImageLayer);
   }
 
 protected:
   virtual ~ClientImageLayer()
   {
     DestroyBackBuffer();
     MOZ_COUNT_DTOR(ClientImageLayer);
   }
 
   virtual void SetContainer(ImageContainer* aContainer) MOZ_OVERRIDE
   {
     ImageLayer::SetContainer(aContainer);
-    mImageClientTypeContainer = CompositableType::BUFFER_UNKNOWN;
+    mImageClientTypeContainer = CompositableType::UNKNOWN;
   }
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ImageLayer::SetVisibleRegion(aRegion);
   }
@@ -91,17 +91,17 @@ protected:
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
 
   CompositableType GetImageClientType()
   {
-    if (mImageClientTypeContainer != CompositableType::BUFFER_UNKNOWN) {
+    if (mImageClientTypeContainer != CompositableType::UNKNOWN) {
       return mImageClientTypeContainer;
     }
 
     if (mContainer->IsAsync()) {
       mImageClientTypeContainer = CompositableType::IMAGE_BRIDGE;
       return mImageClientTypeContainer;
     }
 
@@ -111,17 +111,17 @@ protected:
     if (autoLock.GetImage()->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
       mImageClientTypeContainer = CompositableType::IMAGE_OVERLAY;
       return mImageClientTypeContainer;
     }
 #endif
 
   	mImageClientTypeContainer = autoLock.GetImage()
 							  ? CompositableType::IMAGE
-							  : CompositableType::BUFFER_UNKNOWN;
+							  : CompositableType::UNKNOWN;
     return mImageClientTypeContainer;
   }
 
   RefPtr<ImageClient> mImageClient;
   CompositableType mImageClientTypeContainer;
 };
 
 void
@@ -137,20 +137,20 @@ ClientImageLayer::RenderLayer()
 
   if (mImageClient) {
     mImageClient->OnTransaction();
   }
 
   if (!mImageClient ||
       !mImageClient->UpdateImage(mContainer, GetContentFlags())) {
     CompositableType type = GetImageClientType();
-    if (type == CompositableType::BUFFER_UNKNOWN) {
+    if (type == CompositableType::UNKNOWN) {
       return;
     }
-    TextureFlags flags = TextureFlags::FRONT;
+    TextureFlags flags = TextureFlags::DEFAULT;
     if (mDisallowBigImage) {
       flags |= TextureFlags::DISALLOW_BIGIMAGE;
     }
     mImageClient = ImageClient::CreateImageClient(type,
                                                   ClientManager()->AsShadowForwarder(),
                                                   flags);
     if (type == CompositableType::IMAGE_BRIDGE) {
       static_cast<ImageClientBridge*>(mImageClient.get())->SetLayer(this);
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -51,20 +51,16 @@ namespace layers {
 static TextureFlags TextureFlagsForRotatedContentBufferFlags(uint32_t aBufferFlags)
 {
   TextureFlags result = TextureFlags::NO_FLAGS;
 
   if (aBufferFlags & RotatedContentBuffer::BUFFER_COMPONENT_ALPHA) {
     result |= TextureFlags::COMPONENT_ALPHA;
   }
 
-  if (aBufferFlags & RotatedContentBuffer::ALLOW_REPEAT) {
-    result |= TextureFlags::ALLOW_REPEAT;
-  }
-
   return result;
 }
 
 /* static */ TemporaryRef<ContentClient>
 ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
 {
   LayersBackend backend = aForwarder->GetCompositorBackendType();
   if (backend != LayersBackend::LAYERS_OPENGL &&
@@ -281,42 +277,42 @@ ContentClientRemoteBuffer::BuildTextureC
                     "Bad! Did we create a buffer twice without painting?");
 
   mIsNewBuffer = true;
 
   DestroyBuffers();
 
   mSurfaceFormat = aFormat;
   mSize = gfx::IntSize(aRect.width, aRect.height);
-  mTextureInfo.mTextureFlags = TextureFlagsForRotatedContentBufferFlags(aFlags);
+  mTextureFlags = TextureFlagsForRotatedContentBufferFlags(aFlags);
 
   if (aFlags & BUFFER_COMPONENT_ALPHA) {
-    mTextureInfo.mTextureFlags |= TextureFlags::COMPONENT_ALPHA;
+    mTextureFlags |= TextureFlags::COMPONENT_ALPHA;
   }
 
   CreateBackBuffer(mBufferRect);
 }
 
 void
 ContentClientRemoteBuffer::CreateBackBuffer(const nsIntRect& aBufferRect)
 {
   // gfx::BackendType::NONE means fallback to the content backend
   mTextureClient = CreateTextureClientForDrawing(
     mSurfaceFormat, mSize, gfx::BackendType::NONE,
-    mTextureInfo.mTextureFlags,
+    mTextureFlags,
     TextureAllocationFlags::ALLOC_CLEAR_BUFFER
   );
   if (!mTextureClient || !AddTextureClient(mTextureClient)) {
     AbortTextureClientCreation();
     return;
   }
 
-  if (mTextureInfo.mTextureFlags & TextureFlags::COMPONENT_ALPHA) {
+  if (mTextureFlags & TextureFlags::COMPONENT_ALPHA) {
     mTextureClientOnWhite = mTextureClient->CreateSimilar(
-      mTextureInfo.mTextureFlags,
+      mTextureFlags,
       TextureAllocationFlags::ALLOC_CLEAR_BUFFER_WHITE
     );
     if (!mTextureClientOnWhite || !AddTextureClient(mTextureClientOnWhite)) {
       AbortTextureClientCreation();
       return;
     }
   }
 }
@@ -697,19 +693,17 @@ ContentClientIncremental::BeginPaintBuff
   bool canReuseBuffer;
   nsIntRect destBufferRect;
 
   while (true) {
     mode = aLayer->GetSurfaceMode();
     neededRegion = aLayer->GetVisibleRegion();
     // If we're going to resample, we need a buffer that's in clamp mode.
     canReuseBuffer = neededRegion.GetBounds().Size() <= mBufferRect.Size() &&
-      mHasBuffer &&
-      (!(aFlags & RotatedContentBuffer::PAINT_WILL_RESAMPLE) ||
-       !(mTextureInfo.mTextureFlags & TextureFlags::ALLOW_REPEAT));
+      mHasBuffer && !(aFlags & RotatedContentBuffer::PAINT_WILL_RESAMPLE);
 
     if (canReuseBuffer) {
       if (mBufferRect.Contains(neededRegion.GetBounds())) {
         // We don't need to adjust mBufferRect.
         destBufferRect = mBufferRect;
       } else {
         // The buffer's big enough but doesn't contain everything that's
         // going to be visible. We'll move it.
@@ -795,19 +789,16 @@ ContentClientIncremental::BeginPaintBuff
     mBufferRotation.MoveTo(0, 0);
     canReuseBuffer = false;
   }
 
   nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
   bool createdBuffer = false;
 
   TextureFlags bufferFlags = TextureFlags::NO_FLAGS;
-  if (canHaveRotation) {
-    bufferFlags |= TextureFlags::ALLOW_REPEAT;
-  }
   if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
     bufferFlags |= TextureFlags::COMPONENT_ALPHA;
   }
   if (canReuseBuffer) {
     nsIntRect keepArea;
     if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
       // Set mBufferRotation so that the pixels currently in mBuffer
       // will still be rendered in the right place when mBufferRect
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -248,35 +248,29 @@ public:
   virtual const nsIntPoint& BufferRotation() const
   {
     return RotatedContentBuffer::BufferRotation();
   }
 
   virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
 
-  virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
-  {
-    return mTextureInfo;
-  }
-
 protected:
   void DestroyBuffers();
 
   virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
                                        const nsIntRegion& aVisibleRegion,
                                        bool aDidSelfCopy);
 
   void BuildTextureClients(gfx::SurfaceFormat aFormat,
                            const nsIntRect& aRect,
                            uint32_t aFlags);
 
   void CreateBackBuffer(const nsIntRect& aBufferRect);
 
-
   // Ensure we have a valid back buffer if we have a valid front buffer (i.e.
   // if a backbuffer has been created.)
   virtual void EnsureBackBufferIfFrontBuffer() {}
 
   // Create the front buffer for the ContentClient/Host pair if necessary
   // and notify the compositor that we have created the buffer(s).
   virtual void DestroyFrontBuffer() {}
 
@@ -289,17 +283,16 @@ protected:
 
   RefPtr<TextureClient> mTextureClient;
   RefPtr<TextureClient> mTextureClientOnWhite;
   // keep a record of texture clients we have created and need to keep around
   // (for RotatedBuffer to access), then unlock and remove them when we are done
   // painting.
   nsTArray<RefPtr<TextureClient> > mOldTextures;
 
-  TextureInfo mTextureInfo;
   bool mIsNewBuffer;
   bool mFrontAndBackBufferDiffer;
   gfx::IntSize mSize;
   gfx::SurfaceFormat mSurfaceFormat;
 };
 
 /**
  * A double buffered ContentClient. mTextureClient is the back buffer, which
@@ -312,19 +305,18 @@ protected:
  * references. In response to the compositor's reply we swap our references
  * (in SwapBuffers).
  */
 class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
 {
 public:
   explicit ContentClientDoubleBuffered(CompositableForwarder* aFwd)
     : ContentClientRemoteBuffer(aFwd)
-  {
-    mTextureInfo.mCompositableType = CompositableType::CONTENT_DOUBLE;
-  }
+  {}
+
   virtual ~ContentClientDoubleBuffered() {}
 
   virtual void Clear() MOZ_OVERRIDE
   {
     ContentClientRemoteBuffer::Clear();
     mFrontClient = nullptr;
     mFrontClientOnWhite = nullptr;
   }
@@ -336,16 +328,21 @@ public:
   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
 
   virtual void BeginPaint() MOZ_OVERRIDE;
 
   virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE;
 
   virtual void EnsureBackBufferIfFrontBuffer() MOZ_OVERRIDE;
 
+  virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
+  {
+    return TextureInfo(CompositableType::CONTENT_DOUBLE, mTextureFlags);
+  }
+
 protected:
   virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
 
 private:
   void UpdateDestinationFrom(const RotatedBuffer& aSource,
                              const nsIntRegion& aUpdateRegion);
 
   virtual void AbortTextureClientCreation() MOZ_OVERRIDE
@@ -372,21 +369,25 @@ private:
  * the compositor.
  */
 class ContentClientSingleBuffered : public ContentClientRemoteBuffer
 {
 public:
   explicit ContentClientSingleBuffered(CompositableForwarder* aFwd)
     : ContentClientRemoteBuffer(aFwd)
   {
-    mTextureInfo.mCompositableType = CompositableType::CONTENT_SINGLE;
   }
   virtual ~ContentClientSingleBuffered() {}
 
   virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE;
+
+  virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
+  {
+    return TextureInfo(CompositableType::CONTENT_SINGLE, mTextureFlags);
+  }
 };
 
 /**
  * A single buffered ContentClient that creates temporary buffers which are
  * used to update the host-side texture. The ownership of the buffers is
  * passed to the host side during the transaction, and we need to create
  * new ones each frame.
  */
@@ -395,17 +396,17 @@ class ContentClientIncremental : public 
 {
 public:
   explicit ContentClientIncremental(CompositableForwarder* aFwd)
     : ContentClientRemote(aFwd)
     , mContentType(gfxContentType::COLOR_ALPHA)
     , mHasBuffer(false)
     , mHasBufferOnWhite(false)
   {
-    mTextureInfo.mCompositableType = CompositableType::BUFFER_CONTENT_INC;
+    mTextureInfo.mCompositableType = CompositableType::CONTENT_INC;
   }
 
   typedef RotatedContentBuffer::PaintState PaintState;
   typedef RotatedContentBuffer::ContentType ContentType;
 
   virtual TextureInfo GetTextureInfo() const
   {
     return mTextureInfo;
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -49,17 +49,17 @@ ImageClient::CreateImageClient(Composita
   RefPtr<ImageClient> result = nullptr;
   switch (aCompositableHostType) {
   case CompositableType::IMAGE:
     result = new ImageClientSingle(aForwarder, aFlags, CompositableType::IMAGE);
     break;
   case CompositableType::IMAGE_BRIDGE:
     result = new ImageClientBridge(aForwarder, aFlags);
     break;
-  case CompositableType::BUFFER_UNKNOWN:
+  case CompositableType::UNKNOWN:
     result = nullptr;
     break;
 #ifdef MOZ_WIDGET_GONK
   case CompositableType::IMAGE_OVERLAY:
     result = new ImageClientOverlay(aForwarder, aFlags);
     break;
 #endif
   default:
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -470,16 +470,19 @@ TextureClient::CreateWithBufferSize(ISur
   return texture;
 }
 
 TextureClient::TextureClient(TextureFlags aFlags)
   : mFlags(aFlags)
   , mShared(false)
   , mValid(true)
   , mAddedToCompositableClient(false)
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+  , mPoolTracker(nullptr)
+#endif
 {}
 
 TextureClient::~TextureClient()
 {
   // All the destruction code that may lead to virtual method calls must
   // be in Finalize() which is called just before the destructor.
 }
 
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -32,30 +32,39 @@ class gfxReusableSurfaceWrapper;
 class gfxImageSurface;
 
 namespace mozilla {
 namespace gl {
 class GLContext;
 class SharedSurface;
 }
 
+// When defined, we track which pool the tile came from and test for
+// any inconsistencies.  This can be defined in release build as well.
+#ifdef DEBUG
+#define GFX_DEBUG_TRACK_CLIENTS_IN_POOL 1
+#endif
+
 namespace layers {
 
 class AsyncTransactionTracker;
 class ContentClient;
 class CompositableForwarder;
 class ISurfaceAllocator;
 class CompositableClient;
 class PlanarYCbCrImage;
 struct PlanarYCbCrData;
 class Image;
 class PTextureChild;
 class TextureChild;
 class BufferTextureClient;
 class TextureClient;
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+class TextureClientPool;
+#endif
 class KeepAlive;
 
 /**
  * TextureClient is the abstraction that allows us to share data between the
  * content and the compositor side.
  */
 
 enum TextureAllocationFlags {
@@ -469,16 +478,22 @@ protected:
   bool mAddedToCompositableClient;
 
   RefPtr<TextureReadbackSink> mReadbackSink;
 
   friend class TextureChild;
   friend class RemoveTextureFromCompositableTracker;
   friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
   friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
+
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+public:
+  // Pointer to the pool this tile came from.
+  TextureClientPool* mPoolTracker;
+#endif
 };
 
 /**
  * Task that releases TextureClient pointer on a specified thread.
  */
 class TextureClientReleaseTask : public Task
 {
 public:
--- a/gfx/layers/client/TextureClientPool.cpp
+++ b/gfx/layers/client/TextureClientPool.cpp
@@ -15,17 +15,18 @@ namespace mozilla {
 namespace layers {
 
 static void
 ShrinkCallback(nsITimer *aTimer, void *aClosure)
 {
   static_cast<TextureClientPool*>(aClosure)->ShrinkToMinimumSize();
 }
 
-TextureClientPool::TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
+TextureClientPool::TextureClientPool(gfx::SurfaceFormat aFormat,
+                                     gfx::IntSize aSize,
                                      uint32_t aMaxTextureClients,
                                      uint32_t aShrinkTimeoutMsec,
                                      ISurfaceAllocator *aAllocator)
   : mFormat(aFormat)
   , mSize(aSize)
   , mMaxTextureClients(aMaxTextureClients)
   , mShrinkTimeoutMsec(aShrinkTimeoutMsec)
   , mOutstandingClients(0)
@@ -37,25 +38,58 @@ TextureClientPool::TextureClientPool(gfx
   }
 }
 
 TextureClientPool::~TextureClientPool()
 {
   mTimer->Cancel();
 }
 
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+static bool TestClientPool(const char* what,
+                           TextureClient* aClient,
+                           TextureClientPool* aPool)
+{
+  TextureClientPool* actual = aClient->mPoolTracker;
+  bool ok = (actual == aPool);
+  if (ok) {
+    ok = (aClient->GetFormat() == aPool->GetFormat());
+  }
+
+  if (!ok) {
+    if (actual) {
+      gfxCriticalError() << "Pool error(" << what << "): "
+                   << aPool << "-" << aPool->GetFormat() << ", "
+                   << actual << "-" << actual->GetFormat() << ", "
+                   << aClient->GetFormat();
+      MOZ_CRASH("Crashing with actual");
+    } else {
+      gfxCriticalError() << "Pool error(" << what << "): "
+                   << aPool << "-" << aPool->GetFormat() << ", nullptr, "
+                   << aClient->GetFormat();
+      MOZ_CRASH("Crashing without actual");
+    }
+  }
+  return ok;
+}
+#endif
+
 TemporaryRef<TextureClient>
 TextureClientPool::GetTextureClient()
 {
   // Try to fetch a client from the pool
   RefPtr<TextureClient> textureClient;
   if (mTextureClients.size()) {
     mOutstandingClients++;
     textureClient = mTextureClients.top();
     mTextureClients.pop();
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+    DebugOnly<bool> ok = TestClientPool("fetch", textureClient, this);
+    MOZ_ASSERT(ok);
+#endif
     return textureClient;
   }
 
   // We're increasing the number of outstanding TextureClients without reusing a
   // client, we may need to free a deferred-return TextureClient.
   ShrinkToMaximumSize();
 
   // No unused clients in the pool, create one
@@ -65,25 +99,32 @@ TextureClientPool::GetTextureClient()
       mFormat, mSize, gfx::BackendType::NONE,
       TextureFlags::IMMEDIATE_UPLOAD, ALLOC_DEFAULT);
   } else {
     textureClient = TextureClient::CreateForDrawing(mSurfaceAllocator,
       mFormat, mSize, gfx::BackendType::NONE, TextureFlags::IMMEDIATE_UPLOAD);
   }
 
   mOutstandingClients++;
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+  textureClient->mPoolTracker = this;
+#endif
   return textureClient;
 }
 
 void
 TextureClientPool::ReturnTextureClient(TextureClient *aClient)
 {
   if (!aClient) {
     return;
   }
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+  DebugOnly<bool> ok = TestClientPool("return", aClient, this);
+  MOZ_ASSERT(ok);
+#endif
   // Add the client to the pool:
   MOZ_ASSERT(mOutstandingClients > mTextureClientsDeferred.size());
   mOutstandingClients--;
   mTextureClients.push(aClient);
 
   // Shrink down if we're beyond our maximum size
   ShrinkToMaximumSize();
 
@@ -96,16 +137,20 @@ TextureClientPool::ReturnTextureClient(T
 }
 
 void
 TextureClientPool::ReturnTextureClientDeferred(TextureClient *aClient)
 {
   if (!aClient) {
     return;
   }
+#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
+  DebugOnly<bool> ok = TestClientPool("defer", aClient, this);
+  MOZ_ASSERT(ok);
+#endif
   mTextureClientsDeferred.push(aClient);
   ShrinkToMaximumSize();
 }
 
 void
 TextureClientPool::ShrinkToMaximumSize()
 {
   uint32_t totalClientsOutstanding = mTextureClients.size() + mOutstandingClients;
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -518,17 +518,17 @@ protected:
 
     mTiledBuffer.Release();
     mLowPrecisionTiledBuffer.Release();
   }
 
 public:
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
-    return TextureInfo(CompositableType::BUFFER_TILED);
+    return TextureInfo(CompositableType::CONTENT_TILED);
   }
 
   virtual void ClearCachedResources() MOZ_OVERRIDE;
 
   enum TiledBufferType {
     TILED_BUFFER,
     LOW_PRECISION_TILED_BUFFER
   };
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -176,21 +176,20 @@ CompositableHost::RemoveMaskEffect()
 /* static */ TemporaryRef<CompositableHost>
 CompositableHost::Create(const TextureInfo& aTextureInfo)
 {
   RefPtr<CompositableHost> result;
   switch (aTextureInfo.mCompositableType) {
   case CompositableType::IMAGE_BRIDGE:
     NS_ERROR("Cannot create an image bridge compositable this way");
     break;
-  case CompositableType::BUFFER_CONTENT_INC:
+  case CompositableType::CONTENT_INC:
     result = new ContentHostIncremental(aTextureInfo);
     break;
-  case CompositableType::BUFFER_TILED:
-  case CompositableType::BUFFER_SIMPLE_TILED:
+  case CompositableType::CONTENT_TILED:
     result = new TiledContentHost(aTextureInfo);
     break;
   case CompositableType::IMAGE:
     result = new ImageHost(aTextureInfo);
     break;
 #ifdef MOZ_WIDGET_GONK
   case CompositableType::IMAGE_OVERLAY:
     result = new ImageHostOverlay(aTextureInfo);
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -236,17 +236,17 @@ public:
  * avoid blocking the main thread.
  */
 class ContentHostIncremental : public ContentHostBase
 {
 public:
   explicit ContentHostIncremental(const TextureInfo& aTextureInfo);
   ~ContentHostIncremental();
 
-  virtual CompositableType GetType() { return CompositableType::BUFFER_CONTENT_INC; }
+  virtual CompositableType GetType() { return CompositableType::CONTENT_INC; }
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE { return LayerRenderState(); }
 
   virtual bool CreatedIncrementalTexture(ISurfaceAllocator* aAllocator,
                                          const TextureInfo& aTextureInfo,
                                          const nsIntRect& aBufferRect) MOZ_OVERRIDE;
 
   virtual void UpdateIncremental(TextureIdentifier aTextureId,
--- a/gfx/layers/composite/PaintedLayerComposite.cpp
+++ b/gfx/layers/composite/PaintedLayerComposite.cpp
@@ -48,18 +48,18 @@ PaintedLayerComposite::~PaintedLayerComp
   MOZ_COUNT_DTOR(PaintedLayerComposite);
   CleanupResources();
 }
 
 bool
 PaintedLayerComposite::SetCompositableHost(CompositableHost* aHost)
 {
   switch (aHost->GetType()) {
-    case CompositableType::BUFFER_CONTENT_INC:
-    case CompositableType::BUFFER_TILED:
+    case CompositableType::CONTENT_INC:
+    case CompositableType::CONTENT_TILED:
     case CompositableType::CONTENT_SINGLE:
     case CompositableType::CONTENT_DOUBLE:
       mBuffer = static_cast<ContentHost*>(aHost);
       return true;
     default:
       return false;
   }
 }
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -229,17 +229,17 @@ public:
 
   void Composite(EffectChain& aEffectChain,
                  float aOpacity,
                  const gfx::Matrix4x4& aTransform,
                  const gfx::Filter& aFilter,
                  const gfx::Rect& aClipRect,
                  const nsIntRegion* aVisibleRegion = nullptr);
 
-  virtual CompositableType GetType() { return CompositableType::BUFFER_TILED; }
+  virtual CompositableType GetType() { return CompositableType::CONTENT_TILED; }
 
   virtual TiledLayerComposer* AsTiledLayerComposer() MOZ_OVERRIDE { return this; }
 
   virtual void Attach(Layer* aLayer,
                       Compositor* aCompositor,
                       AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;
 
   virtual void Detach(Layer* aLayer = nullptr,
--- a/intl/locale/langGroups.properties
+++ b/intl/locale/langGroups.properties
@@ -176,21 +176,25 @@ ve=x-western
 vi=x-western
 vo=x-western
 wa=x-western
 wo=x-western
 xh=x-western
 yi=he
 yo=x-western
 zh-cn=zh-CN
-# XXX : The following two entries are added as a quick fix (bug 251241).
+# XXX : The following five entries are added as a quick fix (bug 251241, bug 1104589).
 # When we have a general solution for ISO 15924 (script codes), the issue has
 # to be revisited.
 zh-hans=zh-CN
 zh-hant=zh-TW
+zh-latn=x-western
+ja-latn=x-western
+ko-latn=x-western
+#
 zh-tw=zh-TW
 zh-hk=zh-HK
 zh=zh-CN
 zh-min-nan=x-western
 zu=x-western
 #
 #==============================
 #
--- a/intl/locale/nsLanguageAtomService.cpp
+++ b/intl/locale/nsLanguageAtomService.cpp
@@ -100,35 +100,31 @@ nsLanguageAtomService::GetLanguageGroup(
       if (NS_FAILED(InitLangGroupTable())) {
         if (aError) {
           *aError = NS_ERROR_FAILURE;
         }
         return nullptr;
       }
     }
 
-    nsString langStr;
+    nsAutoString langStr;
     aLanguage->ToString(langStr);
 
     nsXPIDLString langGroupStr;
     res = mLangGroups->GetStringFromName(langStr.get(),
                                          getter_Copies(langGroupStr));
-    if (NS_FAILED(res)) {
-      int32_t hyphen = langStr.FindChar('-');
-      if (hyphen >= 0) {
-        nsAutoString truncated(langStr);
-        truncated.Truncate(hyphen);
-        res = mLangGroups->GetStringFromName(truncated.get(),
-                                             getter_Copies(langGroupStr));
-        if (NS_FAILED(res)) {
-          langGroupStr.AssignLiteral("x-unicode");
-        }
-      } else {
+    while (NS_FAILED(res)) {
+      int32_t hyphen = langStr.RFindChar('-');
+      if (hyphen <= 0) {
         langGroupStr.AssignLiteral("x-unicode");
+        break;
       }
+      langStr.Truncate(hyphen);
+      res = mLangGroups->GetStringFromName(langStr.get(),
+                                           getter_Copies(langGroupStr));
     }
 
     nsCOMPtr<nsIAtom> langGroup = do_GetAtom(langGroupStr);
 
     // The hashtable will keep an owning reference to the atom
     mLangToGroup.Put(aLanguage, langGroup);
     retVal = langGroup.get();
   }
--- a/js/ipc/CPOWTimer.cpp
+++ b/js/ipc/CPOWTimer.cpp
@@ -4,15 +4,24 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsfriendapi.h"
 #include "xpcprivate.h"
 #include "CPOWTimer.h"
 
-CPOWTimer::~CPOWTimer() {
+CPOWTimer::~CPOWTimer()
+{
     /* This is a best effort to find the compartment responsible for this CPOW call */
-    xpc::CompartmentPrivate* compartment = xpc::CompartmentPrivate::Get(js::GetObjectCompartment(mozilla::dom::GetIncumbentGlobal()
-                                                                                                 ->GetGlobalJSObject()));
+    nsIGlobalObject *global = mozilla::dom::GetIncumbentGlobal();
+    if (!global)
+        return;
+    JSObject *obj = global->GetGlobalJSObject();
+    if (!obj)
+        return;
+    JSCompartment *compartment = js::GetObjectCompartment(obj);
+    xpc::CompartmentPrivate *compartmentPrivate = xpc::CompartmentPrivate::Get(compartment);
+    if (!compartmentPrivate)
+        return;
     PRIntervalTime time = PR_IntervalNow() - startInterval;
-    compartment->CPOWTime += time;
+    compartmentPrivate->CPOWTime += time;
 }
--- a/js/src/asmjs/AsmJSFrameIterator.cpp
+++ b/js/src/asmjs/AsmJSFrameIterator.cpp
@@ -15,17 +15,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include "asmjs/AsmJSFrameIterator.h"
 
 #include "asmjs/AsmJSModule.h"
 #include "asmjs/AsmJSValidate.h"
-#include "jit/IonMacroAssembler.h"
+#include "jit/MacroAssembler.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::DebugOnly;
 
 /*****************************************************************************/
 // AsmJSFrameIterator implementation
--- a/js/src/asmjs/AsmJSModule.h
+++ b/js/src/asmjs/AsmJSModule.h
@@ -24,18 +24,18 @@
 #include "mozilla/PodOperations.h"
 
 #include "jsscript.h"
 
 #include "asmjs/AsmJSFrameIterator.h"
 #include "asmjs/AsmJSValidate.h"
 #include "builtin/SIMD.h"
 #include "gc/Marking.h"
-#include "jit/IonMacroAssembler.h"
 #include "jit/IonTypes.h"
+#include "jit/MacroAssembler.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "jit/RegisterSets.h"
 #include "jit/shared/Assembler-shared.h"
 #include "vm/TypedArrayObject.h"
 
 namespace js {
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -2288,17 +2288,17 @@ class FunctionCompiler
     LocalMap               locals_;
     VarInitializerVector   varInitializers_;
     Maybe<RetType>         alreadyReturned_;
 
     TempAllocator *        alloc_;
     MIRGraph *             graph_;
     CompileInfo *          info_;
     MIRGenerator *         mirGen_;
-    Maybe<IonContext>      ionContext_;
+    Maybe<JitContext>      jitContext_;
 
     MBasicBlock *          curBlock_;
 
     NodeStack              loopStack_;
     NodeStack              breakableStack_;
     UnlabeledBlockMap      unlabeledBreaks_;
     UnlabeledBlockMap      unlabeledContinues_;
     LabeledBlockMap        labeledBreaks_;
@@ -2396,17 +2396,17 @@ class FunctionCompiler
         return varInitializers_.append(init);
     }
 
     bool prepareToEmitMIR(const VarTypeVector &argTypes)
     {
         MOZ_ASSERT(locals_.count() == argTypes.length() + varInitializers_.length());
 
         alloc_  = lifo_.new_<TempAllocator>(&lifo_);
-        ionContext_.emplace(m_.cx(), alloc_);
+        jitContext_.emplace(m_.cx(), alloc_);
 
         graph_  = lifo_.new_<MIRGraph>(alloc_);
         info_   = lifo_.new_<CompileInfo>(locals_.count(), SequentialExecution);
         const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_AsmJS);
         const JitCompileOptions options;
         mirGen_ = lifo_.new_<MIRGenerator>(CompileCompartment::get(cx()->compartment()),
                                            options, alloc_,
                                            graph_, info_, optimizationInfo);
@@ -7575,17 +7575,17 @@ CheckFunctionsSequential(ModuleCompiler 
             return false;
 
         // In the case of the change-heap function, no MIR is produced.
         if (!mir)
             continue;
 
         int64_t before = PRMJ_Now();
 
-        IonContext icx(m.cx(), &mir->alloc());
+        JitContext jcx(m.cx(), &mir->alloc());
 
         IonSpewNewFunction(&mir->graph(), NullPtr());
 
         if (!OptimizeMIR(mir))
             return m.failOffset(func->srcBegin(), "internal compiler failure (probably out of memory)");
 
         LIRGraph *lir = GenerateLIR(mir);
         if (!lir)
@@ -7682,17 +7682,17 @@ GetUsedTask(ModuleCompiler &m, ParallelG
     if (!task)
         return false;
 
     ModuleCompiler::Func &func = *reinterpret_cast<ModuleCompiler::Func *>(task->func);
     func.accumulateCompileTime(task->compileTime);
 
     {
         // Perform code generation on the main thread.
-        IonContext ionContext(m.cx(), &task->mir->alloc());
+        JitContext jitContext(m.cx(), &task->mir->alloc());
         if (!GenerateCode(m, func, *task->mir, *task->lir))
             return false;
     }
 
     group.compiledJobs++;
 
     // Clear the LifoAlloc for use by another helper.
     TempAllocator &tempAlloc = task->mir->alloc();
@@ -8581,16 +8581,26 @@ GenerateFFIIonExit(ModuleCompiler &m, co
         masm.loadPtr(Address(reg0, offsetOfActivation), reg1);
         masm.store8(Imm32(0), Address(reg1, JitActivation::offsetOfActiveUint8()));
         masm.loadPtr(Address(reg1, JitActivation::offsetOfPrevJitTop()), reg2);
         masm.storePtr(reg2, Address(reg0, offsetOfJitTop));
         masm.loadPtr(Address(reg1, JitActivation::offsetOfPrevJitJSContext()), reg2);
         masm.storePtr(reg2, Address(reg0, offsetOfJitJSContext));
     }
 
+    MOZ_ASSERT(masm.framePushed() == framePushed);
+
+    // Reload the global register since Ion code can clobber any register.
+#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
+    JS_STATIC_ASSERT(MaybeSavedGlobalReg > 0);
+    masm.loadPtr(Address(StackPointer, savedGlobalOffset), GlobalReg);
+#else
+    JS_STATIC_ASSERT(MaybeSavedGlobalReg == 0);
+#endif
+
     masm.branchTestMagic(Assembler::Equal, JSReturnOperand, throwLabel);
 
     Label oolConvert;
     switch (exit.sig().retType().which()) {
       case RetType::Void:
         break;
       case RetType::Signed:
         masm.convertValueToInt32(JSReturnOperand, ReturnDoubleReg, ReturnReg, &oolConvert,
@@ -8604,26 +8614,16 @@ GenerateFFIIonExit(ModuleCompiler &m, co
       case RetType::Int32x4:
       case RetType::Float32x4:
         MOZ_CRASH("SIMD types shouldn't be returned from a FFI");
     }
 
     Label done;
     masm.bind(&done);
 
-    MOZ_ASSERT(masm.framePushed() == framePushed);
-
-    // Reload the global register since Ion code can clobber any register.
-#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
-    JS_STATIC_ASSERT(MaybeSavedGlobalReg > 0);
-    masm.loadPtr(Address(StackPointer, savedGlobalOffset), GlobalReg);
-#else
-    JS_STATIC_ASSERT(MaybeSavedGlobalReg == 0);
-#endif
-
     // The heap pointer has to be reloaded anyway since Ion could have clobbered
     // it. Additionally, the FFI may have detached the heap buffer.
     masm.loadAsmJSHeapRegisterFromGlobalData();
     GenerateCheckForHeapDetachment(m, ABIArgGenerator::NonReturn_VolatileReg0);
 
     Label profilingReturn;
     GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::JitFFI, &profilingReturn);
 
@@ -9042,17 +9042,17 @@ GenerateStubs(ModuleCompiler &m)
 }
 
 static bool
 FinishModule(ModuleCompiler &m,
              ScopedJSDeletePtr<AsmJSModule> *module)
 {
     LifoAlloc lifo(TempAllocator::PreferredLifoChunkSize);
     TempAllocator alloc(&lifo);
-    IonContext ionContext(m.cx(), &alloc);
+    JitContext jitContext(m.cx(), &alloc);
 
     m.masm().resetForNewCodeGenerator(alloc);
 
     if (!GenerateStubs(m))
         return false;
 
     return m.finish(module);
 }
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -974,17 +974,20 @@ TypedArrayDataPtrFromArgs(JSContext *cx,
     Rooted<TypedArrayObject*> typedArray(cx, &argobj.as<TypedArrayObject>());
 
     int32_t index;
     if (!ToInt32(cx, args[1], &index))
         return false;
 
     int32_t byteStart = index * typedArray->bytesPerElement();
     if (byteStart < 0 || (uint32_t(byteStart) + NumElem * sizeof(VElem)) > typedArray->byteLength())
-        return ErrorBadArgs(cx);
+    {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
+        return false;
+    }
 
     *data = reinterpret_cast<VElem*>(static_cast<char*>(typedArray->viewData()) + byteStart);
     return true;
 }
 
 template<class V, unsigned NumElem>
 static bool
 Load(JSContext *cx, unsigned argc, Value *vp)
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -2306,17 +2306,17 @@ InlineTypedObject::objectMovedDuringMino
     TypeDescr &descr = dst->as<InlineTypedObject>().typeDescr();
     if (descr.kind() == type::Array) {
         // The forwarding pointer can be direct as long as there is enough
         // space for it. Other objects might point into the object's buffer,
         // but they will not set any direct forwarding pointers.
         uint8_t *oldData = reinterpret_cast<uint8_t *>(src) + offsetOfDataStart();
         uint8_t *newData = dst->as<InlineTypedObject>().inlineTypedMem();
         trc->runtime()->gc.nursery.maybeSetForwardingPointer(trc, oldData, newData,
-                                                             descr.size() >= sizeof(uintptr_t));
+                                                             size_t(descr.size()) >= sizeof(uintptr_t));
     }
 }
 
 ArrayBufferObject *
 InlineTransparentTypedObject::getOrCreateBuffer(JSContext *cx)
 {
     LazyArrayBufferTable *&table = cx->compartment()->lazyArrayBuffers;
     if (!table) {
--- a/js/src/gc/ForkJoinNursery.cpp
+++ b/js/src/gc/ForkJoinNursery.cpp
@@ -9,17 +9,17 @@
 
 #include "gc/ForkJoinNursery-inl.h"
 
 #include "mozilla/IntegerPrintfMacros.h"
 
 #include "prmjtime.h"
 
 #include "gc/Heap.h"
-#include "jit/IonFrames.h"
+#include "jit/JitFrames.h"
 #include "jit/RematerializedFrame.h"
 #include "vm/ArrayObject.h"
 #include "vm/ForkJoin.h"
 
 #include "jsgcinlines.h"
 #include "gc/Nursery-inl.h"
 #include "vm/NativeObject-inl.h"
 
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -14,17 +14,17 @@
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsinfer.h"
 #include "jsutil.h"
 #include "prmjtime.h"
 
 #include "gc/GCInternals.h"
 #include "gc/Memory.h"
-#include "jit/IonFrames.h"
+#include "jit/JitFrames.h"
 #include "vm/ArrayObject.h"
 #include "vm/Debugger.h"
 #if defined(DEBUG)
 #include "vm/ScopeObject.h"
 #endif
 #include "vm/TypedArrayObject.h"
 
 #include "jsgcinlines.h"
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -16,17 +16,17 @@
 #include "jstypes.h"
 #include "jswatchpoint.h"
 
 #include "builtin/MapObject.h"
 #include "frontend/BytecodeCompiler.h"
 #include "gc/ForkJoinNursery.h"
 #include "gc/GCInternals.h"
 #include "gc/Marking.h"
-#include "jit/IonMacroAssembler.h"
+#include "jit/MacroAssembler.h"
 #include "js/HashTable.h"
 #include "vm/Debugger.h"
 #include "vm/JSONParser.h"
 #include "vm/PropDesc.h"
 
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
@@ -26,17 +26,17 @@
 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "irregexp/NativeRegExpMacroAssembler.h"
 
 #include "irregexp/RegExpStack.h"
-#include "jit/IonLinker.h"
+#include "jit/Linker.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "vm/MatchPairs.h"
 
 using namespace js;
 using namespace js::irregexp;
 using namespace js::jit;
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1717,17 +1717,17 @@ irregexp::CompilePattern(JSContext *cx, 
 
     Analysis analysis(cx, ignore_case, is_ascii);
     analysis.EnsureAnalyzed(node);
     if (analysis.has_failed()) {
         JS_ReportError(cx, analysis.errorMessage());
         return RegExpCode();
     }
 
-    Maybe<jit::IonContext> ctx;
+    Maybe<jit::JitContext> ctx;
     Maybe<NativeRegExpMacroAssembler> native_assembler;
     Maybe<InterpretedRegExpMacroAssembler> interpreted_assembler;
 
     RegExpMacroAssembler *assembler;
     if (IsNativeRegExpEnabled(cx) && !force_bytecode) {
         NativeRegExpMacroAssembler::Mode mode =
             is_ascii ? NativeRegExpMacroAssembler::ASCII
                      : NativeRegExpMacroAssembler::CHAR16;
--- a/js/src/irregexp/RegExpMacroAssembler.h
+++ b/js/src/irregexp/RegExpMacroAssembler.h
@@ -28,17 +28,17 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef V8_REGEXP_MACRO_ASSEMBLER_H_
 #define V8_REGEXP_MACRO_ASSEMBLER_H_
 
 #include "irregexp/RegExpAST.h"
 #include "irregexp/RegExpEngine.h"
-#include "jit/IonMacroAssembler.h"
+#include "jit/MacroAssembler.h"
 
 namespace js {
 namespace irregexp {
 
 class MOZ_STACK_CLASS RegExpMacroAssembler
 {
   public:
     RegExpMacroAssembler(LifoAlloc &alloc, RegExpShared *shared, size_t numSavedRegisters)
--- a/js/src/jit/AliasAnalysis.cpp
+++ b/js/src/jit/AliasAnalysis.cpp
@@ -158,17 +158,17 @@ IonSpewAliasInfo(const char *pre, MInstr
 // having an implicit dependency on the last instruction of the loop header, so that
 // it's never moved before the loop header.
 //
 // The algorithm depends on the invariant that both control instructions and effectful
 // instructions (stores) are never hoisted.
 bool
 AliasAnalysis::analyze()
 {
-    Vector<MInstructionVector, AliasSet::NumCategories, IonAllocPolicy> stores(alloc());
+    Vector<MInstructionVector, AliasSet::NumCategories, JitAllocPolicy> stores(alloc());
 
     // Initialize to the first instruction.
     MInstruction *firstIns = *graph_.entryBlock()->begin();
     for (unsigned i = 0; i < AliasSet::NumCategories; i++) {
         MInstructionVector defs(alloc());
         if (!defs.append(firstIns))
             return false;
         if (!stores.append(Move(defs)))
--- a/js/src/jit/BacktrackingAllocator.h
+++ b/js/src/jit/BacktrackingAllocator.h
@@ -23,17 +23,17 @@ namespace jit {
 
 // Information about a group of registers. Registers may be grouped together
 // when (a) all of their lifetimes are disjoint, (b) they are of the same type
 // (double / non-double) and (c) it is desirable that they have the same
 // allocation.
 struct VirtualRegisterGroup : public TempObject
 {
     // All virtual registers in the group.
-    Vector<uint32_t, 2, IonAllocPolicy> registers;
+    Vector<uint32_t, 2, JitAllocPolicy> registers;
 
     // Desired physical register to use for registers in the group.
     LAllocation allocation;
 
     // Spill location to be shared by registers in the group.
     LAllocation spill;
 
     explicit VirtualRegisterGroup(TempAllocator &alloc)
--- a/js/src/jit/Bailouts.cpp
+++ b/js/src/jit/Bailouts.cpp
@@ -27,17 +27,17 @@ using mozilla::IsInRange;
 uint32_t
 jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
 {
     JSContext *cx = GetJSContextFromJitCode();
     MOZ_ASSERT(bailoutInfo);
 
     // We don't have an exit frame.
     MOZ_ASSERT(IsInRange(FAKE_JIT_TOP_FOR_BAILOUT, 0, 0x1000) &&
-               IsInRange(FAKE_JIT_TOP_FOR_BAILOUT + sizeof(IonCommonFrameLayout), 0, 0x1000),
+               IsInRange(FAKE_JIT_TOP_FOR_BAILOUT + sizeof(CommonFrameLayout), 0, 0x1000),
                "Fake jitTop pointer should be within the first page.");
     cx->mainThread().jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
 
     JitActivationIterator jitActivations(cx->runtime());
     BailoutFrameInfo bailoutData(jitActivations, sp);
     JitFrameIterator iter(jitActivations);
     MOZ_ASSERT(!iter.ionScript()->invalidated());
 
@@ -139,17 +139,17 @@ jit::InvalidationBailout(InvalidationBai
         // pseudostack frame would not have been pushed in the first
         // place, so don't pop anything in that case.
         bool popSPSFrame = iter.ionScript()->hasSPSInstrumentation() &&
                            (SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck) &&
                            !poppedLastSPSFrame;
         JSScript *script = iter.script();
         probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
 
-        IonJSFrameLayout *frame = iter.jsFrame();
+        JitFrameLayout *frame = iter.jsFrame();
         JitSpew(JitSpew_IonInvalidate, "Bailout failed (%s): converting to exit frame",
                 (retval == BAILOUT_RETURN_FATAL_ERROR) ? "Fatal Error" : "Over Recursion");
         JitSpew(JitSpew_IonInvalidate, "   orig calleeToken %p", (void *) frame->calleeToken());
         JitSpew(JitSpew_IonInvalidate, "   orig frameSize %u", unsigned(frame->prevFrameLocalSize()));
         JitSpew(JitSpew_IonInvalidate, "   orig ra %p", (void *) frame->returnAddress());
 
         frame->replaceCalleeToken(nullptr);
         EnsureExitFrame(frame);
--- a/js/src/jit/Bailouts.h
+++ b/js/src/jit/Bailouts.h
@@ -4,18 +4,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_Bailouts_h
 #define jit_Bailouts_h
 
 #include "jstypes.h"
 
-#include "jit/IonFrames.h"
 #include "jit/JitFrameIterator.h"
+#include "jit/JitFrames.h"
 #include "vm/Stack.h"
 
 namespace js {
 namespace jit {
 
 // A "bailout" is a condition in which we need to recover an interpreter frame
 // from an IonFrame. Bailouts can happen for the following reasons:
 //   (1) A deoptimization guard, for example, an add overflows or a type check
@@ -81,17 +81,17 @@ namespace jit {
 // Then, we can provide a per-script mapping from BailoutIds to snapshots,
 // which takes only four bytes per entry.
 //
 // This strategy does not work as given, because the bailout handler has no way
 // to compute the location of an IonScript. Currently, we do not use frame
 // pointers. To account for this we segregate frames into a limited set of
 // "frame sizes", and create a table for each frame size. We also have the
 // option of not using bailout tables, for platforms or situations where the
-// 10 byte cost is more optimal than a bailout table. See IonFrames.h for more
+// 10 byte cost is more optimal than a bailout table. See JitFrames.h for more
 // detail.
 
 static const BailoutId INVALID_BAILOUT_ID = BailoutId(-1);
 
 // Keep this arbitrarily small for now, for testing.
 static const uint32_t BAILOUT_TABLE_SIZE = 16;
 
 // Bailout return codes.
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -15,17 +15,17 @@
 #include "jit/RematerializedFrame.h"
 
 #include "vm/ArgumentsObject.h"
 #include "vm/Debugger.h"
 #include "vm/TraceLogging.h"
 
 #include "jsscriptinlines.h"
 
-#include "jit/IonFrames-inl.h"
+#include "jit/JitFrames-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 // BaselineStackBuilder may reallocate its buffer if the current one is too
 // small. To avoid dangling pointers, BufferPointer represents a pointer into
 // this buffer as a pointer to the header and a fixed offset.
 template <typename T>
@@ -70,32 +70,32 @@ class BufferPointer
  * data that's written to the reconstructed stack grows from high to low in memory.
  *
  * The lowest region of the allocated memory contains a BaselineBailoutInfo structure that
  * points to the start and end of the written data.
  */
 struct BaselineStackBuilder
 {
     JitFrameIterator &iter_;
-    IonJSFrameLayout *frame_;
+    JitFrameLayout *frame_;
 
     static size_t HeaderSize() {
         return AlignBytes(sizeof(BaselineBailoutInfo), sizeof(void *));
     }
     size_t bufferTotal_;
     size_t bufferAvail_;
     size_t bufferUsed_;
     uint8_t *buffer_;
     BaselineBailoutInfo *header_;
 
     size_t framePushed_;
 
     BaselineStackBuilder(JitFrameIterator &iter, size_t initialSize)
       : iter_(iter),
-        frame_(static_cast<IonJSFrameLayout*>(iter.current())),
+        frame_(static_cast<JitFrameLayout*>(iter.current())),
         bufferTotal_(initialSize),
         bufferAvail_(0),
         bufferUsed_(0),
         buffer_(nullptr),
         header_(nullptr),
         framePushed_(0)
     {
         MOZ_ASSERT(bufferTotal_ >= HeaderSize());
@@ -295,87 +295,87 @@ struct BaselineStackBuilder
     }
 
     inline uint8_t *virtualPointerAtStackOffset(size_t offset) {
         if (offset < bufferUsed_)
             return reinterpret_cast<uint8_t *>(frame_) - (bufferUsed_ - offset);
         return reinterpret_cast<uint8_t *>(frame_) + (offset - bufferUsed_);
     }
 
-    inline IonJSFrameLayout *startFrame() {
+    inline JitFrameLayout *startFrame() {
         return frame_;
     }
 
-    BufferPointer<IonJSFrameLayout> topFrameAddress() {
-        return pointerAtStackOffset<IonJSFrameLayout>(0);
+    BufferPointer<JitFrameLayout> topFrameAddress() {
+        return pointerAtStackOffset<JitFrameLayout>(0);
     }
 
     //
     // This method should only be called when the builder is in a state where it is
     // starting to construct the stack frame for the next callee.  This means that
     // the lowest value on the constructed stack is the return address for the previous
     // caller frame.
     //
     // This method is used to compute the value of the frame pointer (e.g. ebp on x86)
     // that would have been saved by the baseline jitcode when it was entered.  In some
     // cases, this value can be bogus since we can ensure that the caller would have saved
     // it anyway.
     //
     void *calculatePrevFramePtr() {
         // Get the incoming frame.
-        BufferPointer<IonJSFrameLayout> topFrame = topFrameAddress();
+        BufferPointer<JitFrameLayout> topFrame = topFrameAddress();
         FrameType type = topFrame->prevType();
 
         // For IonJS and Entry frames, the "saved" frame pointer in the baseline
         // frame is meaningless, since Ion saves all registers before calling other ion
         // frames, and the entry frame saves all registers too.
         if (type == JitFrame_IonJS || type == JitFrame_Entry)
             return nullptr;
 
         // BaselineStub - Baseline calling into Ion.
         //  PrevFramePtr needs to point to the BaselineStubFrame's saved frame pointer.
-        //      STACK_START_ADDR + IonJSFrameLayout::Size() + PREV_FRAME_SIZE
-        //                      - IonBaselineStubFrameLayout::reverseOffsetOfSavedFramePtr()
+        //      STACK_START_ADDR + JitFrameLayout::Size() + PREV_FRAME_SIZE
+        //                      - BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr()
         if (type == JitFrame_BaselineStub) {
-            size_t offset = IonJSFrameLayout::Size() + topFrame->prevFrameLocalSize() +
-                            IonBaselineStubFrameLayout::reverseOffsetOfSavedFramePtr();
+            size_t offset = JitFrameLayout::Size() + topFrame->prevFrameLocalSize() +
+                            BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr();
             return virtualPointerAtStackOffset(offset);
         }
 
         MOZ_ASSERT(type == JitFrame_Rectifier);
         // Rectifier - behaviour depends on the frame preceding the rectifier frame, and
         // whether the arch is x86 or not.  The x86 rectifier frame saves the frame pointer,
         // so we can calculate it directly.  For other archs, the previous frame pointer
         // is stored on the stack in the frame that precedes the rectifier frame.
-        size_t priorOffset = IonJSFrameLayout::Size() + topFrame->prevFrameLocalSize();
+        size_t priorOffset = JitFrameLayout::Size() + topFrame->prevFrameLocalSize();
 #if defined(JS_CODEGEN_X86)
         // On X86, the FramePointer is pushed as the first value in the Rectifier frame.
         MOZ_ASSERT(BaselineFrameReg == FramePointer);
         priorOffset -= sizeof(void *);
         return virtualPointerAtStackOffset(priorOffset);
 #elif defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
         // On X64, ARM and MIPS, the frame pointer save location depends on
         // the caller of the rectifier frame.
-        BufferPointer<IonRectifierFrameLayout> priorFrame =
-            pointerAtStackOffset<IonRectifierFrameLayout>(priorOffset);
+        BufferPointer<RectifierFrameLayout> priorFrame =
+            pointerAtStackOffset<RectifierFrameLayout>(priorOffset);
         FrameType priorType = priorFrame->prevType();
         MOZ_ASSERT(priorType == JitFrame_IonJS || priorType == JitFrame_BaselineStub);
 
         // If the frame preceding the rectifier is an IonJS frame, then once again
         // the frame pointer does not matter.
         if (priorType == JitFrame_IonJS)
             return nullptr;
 
         // Otherwise, the frame preceding the rectifier is a BaselineStub frame.
-        //  let X = STACK_START_ADDR + IonJSFrameLayout::Size() + PREV_FRAME_SIZE
-        //      X + IonRectifierFrameLayout::Size()
-        //        + ((IonRectifierFrameLayout *) X)->prevFrameLocalSize()
+        //  let X = STACK_START_ADDR + JitFrameLayout::Size() + PREV_FRAME_SIZE
+        //      X + RectifierFrameLayout::Size()
+        //        + ((RectifierFrameLayout *) X)->prevFrameLocalSize()
         //        - BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr()
-        size_t extraOffset = IonRectifierFrameLayout::Size() + priorFrame->prevFrameLocalSize() +
-                             IonBaselineStubFrameLayout::reverseOffsetOfSavedFramePtr();
+        size_t extraOffset = RectifierFrameLayout::Size() + priorFrame->prevFrameLocalSize() +
+                             BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr();
         return virtualPointerAtStackOffset(priorOffset + extraOffset);
 #elif defined(JS_CODEGEN_NONE)
         MOZ_CRASH();
 #else
 #  error "Bad architecture!"
 #endif
     }
 };
@@ -714,17 +714,17 @@ InitFromBailout(JSContext *cx, HandleScr
 
     if (fun) {
         // The unpacked thisv and arguments should overwrite the pushed args present
         // in the calling frame.
         Value thisv = iter.read();
         JitSpew(JitSpew_BaselineBailouts, "      Is function!");
         JitSpew(JitSpew_BaselineBailouts, "      thisv=%016llx", *((uint64_t *) &thisv));
 
-        size_t thisvOffset = builder.framePushed() + IonJSFrameLayout::offsetOfThis();
+        size_t thisvOffset = builder.framePushed() + JitFrameLayout::offsetOfThis();
         *builder.valuePointerAtStackOffset(thisvOffset) = thisv;
 
         MOZ_ASSERT(iter.numAllocations() >= CountArgSlots(script, fun));
         JitSpew(JitSpew_BaselineBailouts, "      frame slots %u, nargs %u, nfixed %u",
                 iter.numAllocations(), fun->nargs(), script->nfixed());
 
         if (!callerPC) {
             // This is the first frame. Store the formals in a Vector until we
@@ -737,17 +737,17 @@ InitFromBailout(JSContext *cx, HandleScr
                 return false;
         }
 
         for (uint32_t i = 0; i < fun->nargs(); i++) {
             Value arg = iter.read();
             JitSpew(JitSpew_BaselineBailouts, "      arg %d = %016llx",
                         (int) i, *((uint64_t *) &arg));
             if (callerPC) {
-                size_t argOffset = builder.framePushed() + IonJSFrameLayout::offsetOfActualArg(i);
+                size_t argOffset = builder.framePushed() + JitFrameLayout::offsetOfActualArg(i);
                 *builder.valuePointerAtStackOffset(argOffset) = arg;
             } else {
                 startFrameFormals[i].set(arg);
             }
         }
     }
 
     for (uint32_t i = 0; i < script->nfixed(); i++) {
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -8,19 +8,19 @@
 
 #include "mozilla/UniquePtr.h"
 
 #include "jit/BaselineHelpers.h"
 #include "jit/BaselineIC.h"
 #include "jit/BaselineJIT.h"
 #include "jit/FixedList.h"
 #include "jit/IonAnalysis.h"
-#include "jit/IonLinker.h"
 #include "jit/JitcodeMap.h"
 #include "jit/JitSpewer.h"
+#include "jit/Linker.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "vm/TraceLogging.h"
 
 #include "jsscriptinlines.h"
 
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -3,22 +3,21 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/BaselineDebugModeOSR.h"
 
 #include "mozilla/DebugOnly.h"
 
-#include "jit/IonLinker.h"
-
 #include "jit/JitcodeMap.h"
+#include "jit/Linker.h"
 #include "jit/PerfSpewer.h"
 
-#include "jit/IonFrames-inl.h"
+#include "jit/JitFrames-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::DebugOnly;
 
 struct DebugModeOSREntry
@@ -210,17 +209,17 @@ CollectJitStackScripts(JSContext *cx, co
             }
             entries.back().oldStub = prevFrameStubPtr;
             prevFrameStubPtr = nullptr;
             break;
           }
 
           case JitFrame_BaselineStub:
             prevFrameStubPtr =
-                reinterpret_cast<IonBaselineStubFrameLayout *>(iter.fp())->maybeStubPtr();
+                reinterpret_cast<BaselineStubFrameLayout *>(iter.fp())->maybeStubPtr();
             break;
 
           case JitFrame_IonJS: {
             InlineFrameIterator inlineIter(cx, &iter);
             while (true) {
                 if (obs.shouldRecompileOrInvalidate(inlineIter.script())) {
                     if (!entries.append(DebugModeOSREntry(inlineIter.script())))
                         return false;
@@ -335,17 +334,17 @@ PatchBaselineFramesForDebugMode(JSContex
     //  G. Undo cases B, C, D, or E above on previously patched yet unpopped
     //     frames.
     //
     // In general, we patch the return address from the VM call to return to a
     // "continuation fixer" to fix up machine state (registers and stack
     // state). Specifics on what need to be done are documented below.
     //
 
-    IonCommonFrameLayout *prev = nullptr;
+    CommonFrameLayout *prev = nullptr;
     size_t entryIndex = *start;
 
     for (JitFrameIterator iter(activation); !iter.done(); ++iter) {
         switch (iter.type()) {
           case JitFrame_BaselineJS: {
             // If the script wasn't recompiled or is not observed, there's
             // nothing to patch.
             if (!obs.shouldRecompileOrInvalidate(iter.script()))
@@ -497,18 +496,18 @@ PatchBaselineFramesForDebugMode(JSContex
                 break;
 
             DebugModeOSREntry &entry = entries[entryIndex];
 
             // If the script wasn't recompiled, there's nothing to patch.
             if (!entry.recompiled())
                 break;
 
-            IonBaselineStubFrameLayout *layout =
-                reinterpret_cast<IonBaselineStubFrameLayout *>(iter.fp());
+            BaselineStubFrameLayout *layout =
+                reinterpret_cast<BaselineStubFrameLayout *>(iter.fp());
             MOZ_ASSERT(layout->maybeStubPtr() == entry.oldStub);
 
             // Patch baseline stub frames for case A above.
             //
             // We need to patch the stub frame to point to an ICStub belonging
             // to the recompiled baseline script. These stubs are allocated up
             // front in CloneOldBaselineStub. They share the same JitCode as
             // the old baseline script's stubs, so we don't need to patch the
--- a/js/src/jit/BaselineFrame.cpp
+++ b/js/src/jit/BaselineFrame.cpp
@@ -6,17 +6,17 @@
 
 #include "jit/BaselineFrame-inl.h"
 
 #include "jit/BaselineJIT.h"
 #include "jit/Ion.h"
 #include "vm/Debugger.h"
 #include "vm/ScopeObject.h"
 
-#include "jit/IonFrames-inl.h"
+#include "jit/JitFrames-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 static void
 MarkLocals(BaselineFrame *frame, JSTracer *trc, unsigned start, unsigned end)
 {
--- a/js/src/jit/BaselineFrame.h
+++ b/js/src/jit/BaselineFrame.h
@@ -2,28 +2,28 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_BaselineFrame_h
 #define jit_BaselineFrame_h
 
-#include "jit/IonFrames.h"
+#include "jit/JitFrames.h"
 #include "vm/Stack.h"
 
 namespace js {
 namespace jit {
 
 struct BaselineDebugModeOSRInfo;
 
 // The stack looks like this, fp is the frame pointer:
 //
 // fp+y   arguments
-// fp+x   IonJSFrameLayout (frame header)
+// fp+x   JitFrameLayout (frame header)
 // fp  => saved frame pointer
 // fp-x   BaselineFrame
 //        locals
 //        stack values
 
 // Eval frames
 //
 // Like js::InterpreterFrame, every BaselineFrame is either a global frame
@@ -369,33 +369,33 @@ class BaselineFrame
     }
     bool isNonEvalFunctionFrame() const {
         return isFunctionFrame() && !isEvalFrame();
     }
     bool isDebuggerEvalFrame() const {
         return false;
     }
 
-    IonJSFrameLayout *framePrefix() const {
+    JitFrameLayout *framePrefix() const {
         uint8_t *fp = (uint8_t *)this + Size() + FramePointerOffset;
-        return (IonJSFrameLayout *)fp;
+        return (JitFrameLayout *)fp;
     }
 
     // Methods below are used by the compiler.
     static size_t offsetOfCalleeToken() {
-        return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfCalleeToken();
+        return FramePointerOffset + js::jit::JitFrameLayout::offsetOfCalleeToken();
     }
     static size_t offsetOfThis() {
-        return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfThis();
+        return FramePointerOffset + js::jit::JitFrameLayout::offsetOfThis();
     }
     static size_t offsetOfArg(size_t index) {
-        return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfActualArg(index);
+        return FramePointerOffset + js::jit::JitFrameLayout::offsetOfActualArg(index);
     }
     static size_t offsetOfNumActualArgs() {
-        return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfNumActualArgs();
+        return FramePointerOffset + js::jit::JitFrameLayout::offsetOfNumActualArgs();
     }
     static size_t Size() {
         return sizeof(BaselineFrame);
     }
 
     // The reverseOffsetOf methods below compute the offset relative to the
     // frame's base pointer. Since the stack grows down, these offsets are
     // negative.
--- a/js/src/jit/BaselineFrameInfo.h
+++ b/js/src/jit/BaselineFrameInfo.h
@@ -7,17 +7,17 @@
 #ifndef jit_BaselineFrameInfo_h
 #define jit_BaselineFrameInfo_h
 
 #include "mozilla/Alignment.h"
 
 #include "jit/BaselineFrame.h"
 #include "jit/BaselineRegisters.h"
 #include "jit/FixedList.h"
-#include "jit/IonMacroAssembler.h"
+#include "jit/MacroAssembler.h"
 
 namespace js {
 namespace jit {
 
 struct BytecodeInfo;
 
 // FrameInfo overview.
 //
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -11,45 +11,45 @@
 
 #include "jslibmath.h"
 #include "jstypes.h"
 
 #include "builtin/Eval.h"
 #include "jit/BaselineDebugModeOSR.h"
 #include "jit/BaselineHelpers.h"
 #include "jit/BaselineJIT.h"
-#include "jit/IonLinker.h"
 #include "jit/JitSpewer.h"
+#include "jit/Linker.h"
 #include "jit/Lowering.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "vm/Opcodes.h"
 #include "vm/TypedArrayCommon.h"
 
 #include "jsboolinlines.h"
 #include "jsscriptinlines.h"
 
-#include "jit/IonFrames-inl.h"
+#include "jit/JitFrames-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/ScopeObject-inl.h"
 #include "vm/StringObject-inl.h"
 
 using mozilla::DebugOnly;
 
 namespace js {
 namespace jit {
 
 #ifdef DEBUG
 void
 FallbackICSpew(JSContext *cx, ICFallbackStub *stub, const char *fmt, ...)
 {
     if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
-        RootedScript script(cx, GetTopIonJSScript(cx));
+        RootedScript script(cx, GetTopJitJSScript(cx));
         jsbytecode *pc = stub->icEntry()->pc(script);
 
         char fmtbuf[100];
         va_list args;
         va_start(args, fmt);
         vsnprintf(fmtbuf, 100, fmt, args);
         va_end(args);
 
@@ -64,17 +64,17 @@ FallbackICSpew(JSContext *cx, ICFallback
                 fmtbuf);
     }
 }
 
 void
 TypeFallbackICSpew(JSContext *cx, ICTypeMonitor_Fallback *stub, const char *fmt, ...)
 {
     if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
-        RootedScript script(cx, GetTopIonJSScript(cx));
+        RootedScript script(cx, GetTopJitJSScript(cx));
         jsbytecode *pc = stub->icEntry()->pc(script);
 
         char fmtbuf[100];
         va_list args;
         va_start(args, fmt);
         vsnprintf(fmtbuf, 100, fmt, args);
         va_end(args);
 
@@ -613,17 +613,17 @@ ICStubCompiler::getStubCode()
 
     // Check for existing cached stubcode.
     uint32_t stubKey = getKey();
     JitCode *stubCode = comp->getStubCode(stubKey);
     if (stubCode)
         return stubCode;
 
     // Compile new stubcode.
-    IonContext ictx(cx, nullptr);
+    JitContext jctx(cx, nullptr);
     MacroAssembler masm;
 #ifdef JS_CODEGEN_ARM
     masm.setSecondScratchReg(BaselineSecondScratchReg);
 #endif
 
     if (!generateStubCode(masm))
         return nullptr;
     Linker linker(masm);
@@ -1015,17 +1015,17 @@ ICWarmUpCounter_Fallback::Compiler::gene
 
     Label noCompiledCode;
     // Call DoWarmUpCounterFallback to compile/check-for Ion-compiled function
     {
         // Push IonOsrTempData pointer storage
         masm.subPtr(Imm32(sizeof(void *)), BaselineStackReg);
         masm.push(BaselineStackReg);
 
-        // Push IonJSFrameLayout pointer.
+        // Push JitFrameLayout pointer.
         masm.loadBaselineFramePtr(R0.scratchReg(), R0.scratchReg());
         masm.push(R0.scratchReg());
 
         // Push stub pointer.
         masm.push(BaselineStubReg);
 
         if (!callVM(DoWarmUpCounterFallbackInfo, masm))
             return false;
@@ -4231,17 +4231,17 @@ ICGetElemNativeCompiler::emitCallScripte
     // be clobbered.
     {
         GeneralRegisterSet availRegs = availableGeneralRegs(0);
         availRegs.take(ArgumentsRectifierReg);
         availRegs.take(code);
         emitProfilingUpdate(masm, availRegs, ICGetElemNativeGetterStub::offsetOfPCOffset());
     }
 
-    masm.callIon(code);
+    masm.callJit(code);
 
     leaveStubFrame(masm, true);
 
     return true;
 }
 
 bool
 ICGetElemNativeCompiler::generateStubCode(MacroAssembler &masm)
@@ -7207,17 +7207,17 @@ ICGetProp_CallScripted::Compiler::genera
     }
     Register code = regs.takeAny();
     masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallScripted::offsetOfGetter()), callee);
     masm.branchIfFunctionHasNoScript(callee, &failureLeaveStubFrame);
     masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
     masm.loadBaselineOrIonRaw(code, code, SequentialExecution, &failureLeaveStubFrame);
 
     // Getter is called with 0 arguments, just |obj| as thisv.
-    // Note that we use Push, not push, so that callIon will align the stack
+    // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
     masm.Push(R0);
     EmitCreateStubFrameDescriptor(masm, scratch);
     masm.Push(Imm32(0));  // ActualArgc is 0
     masm.Push(callee);
     masm.Push(scratch);
 
     // Handle arguments underflow.
@@ -7242,17 +7242,17 @@ ICGetProp_CallScripted::Compiler::genera
     // be clobbered.
     {
         GeneralRegisterSet availRegs = availableGeneralRegs(0);
         availRegs.take(ArgumentsRectifierReg);
         availRegs.take(code);
         emitProfilingUpdate(masm, availRegs, ICGetProp_CallScripted::offsetOfPCOffset());
     }
 
-    masm.callIon(code);
+    masm.callJit(code);
 
     leaveStubFrame(masm, true);
 
     // Enter type monitor IC to type-check result.
     EmitEnterTypeMonitorIC(masm);
 
     // Leave stub frame and go to next stub.
     masm.bind(&failureLeaveStubFrame);
@@ -8297,17 +8297,17 @@ ICSetProp_CallScripted::Compiler::genera
     }
     Register code = regs.takeAny();
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallScripted::offsetOfSetter()), callee);
     masm.branchIfFunctionHasNoScript(callee, &failureLeaveStubFrame);
     masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
     masm.loadBaselineOrIonRaw(code, code, SequentialExecution, &failureLeaveStubFrame);
 
     // Setter is called with the new value as the only argument, and |obj| as thisv.
-    // Note that we use Push, not push, so that callIon will align the stack
+    // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
 
     // To Push R1, read it off of the stowed values on stack.
     // Stack: [ ..., R0, R1, ..STUBFRAME-HEADER.. ]
     masm.movePtr(BaselineStackReg, scratch);
     masm.PushValue(Address(scratch, STUB_FRAME_SIZE));
     masm.Push(R0);
     EmitCreateStubFrameDescriptor(masm, scratch);
@@ -8337,17 +8337,17 @@ ICSetProp_CallScripted::Compiler::genera
     // be clobbered.
     {
         GeneralRegisterSet availRegs = availableGeneralRegs(0);
         availRegs.take(ArgumentsRectifierReg);
         availRegs.take(code);
         emitProfilingUpdate(masm, availRegs, ICSetProp_CallScripted::offsetOfPCOffset());
     }
 
-    masm.callIon(code);
+    masm.callJit(code);
 
     leaveStubFrame(masm, true);
     // Do not care about return value from function. The original RHS should be returned
     // as the result of this operation.
     EmitUnstowICValues(masm, 2);
     masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
 
@@ -9593,17 +9593,17 @@ ICCallScriptedCompiler::generateStubCode
 
     // The callee is on top of the stack. Pop and unbox it.
     ValueOperand val = regs.takeAnyValue();
     masm.popValue(val);
     callee = masm.extractObject(val, ExtractTemp0);
 
     EmitCreateStubFrameDescriptor(masm, scratch);
 
-    // Note that we use Push, not push, so that callIon will align the stack
+    // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
     masm.Push(argcReg);
     masm.PushCalleeToken(callee, isConstructing_);
     masm.Push(scratch);
 
     // Handle arguments underflow.
     Label noUnderflow;
     masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), callee);
@@ -9629,17 +9629,17 @@ ICCallScriptedCompiler::generateStubCode
         GeneralRegisterSet availRegs = availableGeneralRegs(0);
         availRegs.take(ArgumentsRectifierReg);
         availRegs.take(code);
         emitProfilingUpdate(masm, availRegs, kind == ICStub::Call_Scripted ?
                                                 ICCall_Scripted::offsetOfPCOffset()
                                               : ICCall_AnyScripted::offsetOfPCOffset());
     }
 
-    masm.callIon(code);
+    masm.callJit(code);
 
     // If this is a constructing call, and the callee returns a non-object, replace it with
     // the |this| object passed in.
     if (isConstructing_) {
         Label skipThisReplace;
         masm.branchTestObject(Assembler::Equal, JSReturnOperand, &skipThisReplace);
 
         Register scratchReg = JSReturnOperand.scratchReg();
@@ -9887,17 +9887,17 @@ ICCall_Native::Compiler::generateStubCod
 
     // Construct a native exit frame.
     masm.push(argcReg);
 
     Register scratch = regs.takeAny();
     EmitCreateStubFrameDescriptor(masm, scratch);
     masm.push(scratch);
     masm.push(BaselineTailCallReg);
-    masm.enterFakeExitFrame(IonNativeExitFrameLayout::Token());
+    masm.enterFakeExitFrame(NativeExitFrameLayout::Token());
 
     // If needed, update SPS Profiler frame entry.  At this point, BaselineTailCallReg
     // and scratch can be clobbered.
     emitProfilingUpdate(masm, BaselineTailCallReg, scratch, ICCall_Native::offsetOfPCOffset());
 
     // Execute call.
     masm.setupUnalignedABICall(3, scratch);
     masm.loadJSContext(scratch);
@@ -9913,17 +9913,17 @@ ICCall_Native::Compiler::generateStubCod
 #else
     masm.callWithABI(Address(callee, JSFunction::offsetOfNativeOrScript()));
 #endif
 
     // Test for failure.
     masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
 
     // Load the return value into R0.
-    masm.loadValue(Address(StackPointer, IonNativeExitFrameLayout::offsetOfResult()), R0);
+    masm.loadValue(Address(StackPointer, NativeExitFrameLayout::offsetOfResult()), R0);
 
     leaveStubFrame(masm);
 
     // Enter type monitor IC to type-check result.
     EmitEnterTypeMonitorIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
@@ -9986,17 +9986,17 @@ ICCall_ClassHook::Compiler::generateStub
     masm.movePtr(StackPointer, vpReg);
 
     // Construct a native exit frame.
     masm.push(argcReg);
 
     EmitCreateStubFrameDescriptor(masm, scratch);
     masm.push(scratch);
     masm.push(BaselineTailCallReg);
-    masm.enterFakeExitFrame(IonNativeExitFrameLayout::Token());
+    masm.enterFakeExitFrame(NativeExitFrameLayout::Token());
 
     // If needed, update SPS Profiler frame entry.  At this point, BaselineTailCallReg
     // and scratch can be clobbered.
     emitProfilingUpdate(masm, BaselineTailCallReg, scratch, ICCall_ClassHook::offsetOfPCOffset());
 
     // Execute call.
     masm.setupUnalignedABICall(3, scratch);
     masm.loadJSContext(scratch);
@@ -10004,17 +10004,17 @@ ICCall_ClassHook::Compiler::generateStub
     masm.passABIArg(argcReg);
     masm.passABIArg(vpReg);
     masm.callWithABI(Address(BaselineStubReg, ICCall_ClassHook::offsetOfNative()));
 
     // Test for failure.
     masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
 
     // Load the return value into R0.
-    masm.loadValue(Address(StackPointer, IonNativeExitFrameLayout::offsetOfResult()), R0);
+    masm.loadValue(Address(StackPointer, NativeExitFrameLayout::offsetOfResult()), R0);
 
     leaveStubFrame(masm);
 
     // Enter type monitor IC to type-check result.
     EmitEnterTypeMonitorIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
@@ -10112,17 +10112,17 @@ ICCall_ScriptedApplyArray::Compiler::gen
     regs.add(argcReg);
 
     // If needed, update SPS Profiler frame entry.  At this point, BaselineTailCallReg
     // and scratch can be clobbered.
     emitProfilingUpdate(masm, regs.getAny(), scratch,
                         ICCall_ScriptedApplyArguments::offsetOfPCOffset());
 
     // Do call
-    masm.callIon(target);
+    masm.callJit(target);
     leaveStubFrame(masm, true);
 
     // Enter type monitor IC to type-check result.
     EmitEnterTypeMonitorIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
@@ -10213,17 +10213,17 @@ ICCall_ScriptedApplyArguments::Compiler:
     regs.add(argcReg);
 
     // If needed, update SPS Profiler frame entry.  At this point, BaselineTailCallReg
     // and scratch can be clobbered.
     emitProfilingUpdate(masm, regs.getAny(), scratch,
                         ICCall_ScriptedApplyArguments::offsetOfPCOffset());
 
     // Do call
-    masm.callIon(target);
+    masm.callJit(target);
     leaveStubFrame(masm, true);
 
     // Enter type monitor IC to type-check result.
     EmitEnterTypeMonitorIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
@@ -10304,17 +10304,17 @@ ICCall_ScriptedFunCall::Compiler::genera
     masm.bind(&done);
 
     // Unbox scripted callee.
     callee = masm.extractObject(val, ExtractTemp0);
 
     Register scratch = regs.takeAny();
     EmitCreateStubFrameDescriptor(masm, scratch);
 
-    // Note that we use Push, not push, so that callIon will align the stack
+    // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
     masm.Push(argcReg);
     masm.Push(callee);
     masm.Push(scratch);
 
     // Handle arguments underflow.
     Label noUnderflow;
     masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), callee);
@@ -10338,17 +10338,17 @@ ICCall_ScriptedFunCall::Compiler::genera
     {
         // Need to avoid using ArgumentsRectifierReg and code register.
         GeneralRegisterSet availRegs = availableGeneralRegs(0);
         availRegs.take(ArgumentsRectifierReg);
         availRegs.take(code);
         emitProfilingUpdate(masm, availRegs, ICCall_ScriptedFunCall::offsetOfPCOffset());
     }
 
-    masm.callIon(code);
+    masm.callJit(code);
 
     leaveStubFrame(masm, true);
 
     // Enter type monitor IC to type-check result.
     EmitEnterTypeMonitorIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -87,17 +87,17 @@ class BaselineInspector
         }
         return ICInspectorType(this, pc, ent);
     }
 
     ICStub *monomorphicStub(jsbytecode *pc);
     bool dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **psecond);
 
   public:
-    typedef Vector<Shape *, 4, IonAllocPolicy> ShapeVector;
+    typedef Vector<Shape *, 4, JitAllocPolicy> ShapeVector;
     bool maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes);
 
     SetElemICInspector setElemICInspector(jsbytecode *pc) {
         return makeICInspector<SetElemICInspector>(pc, ICStub::SetElem_Fallback);
     }
 
     MIRType expectedResultType(jsbytecode *pc);
     MCompare::CompareType expectedCompareType(jsbytecode *pc);
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -17,17 +17,17 @@
 #include "vm/Interpreter.h"
 #include "vm/TraceLogging.h"
 
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 #include "jsopcodeinlines.h"
 #include "jsscriptinlines.h"
 
-#include "jit/IonFrames-inl.h"
+#include "jit/JitFrames-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 /* static */ PCMappingSlotInfo::SlotLocation
 PCMappingSlotInfo::ToSlotLocation(const StackValue *stackVal)
 {
@@ -73,27 +73,27 @@ CheckFrame(InterpreterFrame *fp)
         // Fall back to the interpreter to avoid running out of stack space.
         JitSpew(JitSpew_BaselineAbort, "Too many arguments (%u)", fp->numActualArgs());
         return false;
     }
 
     return true;
 }
 
-static IonExecStatus
+static JitExecStatus
 EnterBaseline(JSContext *cx, EnterJitData &data)
 {
     if (data.osrFrame) {
         // Check for potential stack overflow before OSR-ing.
         uint8_t spDummy;
         uint32_t extra = BaselineFrame::Size() + (data.osrNumStackValues * sizeof(Value));
         uint8_t *checkSp = (&spDummy) - extra;
-        JS_CHECK_RECURSION_WITH_SP(cx, checkSp, return IonExec_Aborted);
+        JS_CHECK_RECURSION_WITH_SP(cx, checkSp, return JitExec_Aborted);
     } else {
-        JS_CHECK_RECURSION(cx, return IonExec_Aborted);
+        JS_CHECK_RECURSION(cx, return JitExec_Aborted);
     }
 
     MOZ_ASSERT(jit::IsBaselineEnabled(cx));
     MOZ_ASSERT_IF(data.osrFrame, CheckFrame(data.osrFrame));
 
     EnterJitCode enter = cx->runtime()->jitRuntime()->enterBaseline();
 
     // Caller must construct |this| before invoking the Ion function.
@@ -120,40 +120,40 @@ EnterBaseline(JSContext *cx, EnterJitDat
     // Jit callers wrap primitive constructor return.
     if (!data.result.isMagic() && data.constructing && data.result.isPrimitive())
         data.result = data.maxArgv[0];
 
     // Release temporary buffer used for OSR into Ion.
     cx->runtime()->getJitRuntime(cx)->freeOsrTempData();
 
     MOZ_ASSERT_IF(data.result.isMagic(), data.result.isMagic(JS_ION_ERROR));
-    return data.result.isMagic() ? IonExec_Error : IonExec_Ok;
+    return data.result.isMagic() ? JitExec_Error : JitExec_Ok;
 }
 
-IonExecStatus
+JitExecStatus
 jit::EnterBaselineMethod(JSContext *cx, RunState &state)
 {
     BaselineScript *baseline = state.script()->baselineScript();
 
     EnterJitData data(cx);
     data.jitcode = baseline->method()->raw();
 
     AutoValueVector vals(cx);
     if (!SetEnterJitData(cx, data, state, vals))
-        return IonExec_Error;
+        return JitExec_Error;
 
-    IonExecStatus status = EnterBaseline(cx, data);
-    if (status != IonExec_Ok)
+    JitExecStatus status = EnterBaseline(cx, data);
+    if (status != JitExec_Ok)
         return status;
 
     state.setReturnValue(data.result);
-    return IonExec_Ok;
+    return JitExec_Ok;
 }
 
-IonExecStatus
+JitExecStatus
 jit::EnterBaselineAtBranch(JSContext *cx, InterpreterFrame *fp, jsbytecode *pc)
 {
     MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
 
     BaselineScript *baseline = fp->script()->baselineScript();
 
     EnterJitData data(cx);
     data.jitcode = baseline->nativeCodeForPC(fp->script(), pc);
@@ -191,39 +191,39 @@ jit::EnterBaselineAtBranch(JSContext *cx
         else
             data.calleeToken = CalleeToToken(fp->script());
     }
 
     TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
     TraceLogStopEvent(logger, TraceLogger::Interpreter);
     TraceLogStartEvent(logger, TraceLogger::Baseline);
 
-    IonExecStatus status = EnterBaseline(cx, data);
-    if (status != IonExec_Ok)
+    JitExecStatus status = EnterBaseline(cx, data);
+